From ef770cbb6913cc4c816bb09acd7cb13f996281bd Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Fri, 1 Jul 2005 13:44:56 +0000 Subject: [PATCH] Fixes from Janko Richter - Fix wrong index results on text, char, varchar for multibyte strings - Fix some SIGFPE signals - Add support for infinite timestamps - Because of locale settings, btree_gist can not be a prefix index anymore (for text). Each node holds now just the lower and upper boundary. --- contrib/btree_gist/btree_bit.c | 2 +- contrib/btree_gist/btree_bytea.c | 2 +- contrib/btree_gist/btree_cash.c | 17 +- contrib/btree_gist/btree_float4.c | 13 +- contrib/btree_gist/btree_float8.c | 13 +- contrib/btree_gist/btree_inet.c | 15 +- contrib/btree_gist/btree_int2.c | 16 +- contrib/btree_gist/btree_int4.c | 18 +- contrib/btree_gist/btree_int8.c | 19 +- contrib/btree_gist/btree_interval.c | 14 +- contrib/btree_gist/btree_macaddr.c | 12 +- contrib/btree_gist/btree_numeric.c | 2 +- contrib/btree_gist/btree_oid.c | 13 +- contrib/btree_gist/btree_text.c | 27 +- contrib/btree_gist/btree_ts.c | 62 ++- contrib/btree_gist/btree_utils_num.h | 20 +- contrib/btree_gist/btree_utils_var.c | 162 +++---- contrib/btree_gist/btree_utils_var.h | 3 +- contrib/btree_gist/data/char.data | 466 ++++++++++++++++++++ contrib/btree_gist/data/timestamp.data | 24 + contrib/btree_gist/data/timestamptz.data | 18 + contrib/btree_gist/expected/bytea.out | 8 +- contrib/btree_gist/expected/char.out | 8 +- contrib/btree_gist/expected/text.out | 8 +- contrib/btree_gist/expected/timestamp.out | 16 +- contrib/btree_gist/expected/timestamptz.out | 48 +- contrib/btree_gist/expected/varchar.out | 8 +- 27 files changed, 730 insertions(+), 304 deletions(-) diff --git a/contrib/btree_gist/btree_bit.c b/contrib/btree_gist/btree_bit.c index 0c7108bc60..d8e401acfc 100644 --- a/contrib/btree_gist/btree_bit.c +++ b/contrib/btree_gist/btree_bit.c @@ -98,7 +98,7 @@ gbt_bit_l2n(GBT_VARKEY * leaf) static const gbtree_vinfo tinfo = { gbt_t_bit, - FALSE, + 0, TRUE, gbt_bitgt, gbt_bitge, diff --git a/contrib/btree_gist/btree_bytea.c b/contrib/btree_gist/btree_bytea.c index 375cc26cc6..d5345872d6 100644 --- a/contrib/btree_gist/btree_bytea.c +++ b/contrib/btree_gist/btree_bytea.c @@ -65,7 +65,7 @@ gbt_byteacmp(const bytea *a, const bytea *b) static const gbtree_vinfo tinfo = { gbt_t_bytea, - FALSE, + 0, TRUE, gbt_byteagt, gbt_byteage, diff --git a/contrib/btree_gist/btree_cash.c b/contrib/btree_gist/btree_cash.c index 84e4610118..cef6103734 100644 --- a/contrib/btree_gist/btree_cash.c +++ b/contrib/btree_gist/btree_cash.c @@ -125,21 +125,10 @@ Datum gbt_cash_penalty(PG_FUNCTION_ARGS) { cashKEY *origentry = (cashKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); - cashKEY *newentry = (cashKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); - float *result = (float *) PG_GETARG_POINTER(2); + cashKEY *newentry = (cashKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); + float *result = (float *) PG_GETARG_POINTER(2); - Cash res; - - *result = 0.0; - - penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / ((double) (res + origentry->upper - origentry->lower))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + penalty_num(result,origentry->lower,origentry->upper,newentry->lower,newentry->upper); PG_RETURN_POINTER(result); diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c index b36178e454..9d6c174773 100644 --- a/contrib/btree_gist/btree_float4.c +++ b/contrib/btree_gist/btree_float4.c @@ -127,18 +127,7 @@ gbt_float4_penalty(PG_FUNCTION_ARGS) float4KEY *newentry = (float4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); float *result = (float *) PG_GETARG_POINTER(2); - float4 res; - - *result = 0.0; - - penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / ((double) (res + origentry->upper - origentry->lower))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + penalty_num(result,origentry->lower,origentry->upper,newentry->lower,newentry->upper); PG_RETURN_POINTER(result); diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c index a5511d5abf..7345d37b21 100644 --- a/contrib/btree_gist/btree_float8.c +++ b/contrib/btree_gist/btree_float8.c @@ -129,18 +129,7 @@ gbt_float8_penalty(PG_FUNCTION_ARGS) float8KEY *newentry = (float8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); float *result = (float *) PG_GETARG_POINTER(2); - float8 res; - - *result = 0.0; - - penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / ((double) (res + origentry->upper - origentry->lower))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + penalty_num(result,origentry->lower,origentry->upper,newentry->lower,newentry->upper); PG_RETURN_POINTER(result); diff --git a/contrib/btree_gist/btree_inet.c b/contrib/btree_gist/btree_inet.c index fad053a36f..3719d3bb1a 100644 --- a/contrib/btree_gist/btree_inet.c +++ b/contrib/btree_gist/btree_inet.c @@ -194,19 +194,8 @@ gbt_inet_penalty(PG_FUNCTION_ARGS) inetKEY *newentry = (inetKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); float *result = (float *) PG_GETARG_POINTER(2); - double res; - - *result = 0.0; - - penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / ((double) (res + origentry->upper - origentry->lower))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } - + penalty_num(result,origentry->lower,origentry->upper,newentry->lower,newentry->upper); + PG_RETURN_POINTER(result); } diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c index 3eb5801a7e..8bbdb1d802 100644 --- a/contrib/btree_gist/btree_int2.c +++ b/contrib/btree_gist/btree_int2.c @@ -128,20 +128,10 @@ Datum gbt_int2_penalty(PG_FUNCTION_ARGS) { int16KEY *origentry = (int16KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); - int16KEY *newentry = (int16KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); - float *result = (float *) PG_GETARG_POINTER(2); - int2 res; + int16KEY *newentry = (int16KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); + float *result = (float *) PG_GETARG_POINTER(2); - *result = 0.0; - - penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / ((double) (res + origentry->upper - origentry->lower))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + penalty_num(result,origentry->lower,origentry->upper,newentry->lower,newentry->upper); PG_RETURN_POINTER(result); } diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c index 6693185c98..43a4cbe6be 100644 --- a/contrib/btree_gist/btree_int4.c +++ b/contrib/btree_gist/btree_int4.c @@ -126,20 +126,10 @@ Datum gbt_int4_penalty(PG_FUNCTION_ARGS) { int32KEY *origentry = (int32KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); - int32KEY *newentry = (int32KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); - float *result = (float *) PG_GETARG_POINTER(2); - int4 res; - - *result = 0.0; - - penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / ((double) (res + origentry->upper - origentry->lower))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + int32KEY *newentry = (int32KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); + float *result = (float *) PG_GETARG_POINTER(2); + + penalty_num(result,origentry->lower,origentry->upper,newentry->lower,newentry->upper); PG_RETURN_POINTER(result); } diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c index 0741193c6f..7de02dbca7 100644 --- a/contrib/btree_gist/btree_int8.c +++ b/contrib/btree_gist/btree_int8.c @@ -125,23 +125,12 @@ Datum gbt_int8_penalty(PG_FUNCTION_ARGS) { int64KEY *origentry = (int64KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); - int64KEY *newentry = (int64KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); - float *result = (float *) PG_GETARG_POINTER(2); - int64 res; - - *result = 0.0; - - penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / ((double) (res + origentry->upper - origentry->lower))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + int64KEY *newentry = (int64KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); + float *result = (float *) PG_GETARG_POINTER(2); + penalty_num(result,origentry->lower,origentry->upper,newentry->lower,newentry->upper); + PG_RETURN_POINTER(result); - } Datum diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c index 97374a4054..206b4c9488 100644 --- a/contrib/btree_gist/btree_interval.c +++ b/contrib/btree_gist/btree_interval.c @@ -203,24 +203,14 @@ gbt_intv_penalty(PG_FUNCTION_ARGS) intvKEY *newentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); float *result = (float *) PG_GETARG_POINTER(2); double iorg[2], - inew[2], - res; + inew[2]; iorg[0] = intr2num(&origentry->lower); iorg[1] = intr2num(&origentry->upper); inew[0] = intr2num(&newentry->lower); inew[1] = intr2num(&newentry->upper); - penalty_range_enlarge(iorg[0], iorg[1], inew[0], inew[1]); - - *result = 0.0; - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / (res + iorg[1] - iorg[0])); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + penalty_num(result,iorg[0],iorg[1],inew[0],inew[1]); PG_RETURN_POINTER(result); diff --git a/contrib/btree_gist/btree_macaddr.c b/contrib/btree_gist/btree_macaddr.c index 3f08a58655..ee56f0fac1 100644 --- a/contrib/btree_gist/btree_macaddr.c +++ b/contrib/btree_gist/btree_macaddr.c @@ -151,23 +151,13 @@ gbt_macad_penalty(PG_FUNCTION_ARGS) float *result = (float *) PG_GETARG_POINTER(2); uint64 iorg[2], inew[2]; - uint64 res; iorg[0] = mac_2_uint64(&origentry->lower); iorg[1] = mac_2_uint64(&origentry->upper); inew[0] = mac_2_uint64(&newentry->lower); inew[1] = mac_2_uint64(&newentry->upper); - penalty_range_enlarge(iorg[0], iorg[1], inew[0], inew[1]); - - *result = 0.0; - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (((double) res) / ((double) res + (double) iorg[1] - (double) iorg[0])); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + penalty_num(result,iorg[0],iorg[1],inew[0],inew[1]); PG_RETURN_POINTER(result); diff --git a/contrib/btree_gist/btree_numeric.c b/contrib/btree_gist/btree_numeric.c index fcfd4613ef..b9da2dda2f 100644 --- a/contrib/btree_gist/btree_numeric.c +++ b/contrib/btree_gist/btree_numeric.c @@ -65,7 +65,7 @@ gbt_numeric_cmp(const bytea *a, const bytea *b) static const gbtree_vinfo tinfo = { gbt_t_numeric, - FALSE, + 0, FALSE, gbt_numeric_gt, gbt_numeric_ge, diff --git a/contrib/btree_gist/btree_oid.c b/contrib/btree_gist/btree_oid.c index db4182fc04..d76d876372 100644 --- a/contrib/btree_gist/btree_oid.c +++ b/contrib/btree_gist/btree_oid.c @@ -129,18 +129,7 @@ gbt_oid_penalty(PG_FUNCTION_ARGS) oidKEY *newentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); float *result = (float *) PG_GETARG_POINTER(2); - Oid res = 0; - - *result = 0.0; - - penalty_range_enlarge(origentry->lower, origentry->upper, newentry->lower, newentry->upper); - - if (res > 0) - { - *result += FLT_MIN; - *result += (float) (res / ((double) (res + origentry->upper - origentry->lower))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + penalty_num(result,origentry->lower,origentry->upper,newentry->lower,newentry->upper); PG_RETURN_POINTER(result); } diff --git a/contrib/btree_gist/btree_text.c b/contrib/btree_gist/btree_text.c index d81e7d0fd9..1275df6aef 100644 --- a/contrib/btree_gist/btree_text.c +++ b/contrib/btree_gist/btree_text.c @@ -62,11 +62,11 @@ gbt_textcmp(const bytea *a, const bytea *b) return DatumGetInt32(DirectFunctionCall2(bttextcmp, PointerGetDatum(a), PointerGetDatum(b))); } -static const gbtree_vinfo tinfo = +static gbtree_vinfo tinfo = { gbt_t_text, - TRUE, - TRUE, + 0, + FALSE, gbt_textgt, gbt_textge, gbt_texteq, @@ -77,7 +77,6 @@ static const gbtree_vinfo tinfo = }; - /************************************************** * Text ops **************************************************/ @@ -88,6 +87,11 @@ gbt_text_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + if ( tinfo.eml == 0 ) + { + tinfo.eml = pg_database_encoding_max_length(); + } + PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo)); } @@ -98,6 +102,11 @@ gbt_bpchar_compress(PG_FUNCTION_ARGS) GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; + if ( tinfo.eml == 0 ) + { + tinfo.eml = pg_database_encoding_max_length(); + } + if (entry->leafkey) { @@ -127,6 +136,11 @@ gbt_text_consistent(PG_FUNCTION_ARGS) bool retval = FALSE; GBT_VARKEY_R r = gbt_var_key_readable(key); + if ( tinfo.eml == 0 ) + { + tinfo.eml = pg_database_encoding_max_length(); + } + retval = gbt_var_consistent(&r, query, &strategy, GIST_LEAF(entry), &tinfo); PG_RETURN_BOOL(retval); @@ -144,6 +158,11 @@ gbt_bpchar_consistent(PG_FUNCTION_ARGS) bool retval; GBT_VARKEY_R r = gbt_var_key_readable(key); + if ( tinfo.eml == 0 ) + { + tinfo.eml = pg_database_encoding_max_length(); + } + retval = gbt_var_consistent(&r, trim, &strategy, GIST_LEAF(entry), &tinfo); PG_RETURN_BOOL(retval); } diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c index 37f72d3a51..6c9481b4b2 100644 --- a/contrib/btree_gist/btree_ts.c +++ b/contrib/btree_gist/btree_ts.c @@ -114,7 +114,7 @@ tstz_to_ts_gmt(Timestamp *gmt, TimestampTz *ts) *gmt = *ts; DecodeSpecial(0, "gmt", &val); - if (!TIMESTAMP_NOT_FINITE(*ts)) + if ( *ts < DT_NOEND && *ts > DT_NOBEGIN ) { tz = val * 60; @@ -218,6 +218,14 @@ gbt_ts_union(PG_FUNCTION_ARGS) } +#define penalty_check_max_float(val) do { \ + if ( val > FLT_MAX ) \ + val = FLT_MAX; \ + if ( val < -FLT_MAX ) \ + val = -FLT_MAX; \ +} while(false); + + Datum gbt_ts_penalty(PG_FUNCTION_ARGS) { @@ -225,48 +233,28 @@ gbt_ts_penalty(PG_FUNCTION_ARGS) tsKEY *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); tsKEY *newentry = (tsKEY *) 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 - intr = DatumGetIntervalP(DirectFunctionCall2( - timestamp_mi, - P_TimestampGetDatum(newentry->upper), - P_TimestampGetDatum(origentry->upper) - )); + double orgdbl[2], + newdbl[2]; - /* see interval_larger */ + /* + We are allways using "double" timestamps here. + Precision should be good enough. + */ + orgdbl[0] = ( (double) origentry->lower ) ; + orgdbl[1] = ( (double) origentry->upper ) ; + newdbl[0] = ( (double) newentry->lower ) ; + newdbl[1] = ( (double) newentry->upper ) ; - res = Max(intr->time + intr->month * (30 * 86400), 0); + penalty_check_max_float( orgdbl[0] ); + penalty_check_max_float( orgdbl[1] ); + penalty_check_max_float( newdbl[0] ); + penalty_check_max_float( newdbl[1] ); - intr = DatumGetIntervalP(DirectFunctionCall2( - timestamp_mi, - P_TimestampGetDatum(origentry->lower), - P_TimestampGetDatum(newentry->lower) - )); - - /* see interval_larger */ - res += Max(intr->time + intr->month * (30 * 86400), 0); - - *result = 0.0; - - if (res > 0) - { - intr = DatumGetIntervalP(DirectFunctionCall2( - timestamp_mi, - P_TimestampGetDatum(origentry->upper), - P_TimestampGetDatum(origentry->lower) - )); - *result += FLT_MIN; - *result += (float) (res / ((double) (res + intr->time + intr->month * (30 * 86400)))); - *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); - } + penalty_num(result,orgdbl[0],orgdbl[1],newdbl[0],newdbl[1]); PG_RETURN_POINTER(result); + } diff --git a/contrib/btree_gist/btree_utils_num.h b/contrib/btree_gist/btree_utils_num.h index 714144f676..8f140953f5 100644 --- a/contrib/btree_gist/btree_utils_num.h +++ b/contrib/btree_gist/btree_utils_num.h @@ -43,16 +43,26 @@ typedef struct */ -#define penalty_range_enlarge(olower,oupper,nlower,nupper) do { \ - res = 0; \ + +/* + * Note: The factor 0.49 in following macro avoids floating point overflows +*/ +#define penalty_num(result,olower,oupper,nlower,nupper) do { \ + double tmp = 0.0F; \ + (*(result)) = 0.0F; \ if ( (nupper) > (oupper) ) \ - res += ( (nupper) - (oupper) ); \ + tmp += ( ((double)nupper)*0.49F - ((double)oupper)*0.49F ); \ if ( (olower) > (nlower) ) \ - res += ( (olower) - (nlower) ); \ + tmp += ( ((double)olower)*0.49F - ((double)nlower)*0.49F ); \ + if (tmp > 0.0F) \ + { \ + (*(result)) += FLT_MIN; \ + (*(result)) += (float) ( ((double)(tmp)) / ( (double)(tmp) + ( ((double)(oupper))*0.49F - ((double)(olower))*0.49F ) ) ); \ + (*(result)) *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); \ + } \ } while (0); - 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/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c index 720381428f..8de39bb327 100644 --- a/contrib/btree_gist/btree_utils_var.c +++ b/contrib/btree_gist/btree_utils_var.c @@ -1,6 +1,7 @@ #include "btree_gist.h" #include "utils/pg_locale.h" #include "btree_utils_var.h" +#include "utils/builtins.h" PG_FUNCTION_INFO_V1(gbt_var_decompress); Datum gbt_var_decompress(PG_FUNCTION_ARGS); @@ -90,69 +91,91 @@ gbt_var_leaf2node(GBT_VARKEY * leaf, const gbtree_vinfo * tinfo) static int32 gbt_var_node_cp_len(const GBT_VARKEY * node, const gbtree_vinfo * tinfo) { - int32 i; - int32 s = (tinfo->str) ? (1) : (0); - GBT_VARKEY_R r = gbt_var_key_readable(node); - int32 t1len = VARSIZE(r.lower) - VARHDRSZ - s; - int32 t2len = VARSIZE(r.upper) - VARHDRSZ - s; - int32 ml = Min(t1len, t2len); - char *p1 = VARDATA(r.lower), - *p2 = VARDATA(r.upper); + GBT_VARKEY_R r = gbt_var_key_readable(node); + int32 i = 0; + int32 l = 0; + int32 t1len = VARSIZE(r.lower) - VARHDRSZ ; + int32 t2len = VARSIZE(r.upper) - VARHDRSZ ; + int32 ml = Min(t1len, t2len); + + char *p1 = VARDATA(r.lower); + char *p2 = VARDATA(r.upper); - for (i = 0; i < ml; i++) + if ( ml == 0 ) + return 0; + + while ( i < ml ) { - if (*p1 != *p2) - return i; - p1++; - p2++; + if ( tinfo->eml > 1 && l == 0 ) + { + + if ( ( l = pg_mblen(p1) ) != pg_mblen(p2) ) + { + return i; + } + } + if (*p1 != *p2) + { + if( tinfo->eml > 1 ) + { + return (i-l+1); + } else { + return i; + } + } + + p1++; + p2++; + l--; + i++; } - return (ml); + return (ml); /* lower == upper */ } - /* - * returns true, if query matches prefix using common prefix + * returns true, if query matches prefix ( common prefix ) */ - static bool gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo * tinfo) { - int k; - int32 s = (tinfo->str) ? (1) : (0); - bool out = FALSE; - int32 qlen = VARSIZE(query) - VARHDRSZ - s; - int32 nlen = VARSIZE(pf) - VARHDRSZ - s; + bool out = FALSE; + int32 k = 0; + int32 qlen = VARSIZE(query) - VARHDRSZ ; + int32 nlen = VARSIZE(pf) - VARHDRSZ ; if (nlen <= qlen) { - char *q = VARDATA(query); - char *n = VARDATA(pf); - - out = TRUE; - for (k = 0; k < nlen; k++) - { - if (*n != *q) - { - out = FALSE; - break; - } - if (k < (nlen - 1)) - { - q++; - n++; - } - } + char *q = VARDATA(query); + char *n = VARDATA(pf); + + if ( tinfo->eml > 1 ) + { + out = ( varstr_cmp(q, nlen, n, nlen) == 0 ); + } else { + out = TRUE; + for (k = 0; k < nlen; k++) + { + if (*n != *q) + { + out = FALSE; + break; + } + if (k < (nlen - 1)) + { + q++; + n++; + } + } + } } return out; } - - /* * returns true, if query matches node using common prefix */ @@ -161,44 +184,36 @@ static bool gbt_var_node_pf_match(const GBT_VARKEY_R * node, const bytea *query, const gbtree_vinfo * tinfo) { - return ( + return ( tinfo->trnc && ( gbt_bytea_pf_match(node->lower, query, tinfo) || gbt_bytea_pf_match(node->upper, query, tinfo) - ); + ) ); } /* * truncates / compresses the node key +* cpf_length .. common prefix length */ static GBT_VARKEY * -gbt_var_node_truncate(const GBT_VARKEY * node, int32 length, const gbtree_vinfo * tinfo) +gbt_var_node_truncate(const GBT_VARKEY * node, int32 cpf_length, const gbtree_vinfo * tinfo) { - - int32 s = (tinfo->str) ? (1) : (0); GBT_VARKEY *out = NULL; GBT_VARKEY_R r = gbt_var_key_readable(node); - int32 len1 = VARSIZE(r.lower) - VARHDRSZ; - int32 len2 = VARSIZE(r.upper) - VARHDRSZ; - int32 si = 0; + int32 len1 = VARSIZE(r.lower) - VARHDRSZ; + int32 len2 = VARSIZE(r.upper) - VARHDRSZ; + int32 si = 0; - if (tinfo->str) - length++; /* because of tailing '\0' */ + len1 = Min(len1,(cpf_length + 1)); + len2 = Min(len2,(cpf_length + 1)); - len1 = Min(len1, length); - len2 = Min(len2, length); si = 2 * VARHDRSZ + INTALIGN(VARHDRSZ + len1) + len2; out = (GBT_VARKEY *) palloc(si); out->vl_len = si; - memcpy((void *) &(((char *) out)[VARHDRSZ]), (void *) r.lower, len1 + VARHDRSZ - s); - memcpy((void *) &(((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1)]), (void *) r.upper, len2 + VARHDRSZ - s); + memcpy((void *) &(((char *) out)[VARHDRSZ]), (void *) r.lower, len1 + VARHDRSZ ); + memcpy((void *) &(((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1)]), (void *) r.upper, len2 + VARHDRSZ ); - if (tinfo->str) - { - ((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1) - 1] = '\0'; - ((char *) out)[2 * VARHDRSZ + INTALIGN(VARHDRSZ + len1) + len2 - 1] = '\0'; - } *((int32 *) &(((char *) out)[VARHDRSZ])) = len1 + VARHDRSZ; *((int32 *) &(((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1)])) = len2 + VARHDRSZ; @@ -356,7 +371,6 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree GBT_VARKEY_R ok, nk; GBT_VARKEY *tmp = NULL; - int32 s = (tinfo->str) ? (1) : (0); *res = 0.0; @@ -369,7 +383,7 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree } ok = gbt_var_key_readable(orge); - if ((VARSIZE(ok.lower) - VARHDRSZ) == s && (VARSIZE(ok.upper) - VARHDRSZ) == s) + if ((VARSIZE(ok.lower) - VARHDRSZ) == 0 && (VARSIZE(ok.upper) - VARHDRSZ) == 0) *res = 0.0; else if (!( ( @@ -396,22 +410,14 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree { GBT_VARKEY_R uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(d)); - if (tinfo->str) - { - dres = (VARDATA(ok.lower)[ul] - VARDATA(uk.lower)[ul]) + - (VARDATA(uk.upper)[ul] - VARDATA(ok.upper)[ul]); - } - else - { - char tmp[4]; - - tmp[0] = ((VARSIZE(ok.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.lower)[ul]); - tmp[1] = ((VARSIZE(uk.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.lower)[ul]); - tmp[2] = ((VARSIZE(ok.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.upper)[ul]); - tmp[3] = ((VARSIZE(uk.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.upper)[ul]); - dres = (tmp[0] - tmp[1]) + - (tmp[3] - tmp[2]); - } + char tmp[4]; + + tmp[0] = ((VARSIZE(ok.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.lower)[ul]); + tmp[1] = ((VARSIZE(uk.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.lower)[ul]); + tmp[2] = ((VARSIZE(ok.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.upper)[ul]); + tmp[3] = ((VARSIZE(uk.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.upper)[ul]); + dres = (tmp[0] - tmp[1]) + + (tmp[3] - tmp[2]); dres /= 256.0; } diff --git a/contrib/btree_gist/btree_utils_var.h b/contrib/btree_gist/btree_utils_var.h index ecb3f3f3f1..e4d48d3910 100644 --- a/contrib/btree_gist/btree_utils_var.h +++ b/contrib/btree_gist/btree_utils_var.h @@ -1,3 +1,4 @@ +#include "mb/pg_wchar.h" /* Variable length key */ typedef bytea GBT_VARKEY; @@ -27,7 +28,7 @@ typedef struct /* Attribs */ enum gbtree_type t; /* data type */ - bool str; /* true, if string ( else binary ) */ + int32 eml; /* cached pg_database_encoding_max_length (0: undefined) */ bool trnc; /* truncate (=compress) key */ /* Methods */ diff --git a/contrib/btree_gist/data/char.data b/contrib/btree_gist/data/char.data index 72dc75604c..99bb6abedf 100644 --- a/contrib/btree_gist/data/char.data +++ b/contrib/btree_gist/data/char.data @@ -532,3 +532,469 @@ c30f7472766d25af1dc80 7c5aba41f53293b712fd 3 166d77ac1b46a1ec38aa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/btree_gist/data/timestamp.data b/contrib/btree_gist/data/timestamp.data index 34d50151c9..065bc50775 100644 --- a/contrib/btree_gist/data/timestamp.data +++ b/contrib/btree_gist/data/timestamp.data @@ -341,6 +341,14 @@ 2002-10-29 03:21:13 2000-06-22 14:23:04 1981-01-01 00:15:56 +infinity +infinity +infinity +infinity +infinity +infinity +infinity +infinity 2001-12-31 12:30:28 2003-09-25 04:51:05 2020-12-07 22:47:38 @@ -557,6 +565,14 @@ 2002-09-19 07:59:10 2016-03-16 14:50:17 1986-02-06 02:57:29 +-infinity +-infinity +-infinity +-infinity +-infinity +-infinity +-infinity +-infinity 2018-07-07 23:37:36 1972-02-07 07:48:10 2001-05-06 17:04:36 @@ -590,6 +606,14 @@ 2008-08-01 06:57:47 2032-11-22 15:34:23 1976-01-04 02:56:30 +infinity +infinity +infinity +infinity +infinity +infinity +infinity +infinity 2037-04-11 12:30:59 2011-02-24 11:33:55 1992-11-16 04:53:09 diff --git a/contrib/btree_gist/data/timestamptz.data b/contrib/btree_gist/data/timestamptz.data index f67bb189be..7f07cdcc27 100644 --- a/contrib/btree_gist/data/timestamptz.data +++ b/contrib/btree_gist/data/timestamptz.data @@ -393,6 +393,12 @@ 2004-01-28 20:45:12 GMT+0 1991-03-21 13:23:37 GMT-5 2029-07-26 06:01:08 GMT+9 +infinity +infinity +infinity +infinity +infinity +infinity 2002-11-15 19:24:22 GMT 1987-05-02 16:25:01 GMT-6 1999-04-01 05:54:41 GMT-2 @@ -422,6 +428,12 @@ 1984-10-17 02:42:50 GMT-7 2001-04-29 03:59:54 GMT-1 1996-08-15 07:16:34 GMT-3 +infinity +infinity +infinity +infinity +infinity +infinity \N 1974-02-10 02:40:01 GMT-11 2033-03-28 21:51:56 GMT+10 @@ -475,6 +487,12 @@ 1973-06-15 06:34:08 GMT-11 1976-03-21 22:21:06 GMT-10 1976-06-15 07:14:46 GMT-10 +-infinity +-infinity +-infinity +-infinity +-infinity +-infinity 1972-01-15 06:30:22 GMT-11 1971-08-06 10:41:43 GMT-11 1995-08-21 21:12:06 GMT-3 diff --git a/contrib/btree_gist/expected/bytea.out b/contrib/btree_gist/expected/bytea.out index d17ca56431..917fac1812 100644 --- a/contrib/btree_gist/expected/bytea.out +++ b/contrib/btree_gist/expected/bytea.out @@ -6,13 +6,13 @@ SET enable_seqscan=on; SELECT count(*) FROM byteatmp WHERE a < '31b0'; count ------- - 122 + 588 (1 row) SELECT count(*) FROM byteatmp WHERE a <= '31b0'; count ------- - 123 + 589 (1 row) SELECT count(*) FROM byteatmp WHERE a = '31b0'; @@ -38,13 +38,13 @@ SET enable_seqscan=off; SELECT count(*) FROM byteatmp WHERE a < '31b0'::bytea; count ------- - 122 + 588 (1 row) SELECT count(*) FROM byteatmp WHERE a <= '31b0'::bytea; count ------- - 123 + 589 (1 row) SELECT count(*) FROM byteatmp WHERE a = '31b0'::bytea; diff --git a/contrib/btree_gist/expected/char.out b/contrib/btree_gist/expected/char.out index f13772970f..5260995a75 100644 --- a/contrib/btree_gist/expected/char.out +++ b/contrib/btree_gist/expected/char.out @@ -5,13 +5,13 @@ SET enable_seqscan=on; SELECT count(*) FROM chartmp WHERE a < '31b0'::char(32); count ------- - 121 + 587 (1 row) SELECT count(*) FROM chartmp WHERE a <= '31b0'::char(32); count ------- - 122 + 588 (1 row) SELECT count(*) FROM chartmp WHERE a = '31b0'::char(32); @@ -37,13 +37,13 @@ SET enable_seqscan=off; SELECT count(*) FROM chartmp WHERE a < '31b0'::char(32); count ------- - 121 + 587 (1 row) SELECT count(*) FROM chartmp WHERE a <= '31b0'::char(32); count ------- - 122 + 588 (1 row) SELECT count(*) FROM chartmp WHERE a = '31b0'::char(32); diff --git a/contrib/btree_gist/expected/text.out b/contrib/btree_gist/expected/text.out index fa7a044846..4905cb023b 100644 --- a/contrib/btree_gist/expected/text.out +++ b/contrib/btree_gist/expected/text.out @@ -6,13 +6,13 @@ SET enable_seqscan=on; SELECT count(*) FROM texttmp WHERE a < '31b0'; count ------- - 122 + 588 (1 row) SELECT count(*) FROM texttmp WHERE a <= '31b0'; count ------- - 123 + 589 (1 row) SELECT count(*) FROM texttmp WHERE a = '31b0'; @@ -38,13 +38,13 @@ SET enable_seqscan=off; SELECT count(*) FROM texttmp WHERE a < '31b0'::text; count ------- - 122 + 588 (1 row) SELECT count(*) FROM texttmp WHERE a <= '31b0'::text; count ------- - 123 + 589 (1 row) SELECT count(*) FROM texttmp WHERE a = '31b0'::text; diff --git a/contrib/btree_gist/expected/timestamp.out b/contrib/btree_gist/expected/timestamp.out index d5a9b3c366..dc53895ca2 100644 --- a/contrib/btree_gist/expected/timestamp.out +++ b/contrib/btree_gist/expected/timestamp.out @@ -5,13 +5,13 @@ SET enable_seqscan=on; SELECT count(*) FROM timestamptmp WHERE a < '2004-10-26 08:55:08'; count ------- - 270 + 278 (1 row) SELECT count(*) FROM timestamptmp WHERE a <= '2004-10-26 08:55:08'; count ------- - 271 + 279 (1 row) SELECT count(*) FROM timestamptmp WHERE a = '2004-10-26 08:55:08'; @@ -23,13 +23,13 @@ SELECT count(*) FROM timestamptmp WHERE a = '2004-10-26 08:55:08'; SELECT count(*) FROM timestamptmp WHERE a >= '2004-10-26 08:55:08'; count ------- - 274 + 290 (1 row) SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08'; count ------- - 273 + 289 (1 row) CREATE INDEX timestampidx ON timestamptmp USING gist ( a ); @@ -37,13 +37,13 @@ SET enable_seqscan=off; SELECT count(*) FROM timestamptmp WHERE a < '2004-10-26 08:55:08'::timestamp; count ------- - 270 + 278 (1 row) SELECT count(*) FROM timestamptmp WHERE a <= '2004-10-26 08:55:08'::timestamp; count ------- - 271 + 279 (1 row) SELECT count(*) FROM timestamptmp WHERE a = '2004-10-26 08:55:08'::timestamp; @@ -55,12 +55,12 @@ SELECT count(*) FROM timestamptmp WHERE a = '2004-10-26 08:55:08'::timestamp; SELECT count(*) FROM timestamptmp WHERE a >= '2004-10-26 08:55:08'::timestamp; count ------- - 274 + 290 (1 row) SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08'::timestamp; count ------- - 273 + 289 (1 row) diff --git a/contrib/btree_gist/expected/timestamptz.out b/contrib/btree_gist/expected/timestamptz.out index 903e81e67a..391705f0db 100644 --- a/contrib/btree_gist/expected/timestamptz.out +++ b/contrib/btree_gist/expected/timestamptz.out @@ -5,13 +5,13 @@ SET enable_seqscan=on; SELECT count(*) FROM timestamptztmp WHERE a < '2018-12-18 10:59:54 GMT+3'; count ------- - 385 + 391 (1 row) SELECT count(*) FROM timestamptztmp WHERE a <= '2018-12-18 10:59:54 GMT+3'; count ------- - 386 + 392 (1 row) SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+3'; @@ -23,25 +23,25 @@ SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+3'; SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+3'; count ------- - 146 + 158 (1 row) SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+3'; count ------- - 145 + 157 (1 row) SELECT count(*) FROM timestamptztmp WHERE a < '2018-12-18 10:59:54 GMT+2'; count ------- - 385 + 391 (1 row) SELECT count(*) FROM timestamptztmp WHERE a <= '2018-12-18 10:59:54 GMT+2'; count ------- - 385 + 391 (1 row) SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+2'; @@ -53,25 +53,25 @@ SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+2'; SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+2'; count ------- - 146 + 158 (1 row) SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+2'; count ------- - 146 + 158 (1 row) SELECT count(*) FROM timestamptztmp WHERE a < '2018-12-18 10:59:54 GMT+4'; count ------- - 386 + 392 (1 row) SELECT count(*) FROM timestamptztmp WHERE a <= '2018-12-18 10:59:54 GMT+4'; count ------- - 386 + 392 (1 row) SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+4'; @@ -83,13 +83,13 @@ SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+4'; SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+4'; count ------- - 145 + 157 (1 row) SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4'; count ------- - 145 + 157 (1 row) CREATE INDEX timestamptzidx ON timestamptztmp USING gist ( a ); @@ -97,13 +97,13 @@ SET enable_seqscan=off; SELECT count(*) FROM timestamptztmp WHERE a < '2018-12-18 10:59:54 GMT+3'::timestamptz; count ------- - 385 + 391 (1 row) SELECT count(*) FROM timestamptztmp WHERE a <= '2018-12-18 10:59:54 GMT+3'::timestamptz; count ------- - 386 + 392 (1 row) SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+3'::timestamptz; @@ -115,25 +115,25 @@ SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+3'::time SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+3'::timestamptz; count ------- - 146 + 158 (1 row) SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+3'::timestamptz; count ------- - 145 + 157 (1 row) SELECT count(*) FROM timestamptztmp WHERE a < '2018-12-18 10:59:54 GMT+2'::timestamptz; count ------- - 385 + 391 (1 row) SELECT count(*) FROM timestamptztmp WHERE a <= '2018-12-18 10:59:54 GMT+2'::timestamptz; count ------- - 385 + 391 (1 row) SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+2'::timestamptz; @@ -145,25 +145,25 @@ SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+2'::time SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+2'::timestamptz; count ------- - 146 + 158 (1 row) SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+2'::timestamptz; count ------- - 146 + 158 (1 row) SELECT count(*) FROM timestamptztmp WHERE a < '2018-12-18 10:59:54 GMT+4'::timestamptz; count ------- - 386 + 392 (1 row) SELECT count(*) FROM timestamptztmp WHERE a <= '2018-12-18 10:59:54 GMT+4'::timestamptz; count ------- - 386 + 392 (1 row) SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+4'::timestamptz; @@ -175,12 +175,12 @@ SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+4'::time SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+4'::timestamptz; count ------- - 145 + 157 (1 row) SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4'::timestamptz; count ------- - 145 + 157 (1 row) diff --git a/contrib/btree_gist/expected/varchar.out b/contrib/btree_gist/expected/varchar.out index 6bfff350fc..d071d714cd 100644 --- a/contrib/btree_gist/expected/varchar.out +++ b/contrib/btree_gist/expected/varchar.out @@ -5,13 +5,13 @@ SET enable_seqscan=on; SELECT count(*) FROM vchartmp WHERE a < '31b0'::varchar(32); count ------- - 121 + 587 (1 row) SELECT count(*) FROM vchartmp WHERE a <= '31b0'::varchar(32); count ------- - 122 + 588 (1 row) SELECT count(*) FROM vchartmp WHERE a = '31b0'::varchar(32); @@ -37,13 +37,13 @@ SET enable_seqscan=off; SELECT count(*) FROM vchartmp WHERE a < '31b0'::varchar(32); count ------- - 121 + 587 (1 row) SELECT count(*) FROM vchartmp WHERE a <= '31b0'::varchar(32); count ------- - 122 + 588 (1 row) SELECT count(*) FROM vchartmp WHERE a = '31b0'::varchar(32); -- 2.40.0