Add support for sorted gist index builds to btree_gist
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 3 Apr 2025 10:46:35 +0000 (13:46 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 3 Apr 2025 10:46:35 +0000 (13:46 +0300)
This enables sortsupport in the btree_gist extension for faster builds
of gist indexes.

Sorted gist index build strategy is the new default now. Regression
tests are unchanged (except for one small change in the 'enum' test to
add coverage for enum values added later) and are using the sorted
build strategy instead.

One version of this was committed a long time ago already, in commit
9f984ba6d2, but it was quickly reverted because of buildfarm
failures. The failures were presumably caused by some small bugs, but
we never got around to debug and commit it again. This patch was
written from scratch, implementing the same idea, with some fragments
and ideas from the original patch.

Author: Bernd Helmle <mailings@oopsware.de>
Author: Andrey Borodin <x4mmm@yandex-team.ru>
Discussion: https://www.postgresql.org/message-id/64d324ce2a6d535d3f0f3baeeea7b25beff82ce4.camel@oopsware.de

29 files changed:
contrib/btree_gist/Makefile
contrib/btree_gist/btree_bit.c
contrib/btree_gist/btree_bool.c
contrib/btree_gist/btree_bytea.c
contrib/btree_gist/btree_cash.c
contrib/btree_gist/btree_date.c
contrib/btree_gist/btree_enum.c
contrib/btree_gist/btree_float4.c
contrib/btree_gist/btree_float8.c
contrib/btree_gist/btree_gist--1.8--1.9.sql [new file with mode: 0644]
contrib/btree_gist/btree_gist.control
contrib/btree_gist/btree_inet.c
contrib/btree_gist/btree_int2.c
contrib/btree_gist/btree_int4.c
contrib/btree_gist/btree_int8.c
contrib/btree_gist/btree_interval.c
contrib/btree_gist/btree_macaddr.c
contrib/btree_gist/btree_macaddr8.c
contrib/btree_gist/btree_numeric.c
contrib/btree_gist/btree_oid.c
contrib/btree_gist/btree_text.c
contrib/btree_gist/btree_time.c
contrib/btree_gist/btree_ts.c
contrib/btree_gist/btree_utils_var.h
contrib/btree_gist/btree_uuid.c
contrib/btree_gist/expected/enum.out
contrib/btree_gist/meson.build
contrib/btree_gist/sql/enum.sql
doc/src/sgml/btree-gist.sgml

index 7ac2df26c1044a74a8152927795dd16d2016acd4..68190ac5e468733c0cf94d074262dfe47cbb2151 100644 (file)
@@ -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 \
index 7c71daae6d7fad4f172ae4f642aa857fedcc7ced..0df2ae20d8b21a584bf63ce21f94d5fdd50deaf0 100644 (file)
@@ -6,6 +6,7 @@
 #include "btree_gist.h"
 #include "btree_utils_var.h"
 #include "utils/fmgrprotos.h"
+#include "utils/sortsupport.h"
 #include "utils/varbit.h"
 
 /* GiST support functions */
@@ -15,6 +16,8 @@ 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 */
@@ -200,3 +203,46 @@ gbt_bit_penalty(PG_FUNCTION_ARGS)
    PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
                                      &tinfo, fcinfo->flinfo));
 }
+
+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;
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   result = DirectFunctionCall2(byteacmp,
+                                PointerGetDatum(arg1.lower),
+                                PointerGetDatum(arg2.lower));
+
+   GBT_FREE_IF_COPY(key1, x);
+   GBT_FREE_IF_COPY(key2, y);
+
+   return DatumGetInt32(result);
+}
+
+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();
+}
index d2145d0d0c300b4b1e92234d102c8af3ef410a0e..1127597bb6017c6a22f6a8beb8c26440dffa4e17 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "btree_gist.h"
 #include "btree_utils_num.h"
+#include "utils/sortsupport.h"
 
 typedef struct boolkey
 {
@@ -20,6 +21,7 @@ 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 bool
 gbt_boolgt(const void *a, const void *b, FmgrInfo *flinfo)
@@ -161,3 +163,24 @@ gbt_bool_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_bool_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   boolKEY    *arg1 = (boolKEY *) DatumGetPointer(x);
+   boolKEY    *arg2 = (boolKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   return (int32) arg1->lower - (int32) arg2->lower;
+}
+
+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();
+}
index 751b7a2ba4f017793780cb649af6682367a7f9cc..26f8710fad5c6f2da39fbe4b464ef8e25fdc6bbb 100644 (file)
@@ -6,6 +6,7 @@
 #include "btree_gist.h"
 #include "btree_utils_var.h"
 #include "utils/fmgrprotos.h"
+#include "utils/sortsupport.h"
 
 /* GiST support functions */
 PG_FUNCTION_INFO_V1(gbt_bytea_compress);
@@ -14,6 +15,7 @@ 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);
 
 
 /* define for comparison */
@@ -156,3 +158,35 @@ gbt_bytea_penalty(PG_FUNCTION_ARGS)
    PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
                                      &tinfo, fcinfo->flinfo));
 }
+
+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;
+
+   /* for leaf items we expect lower == upper, so only 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();
+}
index 51bdacab8eba8319138bc672974fccca1ae7b1ba..01c8d5a5f40744a8e7fb0be10a56bb7ddb425367 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_utils_num.h"
 #include "common/int.h"
 #include "utils/cash.h"
+#include "utils/sortsupport.h"
 
 typedef struct
 {
@@ -23,6 +24,7 @@ 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);
 
 static bool
 gbt_cashgt(const void *a, const void *b, FmgrInfo *flinfo)
@@ -210,3 +212,29 @@ gbt_cash_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_cash_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   cashKEY    *arg1 = (cashKEY *) DatumGetPointer(x);
+   cashKEY    *arg2 = (cashKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   if (arg1->lower > arg2->lower)
+       return 1;
+   else if (arg1->lower < arg2->lower)
+       return -1;
+   else
+       return 0;
+}
+
+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();
+}
index e87f8c03fc7bdd5c30721371e8a6a55e6e565b7c..c008dc61ba5f5ac967aa77057d3a985c05b18776 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_utils_num.h"
 #include "utils/fmgrprotos.h"
 #include "utils/date.h"
+#include "utils/sortsupport.h"
 
 typedef struct
 {
@@ -23,6 +24,7 @@ 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);
 
 static bool
 gbt_dategt(const void *a, const void *b, FmgrInfo *flinfo)
@@ -249,3 +251,26 @@ gbt_date_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_date_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   dateKEY    *akey = (dateKEY *) DatumGetPointer(x);
+   dateKEY    *bkey = (dateKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   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();
+}
index 642a19e6d4697ac8488c3918ea9af787590f7d39..83c95c7bb0401505284dda2c0cc8a113c73cada2 100644 (file)
@@ -7,6 +7,8 @@
 #include "btree_utils_num.h"
 #include "fmgr.h"
 #include "utils/fmgrprotos.h"
+#include "utils/fmgroids.h"
+#include "utils/sortsupport.h"
 
 /* enums are really Oids, so we just use the same structure */
 
@@ -24,6 +26,7 @@ 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 bool
@@ -179,3 +182,39 @@ gbt_enum_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_enum_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   oidKEY     *arg1 = (oidKEY *) DatumGetPointer(x);
+   oidKEY     *arg2 = (oidKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   return DatumGetInt32(CallerFInfoFunctionCall2(enum_cmp,
+                                                 ssup->ssup_extra,
+                                                 InvalidOid,
+                                                 arg1->lower,
+                                                 arg2->lower));
+}
+
+Datum
+gbt_enum_sortsupport(PG_FUNCTION_ARGS)
+{
+   SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
+   FmgrInfo   *flinfo;
+
+   ssup->comparator = gbt_enum_ssup_cmp;
+
+   /*
+    * Since gbt_enum_ssup_cmp() uses enum_cmp() like the rest of the
+    * comparison functions, it also needs to pass flinfo when calling it. The
+    * caller to a SortSupport comparison function doesn't provide an FmgrInfo
+    * struct, so look it up now, save it in ssup_extra and use it in
+    * gbt_enum_ssup_cmp() later.
+    */
+   flinfo = MemoryContextAlloc(ssup->ssup_cxt, sizeof(FmgrInfo));
+   fmgr_info_cxt(F_ENUM_CMP, flinfo, ssup->ssup_cxt);
+   ssup->ssup_extra = flinfo;
+
+   PG_RETURN_VOID();
+}
index 673c14a8f72815447249369254024bf28043befe..bec026a923a18e7a4386eb3946d44d64f13397c2 100644 (file)
@@ -6,6 +6,7 @@
 #include "btree_gist.h"
 #include "btree_utils_num.h"
 #include "utils/float.h"
+#include "utils/sortsupport.h"
 
 typedef struct float4key
 {
@@ -22,6 +23,7 @@ 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);
 
 static bool
 gbt_float4gt(const void *a, const void *b, FmgrInfo *flinfo)
@@ -204,3 +206,24 @@ gbt_float4_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_float4_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   float4KEY  *arg1 = (float4KEY *) DatumGetPointer(x);
+   float4KEY  *arg2 = (float4KEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   return float4_cmp_internal(arg1->lower, 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();
+}
index 9fb9cf024bd25fd8e066e5bdbd642eadebe41f3a..43e7cde2b6958f30dc32f979e28f22da3e4d4914 100644 (file)
@@ -6,6 +6,7 @@
 #include "btree_gist.h"
 #include "btree_utils_num.h"
 #include "utils/float.h"
+#include "utils/sortsupport.h"
 
 typedef struct float8key
 {
@@ -22,6 +23,7 @@ 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);
 
 
 static bool
@@ -212,3 +214,24 @@ gbt_float8_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_float8_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   float8KEY  *arg1 = (float8KEY *) DatumGetPointer(x);
+   float8KEY  *arg2 = (float8KEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   return float8_cmp_internal(arg1->lower, 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();
+}
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 (file)
index 0000000..4b38749
--- /dev/null
@@ -0,0 +1,197 @@
+/* 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 PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_varbit_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_bool_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_bytea_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_cash_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_date_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_enum_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_float4_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_float8_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_inet_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_int2_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_int4_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_int8_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_intv_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_macaddr_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_macad8_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_numeric_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_oid_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_text_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_bpchar_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_time_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_ts_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+CREATE FUNCTION gbt_uuid_sortsupport(internal)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
+
+ALTER OPERATOR FAMILY gist_bit_ops USING gist ADD
+   FUNCTION    11  (bit, bit) gbt_bit_sortsupport (internal) ;
+
+ALTER OPERATOR FAMILY gist_vbit_ops USING gist ADD
+   FUNCTION    11  (varbit, varbit) gbt_varbit_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  (cidr, cidr) 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_macaddr_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) gbt_bpchar_sortsupport (internal) ;
+
+ALTER OPERATOR FAMILY gist_time_ops USING gist ADD
+   FUNCTION    11  (time, time) gbt_time_sortsupport (internal) ;
+
+ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD
+   FUNCTION    11  (timetz, timetz) 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_uuid_ops USING gist ADD
+   FUNCTION    11  (uuid, uuid) gbt_uuid_sortsupport (internal) ;
index abf66538f32443b23e1f2a28bc9541f9d27e4883..69d9341a0adea05f1b1b24f78adc5498e4985125 100644 (file)
@@ -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
index 277fc3412d5548c03ee911d5ad159224354039ad..8b23853bafbb733cb752115f071a25d0e7fdd705 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_utils_num.h"
 #include "catalog/pg_type.h"
 #include "utils/builtins.h"
+#include "utils/sortsupport.h"
 
 typedef struct inetkey
 {
@@ -21,6 +22,7 @@ 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 bool
@@ -178,3 +180,29 @@ gbt_inet_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_inet_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   inetKEY    *arg1 = (inetKEY *) DatumGetPointer(x);
+   inetKEY    *arg2 = (inetKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   if (arg1->lower < arg2->lower)
+       return -1;
+   else if (arg1->lower > arg2->lower)
+       return 1;
+   else
+       return 0;
+}
+
+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();
+}
index 2859fa830b3be8034aa25a129a500f198d9208fe..33eccdedd7049fb3d3a33f7c41d24ec48b5cdfe0 100644 (file)
@@ -6,6 +6,7 @@
 #include "btree_gist.h"
 #include "btree_utils_num.h"
 #include "common/int.h"
+#include "utils/sortsupport.h"
 
 typedef struct int16key
 {
@@ -22,6 +23,7 @@ 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);
 
 
 static bool
@@ -209,3 +211,27 @@ gbt_int2_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_int2_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   int16KEY   *arg1 = (int16KEY *) DatumGetPointer(x);
+   int16KEY   *arg2 = (int16KEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   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();
+}
index 9abda7ef00923dd69af45ce0375cbc4a102f0f21..a82cee9a58a8cc8ff1223353d5d65a3fdb9c1434 100644 (file)
@@ -2,10 +2,10 @@
  * contrib/btree_gist/btree_int4.c
  */
 #include "postgres.h"
-
 #include "btree_gist.h"
 #include "btree_utils_num.h"
 #include "common/int.h"
+#include "utils/sortsupport.h"
 
 typedef struct int32key
 {
@@ -22,6 +22,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
 gbt_int4gt(const void *a, const void *b, FmgrInfo *flinfo)
@@ -208,3 +209,27 @@ gbt_int4_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_int4_ssup_cmp(Datum a, Datum b, SortSupport ssup)
+{
+   int32KEY   *ia = (int32KEY *) DatumGetPointer(a);
+   int32KEY   *ib = (int32KEY *) DatumGetPointer(b);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   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();
+}
index 6e7af9a1833e59954d4141ec18552b1db23259e8..f0c56e017269a22028db34b8dcfb2d67fb93f67d 100644 (file)
@@ -6,6 +6,7 @@
 #include "btree_gist.h"
 #include "btree_utils_num.h"
 #include "common/int.h"
+#include "utils/sortsupport.h"
 
 typedef struct int64key
 {
@@ -22,6 +23,7 @@ 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);
 
 
 static bool
@@ -209,3 +211,28 @@ gbt_int8_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_int8_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   int64KEY   *arg1 = (int64KEY *) DatumGetPointer(x);
+   int64KEY   *arg2 = (int64KEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   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();
+}
index ac0108e62801ffa85c85e79aeb7d6050291a0339..b5e365c6e09b4289f62995ccce2c2f96aadb56ab 100644 (file)
@@ -6,6 +6,7 @@
 #include "btree_gist.h"
 #include "btree_utils_num.h"
 #include "utils/fmgrprotos.h"
+#include "utils/sortsupport.h"
 #include "utils/timestamp.h"
 
 typedef struct
@@ -24,6 +25,7 @@ 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 bool
@@ -291,3 +293,26 @@ gbt_intv_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_intv_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   intvKEY    *arg1 = (intvKEY *) DatumGetPointer(x);
+   intvKEY    *arg2 = (intvKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   return DatumGetInt32(DirectFunctionCall2(interval_cmp,
+                                            IntervalPGetDatum(&arg1->lower),
+                                            IntervalPGetDatum(&arg2->lower)));
+}
+
+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();
+}
index 41e693cb2c2f23ebd7109418481165b2d835a98e..3b2f26719d5dc4f9c9a9e278f7865443951b7ab6 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_utils_num.h"
 #include "utils/fmgrprotos.h"
 #include "utils/inet.h"
+#include "utils/sortsupport.h"
 
 typedef struct
 {
@@ -23,6 +24,7 @@ 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);
 
 
 static bool
@@ -188,3 +190,26 @@ gbt_macad_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_macaddr_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   macKEY     *arg1 = (macKEY *) DatumGetPointer(x);
+   macKEY     *arg2 = (macKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare 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();
+}
index 613a19e317b9c7c5c14246081f504e490e954dff..f2b104617e68015f909a24194e326c676bf2636f 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_utils_num.h"
 #include "utils/fmgrprotos.h"
 #include "utils/inet.h"
+#include "utils/sortsupport.h"
 
 typedef struct
 {
@@ -23,6 +24,7 @@ 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 bool
 gbt_macad8gt(const void *a, const void *b, FmgrInfo *flinfo)
@@ -185,3 +187,26 @@ gbt_macad8_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_macaddr8_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   mac8KEY    *arg1 = (mac8KEY *) DatumGetPointer(x);
+   mac8KEY    *arg2 = (mac8KEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   return DatumGetInt32(DirectFunctionCall2(macaddr8_cmp,
+                                            Macaddr8PGetDatum(&arg1->lower),
+                                            Macaddr8PGetDatum(&arg2->lower)));
+}
+
+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();
+}
index f34e00818bb6be97c372f91f35f3748a2ae1617b..a39c05d9da1cf02e07681d1403843b212f1c1a61 100644 (file)
@@ -11,6 +11,7 @@
 #include "utils/builtins.h"
 #include "utils/numeric.h"
 #include "utils/rel.h"
+#include "utils/sortsupport.h"
 
 /* GiST support functions */
 PG_FUNCTION_INFO_V1(gbt_numeric_compress);
@@ -19,6 +20,7 @@ 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);
 
 
 /* define for comparison */
@@ -216,3 +218,35 @@ gbt_numeric_picksplit(PG_FUNCTION_ARGS)
                      &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(v);
 }
+
+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;
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   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();
+}
index d9afffe7827c5d250678a2a3e25d637324b34a17..ffe0d7983e40f1f4affbca08ac3a9809e6b06494 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "btree_gist.h"
 #include "btree_utils_num.h"
+#include "utils/sortsupport.h"
 
 typedef struct
 {
@@ -21,6 +22,7 @@ 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);
 
 
 static bool
@@ -209,3 +211,29 @@ gbt_oid_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_oid_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   oidKEY     *arg1 = (oidKEY *) DatumGetPointer(x);
+   oidKEY     *arg2 = (oidKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only 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();
+}
index ed706e3eaa7f751c6de0cce45cf83fe414093fef..ddee42504a19228a31947c845323388bddc62070 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_utils_var.h"
 #include "mb/pg_wchar.h"
 #include "utils/fmgrprotos.h"
+#include "utils/sortsupport.h"
 
 /* GiST support functions */
 PG_FUNCTION_INFO_V1(gbt_text_compress);
@@ -17,6 +18,8 @@ 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);
+PG_FUNCTION_INFO_V1(gbt_bpchar_sortsupport);
 
 
 /* define for comparison */
@@ -279,3 +282,69 @@ gbt_text_penalty(PG_FUNCTION_ARGS)
    PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
                                      &tinfo, fcinfo->flinfo));
 }
+
+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;
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   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();
+}
+
+static int
+gbt_bpchar_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;
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   result = DirectFunctionCall2Coll(bpcharcmp,
+                                    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_bpchar_sortsupport(PG_FUNCTION_ARGS)
+{
+   SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
+
+   ssup->comparator = gbt_bpchar_ssup_cmp;
+   ssup->ssup_extra = NULL;
+
+   PG_RETURN_VOID();
+}
index 79a895159b20906c3365219d531eb3ef3a0544d4..1dba95057ba9f7eb2628c3662ffea5e4d3f4f66f 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_utils_num.h"
 #include "utils/fmgrprotos.h"
 #include "utils/date.h"
+#include "utils/sortsupport.h"
 #include "utils/timestamp.h"
 
 typedef struct
@@ -26,6 +27,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
@@ -322,3 +325,26 @@ gbt_time_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   timeKEY    *arg1 = (timeKEY *) DatumGetPointer(x);
+   timeKEY    *arg2 = (timeKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   return DatumGetInt32(DirectFunctionCall2(time_cmp,
+                                            TimeADTGetDatumFast(arg1->lower),
+                                            TimeADTGetDatumFast(arg2->lower)));
+}
+
+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();
+}
index ba3535892eb167c2ca87484959bd20e2c0902c71..eb899c4d21363c0041785c1ed5d37411f561fc74 100644 (file)
@@ -10,6 +10,7 @@
 #include "utils/fmgrprotos.h"
 #include "utils/timestamp.h"
 #include "utils/float.h"
+#include "utils/sortsupport.h"
 
 typedef struct
 {
@@ -29,6 +30,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
@@ -393,3 +395,26 @@ gbt_ts_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_ts_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   tsKEY      *arg1 = (tsKEY *) DatumGetPointer(x);
+   tsKEY      *arg2 = (tsKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   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();
+}
index 9302d41ced68f6064657825c8e31c2fb60046b17..75ad33d24fcd1336e7f6a6f753f168b4f0375f64 100644 (file)
@@ -41,7 +41,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);
 
index 02480808a4a22e54bf08f4221db9b3b097768642..23a307a6a71d59ddc4c19f0fde5f2d4b0c1e5f0b 100644 (file)
@@ -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
@@ -23,6 +24,7 @@ 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
@@ -230,3 +232,24 @@ gbt_uuid_same(PG_FUNCTION_ARGS)
    *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
    PG_RETURN_POINTER(result);
 }
+
+static int
+gbt_uuid_ssup_cmp(Datum x, Datum y, SortSupport ssup)
+{
+   uuidKEY    *arg1 = (uuidKEY *) DatumGetPointer(x);
+   uuidKEY    *arg2 = (uuidKEY *) DatumGetPointer(y);
+
+   /* for leaf items we expect lower == upper, so only compare lower */
+   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();
+}
index c4b769dd4b77cc064919cbd750ce3db905ea7823..5782f43883859d326c2011b19e9099185f1a6c64 100644 (file)
@@ -1,5 +1,8 @@
 -- enum check
-create type rainbow as enum ('r','o','y','g','b','i','v');
+create type rainbow as enum ('r','o','g','b','i','v');
+-- enum values added later take some different codepaths internally,
+-- so make sure we have coverage for those too
+alter type rainbow add value 'y' before 'g';
 CREATE TABLE enumtmp (a rainbow);
 \copy enumtmp from 'data/enum.data'
 SET enable_seqscan=on;
index f4fa9574f1fd7ee6067561d703af2877ed219a13..89932dd3844ee17836c1e767e5f99d205c357317 100644 (file)
@@ -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,
 )
 
index 476211e97952cdff7cf905437823f9fdd8f2cbe8..d662cb63221021b303de16feb16406d5cea8c067 100644 (file)
@@ -1,6 +1,10 @@
 -- enum check
 
-create type rainbow as enum ('r','o','y','g','b','i','v');
+create type rainbow as enum ('r','o','g','b','i','v');
+
+-- enum values added later take some different codepaths internally,
+-- so make sure we have coverage for those too
+alter type rainbow add value 'y' before 'g';
 
 CREATE TABLE enumtmp (a rainbow);
 
index 31e7c78aaef49fe4e8f2d2fdc1a2d20b373695ec..a4c1b99be1faf26c70fa87329e9d1f50705e6744 100644 (file)
   <type>oid</type>, and <type>money</type>.
  </para>
 
+ <para>
+  By default <filename>btree_gist</filename> builds <acronym>GiST</acronym> index with
+  <function>sortsupport</function> in <firstterm>sorted</firstterm> mode. This usually results in
+  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