From d7c3eabb0936170f46ffe4573684123af964b59a Mon Sep 17 00:00:00 2001 From: Andrey Borodin Date: Sat, 3 Oct 2020 21:08:54 +0500 Subject: [PATCH] Sortsupport for sorting GiST build for ints and floats --- contrib/btree_gist/Makefile | 2 +- contrib/btree_gist/btree_float4.c | 70 ++++++++++++++++++ contrib/btree_gist/btree_float8.c | 82 +++++++++++++++++++++ contrib/btree_gist/btree_gist--1.6--1.7.sql | 45 +++++++++++ contrib/btree_gist/btree_gist.control | 2 +- contrib/btree_gist/btree_gist.h | 1 + contrib/btree_gist/btree_int2.c | 69 +++++++++++++++++ contrib/btree_gist/btree_int4.c | 69 +++++++++++++++++ contrib/btree_gist/btree_int8.c | 74 ++++++++++++++++++- src/backend/access/gist/gistvalidate.c | 1 + 10 files changed, 412 insertions(+), 3 deletions(-) create mode 100644 contrib/btree_gist/btree_gist--1.6--1.7.sql diff --git a/contrib/btree_gist/Makefile b/contrib/btree_gist/Makefile index e92d974a1a..a1f818f71e 100644 --- a/contrib/btree_gist/Makefile +++ b/contrib/btree_gist/Makefile @@ -32,7 +32,7 @@ EXTENSION = btree_gist 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.5--1.6.sql btree_gist--1.6--1.7.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_float4.c b/contrib/btree_gist/btree_float4.c index 3604c73313..b83fdd4df3 100644 --- a/contrib/btree_gist/btree_float4.c +++ b/contrib/btree_gist/btree_float4.c @@ -23,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) @@ -209,3 +210,72 @@ 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_cmp(Datum a, Datum b, SortSupport ssup) +{ + float4KEY *ia = (float4KEY *) DatumGetPointer(a); + float4KEY *ib = (float4KEY *) DatumGetPointer(b); + + if (ia->lower == ib->lower) + { + if (ia->upper == ib->upper) + return 0; + + return (ia->upper > ib->upper) ? 1 : -1; + } + + return (ia->lower > ib->lower) ? 1 : -1; +} + +static Datum +gbt_float4_abbrev_convert(Datum original, SortSupport ssup) +{ + float4KEY *b1 = (float4KEY *) DatumGetPointer(original); + float4 z = b1->lower; + + return (Datum) Float4GetDatum(z); +} + +static int +gbt_float4_cmp_abbrev(Datum z1, Datum z2, SortSupport ssup) +{ + if (DatumGetFloat4(z1) > DatumGetFloat4(z2)) + return 1; + else if (DatumGetFloat4(z1) < DatumGetFloat4(z2)) + return -1; + else + return 0; +} + +/* + * We never consider aborting the abbreviation. + */ +static bool +gbt_float4_abbrev_abort(int memtupcount, SortSupport ssup) +{ + return false; +} + +/* + * Sort support routine for fast GiST index build by sorting. + */ +Datum +gbt_float4_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + if (ssup->abbreviate) + { + ssup->comparator = gbt_float4_cmp_abbrev; + ssup->abbrev_converter = gbt_float4_abbrev_convert; + ssup->abbrev_abort = gbt_float4_abbrev_abort; + ssup->abbrev_full_comparator = gbt_float4_cmp; + } + else + { + ssup->comparator = gbt_float4_cmp; + } + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c index 10a5262aaa..2232071c22 100644 --- a/contrib/btree_gist/btree_float8.c +++ b/contrib/btree_gist/btree_float8.c @@ -23,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 @@ -216,3 +217,84 @@ 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_cmp(Datum a, Datum b, SortSupport ssup) +{ + float8KEY *ia = (float8KEY *) DatumGetPointer(a); + float8KEY *ib = (float8KEY *) DatumGetPointer(b); + + if (ia->lower == ib->lower) + { + if (ia->upper == ib->upper) + return 0; + + return (ia->upper > ib->upper) ? 1 : -1; + } + + return (ia->lower > ib->lower) ? 1 : -1; +} + +static Datum +gbt_float8_abbrev_convert(Datum original, SortSupport ssup) +{ + float8KEY *b1 = (float8KEY *) DatumGetPointer(original); + float8 z = b1->lower; + +#if SIZEOF_DATUM == 8 + return (Datum) Float8GetDatum(z); +#else + return (Datum) 0; +#endif +} + +static int +gbt_float8_cmp_abbrev(Datum z1, Datum z2, SortSupport ssup) +{ +#if SIZEOF_DATUM == 8 + if (DatumGetFloat8(z1) > DatumGetFloat8(z2)) + return 1; + else if (DatumGetFloat8(z1) < DatumGetFloat8(z2)) + return -1; + else + return 0; +#else + return 0; +#endif +} + +/* + * We never consider aborting the abbreviation. + */ +static bool +gbt_float8_abbrev_abort(int memtupcount, SortSupport ssup) +{ +#if SIZEOF_DATUM == 8 + return false; +#else + return true; +#endif +} + +/* + * Sort support routine for fast GiST index build by sorting. + */ +Datum +gbt_float8_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + if (ssup->abbreviate) + { + ssup->comparator = gbt_float8_cmp_abbrev; + ssup->abbrev_converter = gbt_float8_abbrev_convert; + ssup->abbrev_abort = gbt_float8_abbrev_abort; + ssup->abbrev_full_comparator = gbt_float8_cmp; + } + else + { + ssup->comparator = gbt_float8_cmp; + } + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_gist--1.6--1.7.sql b/contrib/btree_gist/btree_gist--1.6--1.7.sql new file mode 100644 index 0000000000..db10dc575c --- /dev/null +++ b/contrib/btree_gist/btree_gist--1.6--1.7.sql @@ -0,0 +1,45 @@ +/* contrib/btree_gist/btree_gist--1.6--1.7.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION btree_gist UPDATE TO '1.7'" to load this file. \quit + + +CREATE FUNCTION gbt_int8_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD + FUNCTION 11 (int8, int8) gbt_int8_sortsupport (internal) ; + +CREATE FUNCTION gbt_int4_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD + FUNCTION 11 (int4, int4) gbt_int4_sortsupport (internal) ; + +CREATE FUNCTION gbt_int2_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD + FUNCTION 11 (int2, int2) gbt_int2_sortsupport (internal) ; + +CREATE FUNCTION gbt_float8_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD + FUNCTION 11 (float8, float8) gbt_float8_sortsupport (internal) ; + +CREATE FUNCTION gbt_float4_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT; + +ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD + FUNCTION 11 (float4, float4) gbt_float4_sortsupport (internal) ; diff --git a/contrib/btree_gist/btree_gist.control b/contrib/btree_gist/btree_gist.control index e5c41fe8f3..fa9171a80a 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.6' +default_version = '1.7' 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 14c7c8ee19..35ad287ed3 100644 --- a/contrib/btree_gist/btree_gist.h +++ b/contrib/btree_gist/btree_gist.h @@ -6,6 +6,7 @@ #include "access/nbtree.h" #include "fmgr.h" +#include "utils/sortsupport.h" #define BtreeGistNotEqualStrategyNumber 6 diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c index a91b95ff39..8329bf4d3f 100644 --- a/contrib/btree_gist/btree_int2.c +++ b/contrib/btree_gist/btree_int2.c @@ -24,6 +24,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 gbt_int2gt(const void *a, const void *b, FmgrInfo *flinfo) @@ -214,3 +215,71 @@ 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_cmp(Datum a, Datum b, SortSupport ssup) +{ + int16KEY *ia = (int16KEY *) DatumGetPointer(a); + int16KEY *ib = (int16KEY *) DatumGetPointer(b); + + if (ia->lower == ib->lower) + { + if (ia->upper == ib->upper) + return 0; + + return (ia->upper > ib->upper) ? 1 : -1; + } + + return (ia->lower > ib->lower) ? 1 : -1; +} + +static Datum +gbt_int2_abbrev_convert(Datum original, SortSupport ssup) +{ + int16KEY *b1 = (int16KEY *) DatumGetPointer(original); + int16 z = b1->lower; + + return (Datum) z; +} + +static int +gbt_int2_cmp_abbrev(Datum z1, Datum z2, SortSupport ssup) +{ + if (z1 > z2) + return 1; + else if (z1 < z2) + return -1; + else + return 0; +} + +/* + * We never consider aborting the abbreviation. + */ +static bool +gbt_int2_abbrev_abort(int memtupcount, SortSupport ssup) +{ + return false; +} + +/* + * Sort support routine for fast GiST index build by sorting. + */ +Datum +gbt_int2_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + if (ssup->abbreviate) + { + ssup->comparator = gbt_int2_cmp_abbrev; + ssup->abbrev_converter = gbt_int2_abbrev_convert; + ssup->abbrev_abort = gbt_int2_abbrev_abort; + ssup->abbrev_full_comparator = gbt_int2_cmp; + } + else + { + ssup->comparator = gbt_int2_cmp; + } + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c index 7ea98c478c..363b25f794 100644 --- a/contrib/btree_gist/btree_int4.c +++ b/contrib/btree_gist/btree_int4.c @@ -24,6 +24,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 @@ -215,3 +216,71 @@ 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_cmp(Datum a, Datum b, SortSupport ssup) +{ + int32KEY *ia = (int32KEY *) DatumGetPointer(a); + int32KEY *ib = (int32KEY *) DatumGetPointer(b); + + if (ia->lower == ib->lower) + { + if (ia->upper == ib->upper) + return 0; + + return (ia->upper > ib->upper) ? 1 : -1; + } + + return (ia->lower > ib->lower) ? 1 : -1; +} + +static Datum +gbt_int4_abbrev_convert(Datum original, SortSupport ssup) +{ + int32KEY *b1 = (int32KEY *) DatumGetPointer(original); + int32 z = b1->lower; + + return (Datum) z; +} + +static int +gbt_int4_cmp_abbrev(Datum z1, Datum z2, SortSupport ssup) +{ + if (z1 > z2) + return 1; + else if (z1 < z2) + return -1; + else + return 0; +} + +/* + * We never consider aborting the abbreviation. + */ +static bool +gbt_int4_abbrev_abort(int memtupcount, SortSupport ssup) +{ + return false; +} + +/* + * Sort support routine for fast GiST index build by sorting. + */ +Datum +gbt_int4_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + if (ssup->abbreviate) + { + ssup->comparator = gbt_int4_cmp_abbrev; + ssup->abbrev_converter = gbt_int4_abbrev_convert; + ssup->abbrev_abort = gbt_int4_abbrev_abort; + ssup->abbrev_full_comparator = gbt_int4_cmp; + } + else + { + ssup->comparator = gbt_int4_cmp; + } + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c index df2b0d174b..2160cf4ad4 100644 --- a/contrib/btree_gist/btree_int8.c +++ b/contrib/btree_gist/btree_int8.c @@ -24,7 +24,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 gbt_int8gt(const void *a, const void *b, FmgrInfo *flinfo) @@ -215,3 +215,75 @@ 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_cmp(Datum a, Datum b, SortSupport ssup) +{ + int64KEY *ia = (int64KEY *) DatumGetPointer(a); + int64KEY *ib = (int64KEY *) DatumGetPointer(b); + + if (ia->lower == ib->lower) + { + if (ia->upper == ib->upper) + return 0; + + return (ia->upper > ib->upper) ? 1 : -1; + } + + return (ia->lower > ib->lower) ? 1 : -1; +} + +static Datum +gbt_int8_abbrev_convert(Datum original, SortSupport ssup) +{ + int64KEY *b1 = (int64KEY *) DatumGetPointer(original); + int64 z = b1->lower; + +#if SIZEOF_DATUM == 8 + return (Datum) z; +#else + return (Datum) (z >> 32); +#endif +} + +static int +gbt_int8_cmp_abbrev(Datum z1, Datum z2, SortSupport ssup) +{ + if (z1 > z2) + return 1; + else if (z1 < z2) + return -1; + else + return 0; +} + +/* + * We never consider aborting the abbreviation. + */ +static bool +gbt_int8_abbrev_abort(int memtupcount, SortSupport ssup) +{ + return false; +} + +/* + * Sort support routine for fast GiST index build by sorting. + */ +Datum +gbt_int8_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + if (ssup->abbreviate) + { + ssup->comparator = gbt_int8_cmp_abbrev; + ssup->abbrev_converter = gbt_int8_abbrev_convert; + ssup->abbrev_abort = gbt_int8_abbrev_abort; + ssup->abbrev_full_comparator = gbt_int8_cmp; + } + else + { + ssup->comparator = gbt_int8_cmp; + } + PG_RETURN_VOID(); +} diff --git a/src/backend/access/gist/gistvalidate.c b/src/backend/access/gist/gistvalidate.c index 8a14620fab..e600015b12 100644 --- a/src/backend/access/gist/gistvalidate.c +++ b/src/backend/access/gist/gistvalidate.c @@ -338,6 +338,7 @@ gistadjustmembers(Oid opfamilyoid, case GIST_DISTANCE_PROC: case GIST_FETCH_PROC: case GIST_OPTIONS_PROC: + case GIST_SORTSUPPORT_PROC: /* Optional, so force it to be a soft family dependency */ op->ref_is_hard = false; op->ref_is_family = true; -- 2.24.3 (Apple Git-128)