Skip to content

Commit e9e7b66

Browse files
committed
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 <[email protected]> Discussion: https://www.postgresql.org/message-id/[email protected]
1 parent ea3f9b6 commit e9e7b66

File tree

4 files changed

+74
-1
lines changed

4 files changed

+74
-1
lines changed

src/backend/utils/adt/rangetypes.c

+64
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "utils/date.h"
4444
#include "utils/lsyscache.h"
4545
#include "utils/rangetypes.h"
46+
#include "utils/sortsupport.h"
4647
#include "utils/timestamp.h"
4748

4849

@@ -57,6 +58,7 @@ typedef struct RangeIOData
5758

5859
static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
5960
IOFuncSelector func);
61+
static int range_fast_cmp(Datum a, Datum b, SortSupport ssup);
6062
static char range_parse_flags(const char *flags_str);
6163
static bool range_parse(const char *string, char *flags, char **lbound_str,
6264
char **ubound_str, Node *escontext);
@@ -1290,6 +1292,68 @@ range_cmp(PG_FUNCTION_ARGS)
12901292
PG_RETURN_INT32(cmp);
12911293
}
12921294

1295+
/* Sort support strategy routine */
1296+
Datum
1297+
range_sortsupport(PG_FUNCTION_ARGS)
1298+
{
1299+
SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
1300+
1301+
ssup->comparator = range_fast_cmp;
1302+
ssup->ssup_extra = NULL;
1303+
1304+
PG_RETURN_VOID();
1305+
}
1306+
1307+
/* like range_cmp, but uses the new sortsupport interface */
1308+
static int
1309+
range_fast_cmp(Datum a, Datum b, SortSupport ssup)
1310+
{
1311+
RangeType *range_a = DatumGetRangeTypeP(a);
1312+
RangeType *range_b = DatumGetRangeTypeP(b);
1313+
TypeCacheEntry *typcache;
1314+
RangeBound lower1,
1315+
lower2;
1316+
RangeBound upper1,
1317+
upper2;
1318+
bool empty1,
1319+
empty2;
1320+
int cmp;
1321+
1322+
/* cache the range info between calls */
1323+
if (ssup->ssup_extra == NULL)
1324+
{
1325+
Assert(RangeTypeGetOid(range_a) == RangeTypeGetOid(range_b));
1326+
ssup->ssup_extra =
1327+
lookup_type_cache(RangeTypeGetOid(range_a), TYPECACHE_RANGE_INFO);
1328+
}
1329+
typcache = ssup->ssup_extra;
1330+
1331+
range_deserialize(typcache, range_a, &lower1, &upper1, &empty1);
1332+
range_deserialize(typcache, range_b, &lower2, &upper2, &empty2);
1333+
1334+
/* For b-tree use, empty ranges sort before all else */
1335+
if (empty1 && empty2)
1336+
cmp = 0;
1337+
else if (empty1)
1338+
cmp = -1;
1339+
else if (empty2)
1340+
cmp = 1;
1341+
else
1342+
{
1343+
cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1344+
if (cmp == 0)
1345+
cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1346+
}
1347+
1348+
if ((Datum) range_a != a)
1349+
pfree(range_a);
1350+
if ((Datum) range_b != b)
1351+
pfree(range_b);
1352+
1353+
return cmp;
1354+
}
1355+
1356+
12931357
/* inequality operators using the range_cmp function */
12941358
Datum
12951359
range_lt(PG_FUNCTION_ARGS)

src/include/catalog/catversion.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
*/
5858

5959
/* yyyymmddN */
60-
#define CATALOG_VERSION_NO 202504012
60+
#define CATALOG_VERSION_NO 202504021
6161

6262
#endif

src/include/catalog/pg_amproc.dat

+6
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@
283283
amprocrighttype => 'tsquery', amprocnum => '1', amproc => 'tsquery_cmp' },
284284
{ amprocfamily => 'btree/range_ops', amproclefttype => 'anyrange',
285285
amprocrighttype => 'anyrange', amprocnum => '1', amproc => 'range_cmp' },
286+
{ amprocfamily => 'btree/range_ops', amproclefttype => 'anyrange',
287+
amprocrighttype => 'anyrange', amprocnum => '2',
288+
amproc => 'range_sortsupport' },
286289
{ amprocfamily => 'btree/multirange_ops', amproclefttype => 'anymultirange',
287290
amprocrighttype => 'anymultirange', amprocnum => '1',
288291
amproc => 'multirange_cmp' },
@@ -606,6 +609,9 @@
606609
{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
607610
amprocrighttype => 'anyrange', amprocnum => '7',
608611
amproc => 'range_gist_same' },
612+
{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
613+
amprocrighttype => 'anyrange', amprocnum => '11',
614+
amproc => 'range_sortsupport' },
609615
{ amprocfamily => 'gist/range_ops', amproclefttype => 'any',
610616
amprocrighttype => 'any', amprocnum => '12',
611617
amproc => 'gist_stratnum_common' },

src/include/catalog/pg_proc.dat

+3
Original file line numberDiff line numberDiff line change
@@ -10855,6 +10855,9 @@
1085510855
{ oid => '3870', descr => 'less-equal-greater',
1085610856
proname => 'range_cmp', prorettype => 'int4',
1085710857
proargtypes => 'anyrange anyrange', prosrc => 'range_cmp' },
10858+
{ oid => '8849', descr => 'sort support',
10859+
proname => 'range_sortsupport', prorettype => 'void',
10860+
proargtypes => 'internal', prosrc => 'range_sortsupport' },
1085810861
{ oid => '3871',
1085910862
proname => 'range_lt', prorettype => 'bool',
1086010863
proargtypes => 'anyrange anyrange', prosrc => 'range_lt' },

0 commit comments

Comments
 (0)