]> granicus.if.org Git - postgresql/commitdiff
Fix storage size for btree_gist interval indexes. Fix penalty
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 21 Jul 2005 04:15:04 +0000 (04:15 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 21 Jul 2005 04:15:04 +0000 (04:15 +0000)
calculations for interval and time/timetz to behave sanely for both
integer and float timestamps; up to now I think it's been doing
something pretty strange...

contrib/btree_gist/btree_gist.sql.in
contrib/btree_gist/btree_interval.c
contrib/btree_gist/btree_time.c
contrib/btree_gist/btree_utils_num.h
contrib/btree_gist/expected/init.out

index a5f7ae3ffa0728bb09466e9c7f66bf6e6394641f..c4c260947e9c8a256347dd8a1e711ccd7f2ec0f3 100644 (file)
@@ -49,20 +49,20 @@ INPUT  = gbtreekey16_in,
 OUTPUT = gbtreekey16_out
 );
 
-CREATE FUNCTION gbtreekey24_in(cstring)
-RETURNS gbtreekey24
+CREATE FUNCTION gbtreekey32_in(cstring)
+RETURNS gbtreekey32
 AS 'MODULE_PATHNAME', 'gbtreekey_in'
 LANGUAGE 'c' WITH (isstrict);
 
-CREATE FUNCTION gbtreekey24_out(gbtreekey24)
+CREATE FUNCTION gbtreekey32_out(gbtreekey32)
 RETURNS cstring
 AS 'MODULE_PATHNAME', 'gbtreekey_out'
 LANGUAGE 'c' WITH (isstrict);
 
-CREATE TYPE gbtreekey24 (
-INTERNALLENGTH = 24,
-INPUT  = gbtreekey24_in,
-OUTPUT = gbtreekey24_out
+CREATE TYPE gbtreekey32 (
+INTERNALLENGTH = 32,
+INPUT  = gbtreekey32_in,
+OUTPUT = gbtreekey32_out
 );
 
 CREATE FUNCTION gbtreekey_var_in(cstring)
@@ -697,7 +697,7 @@ AS 'MODULE_PATHNAME'
 LANGUAGE 'C';
       
 CREATE FUNCTION gbt_intv_union(bytea, internal)
-RETURNS gbtreekey24
+RETURNS gbtreekey32
 AS 'MODULE_PATHNAME'
 LANGUAGE 'C';
 
@@ -722,7 +722,7 @@ AS
        FUNCTION        5       gbt_intv_penalty (internal, internal, internal),
        FUNCTION        6       gbt_intv_picksplit (internal, internal),
        FUNCTION        7       gbt_intv_same (internal, internal, internal),
-       STORAGE         gbtreekey24;
+       STORAGE         gbtreekey32;
 
 --
 --
index d3aa4939a38d014bbfa3b3b26a87551357b82201..3c671a3f04638e2e0b6e4cc45b7453696adcb2b1 100644 (file)
@@ -73,22 +73,14 @@ gbt_intvkey_cmp(const void *a, const void *b)
 static double
 intr2num(const Interval *i)
 {
-       double          ret = 0.0;
-       struct pg_tm tm;
-       fsec_t          fsec;
-
-       interval2tm(*i, &tm, &fsec);
-       ret += (tm.tm_year * 360.0 * 86400.0);
-       ret += (tm.tm_mon * 12.0 * 86400.0);
-       ret += (tm.tm_mday * 86400.0);
-       ret += (tm.tm_hour * 3600.0);
-       ret += (tm.tm_min * 60.0);
-       ret += (tm.tm_sec);
-       ret += (fsec / 1000000.0);
-
-       return (ret);
+       return INTERVAL_TO_SEC(i);
 }
 
+/*
+ * INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
+ * in pg_type.  This might be less than sizeof(Interval) if the compiler
+ * insists on adding alignment padding at the end of the struct.
+ */
 #define INTERVALSIZE 16
 
 static const gbtree_ninfo tinfo =
index 9dc3250cf1c09f62d9e6038c7739e665af8a0c63..02f2664349e0ad67104f9cf34b55cf335340a45c 100644 (file)
@@ -207,29 +207,24 @@ gbt_time_penalty(PG_FUNCTION_ARGS)
        timeKEY    *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
        float      *result = (float *) PG_GETARG_POINTER(2);
        Interval   *intr;
-
-#ifdef HAVE_INT64_TIMESTAMP
-       int64           res;
-
-#else
        double          res;
-#endif
+       double          res2;
 
        intr = DatumGetIntervalP(DirectFunctionCall2(
                                                                                                 time_mi_time,
                                                                                P_TimeADTGetDatum(newentry->upper),
                                                                         P_TimeADTGetDatum(origentry->upper)));
-
-       /* see interval_larger */
-       res = Max(intr->time + intr->day * 86400 + intr->month * (30 * 86400), 0);
+       res = INTERVAL_TO_SEC(intr);
+       res = Max(res, 0);
 
        intr = DatumGetIntervalP(DirectFunctionCall2(
                                                                                                 time_mi_time,
                                                                           P_TimeADTGetDatum(origentry->lower),
                                                                          P_TimeADTGetDatum(newentry->lower)));
+       res2 = INTERVAL_TO_SEC(intr);
+       res2 = Max(res2, 0);
 
-       /* see interval_larger */
-       res += Max(intr->time + intr->day * 86400 + intr->month * (30 * 86400), 0);
+       res += res2;
 
        *result = 0.0;
 
@@ -240,7 +235,7 @@ gbt_time_penalty(PG_FUNCTION_ARGS)
                                                                           P_TimeADTGetDatum(origentry->upper),
                                                                         P_TimeADTGetDatum(origentry->lower)));
                *result += FLT_MIN;
-               *result += (float) (res / ((double) (res + intr->time + intr->day * 86400 + intr->month * (30 * 86400))));
+               *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
                *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
        }
 
index 8f140953f5c44da2e94e67912b4079e8b9f76b99..94d4bf7437476b5439f0afda282ab4af1d6df33f 100644 (file)
@@ -63,6 +63,24 @@ typedef struct
 } while (0);
 
 
+/*
+ * Convert an Interval to an approximate equivalent number of seconds
+ * (as a double).  Here because we need it for time/timetz as well as
+ * interval.  See interval_cmp_internal for comparison.
+ */
+#ifdef HAVE_INT64_TIMESTAMP
+#define INTERVAL_TO_SEC(ivp) \
+       (((double) (ivp)->time) / ((double) USECS_PER_SEC) + \
+        (ivp)->day * (24.0 * SECS_PER_HOUR) + \
+        (ivp)->month * (30.0 * SECS_PER_DAY))
+#else
+#define INTERVAL_TO_SEC(ivp) \
+       ((ivp)->time + \
+        (ivp)->day * (24.0 * SECS_PER_HOUR) + \
+        (ivp)->month * (30.0 * SECS_PER_DAY))
+#endif
+
+
 extern bool gbt_num_consistent(const GBT_NUMKEY_R * key, const void *query,
                                   const StrategyNumber *strategy, bool is_leaf,
                                   const gbtree_ninfo * tinfo);
index 9561fac1089e64c6b489728121bc52f28dfb8b9a..1dbbfd74ec291c9e29a09ccb1b17b4d739c64076 100644 (file)
@@ -12,9 +12,9 @@ psql:btree_gist.sql:28: NOTICE:  argument type gbtreekey8 is only a shell
 psql:btree_gist.sql:39: NOTICE:  type "gbtreekey16" is not yet defined
 DETAIL:  Creating a shell type definition.
 psql:btree_gist.sql:44: NOTICE:  argument type gbtreekey16 is only a shell
-psql:btree_gist.sql:55: NOTICE:  type "gbtreekey24" is not yet defined
+psql:btree_gist.sql:55: NOTICE:  type "gbtreekey32" is not yet defined
 DETAIL:  Creating a shell type definition.
-psql:btree_gist.sql:60: NOTICE:  argument type gbtreekey24 is only a shell
+psql:btree_gist.sql:60: NOTICE:  argument type gbtreekey32 is only a shell
 psql:btree_gist.sql:71: NOTICE:  type "gbtreekey_var" is not yet defined
 DETAIL:  Creating a shell type definition.
 psql:btree_gist.sql:76: NOTICE:  argument type gbtreekey_var is only a shell