diff --git a/contrib/btree_gist/btree_gist.sql.in b/contrib/btree_gist/btree_gist.sql.in index a5f7ae3ffa..c4c260947e 100644 --- a/contrib/btree_gist/btree_gist.sql.in +++ b/contrib/btree_gist/btree_gist.sql.in @@ -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; -- -- diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c index d3aa4939a3..3c671a3f04 100644 --- a/contrib/btree_gist/btree_interval.c +++ b/contrib/btree_gist/btree_interval.c @@ -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 = diff --git a/contrib/btree_gist/btree_time.c b/contrib/btree_gist/btree_time.c index 9dc3250cf1..02f2664349 100644 --- a/contrib/btree_gist/btree_time.c +++ b/contrib/btree_gist/btree_time.c @@ -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)); } diff --git a/contrib/btree_gist/btree_utils_num.h b/contrib/btree_gist/btree_utils_num.h index 8f140953f5..94d4bf7437 100644 --- a/contrib/btree_gist/btree_utils_num.h +++ b/contrib/btree_gist/btree_utils_num.h @@ -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); diff --git a/contrib/btree_gist/expected/init.out b/contrib/btree_gist/expected/init.out index 9561fac108..1dbbfd74ec 100644 --- a/contrib/btree_gist/expected/init.out +++ b/contrib/btree_gist/expected/init.out @@ -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