Am Montag, dem 12.02.2024 um 21:00 +0800 schrieb jian he: > + <para> > + Per default <filename>btree_gist</filename> builts > <acronym>GiST</acronym> indexe with > + <function>sortsupport</function> in <firstterm>sorted</firstterm> > mode. This usually results in a > + much better index quality and smaller index sizes by much faster > index built speed. It is still > + possible to revert to buffered built strategy by using the > <literal>buffering</literal> parameter > + when creating the index. > + </para> > + > I believe `built` |`builts` should be `build`.
Right, Fixed. > Also > maybe we can simply copy some texts from > https://www.postgresql.org/docs/current/gist-implementation.html. > how about the following: > <para> > The sorted method is only available if each of the opclasses used > by the > index provides a <function>sortsupport</function> function, as > described > in <xref linkend="gist-extensibility"/>. If they do, this method > is > usually the best, so it is used by default. > It is still possible to change to a buffered build strategy by > using > the <literal>buffering</literal> parameter > to the CREATE INDEX command. > </para> Hmm not sure what you are trying to achieve with this? The opclasses in btree_gist provides sortsupport, but by reading the above i would get the impression they're still optional. > > you've changed contrib/btree_gist/meson.build, seems we also need to > change contrib/btree_gist/Makefile > Oh, good catch. I'm so focused on meson already that i totally forgot the good old Makefile. Fixed. > gist_point_sortsupport have `if (ssup->abbreviate)`, does > range_gist_sortsupport also this part? > I think the `if(ssup->abbreviate)` part is optional? > Can we add some comments on it? I've thought about abbreviated keys support but put that aside for later. I wanted to focus on general sortsupport first before getting my hands on it and so postponed it for another round. If we agree that this patch needs support for abbreviated keys now, i certainly can work on it. Thanks for your review, Bernd
diff --git a/contrib/btree_gist/Makefile b/contrib/btree_gist/Makefile index 7ac2df26c10..68190ac5e46 100644 --- a/contrib/btree_gist/Makefile +++ b/contrib/btree_gist/Makefile @@ -34,7 +34,7 @@ DATA = btree_gist--1.0--1.1.sql \ btree_gist--1.1--1.2.sql btree_gist--1.2.sql btree_gist--1.2--1.3.sql \ btree_gist--1.3--1.4.sql btree_gist--1.4--1.5.sql \ btree_gist--1.5--1.6.sql btree_gist--1.6--1.7.sql \ - btree_gist--1.7--1.8.sql + btree_gist--1.7--1.8.sql btree_gist--1.8--1.9.sql PGFILEDESC = "btree_gist - B-tree equivalent GiST operator classes" REGRESS = init int2 int4 int8 float4 float8 cash oid timestamp timestamptz \ diff --git a/contrib/btree_gist/btree_bit.c b/contrib/btree_gist/btree_bit.c index 6790f22b4b6..67ea5d9e182 100644 --- a/contrib/btree_gist/btree_bit.c +++ b/contrib/btree_gist/btree_bit.c @@ -6,7 +6,7 @@ #include "btree_gist.h" #include "btree_utils_var.h" #include "utils/builtins.h" -#include "utils/bytea.h" +#include "utils/sortsupport.h" #include "utils/varbit.h" @@ -19,10 +19,33 @@ PG_FUNCTION_INFO_V1(gbt_bit_picksplit); PG_FUNCTION_INFO_V1(gbt_bit_consistent); PG_FUNCTION_INFO_V1(gbt_bit_penalty); PG_FUNCTION_INFO_V1(gbt_bit_same); +PG_FUNCTION_INFO_V1(gbt_bit_sortsupport); +PG_FUNCTION_INFO_V1(gbt_varbit_sortsupport); /* define for comparison */ +static int +gbt_bit_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R arg1 = gbt_var_key_readable(key1); + GBT_VARKEY_R arg2 = gbt_var_key_readable(key2); + Datum result; + + /* lower is always equal to upper, so just compare those fields */ + result = DirectFunctionCall2(bitcmp, + PointerGetDatum(arg1.lower), + PointerGetDatum(arg2.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + static bool gbt_bitgt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo) { @@ -208,3 +231,25 @@ gbt_bit_penalty(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo)); } + +Datum +gbt_bit_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bit_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} + +Datum +gbt_varbit_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bit_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} \ No newline at end of file diff --git a/contrib/btree_gist/btree_bool.c b/contrib/btree_gist/btree_bool.c index 8b2af129b52..5058dba2986 100644 --- a/contrib/btree_gist/btree_bool.c +++ b/contrib/btree_gist/btree_bool.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "common/int.h" +#include "utils/sortsupport.h" typedef struct boolkey { @@ -23,6 +24,16 @@ PG_FUNCTION_INFO_V1(gbt_bool_picksplit); PG_FUNCTION_INFO_V1(gbt_bool_consistent); PG_FUNCTION_INFO_V1(gbt_bool_penalty); PG_FUNCTION_INFO_V1(gbt_bool_same); +PG_FUNCTION_INFO_V1(gbt_bool_sortsupport); + +static int +gbt_bool_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + boolKEY *arg1 = (boolKEY *) DatumGetPointer(x); + boolKEY *arg2 = (boolKEY *) DatumGetPointer(y); + + return arg1->lower - arg2->lower; +} static bool gbt_boolgt(const void *a, const void *b, FmgrInfo *flinfo) @@ -167,3 +178,14 @@ gbt_bool_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +Datum +gbt_bool_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bool_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_bytea.c b/contrib/btree_gist/btree_bytea.c index 6b005f0157e..2047e3ddee0 100644 --- a/contrib/btree_gist/btree_bytea.c +++ b/contrib/btree_gist/btree_bytea.c @@ -6,7 +6,7 @@ #include "btree_gist.h" #include "btree_utils_var.h" #include "utils/builtins.h" -#include "utils/bytea.h" +#include "utils/sortsupport.h" /* @@ -18,7 +18,41 @@ PG_FUNCTION_INFO_V1(gbt_bytea_picksplit); PG_FUNCTION_INFO_V1(gbt_bytea_consistent); PG_FUNCTION_INFO_V1(gbt_bytea_penalty); PG_FUNCTION_INFO_V1(gbt_bytea_same); +PG_FUNCTION_INFO_V1(gbt_bytea_sortsupport); +/* sortsupport support */ + +static int +gbt_bytea_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R xkey = gbt_var_key_readable(key1); + GBT_VARKEY_R ykey = gbt_var_key_readable(key2); + Datum result; + + /* lower and upper are always the same, so it is enough to compare lower */ + result = DirectFunctionCall2(byteacmp, + PointerGetDatum(xkey.lower), + PointerGetDatum(ykey.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + +Datum +gbt_bytea_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bytea_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} /* define for comparison */ diff --git a/contrib/btree_gist/btree_cash.c b/contrib/btree_gist/btree_cash.c index 546b948ea40..94090c9ac0d 100644 --- a/contrib/btree_gist/btree_cash.c +++ b/contrib/btree_gist/btree_cash.c @@ -7,6 +7,7 @@ #include "btree_utils_num.h" #include "common/int.h" #include "utils/cash.h" +#include "utils/sortsupport.h" typedef struct { @@ -25,6 +26,21 @@ PG_FUNCTION_INFO_V1(gbt_cash_consistent); PG_FUNCTION_INFO_V1(gbt_cash_distance); PG_FUNCTION_INFO_V1(gbt_cash_penalty); PG_FUNCTION_INFO_V1(gbt_cash_same); +PG_FUNCTION_INFO_V1(gbt_cash_sortsupport); + +extern Datum cash_cmp(PG_FUNCTION_ARGS); + +static int +gbt_cash_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + cashKEY *arg1 = (cashKEY *) DatumGetPointer(x); + cashKEY *arg2 = (cashKEY *) DatumGetPointer(y); + + /* Since lower and upper are always equal, it is enough to compare lower */ + return DatumGetInt32(DirectFunctionCall2(cash_cmp, + CashGetDatum(arg1->lower), + CashGetDatum(arg2->lower))); +} static bool gbt_cashgt(const void *a, const void *b, FmgrInfo *flinfo) @@ -215,3 +231,14 @@ gbt_cash_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +Datum +gbt_cash_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_cash_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_date.c b/contrib/btree_gist/btree_date.c index 68a4107dbf0..c4ff15f27b4 100644 --- a/contrib/btree_gist/btree_date.c +++ b/contrib/btree_gist/btree_date.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "utils/builtins.h" +#include "utils/sortsupport.h" #include "utils/date.h" typedef struct @@ -25,6 +26,30 @@ PG_FUNCTION_INFO_V1(gbt_date_consistent); PG_FUNCTION_INFO_V1(gbt_date_distance); PG_FUNCTION_INFO_V1(gbt_date_penalty); PG_FUNCTION_INFO_V1(gbt_date_same); +PG_FUNCTION_INFO_V1(gbt_date_sortsupport); + +/* sortsupport functions */ + +static int gbt_date_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + dateKEY *akey = (dateKEY *) DatumGetPointer(x); + dateKEY *bkey = (dateKEY *) DatumGetPointer(y); + + return DatumGetInt32(DirectFunctionCall2(date_cmp, + DateADTGetDatum(akey->lower), + DateADTGetDatum(bkey->lower))); +} + +Datum +gbt_date_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_date_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} static bool gbt_dategt(const void *a, const void *b, FmgrInfo *flinfo) diff --git a/contrib/btree_gist/btree_enum.c b/contrib/btree_gist/btree_enum.c index d4dc38a38e5..67395182341 100644 --- a/contrib/btree_gist/btree_enum.c +++ b/contrib/btree_gist/btree_enum.c @@ -7,6 +7,7 @@ #include "btree_utils_num.h" #include "fmgr.h" #include "utils/builtins.h" +#include "utils/sortsupport.h" /* enums are really Oids, so we just use the same structure */ @@ -26,8 +27,20 @@ PG_FUNCTION_INFO_V1(gbt_enum_picksplit); PG_FUNCTION_INFO_V1(gbt_enum_consistent); PG_FUNCTION_INFO_V1(gbt_enum_penalty); PG_FUNCTION_INFO_V1(gbt_enum_same); +PG_FUNCTION_INFO_V1(gbt_enum_sortsupport); +static int +gbt_enum_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + oidKEY *arg1 = (oidKEY *) DatumGetPointer(x); + oidKEY *arg2 = (oidKEY *) DatumGetPointer(y); + + /* Since lower and upper in oidKEY are always the same, just compare lower */ + return DatumGetInt32(CallerFInfoFunctionCall2(enum_cmp, ssup->ssup_extra, + InvalidOid, arg1->lower, arg2->lower)); +} + static bool gbt_enumgt(const void *a, const void *b, FmgrInfo *flinfo) { @@ -183,3 +196,20 @@ gbt_enum_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +Datum +gbt_enum_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_enum_ssup_cmp; + + /* + * Since enum_fast_cmp() also uses enum_cmp() like the rest of the + * comparsion functions, it also needs to pass on flinfo when calling + * it. Thus save it in ->ssup_extra and later retrieve it in enum_fast_cmp(). + */ + ssup->ssup_extra = fcinfo->flinfo; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c index 84ca5eee501..b2229cdb04d 100644 --- a/contrib/btree_gist/btree_float4.c +++ b/contrib/btree_gist/btree_float4.c @@ -5,6 +5,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" +#include "utils/sortsupport.h" #include "utils/float.h" typedef struct float4key @@ -24,6 +25,33 @@ PG_FUNCTION_INFO_V1(gbt_float4_consistent); PG_FUNCTION_INFO_V1(gbt_float4_distance); PG_FUNCTION_INFO_V1(gbt_float4_penalty); PG_FUNCTION_INFO_V1(gbt_float4_same); +PG_FUNCTION_INFO_V1(gbt_float4_sortsupport); + +extern Datum btfloat4cmp(PG_FUNCTION_ARGS); + +/* sortsupport functions */ +static int +gbt_float4_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + float4KEY *arg1 = (float4KEY *) DatumGetPointer(x); + float4KEY *arg2 = (float4KEY *) DatumGetPointer(y); + + /* Since lower and upper for float4KEYs here are always equal it is okay to compare them only */ + return DatumGetInt32(DirectFunctionCall2(btfloat4cmp, + Float4GetDatum(arg1->lower), + Float4GetDatum(arg2->lower))); +} + +Datum +gbt_float4_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_float4_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} static bool gbt_float4gt(const void *a, const void *b, FmgrInfo *flinfo) diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c index 081a719b006..2f312f5bd83 100644 --- a/contrib/btree_gist/btree_float8.c +++ b/contrib/btree_gist/btree_float8.c @@ -5,6 +5,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" +#include "utils/sortsupport.h" #include "utils/float.h" typedef struct float8key @@ -24,7 +25,33 @@ PG_FUNCTION_INFO_V1(gbt_float8_consistent); PG_FUNCTION_INFO_V1(gbt_float8_distance); PG_FUNCTION_INFO_V1(gbt_float8_penalty); PG_FUNCTION_INFO_V1(gbt_float8_same); +PG_FUNCTION_INFO_V1(gbt_float8_sortsupport); +extern Datum btfloat8cmp(PG_FUNCTION_ARGS); + +/* sortsupport functions */ +static int +gbt_float8_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + float8KEY *arg1 = (float8KEY *) DatumGetPointer(x); + float8KEY *arg2 = (float8KEY *) DatumGetPointer(y); + + /* upper and lower for input keys are equal here */ + return DatumGetInt32(DirectFunctionCall2(btfloat8cmp, + Float8GetDatum(arg1->lower), + Float8GetDatum(arg2->lower))); +} + +Datum +gbt_float8_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_float8_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} static bool gbt_float8gt(const void *a, const void *b, FmgrInfo *flinfo) diff --git a/contrib/btree_gist/btree_gist--1.7--1.8.sql b/contrib/btree_gist/btree_gist--1.7--1.8.sql index 307bfe574b0..657285ca7ce 100644 --- a/contrib/btree_gist/btree_gist--1.7--1.8.sql +++ b/contrib/btree_gist/btree_gist--1.7--1.8.sql @@ -85,3 +85,4 @@ ALTER OPERATOR FAMILY gist_enum_ops USING gist ADD ALTER OPERATOR FAMILY gist_bool_ops USING gist ADD FUNCTION 12 (bool, bool) gist_stratnum_btree (int2) ; + diff --git a/contrib/btree_gist/btree_gist--1.8--1.9.sql b/contrib/btree_gist/btree_gist--1.8--1.9.sql new file mode 100644 index 00000000000..c52e750ed1a --- /dev/null +++ b/contrib/btree_gist/btree_gist--1.8--1.9.sql @@ -0,0 +1,192 @@ +/* contrib/btree_gist/btree_gist--1.7--1.8.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION btree_gist UPDATE TO '1.9'" to load this file. \quit + +CREATE FUNCTION gbt_bit_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_varbit_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_bool_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_cash_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_enum_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_inet_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_intv_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_macad8_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_time_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_int2_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_int4_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_int8_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_bytea_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_date_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_float4_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_float8_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_macaddr_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_numeric_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_oid_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_text_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_ts_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION gbt_uuid_sortsupport(internal) + RETURNS void +AS 'MODULE_PATHNAME' + LANGUAGE C IMMUTABLE STRICT; + +ALTER OPERATOR FAMILY gist_vbit_ops USING gist ADD + FUNCTION 11 (varbit, varbit) gbt_varbit_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_bit_ops USING gist ADD + FUNCTION 11 (bit, bit) gbt_bit_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_bool_ops USING gist ADD + FUNCTION 11 (bool, bool) gbt_bool_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_bytea_ops USING gist ADD + FUNCTION 11 (bytea, bytea) gbt_bytea_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD + FUNCTION 11 (money, money) gbt_cash_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_date_ops USING gist ADD + FUNCTION 11 (date, date) gbt_date_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_enum_ops USING gist ADD + FUNCTION 11 (anyenum, anyenum) gbt_enum_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD + FUNCTION 11 (float4, float4) gbt_float4_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD + FUNCTION 11 (float8, float8) gbt_float8_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_inet_ops USING gist ADD + FUNCTION 11 (inet, inet) gbt_inet_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_cidr_ops USING gist ADD + FUNCTION 11 (inet, inet) gbt_inet_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD + FUNCTION 11 (int2, int2) gbt_int2_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD + FUNCTION 11 (int4, int4) gbt_int4_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD + FUNCTION 11 (int8, int8) gbt_int8_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD + FUNCTION 11 (interval, interval) gbt_intv_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_macaddr_ops USING gist ADD + FUNCTION 11 (macaddr, macaddr) gbt_macad8_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_macaddr8_ops USING gist ADD + FUNCTION 11 (macaddr8, macaddr8) gbt_macad8_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_numeric_ops USING gist ADD + FUNCTION 11 (numeric, numeric) gbt_numeric_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD + FUNCTION 11 (oid, oid) gbt_oid_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_text_ops USING gist ADD + FUNCTION 11 (text, text) gbt_text_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_bpchar_ops USING gist ADD + FUNCTION 11 (bpchar, bpchar) bpchar_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_time_ops USING gist ADD + FUNCTION 11 (time, time) gbt_time_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD + FUNCTION 11 (timestamp, timestamp) gbt_ts_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD + FUNCTION 11 (timestamptz, timestamptz) gbt_ts_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD + FUNCTION 11 (timetz, timetz) gbt_time_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_uuid_ops USING gist ADD + FUNCTION 11 (uuid, uuid) gbt_uuid_sortsupport (internal) ; diff --git a/contrib/btree_gist/btree_gist.c b/contrib/btree_gist/btree_gist.c index 5fd4cce27d0..c8acbe76b55 100644 --- a/contrib/btree_gist/btree_gist.c +++ b/contrib/btree_gist/btree_gist.c @@ -6,6 +6,9 @@ #include "access/stratnum.h" #include "utils/builtins.h" +#include "access/gist.h" +#include "btree_gist.h" + PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(gbt_decompress); diff --git a/contrib/btree_gist/btree_gist.control b/contrib/btree_gist/btree_gist.control index abf66538f32..69d9341a0ad 100644 --- a/contrib/btree_gist/btree_gist.control +++ b/contrib/btree_gist/btree_gist.control @@ -1,6 +1,6 @@ # btree_gist extension comment = 'support for indexing common datatypes in GiST' -default_version = '1.8' +default_version = '1.9' module_pathname = '$libdir/btree_gist' relocatable = true trusted = true diff --git a/contrib/btree_gist/btree_gist.h b/contrib/btree_gist/btree_gist.h index 0db8522c8a7..245c3559281 100644 --- a/contrib/btree_gist/btree_gist.h +++ b/contrib/btree_gist/btree_gist.h @@ -9,6 +9,12 @@ #define BtreeGistNotEqualStrategyNumber 6 +typedef struct int32key +{ + int32 lower; + int32 upper; +} int32KEY; + /* indexed types */ enum gbtree_type diff --git a/contrib/btree_gist/btree_inet.c b/contrib/btree_gist/btree_inet.c index 2fb952dca83..77ef14a4f7d 100644 --- a/contrib/btree_gist/btree_inet.c +++ b/contrib/btree_gist/btree_inet.c @@ -8,6 +8,7 @@ #include "catalog/pg_type.h" #include "utils/builtins.h" #include "utils/inet.h" +#include "utils/sortsupport.h" typedef struct inetkey { @@ -24,8 +25,23 @@ PG_FUNCTION_INFO_V1(gbt_inet_picksplit); PG_FUNCTION_INFO_V1(gbt_inet_consistent); PG_FUNCTION_INFO_V1(gbt_inet_penalty); PG_FUNCTION_INFO_V1(gbt_inet_same); +PG_FUNCTION_INFO_V1(gbt_inet_sortsupport); +static int +gbt_inet_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + inetKEY *arg1 = (inetKEY *) DatumGetPointer(x); + inetKEY *arg2 = (inetKEY *) DatumGetPointer(y); + + if (arg1->lower == arg2->lower) + return 0; + else if (arg1->lower > arg2->lower) + return 1; + else + return -1; +} + static bool gbt_inetgt(const void *a, const void *b, FmgrInfo *flinfo) { @@ -185,3 +201,14 @@ gbt_inet_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +Datum +gbt_inet_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_inet_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c index fdbf156586c..b19770ff67f 100644 --- a/contrib/btree_gist/btree_int2.c +++ b/contrib/btree_gist/btree_int2.c @@ -5,6 +5,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" +#include "utils/sortsupport.h" #include "common/int.h" typedef struct int16key @@ -24,6 +25,31 @@ PG_FUNCTION_INFO_V1(gbt_int2_consistent); PG_FUNCTION_INFO_V1(gbt_int2_distance); PG_FUNCTION_INFO_V1(gbt_int2_penalty); PG_FUNCTION_INFO_V1(gbt_int2_same); +PG_FUNCTION_INFO_V1(gbt_int2_sortsupport); + +/* sortsupport functions */ +static int +gbt_int2_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + int16KEY *arg1 = (int16KEY *) DatumGetPointer(x); + int16KEY *arg2 = (int16KEY *) DatumGetPointer(y); + + if (arg1->lower < arg2->lower) + return -1; + else if (arg1->lower > arg2->lower) + return 1; + else + return 0; +} + +Datum +gbt_int2_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_int2_ssup_cmp; + PG_RETURN_VOID(); +} static bool gbt_int2gt(const void *a, const void *b, FmgrInfo *flinfo) diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c index 8915fb5d087..60418511ede 100644 --- a/contrib/btree_gist/btree_int4.c +++ b/contrib/btree_gist/btree_int4.c @@ -2,16 +2,10 @@ * contrib/btree_gist/btree_int4.c */ #include "postgres.h" - +#include "common/int.h" +#include "utils/sortsupport.h" #include "btree_gist.h" #include "btree_utils_num.h" -#include "common/int.h" - -typedef struct int32key -{ - int32 lower; - int32 upper; -} int32KEY; /* ** int32 ops @@ -24,6 +18,7 @@ PG_FUNCTION_INFO_V1(gbt_int4_consistent); PG_FUNCTION_INFO_V1(gbt_int4_distance); PG_FUNCTION_INFO_V1(gbt_int4_penalty); PG_FUNCTION_INFO_V1(gbt_int4_same); +PG_FUNCTION_INFO_V1(gbt_int4_sortsupport); static bool @@ -90,6 +85,29 @@ static const gbtree_ninfo tinfo = gbt_int4_dist }; +static int +gbt_int4_ssup_cmp(Datum a, Datum b, SortSupport ssup) +{ + int32KEY *ia = (int32KEY *) DatumGetPointer(a); + int32KEY *ib = (int32KEY *) DatumGetPointer(b); + + /* int4KEY upper and lower are always the same for input keys here. */ + if (ia->lower < ib->lower) + return -1; + else if (ia->lower > ib->lower) + return 1; + else + return 0; +} + +Datum +gbt_int4_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_int4_ssup_cmp; + PG_RETURN_VOID(); +} PG_FUNCTION_INFO_V1(int4_dist); Datum diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c index 7c63a5b6dc1..00d55163fc9 100644 --- a/contrib/btree_gist/btree_int8.c +++ b/contrib/btree_gist/btree_int8.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "common/int.h" +#include "utils/sortsupport.h" typedef struct int64key { @@ -24,7 +25,32 @@ PG_FUNCTION_INFO_V1(gbt_int8_consistent); PG_FUNCTION_INFO_V1(gbt_int8_distance); PG_FUNCTION_INFO_V1(gbt_int8_penalty); PG_FUNCTION_INFO_V1(gbt_int8_same); +PG_FUNCTION_INFO_V1(gbt_int8_sortsupport); +/* sortsupport functions */ +static int +gbt_int8_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + int64KEY *arg1 = (int64KEY *) DatumGetPointer(x); + int64KEY *arg2 = (int64KEY *) DatumGetPointer(y); + + if (arg1->lower < arg2->lower) + return -1; + else if (arg1->lower > arg2->lower) + return 1; + else + return 0; + +} + +Datum +gbt_int8_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_int8_ssup_cmp; + PG_RETURN_VOID(); +} static bool gbt_int8gt(const void *a, const void *b, FmgrInfo *flinfo) diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c index b0afdf02bb5..4da30be9e46 100644 --- a/contrib/btree_gist/btree_interval.c +++ b/contrib/btree_gist/btree_interval.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "utils/builtins.h" +#include "utils/sortsupport.h" #include "utils/timestamp.h" typedef struct @@ -27,8 +28,21 @@ PG_FUNCTION_INFO_V1(gbt_intv_consistent); PG_FUNCTION_INFO_V1(gbt_intv_distance); PG_FUNCTION_INFO_V1(gbt_intv_penalty); PG_FUNCTION_INFO_V1(gbt_intv_same); +PG_FUNCTION_INFO_V1(gbt_intv_sortsupport); +static int +gbt_intv_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + intvKEY *arg1 = (intvKEY *) DatumGetPointer(x); + intvKEY *arg2 = (intvKEY *) DatumGetPointer(y); + + /* intvKEY lower and upper are always equal here, so compare just lower members is enough */ + return DatumGetInt32(DirectFunctionCall2(interval_cmp, + IntervalPGetDatum(&arg1->lower), + IntervalPGetDatum(&arg2->lower))); +} + static bool gbt_intvgt(const void *a, const void *b, FmgrInfo *flinfo) { @@ -295,3 +309,14 @@ gbt_intv_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +Datum +gbt_intv_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_intv_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_macaddr.c b/contrib/btree_gist/btree_macaddr.c index 17290529c02..b95fd8d3409 100644 --- a/contrib/btree_gist/btree_macaddr.c +++ b/contrib/btree_gist/btree_macaddr.c @@ -7,6 +7,7 @@ #include "btree_utils_num.h" #include "utils/builtins.h" #include "utils/inet.h" +#include "utils/sortsupport.h" typedef struct { @@ -25,6 +26,34 @@ PG_FUNCTION_INFO_V1(gbt_macad_picksplit); PG_FUNCTION_INFO_V1(gbt_macad_consistent); PG_FUNCTION_INFO_V1(gbt_macad_penalty); PG_FUNCTION_INFO_V1(gbt_macad_same); +PG_FUNCTION_INFO_V1(gbt_macaddr_sortsupport); + +/* sortsupport functions */ +static int +gbt_macaddr_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + macKEY *arg1 = (macKEY *) DatumGetPointer(x); + macKEY *arg2 = (macKEY *) DatumGetPointer(y); + + /* macKEY lower and upper members are always equal here, + * so its enough to compare just lower. + */ + return DatumGetInt32(DirectFunctionCall2(macaddr_cmp, + MacaddrPGetDatum(&arg1->lower), + MacaddrPGetDatum(&arg2->lower))); + +} + +Datum +gbt_macaddr_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_macaddr_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} static bool diff --git a/contrib/btree_gist/btree_macaddr8.c b/contrib/btree_gist/btree_macaddr8.c index 796cc4efee3..c3ff7eeb0b5 100644 --- a/contrib/btree_gist/btree_macaddr8.c +++ b/contrib/btree_gist/btree_macaddr8.c @@ -7,6 +7,7 @@ #include "btree_utils_num.h" #include "utils/builtins.h" #include "utils/inet.h" +#include "utils/sortsupport.h" typedef struct { @@ -25,8 +26,20 @@ PG_FUNCTION_INFO_V1(gbt_macad8_picksplit); PG_FUNCTION_INFO_V1(gbt_macad8_consistent); PG_FUNCTION_INFO_V1(gbt_macad8_penalty); PG_FUNCTION_INFO_V1(gbt_macad8_same); +PG_FUNCTION_INFO_V1(gbt_macad8_sortsupport); +static int +gbt_macaddr8_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + mac8KEY *arg1 = (mac8KEY *) DatumGetPointer(x); + mac8KEY *arg2 = (mac8KEY *) DatumGetPointer(y); + + return DatumGetInt32(DirectFunctionCall2(macaddr8_cmp, + Macaddr8PGetDatum(&arg1->lower), + Macaddr8PGetDatum(&arg2->lower))); +} + static bool gbt_macad8gt(const void *a, const void *b, FmgrInfo *flinfo) { @@ -194,3 +207,14 @@ gbt_macad8_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +Datum +gbt_macad8_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_macaddr8_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_numeric.c b/contrib/btree_gist/btree_numeric.c index 35e466cdd94..227712645da 100644 --- a/contrib/btree_gist/btree_numeric.c +++ b/contrib/btree_gist/btree_numeric.c @@ -11,6 +11,7 @@ #include "utils/builtins.h" #include "utils/numeric.h" #include "utils/rel.h" +#include "utils/sortsupport.h" /* ** Bytea ops @@ -21,7 +22,39 @@ PG_FUNCTION_INFO_V1(gbt_numeric_picksplit); PG_FUNCTION_INFO_V1(gbt_numeric_consistent); PG_FUNCTION_INFO_V1(gbt_numeric_penalty); PG_FUNCTION_INFO_V1(gbt_numeric_same); +PG_FUNCTION_INFO_V1(gbt_numeric_sortsupport); +/* Sortsupport functions */ +static int +gbt_numeric_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R arg1 = gbt_var_key_readable(key1); + GBT_VARKEY_R arg2 = gbt_var_key_readable(key2); + Datum result; + + result = DirectFunctionCall2(numeric_cmp, + PointerGetDatum(arg1.lower), + PointerGetDatum(arg2.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + +Datum +gbt_numeric_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_numeric_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} /* define for comparison */ diff --git a/contrib/btree_gist/btree_oid.c b/contrib/btree_gist/btree_oid.c index 3cc7d4245d4..4ce4d3ff87e 100644 --- a/contrib/btree_gist/btree_oid.c +++ b/contrib/btree_gist/btree_oid.c @@ -5,6 +5,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" +#include "utils/sortsupport.h" typedef struct { @@ -23,7 +24,34 @@ PG_FUNCTION_INFO_V1(gbt_oid_consistent); PG_FUNCTION_INFO_V1(gbt_oid_distance); PG_FUNCTION_INFO_V1(gbt_oid_penalty); PG_FUNCTION_INFO_V1(gbt_oid_same); +PG_FUNCTION_INFO_V1(gbt_oid_sortsupport); +/* Sortsupport functions */ +static int +gbt_oid_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + oidKEY *arg1 = (oidKEY *) DatumGetPointer(x); + oidKEY *arg2 = (oidKEY *) DatumGetPointer(y); + + /* upper and lower fields are equal for each oidKEY, so just compare lower */ + if (arg1->lower > arg2->lower) + return 1; + else if (arg1->lower < arg2->lower) + return -1; + else + return 0; +} + +Datum +gbt_oid_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_oid_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} static bool gbt_oidgt(const void *a, const void *b, FmgrInfo *flinfo) diff --git a/contrib/btree_gist/btree_text.c b/contrib/btree_gist/btree_text.c index be0eac7975b..530648cb629 100644 --- a/contrib/btree_gist/btree_text.c +++ b/contrib/btree_gist/btree_text.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_var.h" #include "utils/builtins.h" +#include "utils/sortsupport.h" /* ** Text ops @@ -18,7 +19,40 @@ PG_FUNCTION_INFO_V1(gbt_text_consistent); PG_FUNCTION_INFO_V1(gbt_bpchar_consistent); PG_FUNCTION_INFO_V1(gbt_text_penalty); PG_FUNCTION_INFO_V1(gbt_text_same); +PG_FUNCTION_INFO_V1(gbt_text_sortsupport); +/* Sortsupport functions */ +static int +gbt_text_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R arg1 = gbt_var_key_readable(key1); + GBT_VARKEY_R arg2 = gbt_var_key_readable(key2); + Datum result; + + result = DirectFunctionCall2Coll(bttextcmp, + ssup->ssup_collation, + PointerGetDatum(arg1.lower), + PointerGetDatum(arg2.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + +Datum +gbt_text_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_text_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} /* define for comparison */ diff --git a/contrib/btree_gist/btree_time.c b/contrib/btree_gist/btree_time.c index d89401c0f51..344b5637ea5 100644 --- a/contrib/btree_gist/btree_time.c +++ b/contrib/btree_gist/btree_time.c @@ -7,6 +7,7 @@ #include "btree_utils_num.h" #include "utils/builtins.h" #include "utils/date.h" +#include "utils/sortsupport.h" #include "utils/timestamp.h" typedef struct @@ -28,6 +29,8 @@ PG_FUNCTION_INFO_V1(gbt_time_distance); PG_FUNCTION_INFO_V1(gbt_timetz_consistent); PG_FUNCTION_INFO_V1(gbt_time_penalty); PG_FUNCTION_INFO_V1(gbt_time_same); +PG_FUNCTION_INFO_V1(gbt_time_sortsupport); +PG_FUNCTION_INFO_V1(gbt_timetz_sortsupport); #ifdef USE_FLOAT8_BYVAL @@ -37,6 +40,18 @@ PG_FUNCTION_INFO_V1(gbt_time_same); #endif +static int +gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + timeKEY *arg1 = (timeKEY *) DatumGetPointer(x); + timeKEY *arg2 = (timeKEY *) DatumGetPointer(y); + + /* lower and upper are equal during sortsupport comparison */ + return DatumGetInt32(DirectFunctionCall2(time_cmp, + TimeADTGetDatumFast(arg1->lower), + TimeADTGetDatumFast(arg2->lower))); +} + static bool gbt_timegt(const void *a, const void *b, FmgrInfo *flinfo) { @@ -332,3 +347,14 @@ gbt_time_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +Datum +gbt_time_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_timekey_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c index 3f5ba91891d..ef13fc15bba 100644 --- a/contrib/btree_gist/btree_ts.c +++ b/contrib/btree_gist/btree_ts.c @@ -10,6 +10,7 @@ #include "utils/builtins.h" #include "utils/datetime.h" #include "utils/float.h" +#include "utils/sortsupport.h" typedef struct { @@ -31,6 +32,7 @@ PG_FUNCTION_INFO_V1(gbt_tstz_consistent); PG_FUNCTION_INFO_V1(gbt_tstz_distance); PG_FUNCTION_INFO_V1(gbt_ts_penalty); PG_FUNCTION_INFO_V1(gbt_ts_same); +PG_FUNCTION_INFO_V1(gbt_ts_sortsupport); #ifdef USE_FLOAT8_BYVAL @@ -39,6 +41,29 @@ PG_FUNCTION_INFO_V1(gbt_ts_same); #define TimestampGetDatumFast(X) PointerGetDatum(&(X)) #endif +/* Sortsupport functions */ +static int +gbt_ts_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + tsKEY *arg1 = (tsKEY *) DatumGetPointer(x); + tsKEY *arg2 = (tsKEY *) DatumGetPointer(y); + + /* Sortsupport always gets the same lower and upper value for input keys */ + return DatumGetInt32(DirectFunctionCall2(timestamp_cmp, + TimestampGetDatumFast(arg1->lower), + TimestampGetDatumFast(arg2->lower))); +} + +Datum +gbt_ts_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_ts_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} static bool gbt_tsgt(const void *a, const void *b, FmgrInfo *flinfo) diff --git a/contrib/btree_gist/btree_utils_var.h b/contrib/btree_gist/btree_utils_var.h index 2f8def655c8..16ff165ad3c 100644 --- a/contrib/btree_gist/btree_utils_var.h +++ b/contrib/btree_gist/btree_utils_var.h @@ -42,7 +42,17 @@ typedef struct GBT_VARKEY *(*f_l2n) (GBT_VARKEY *, FmgrInfo *flinfo); /* convert leaf to node */ } gbtree_vinfo; - +/* + * Free ptr1 in case its a copy of ptr2. + * + * This is adapted from varlena's PG_FREE_IF_COPY, though + * doesn't require fcinfo access. + */ +#define GBT_FREE_IF_COPY(ptr1, ptr2) \ + do { \ + if ((Pointer) (ptr1) != DatumGetPointer(ptr2)) \ + pfree(ptr1); \ + } while (0) extern GBT_VARKEY_R gbt_var_key_readable(const GBT_VARKEY *k); diff --git a/contrib/btree_gist/btree_uuid.c b/contrib/btree_gist/btree_uuid.c index fe8c679cbed..08372fc8bc9 100644 --- a/contrib/btree_gist/btree_uuid.c +++ b/contrib/btree_gist/btree_uuid.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "port/pg_bswap.h" +#include "utils/sortsupport.h" #include "utils/uuid.h" typedef struct @@ -25,7 +26,31 @@ PG_FUNCTION_INFO_V1(gbt_uuid_picksplit); PG_FUNCTION_INFO_V1(gbt_uuid_consistent); PG_FUNCTION_INFO_V1(gbt_uuid_penalty); PG_FUNCTION_INFO_V1(gbt_uuid_same); +PG_FUNCTION_INFO_V1(gbt_uuid_sortsupport); +static int uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2); + +/* Sortsupport functions */ +static int +gbt_uuid_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + uuidKEY *arg1 = (uuidKEY *) DatumGetPointer(x); + uuidKEY *arg2 = (uuidKEY *) DatumGetPointer(y); + + /* Sortsupport gets equal upper and lower values for each key to compare */ + return uuid_internal_cmp(&arg1->lower, &arg2->lower); +} + +Datum +gbt_uuid_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_uuid_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} static int uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2) diff --git a/contrib/btree_gist/meson.build b/contrib/btree_gist/meson.build index 73b1bbf52a6..5b4caff5baf 100644 --- a/contrib/btree_gist/meson.build +++ b/contrib/btree_gist/meson.build @@ -51,6 +51,7 @@ install_data( 'btree_gist--1.5--1.6.sql', 'btree_gist--1.6--1.7.sql', 'btree_gist--1.7--1.8.sql', + 'btree_gist--1.8--1.9.sql', kwargs: contrib_data_args, ) diff --git a/doc/src/sgml/btree-gist.sgml b/doc/src/sgml/btree-gist.sgml index 31e7c78aaef..8def2d3798e 100644 --- a/doc/src/sgml/btree-gist.sgml +++ b/doc/src/sgml/btree-gist.sgml @@ -52,6 +52,14 @@ <type>oid</type>, and <type>money</type>. </para> + <para> + Per default <filename>btree_gist</filename> builds <acronym>GiST</acronym> indexe with + <function>sortsupport</function> in <firstterm>sorted</firstterm> mode. This usually results in a + much better index quality and smaller index sizes by much faster index built speed. It is still + possible to revert to buffered built strategy by using the <literal>buffering</literal> parameter + when creating the index. + </para> + <para> This module is considered <quote>trusted</quote>, that is, it can be installed by non-superusers who have <literal>CREATE</literal> privilege
diff --git a/src/backend/utils/adt/rangetypes_gist.c b/src/backend/utils/adt/rangetypes_gist.c index cb28e9859ab..b0c77390024 100644 --- a/src/backend/utils/adt/rangetypes_gist.c +++ b/src/backend/utils/adt/rangetypes_gist.c @@ -21,6 +21,7 @@ #include "utils/fmgrprotos.h" #include "utils/multirangetypes.h" #include "utils/rangetypes.h" +#include "utils/sortsupport.h" /* * Range class properties used to segregate different classes of ranges in @@ -177,6 +178,7 @@ static void range_gist_double_sorting_split(TypeCacheEntry *typcache, static void range_gist_consider_split(ConsiderSplitContext *context, RangeBound *right_lower, int min_left_count, RangeBound *left_upper, int max_left_count); +static int range_gist_cmp(Datum a, Datum b, SortSupport ssup); static int get_gist_range_class(RangeType *range); static int single_bound_cmp(const void *a, const void *b, void *arg); static int interval_cmp_lower(const void *a, const void *b, void *arg); @@ -773,6 +775,20 @@ range_gist_picksplit(PG_FUNCTION_ARGS) PG_RETURN_POINTER(v); } +/* + * Sort support routine for fast GiST index build by sorting. + */ +Datum +range_gist_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = range_gist_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} + /* equality comparator for GiST */ Datum range_gist_same(PG_FUNCTION_ARGS) @@ -1693,6 +1709,60 @@ range_gist_consider_split(ConsiderSplitContext *context, } } +/* + * GiST sortsupport comparator for ranges. + * similar to range_cmp, but range typcache is cached. + */ +static int +range_gist_cmp(Datum a, Datum b, SortSupport ssup) +{ + RangeType *range_a = DatumGetRangeTypeP(a); + RangeType *range_b = DatumGetRangeTypeP(b); + TypeCacheEntry *typcache = ssup->ssup_extra; + RangeBound lower1, + lower2; + RangeBound upper1, + upper2; + bool empty1, + empty2; + int result; + + if (typcache == NULL) + { + Assert(RangeTypeGetOid(range_a) == RangeTypeGetOid(range_b)); + typcache = lookup_type_cache(RangeTypeGetOid(range_a), TYPECACHE_RANGE_INFO); + + /* + * Cache the range info between calls to avoid having to call + * lookup_type_cache() for each comparison. + */ + ssup->ssup_extra = typcache; + } + + range_deserialize(typcache, range_a, &lower1, &upper1, &empty1); + range_deserialize(typcache, range_b, &lower2, &upper2, &empty2); + + if (empty1 && empty2) + result = 0; + else if (empty1) + result = -1; + else if (empty2) + result = 1; + else + { + result = range_cmp_bounds(typcache, &lower1, &lower2); + if (result == 0) + result = range_cmp_bounds(typcache, &upper1, &upper2); + } + + if ((Datum) range_a != a) + pfree(range_a); + if ((Datum) range_b != b) + pfree(range_b); + + return result; +} + /* * Find class number for range. * diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat index 352558c1f06..fc229d99845 100644 --- a/src/include/catalog/pg_amproc.dat +++ b/src/include/catalog/pg_amproc.dat @@ -607,6 +607,9 @@ { amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange', amprocrighttype => 'anyrange', amprocnum => '7', amproc => 'range_gist_same' }, +{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange', + amprocrighttype => 'anyrange', amprocnum => '11', + amproc => 'range_gist_sortsupport' }, { amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange', amprocrighttype => 'anyrange', amprocnum => '12', amproc => 'gist_stratnum_identity' }, diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 29af4ce65d5..22315fefc9b 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -10589,6 +10589,9 @@ { oid => '3881', descr => 'GiST support', proname => 'range_gist_same', prorettype => 'internal', proargtypes => 'anyrange anyrange internal', prosrc => 'range_gist_same' }, +{ oid => '8849', descr => 'GiST support', + proname => 'range_gist_sortsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'range_gist_sortsupport' }, { oid => '6154', descr => 'GiST support', proname => 'multirange_gist_consistent', prorettype => 'bool', proargtypes => 'internal anymultirange int2 oid internal',