mirror of
https://github.com/postgres/postgres.git
synced 2025-07-23 03:21:12 +03:00
Add GiST and btree sortsupport routines for range types
For GiST, having a sortsupport function allows building the index using the "sorted build" method, which is much faster. For b-tree, the sortsupport routine doesn't give any new functionality, but speeds up sorting a tiny bit. The difference is not very significant, about 2% in cursory testing on my laptop, because the range type comparison function has quite a lot of overhead from detoasting. In any case, since we have the function for GiST anyway, we might as well register it for the btree opfamily too. Author: Bernd Helmle <mailings@oopsware.de> Discussion: https://www.postgresql.org/message-id/64d324ce2a6d535d3f0f3baeeea7b25beff82ce4.camel@oopsware.de
This commit is contained in:
@ -43,6 +43,7 @@
|
||||
#include "utils/date.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/rangetypes.h"
|
||||
#include "utils/sortsupport.h"
|
||||
#include "utils/timestamp.h"
|
||||
|
||||
|
||||
@ -57,6 +58,7 @@ typedef struct RangeIOData
|
||||
|
||||
static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
|
||||
IOFuncSelector func);
|
||||
static int range_fast_cmp(Datum a, Datum b, SortSupport ssup);
|
||||
static char range_parse_flags(const char *flags_str);
|
||||
static bool range_parse(const char *string, char *flags, char **lbound_str,
|
||||
char **ubound_str, Node *escontext);
|
||||
@ -1290,6 +1292,68 @@ range_cmp(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_INT32(cmp);
|
||||
}
|
||||
|
||||
/* Sort support strategy routine */
|
||||
Datum
|
||||
range_sortsupport(PG_FUNCTION_ARGS)
|
||||
{
|
||||
SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
|
||||
|
||||
ssup->comparator = range_fast_cmp;
|
||||
ssup->ssup_extra = NULL;
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/* like range_cmp, but uses the new sortsupport interface */
|
||||
static int
|
||||
range_fast_cmp(Datum a, Datum b, SortSupport ssup)
|
||||
{
|
||||
RangeType *range_a = DatumGetRangeTypeP(a);
|
||||
RangeType *range_b = DatumGetRangeTypeP(b);
|
||||
TypeCacheEntry *typcache;
|
||||
RangeBound lower1,
|
||||
lower2;
|
||||
RangeBound upper1,
|
||||
upper2;
|
||||
bool empty1,
|
||||
empty2;
|
||||
int cmp;
|
||||
|
||||
/* cache the range info between calls */
|
||||
if (ssup->ssup_extra == NULL)
|
||||
{
|
||||
Assert(RangeTypeGetOid(range_a) == RangeTypeGetOid(range_b));
|
||||
ssup->ssup_extra =
|
||||
lookup_type_cache(RangeTypeGetOid(range_a), TYPECACHE_RANGE_INFO);
|
||||
}
|
||||
typcache = ssup->ssup_extra;
|
||||
|
||||
range_deserialize(typcache, range_a, &lower1, &upper1, &empty1);
|
||||
range_deserialize(typcache, range_b, &lower2, &upper2, &empty2);
|
||||
|
||||
/* For b-tree use, empty ranges sort before all else */
|
||||
if (empty1 && empty2)
|
||||
cmp = 0;
|
||||
else if (empty1)
|
||||
cmp = -1;
|
||||
else if (empty2)
|
||||
cmp = 1;
|
||||
else
|
||||
{
|
||||
cmp = range_cmp_bounds(typcache, &lower1, &lower2);
|
||||
if (cmp == 0)
|
||||
cmp = range_cmp_bounds(typcache, &upper1, &upper2);
|
||||
}
|
||||
|
||||
if ((Datum) range_a != a)
|
||||
pfree(range_a);
|
||||
if ((Datum) range_b != b)
|
||||
pfree(range_b);
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
|
||||
/* inequality operators using the range_cmp function */
|
||||
Datum
|
||||
range_lt(PG_FUNCTION_ARGS)
|
||||
|
@ -57,6 +57,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 202504012
|
||||
#define CATALOG_VERSION_NO 202504021
|
||||
|
||||
#endif
|
||||
|
@ -283,6 +283,9 @@
|
||||
amprocrighttype => 'tsquery', amprocnum => '1', amproc => 'tsquery_cmp' },
|
||||
{ amprocfamily => 'btree/range_ops', amproclefttype => 'anyrange',
|
||||
amprocrighttype => 'anyrange', amprocnum => '1', amproc => 'range_cmp' },
|
||||
{ amprocfamily => 'btree/range_ops', amproclefttype => 'anyrange',
|
||||
amprocrighttype => 'anyrange', amprocnum => '2',
|
||||
amproc => 'range_sortsupport' },
|
||||
{ amprocfamily => 'btree/multirange_ops', amproclefttype => 'anymultirange',
|
||||
amprocrighttype => 'anymultirange', amprocnum => '1',
|
||||
amproc => 'multirange_cmp' },
|
||||
@ -606,6 +609,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_sortsupport' },
|
||||
{ amprocfamily => 'gist/range_ops', amproclefttype => 'any',
|
||||
amprocrighttype => 'any', amprocnum => '12',
|
||||
amproc => 'gist_stratnum_common' },
|
||||
|
@ -10855,6 +10855,9 @@
|
||||
{ oid => '3870', descr => 'less-equal-greater',
|
||||
proname => 'range_cmp', prorettype => 'int4',
|
||||
proargtypes => 'anyrange anyrange', prosrc => 'range_cmp' },
|
||||
{ oid => '8849', descr => 'sort support',
|
||||
proname => 'range_sortsupport', prorettype => 'void',
|
||||
proargtypes => 'internal', prosrc => 'range_sortsupport' },
|
||||
{ oid => '3871',
|
||||
proname => 'range_lt', prorettype => 'bool',
|
||||
proargtypes => 'anyrange anyrange', prosrc => 'range_lt' },
|
||||
|
Reference in New Issue
Block a user