v7.3-Add-GIST-sortsupport-rangetypes.patch
text/x-patch
Filename: v7.3-Add-GIST-sortsupport-rangetypes.patch
Type: text/x-patch
Part: 1
Patch
Format: unified
Series: patch v7
| File | + | − |
|---|---|---|
| src/backend/utils/adt/rangetypes_gist.c | 70 | 0 |
| src/include/catalog/pg_amproc.dat | 3 | 0 |
| src/include/catalog/pg_proc.dat | 3 | 0 |
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 5d7fe292bf6..c73a3243b65 100644
--- a/src/include/catalog/pg_amproc.dat
+++ b/src/include/catalog/pg_amproc.dat
@@ -606,6 +606,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 1ec0d6f6b5f..f019a59b6bc 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -10768,6 +10768,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',