1/*-------------------------------------------------------------------------
4 * implementation of k-d tree over points for SP-GiST
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/access/spgist/spgkdtreeproc.c
13 *-------------------------------------------------------------------------
23#include "utils/fmgrprotos.h"
30 /* spgConfigIn *cfgin = (spgConfigIn *) PG_GETARG_POINTER(0); */
34 cfg->
labelType = VOIDOID;
/* we don't need node labels */
43 double tstcoord = (isX) ? tst->
x : tst->
y;
45 if (coord == tstcoord)
47 else if (coord > tstcoord)
62 elog(
ERROR,
"allTheSame should not occur for k-d trees");
90 if (pa->
p->
x == pb->
p->
x)
92 return (pa->
p->
x > pb->
p->
x) ? 1 : -1;
101 if (pa->
p->
y == pb->
p->
y)
103 return (pa->
p->
y > pb->
p->
y) ? 1 : -1;
127 coord = (in->
level % 2) ? sorted[middle].p->x : sorted[middle].
p->
y;
133 out->
nodeLabels = NULL;
/* we don't need node labels */
139 * Note: points that have coordinates exactly equal to coord may get
140 * classified into either node, depending on where they happen to fall in
141 * the sorted list. This is okay as long as the inner_consistent function
142 * descends into both sides for such cases. This is better than the
143 * alternative of trying to have an exact boundary, because it keeps the
144 * tree balanced even when we have many instances of the same point value.
145 * So we should never trigger the allTheSame logic.
173 elog(
ERROR,
"allTheSame should not occur for k-d trees");
177 /* "which" is a bitmask of children that satisfy all constraints */
178 which = (1 << 1) | (1 << 2);
188 if ((in->
level % 2) != 0 &&
FPlt(query->
x, coord))
192 if ((in->
level % 2) != 0 &&
FPgt(query->
x, coord))
196 if ((in->
level % 2) != 0)
198 if (
FPlt(query->
x, coord))
200 else if (
FPgt(query->
x, coord))
205 if (
FPlt(query->
y, coord))
207 else if (
FPgt(query->
y, coord))
213 if ((in->
level % 2) == 0 &&
FPlt(query->
y, coord))
218 if ((in->
level % 2) == 0 &&
FPgt(query->
y, coord))
224 * For this operator, the query is a box not a point. We
225 * cheat to the extent of assuming that DatumGetPointP won't
226 * do anything that would be bad for a pointer-to-box.
230 if ((in->
level % 2) != 0)
234 else if (
FPgt(boxQuery->
low.
x, coord))
241 else if (
FPgt(boxQuery->
low.
y, coord))
246 elog(
ERROR,
"unrecognized strategy number: %d",
252 break;
/* no need to consider remaining conditions */
255 /* We must descend into the children identified by which */
258 /* Fast-path for no matching children */
265 * When ordering scan keys are specified, we've to calculate distance for
266 * them. In order to do that, we need calculate bounding boxes for both
267 * children nodes. Calculation of those bounding boxes on non-zero level
268 * require knowledge of bounding box of upper node. So, we save bounding
269 * boxes to traversalValues.
283 infArea.
high.
x = inf;
284 infArea.
high.
y = inf;
285 infArea.
low.
x = -inf;
286 infArea.
low.
y = -inf;
295 bboxes[0].
low = area->
low;
301 bboxes[0].
high.
x = bboxes[1].
low.
x = coord;
308 bboxes[0].
high.
y = bboxes[1].
low.
y = coord;
314 for (
i = 1;
i <= 2;
i++)
316 if (which & (1 <<
i))
337 /* Set up level increments, too */
346 * spg_kd_leaf_consistent() is the same as spg_quad_leaf_consistent(),
347 * since we support the same operators and the same leaf data type.
348 * So we just borrow that function.
static float8 get_float8_infinity(void)
#define PG_GETARG_POINTER(n)
static bool FPlt(double A, double B)
static Point * DatumGetPointP(Datum X)
static Datum PointPGetDatum(const Point *X)
static BOX * DatumGetBoxP(Datum X)
static bool FPgt(double A, double B)
static Datum BoxPGetDatum(const BOX *X)
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
#define qsort(a, b, c, d)
static float8 DatumGetFloat8(Datum X)
static Datum Float8GetDatum(float8 X)
Datum spg_kd_inner_consistent(PG_FUNCTION_ARGS)
static int x_cmp(const void *a, const void *b)
Datum spg_kd_config(PG_FUNCTION_ARGS)
Datum spg_kd_choose(PG_FUNCTION_ARGS)
struct SortedPoint SortedPoint
static int y_cmp(const void *a, const void *b)
static int getSide(double coord, bool isX, Point *tst)
Datum spg_kd_picksplit(PG_FUNCTION_ARGS)
BOX * box_copy(BOX *orig)
double * spg_key_orderbys_distances(Datum key, bool isLeaf, ScanKey orderbys, int norderbys)
#define RTLeftStrategyNumber
#define RTRightStrategyNumber
#define RTSameStrategyNumber
#define RTOldBelowStrategyNumber
#define RTBelowStrategyNumber
#define RTOldAboveStrategyNumber
#define RTAboveStrategyNumber
#define RTContainedByStrategyNumber
StrategyNumber sk_strategy
spgChooseResultType resultType
struct spgChooseOut::@53::@54 matchNode
union spgChooseOut::@53 result
MemoryContext traversalMemoryContext