PostgreSQL Source Code git master
Loading...
Searching...
No Matches
spgquadtreeproc.c File Reference
#include "postgres.h"
#include "access/spgist.h"
#include "access/spgist_private.h"
#include "access/stratnum.h"
#include "catalog/pg_type.h"
#include "utils/float.h"
#include "utils/fmgrprotos.h"
#include "utils/geo_decls.h"
Include dependency graph for spgquadtreeproc.c:

Go to the source code of this file.

Macros

#define SPTEST(f, x, y)    DatumGetBool(DirectFunctionCall2(f, PointPGetDatum(x), PointPGetDatum(y)))
 

Functions

Datum spg_quad_config (PG_FUNCTION_ARGS)
 
static int16 getQuadrant (Point *centroid, Point *tst)
 
static BOXgetQuadrantArea (BOX *bbox, Point *centroid, int quadrant)
 
Datum spg_quad_choose (PG_FUNCTION_ARGS)
 
Datum spg_quad_picksplit (PG_FUNCTION_ARGS)
 
Datum spg_quad_inner_consistent (PG_FUNCTION_ARGS)
 
Datum spg_quad_leaf_consistent (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ SPTEST

#define SPTEST (   f,
  x,
  y 
)     DatumGetBool(DirectFunctionCall2(f, PointPGetDatum(x), PointPGetDatum(y)))

Definition at line 41 of file spgquadtreeproc.c.

57{
62 return 1;
63
67 return 2;
68
72 return 3;
73
76 return 4;
77
78 elog(ERROR, "getQuadrant: impossible case");
79 return 0;
80}
81
82/* Returns bounding box of a given quadrant inside given bounding box */
83static BOX *
85{
86 BOX *result = palloc_object(BOX);
87
88 switch (quadrant)
89 {
90 case 1:
91 result->high = bbox->high;
92 result->low = *centroid;
93 break;
94 case 2:
95 result->high.x = bbox->high.x;
96 result->high.y = centroid->y;
97 result->low.x = centroid->x;
98 result->low.y = bbox->low.y;
99 break;
100 case 3:
101 result->high = *centroid;
102 result->low = bbox->low;
103 break;
104 case 4:
105 result->high.x = centroid->x;
106 result->high.y = bbox->high.y;
107 result->low.x = bbox->low.x;
108 result->low.y = centroid->y;
109 break;
110 }
111
112 return result;
113}
114
115Datum
117{
121 *centroid;
122
123 if (in->allTheSame)
124 {
126 /* nodeN will be set by core */
127 out->result.matchNode.levelAdd = 0;
130 }
131
132 Assert(in->hasPrefix);
134
135 Assert(in->nNodes == 4);
136
139 out->result.matchNode.levelAdd = 0;
141
143}
144
145#ifdef USE_MEDIAN
146static int
147x_cmp(const void *a, const void *b, void *arg)
148{
149 Point *pa = *(Point *const *) a;
150 Point *pb = *(Point *const *) b;
151
152 if (pa->x == pb->x)
153 return 0;
154 return (pa->x > pb->x) ? 1 : -1;
155}
156
157static int
158y_cmp(const void *a, const void *b, void *arg)
159{
160 Point *pa = *(Point *const *) a;
161 Point *pb = *(Point *const *) b;
162
163 if (pa->y == pb->y)
164 return 0;
165 return (pa->y > pb->y) ? 1 : -1;
166}
167#endif
168
169Datum
171{
174 int i;
176
177#ifdef USE_MEDIAN
178 /* Use the median values of x and y as the centroid point */
179 Point **sorted;
180
181 sorted = palloc_array(Point *, in->nTuples);
182 for (i = 0; i < in->nTuples; i++)
183 sorted[i] = DatumGetPointP(in->datums[i]);
184
186
187 qsort(sorted, in->nTuples, sizeof(*sorted), x_cmp);
188 centroid->x = sorted[in->nTuples >> 1]->x;
189 qsort(sorted, in->nTuples, sizeof(*sorted), y_cmp);
190 centroid->y = sorted[in->nTuples >> 1]->y;
191#else
192 /* Use the average values of x and y as the centroid point */
194
195 for (i = 0; i < in->nTuples; i++)
196 {
197 centroid->x += DatumGetPointP(in->datums[i])->x;
198 centroid->y += DatumGetPointP(in->datums[i])->y;
199 }
200
201 centroid->x /= in->nTuples;
202 centroid->y /= in->nTuples;
203#endif
204
205 out->hasPrefix = true;
207
208 out->nNodes = 4;
209 out->nodeLabels = NULL; /* we don't need node labels */
210
211 out->mapTuplesToNodes = palloc_array(int, in->nTuples);
213
214 for (i = 0; i < in->nTuples; i++)
215 {
216 Point *p = DatumGetPointP(in->datums[i]);
217 int quadrant = getQuadrant(centroid, p) - 1;
218
221 }
222
224}
225
226
227Datum
229{
233 BOX infbbox;
234 BOX *bbox = NULL;
235 int which;
236 int i;
237
238 Assert(in->hasPrefix);
240
241 /*
242 * When ordering scan keys are specified, we've to calculate distance for
243 * them. In order to do that, we need calculate bounding boxes for all
244 * children nodes. Calculation of those bounding boxes on non-zero level
245 * require knowledge of bounding box of upper node. So, we save bounding
246 * boxes to traversalValues.
247 */
248 if (in->norderbys > 0)
249 {
250 out->distances = palloc_array(double *, in->nNodes);
251 out->traversalValues = palloc_array(void *, in->nNodes);
252
253 if (in->level == 0)
254 {
255 double inf = get_float8_infinity();
256
257 infbbox.high.x = inf;
258 infbbox.high.y = inf;
259 infbbox.low.x = -inf;
260 infbbox.low.y = -inf;
261 bbox = &infbbox;
262 }
263 else
264 {
265 bbox = in->traversalValue;
266 Assert(bbox);
267 }
268 }
269
270 if (in->allTheSame)
271 {
272 /* Report that all nodes should be visited */
273 out->nNodes = in->nNodes;
274 out->nodeNumbers = palloc_array(int, in->nNodes);
275 for (i = 0; i < in->nNodes; i++)
276 {
277 out->nodeNumbers[i] = i;
278
279 if (in->norderbys > 0)
280 {
282
283 /* Use parent quadrant box as traversalValue */
285
287
288 out->traversalValues[i] = quadrant;
290 in->orderbys, in->norderbys);
291 }
292 }
294 }
295
296 Assert(in->nNodes == 4);
297
298 /* "which" is a bitmask of quadrants that satisfy all constraints */
299 which = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
300
301 for (i = 0; i < in->nkeys; i++)
302 {
304 BOX *boxQuery;
305
306 switch (in->scankeys[i].sk_strategy)
307 {
309 if (SPTEST(point_right, centroid, query))
310 which &= (1 << 3) | (1 << 4);
311 break;
313 if (SPTEST(point_left, centroid, query))
314 which &= (1 << 1) | (1 << 2);
315 break;
317 which &= (1 << getQuadrant(centroid, query));
318 break;
321 if (SPTEST(point_above, centroid, query))
322 which &= (1 << 2) | (1 << 3);
323 break;
326 if (SPTEST(point_below, centroid, query))
327 which &= (1 << 1) | (1 << 4);
328 break;
330
331 /*
332 * For this operator, the query is a box not a point. We
333 * cheat to the extent of assuming that DatumGetPointP won't
334 * do anything that would be bad for a pointer-to-box.
335 */
337
341 {
342 /* centroid is in box, so all quadrants are OK */
343 }
344 else
345 {
346 /* identify quadrant(s) containing all corners of box */
347 Point p;
348 int r = 0;
349
350 p = boxQuery->low;
351 r |= 1 << getQuadrant(centroid, &p);
352 p.y = boxQuery->high.y;
353 r |= 1 << getQuadrant(centroid, &p);
354 p = boxQuery->high;
355 r |= 1 << getQuadrant(centroid, &p);
356 p.x = boxQuery->low.x;
357 r |= 1 << getQuadrant(centroid, &p);
358
359 which &= r;
360 }
361 break;
362 default:
363 elog(ERROR, "unrecognized strategy number: %d",
364 in->scankeys[i].sk_strategy);
365 break;
366 }
367
368 if (which == 0)
369 break; /* no need to consider remaining conditions */
370 }
371
372 out->levelAdds = palloc_array(int, 4);
373 for (i = 0; i < 4; ++i)
374 out->levelAdds[i] = 1;
375
376 /* We must descend into the quadrant(s) identified by which */
377 out->nodeNumbers = palloc_array(int, 4);
378 out->nNodes = 0;
379
380 for (i = 1; i <= 4; i++)
381 {
382 if (which & (1 << i))
383 {
384 out->nodeNumbers[out->nNodes] = i - 1;
385
386 if (in->norderbys > 0)
387 {
390
392
393 out->traversalValues[out->nNodes] = quadrant;
394
396 in->orderbys, in->norderbys);
397 }
398
399 out->nNodes++;
400 }
401 }
402
404}
405
406
407Datum
409{
412 Point *datum = DatumGetPointP(in->leafDatum);
413 bool res;
414 int i;
415
416 /* all tests are exact */
417 out->recheck = false;
418
419 /* leafDatum is what it is... */
420 out->leafValue = in->leafDatum;
421
422 /* Perform the required comparison(s) */
423 res = true;
424 for (i = 0; i < in->nkeys; i++)
425 {
427
428 switch (in->scankeys[i].sk_strategy)
429 {
431 res = SPTEST(point_left, datum, query);
432 break;
434 res = SPTEST(point_right, datum, query);
435 break;
437 res = SPTEST(point_eq, datum, query);
438 break;
441 res = SPTEST(point_below, datum, query);
442 break;
445 res = SPTEST(point_above, datum, query);
446 break;
448
449 /*
450 * For this operator, the query is a box not a point. We
451 * cheat to the extent of assuming that DatumGetPointP won't
452 * do anything that would be bad for a pointer-to-box.
453 */
454 res = SPTEST(box_contain_pt, query, datum);
455 break;
456 default:
457 elog(ERROR, "unrecognized strategy number: %d",
458 in->scankeys[i].sk_strategy);
459 break;
460 }
461
462 if (!res)
463 break;
464 }
465
466 if (res && in->norderbys > 0)
467 /* ok, it passes -> let's compute the distances */
469 in->orderbys, in->norderbys);
470
471 PG_RETURN_BOOL(res);
472}
#define Assert(condition)
Definition c.h:873
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define palloc_object(type)
Definition fe_memutils.h:74
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define palloc0_object(type)
Definition fe_memutils.h:75
static float8 get_float8_infinity(void)
Definition float.h:65
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define DirectFunctionCall2(func, arg1, arg2)
Definition fmgr.h:686
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
static Point * DatumGetPointP(Datum X)
Definition geo_decls.h:175
static Datum PointPGetDatum(const Point *X)
Definition geo_decls.h:180
static BOX * DatumGetBoxP(Datum X)
Definition geo_decls.h:233
static Datum BoxPGetDatum(const BOX *X)
Definition geo_decls.h:238
Datum point_eq(PG_FUNCTION_ARGS)
Definition geo_ops.c:1955
Datum point_above(PG_FUNCTION_ARGS)
Definition geo_ops.c:1919
Datum box_contain_pt(PG_FUNCTION_ARGS)
Definition geo_ops.c:3146
Datum point_below(PG_FUNCTION_ARGS)
Definition geo_ops.c:1928
Datum point_horiz(PG_FUNCTION_ARGS)
Definition geo_ops.c:1946
Datum point_left(PG_FUNCTION_ARGS)
Definition geo_ops.c:1901
Datum point_right(PG_FUNCTION_ARGS)
Definition geo_ops.c:1910
Datum point_vert(PG_FUNCTION_ARGS)
Definition geo_ops.c:1937
int b
Definition isn.c:74
int a
Definition isn.c:73
int i
Definition isn.c:77
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
void * arg
#define qsort(a, b, c, d)
Definition port.h:495
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
@ spgMatchNode
Definition spgist.h:69
static int x_cmp(const void *a, const void *b)
static int y_cmp(const void *a, const void *b)
BOX * box_copy(BOX *orig)
Definition spgproc.c:82
double * spg_key_orderbys_distances(Datum key, bool isLeaf, ScanKey orderbys, int norderbys)
Definition spgproc.c:63
Datum spg_quad_picksplit(PG_FUNCTION_ARGS)
Datum spg_quad_choose(PG_FUNCTION_ARGS)
static int16 getQuadrant(Point *centroid, Point *tst)
Datum spg_quad_leaf_consistent(PG_FUNCTION_ARGS)
Datum spg_quad_inner_consistent(PG_FUNCTION_ARGS)
static BOX * getQuadrantArea(BOX *bbox, Point *centroid, int quadrant)
#define SPTEST(f, x, y)
#define RTLeftStrategyNumber
Definition stratnum.h:51
#define RTRightStrategyNumber
Definition stratnum.h:55
#define RTSameStrategyNumber
Definition stratnum.h:56
#define RTOldBelowStrategyNumber
Definition stratnum.h:79
#define RTBelowStrategyNumber
Definition stratnum.h:60
#define RTOldAboveStrategyNumber
Definition stratnum.h:80
#define RTAboveStrategyNumber
Definition stratnum.h:61
#define RTContainedByStrategyNumber
Definition stratnum.h:58
Point low
Definition geo_decls.h:142
Point high
Definition geo_decls.h:141
float8 y
Definition geo_decls.h:98
float8 x
Definition geo_decls.h:97
Datum sk_argument
Definition skey.h:72
StrategyNumber sk_strategy
Definition skey.h:68
bool hasPrefix
Definition spgist.h:61
Datum prefixDatum
Definition spgist.h:62
int nNodes
Definition spgist.h:63
Datum datum
Definition spgist.h:55
bool allTheSame
Definition spgist.h:60
spgChooseResultType resultType
Definition spgist.h:76
int levelAdd
Definition spgist.h:82
Datum restDatum
Definition spgist.h:83
int nodeN
Definition spgist.h:81
union spgChooseOut::@54 result
struct spgChooseOut::@54::@55 matchNode
void * traversalValue
Definition spgist.h:141
MemoryContext traversalMemoryContext
Definition spgist.h:142
void ** traversalValues
Definition spgist.h:160
double ** distances
Definition spgist.h:161
double * distances
Definition spgist.h:188
Datum * datums
Definition spgist.h:113
int * mapTuplesToNodes
Definition spgist.h:125
Datum * nodeLabels
Definition spgist.h:123
Datum * leafTupleDatums
Definition spgist.h:126
Datum prefixDatum
Definition spgist.h:120

Function Documentation

◆ getQuadrant()

static int16 getQuadrant ( Point centroid,
Point tst 
)
static

Definition at line 57 of file spgquadtreeproc.c.

58{
63 return 1;
64
68 return 2;
69
73 return 3;
74
77 return 4;
78
79 elog(ERROR, "getQuadrant: impossible case");
80 return 0;
81}

References elog, ERROR, fb(), point_above(), point_below(), point_horiz(), point_left(), point_right(), point_vert(), and SPTEST.

Referenced by spg_quad_choose(), spg_quad_inner_consistent(), and spg_quad_picksplit().

◆ getQuadrantArea()

static BOX * getQuadrantArea ( BOX bbox,
Point centroid,
int  quadrant 
)
static

Definition at line 85 of file spgquadtreeproc.c.

86{
87 BOX *result = palloc_object(BOX);
88
89 switch (quadrant)
90 {
91 case 1:
92 result->high = bbox->high;
93 result->low = *centroid;
94 break;
95 case 2:
96 result->high.x = bbox->high.x;
97 result->high.y = centroid->y;
98 result->low.x = centroid->x;
99 result->low.y = bbox->low.y;
100 break;
101 case 3:
102 result->high = *centroid;
103 result->low = bbox->low;
104 break;
105 case 4:
106 result->high.x = centroid->x;
107 result->high.y = bbox->high.y;
108 result->low.x = bbox->low.x;
109 result->low.y = centroid->y;
110 break;
111 }
112
113 return result;
114}

References fb(), BOX::high, BOX::low, palloc_object, Point::x, and Point::y.

Referenced by spg_quad_inner_consistent().

◆ spg_quad_choose()

◆ spg_quad_config()

Datum spg_quad_config ( PG_FUNCTION_ARGS  )

Definition at line 27 of file spgquadtreeproc.c.

28{
29#ifdef NOT_USED
31#endif
33
34 cfg->prefixType = POINTOID;
35 cfg->labelType = VOIDOID; /* we don't need node labels */
36 cfg->canReturnData = true;
37 cfg->longValuesOK = false;
39}
bool longValuesOK
Definition spgist.h:47
bool canReturnData
Definition spgist.h:46
Oid labelType
Definition spgist.h:44
Oid prefixType
Definition spgist.h:43

References spgConfigOut::canReturnData, fb(), spgConfigOut::labelType, spgConfigOut::longValuesOK, PG_GETARG_POINTER, PG_RETURN_VOID, and spgConfigOut::prefixType.

◆ spg_quad_inner_consistent()

Datum spg_quad_inner_consistent ( PG_FUNCTION_ARGS  )

Definition at line 229 of file spgquadtreeproc.c.

230{
234 BOX infbbox;
235 BOX *bbox = NULL;
236 int which;
237 int i;
238
239 Assert(in->hasPrefix);
241
242 /*
243 * When ordering scan keys are specified, we've to calculate distance for
244 * them. In order to do that, we need calculate bounding boxes for all
245 * children nodes. Calculation of those bounding boxes on non-zero level
246 * require knowledge of bounding box of upper node. So, we save bounding
247 * boxes to traversalValues.
248 */
249 if (in->norderbys > 0)
250 {
251 out->distances = palloc_array(double *, in->nNodes);
252 out->traversalValues = palloc_array(void *, in->nNodes);
253
254 if (in->level == 0)
255 {
256 double inf = get_float8_infinity();
257
258 infbbox.high.x = inf;
259 infbbox.high.y = inf;
260 infbbox.low.x = -inf;
261 infbbox.low.y = -inf;
262 bbox = &infbbox;
263 }
264 else
265 {
266 bbox = in->traversalValue;
267 Assert(bbox);
268 }
269 }
270
271 if (in->allTheSame)
272 {
273 /* Report that all nodes should be visited */
274 out->nNodes = in->nNodes;
275 out->nodeNumbers = palloc_array(int, in->nNodes);
276 for (i = 0; i < in->nNodes; i++)
277 {
278 out->nodeNumbers[i] = i;
279
280 if (in->norderbys > 0)
281 {
283
284 /* Use parent quadrant box as traversalValue */
286
288
289 out->traversalValues[i] = quadrant;
291 in->orderbys, in->norderbys);
292 }
293 }
295 }
296
297 Assert(in->nNodes == 4);
298
299 /* "which" is a bitmask of quadrants that satisfy all constraints */
300 which = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
301
302 for (i = 0; i < in->nkeys; i++)
303 {
305 BOX *boxQuery;
306
307 switch (in->scankeys[i].sk_strategy)
308 {
310 if (SPTEST(point_right, centroid, query))
311 which &= (1 << 3) | (1 << 4);
312 break;
314 if (SPTEST(point_left, centroid, query))
315 which &= (1 << 1) | (1 << 2);
316 break;
318 which &= (1 << getQuadrant(centroid, query));
319 break;
322 if (SPTEST(point_above, centroid, query))
323 which &= (1 << 2) | (1 << 3);
324 break;
327 if (SPTEST(point_below, centroid, query))
328 which &= (1 << 1) | (1 << 4);
329 break;
331
332 /*
333 * For this operator, the query is a box not a point. We
334 * cheat to the extent of assuming that DatumGetPointP won't
335 * do anything that would be bad for a pointer-to-box.
336 */
338
342 {
343 /* centroid is in box, so all quadrants are OK */
344 }
345 else
346 {
347 /* identify quadrant(s) containing all corners of box */
348 Point p;
349 int r = 0;
350
351 p = boxQuery->low;
352 r |= 1 << getQuadrant(centroid, &p);
353 p.y = boxQuery->high.y;
354 r |= 1 << getQuadrant(centroid, &p);
355 p = boxQuery->high;
356 r |= 1 << getQuadrant(centroid, &p);
357 p.x = boxQuery->low.x;
358 r |= 1 << getQuadrant(centroid, &p);
359
360 which &= r;
361 }
362 break;
363 default:
364 elog(ERROR, "unrecognized strategy number: %d",
365 in->scankeys[i].sk_strategy);
366 break;
367 }
368
369 if (which == 0)
370 break; /* no need to consider remaining conditions */
371 }
372
373 out->levelAdds = palloc_array(int, 4);
374 for (i = 0; i < 4; ++i)
375 out->levelAdds[i] = 1;
376
377 /* We must descend into the quadrant(s) identified by which */
378 out->nodeNumbers = palloc_array(int, 4);
379 out->nNodes = 0;
380
381 for (i = 1; i <= 4; i++)
382 {
383 if (which & (1 << i))
384 {
385 out->nodeNumbers[out->nNodes] = i - 1;
386
387 if (in->norderbys > 0)
388 {
391
393
394 out->traversalValues[out->nNodes] = quadrant;
395
397 in->orderbys, in->norderbys);
398 }
399
400 out->nNodes++;
401 }
402 }
403
405}

References spgInnerConsistentIn::allTheSame, Assert, box_contain_pt(), box_copy(), BoxPGetDatum(), DatumGetBool(), DatumGetBoxP(), DatumGetPointP(), DirectFunctionCall2, spgInnerConsistentOut::distances, elog, ERROR, fb(), get_float8_infinity(), getQuadrant(), getQuadrantArea(), spgInnerConsistentIn::hasPrefix, i, spgInnerConsistentIn::level, spgInnerConsistentOut::levelAdds, MemoryContextSwitchTo(), spgInnerConsistentIn::nkeys, spgInnerConsistentIn::nNodes, spgInnerConsistentOut::nNodes, spgInnerConsistentOut::nodeNumbers, spgInnerConsistentIn::norderbys, spgInnerConsistentIn::orderbys, palloc_array, PG_GETARG_POINTER, PG_RETURN_VOID, point_above(), point_below(), point_left(), point_right(), PointerGetDatum(), spgInnerConsistentIn::prefixDatum, RTAboveStrategyNumber, RTBelowStrategyNumber, RTContainedByStrategyNumber, RTLeftStrategyNumber, RTOldAboveStrategyNumber, RTOldBelowStrategyNumber, RTRightStrategyNumber, RTSameStrategyNumber, spgInnerConsistentIn::scankeys, ScanKeyData::sk_argument, ScanKeyData::sk_strategy, spg_key_orderbys_distances(), SPTEST, spgInnerConsistentIn::traversalMemoryContext, spgInnerConsistentIn::traversalValue, spgInnerConsistentOut::traversalValues, Point::x, and Point::y.

◆ spg_quad_leaf_consistent()

Datum spg_quad_leaf_consistent ( PG_FUNCTION_ARGS  )

Definition at line 409 of file spgquadtreeproc.c.

410{
413 Point *datum = DatumGetPointP(in->leafDatum);
414 bool res;
415 int i;
416
417 /* all tests are exact */
418 out->recheck = false;
419
420 /* leafDatum is what it is... */
421 out->leafValue = in->leafDatum;
422
423 /* Perform the required comparison(s) */
424 res = true;
425 for (i = 0; i < in->nkeys; i++)
426 {
428
429 switch (in->scankeys[i].sk_strategy)
430 {
432 res = SPTEST(point_left, datum, query);
433 break;
435 res = SPTEST(point_right, datum, query);
436 break;
438 res = SPTEST(point_eq, datum, query);
439 break;
442 res = SPTEST(point_below, datum, query);
443 break;
446 res = SPTEST(point_above, datum, query);
447 break;
449
450 /*
451 * For this operator, the query is a box not a point. We
452 * cheat to the extent of assuming that DatumGetPointP won't
453 * do anything that would be bad for a pointer-to-box.
454 */
455 res = SPTEST(box_contain_pt, query, datum);
456 break;
457 default:
458 elog(ERROR, "unrecognized strategy number: %d",
459 in->scankeys[i].sk_strategy);
460 break;
461 }
462
463 if (!res)
464 break;
465 }
466
467 if (res && in->norderbys > 0)
468 /* ok, it passes -> let's compute the distances */
470 in->orderbys, in->norderbys);
471
472 PG_RETURN_BOOL(res);
473}

References box_contain_pt(), DatumGetPointP(), spgLeafConsistentOut::distances, elog, ERROR, i, spgLeafConsistentIn::leafDatum, spgLeafConsistentOut::leafValue, spgLeafConsistentIn::nkeys, spgLeafConsistentIn::norderbys, spgLeafConsistentIn::orderbys, PG_GETARG_POINTER, PG_RETURN_BOOL, point_above(), point_below(), point_eq(), point_left(), point_right(), spgLeafConsistentOut::recheck, RTAboveStrategyNumber, RTBelowStrategyNumber, RTContainedByStrategyNumber, RTLeftStrategyNumber, RTOldAboveStrategyNumber, RTOldBelowStrategyNumber, RTRightStrategyNumber, RTSameStrategyNumber, spgLeafConsistentIn::scankeys, ScanKeyData::sk_argument, ScanKeyData::sk_strategy, spg_key_orderbys_distances(), and SPTEST.

◆ spg_quad_picksplit()

Datum spg_quad_picksplit ( PG_FUNCTION_ARGS  )

Definition at line 171 of file spgquadtreeproc.c.

172{
175 int i;
177
178#ifdef USE_MEDIAN
179 /* Use the median values of x and y as the centroid point */
180 Point **sorted;
181
182 sorted = palloc_array(Point *, in->nTuples);
183 for (i = 0; i < in->nTuples; i++)
184 sorted[i] = DatumGetPointP(in->datums[i]);
185
187
188 qsort(sorted, in->nTuples, sizeof(*sorted), x_cmp);
189 centroid->x = sorted[in->nTuples >> 1]->x;
190 qsort(sorted, in->nTuples, sizeof(*sorted), y_cmp);
191 centroid->y = sorted[in->nTuples >> 1]->y;
192#else
193 /* Use the average values of x and y as the centroid point */
195
196 for (i = 0; i < in->nTuples; i++)
197 {
198 centroid->x += DatumGetPointP(in->datums[i])->x;
199 centroid->y += DatumGetPointP(in->datums[i])->y;
200 }
201
202 centroid->x /= in->nTuples;
203 centroid->y /= in->nTuples;
204#endif
205
206 out->hasPrefix = true;
208
209 out->nNodes = 4;
210 out->nodeLabels = NULL; /* we don't need node labels */
211
212 out->mapTuplesToNodes = palloc_array(int, in->nTuples);
214
215 for (i = 0; i < in->nTuples; i++)
216 {
217 Point *p = DatumGetPointP(in->datums[i]);
218 int quadrant = getQuadrant(centroid, p) - 1;
219
222 }
223
225}

References DatumGetPointP(), spgPickSplitIn::datums, fb(), getQuadrant(), spgPickSplitOut::hasPrefix, i, spgPickSplitOut::leafTupleDatums, spgPickSplitOut::mapTuplesToNodes, spgPickSplitOut::nNodes, spgPickSplitOut::nodeLabels, spgPickSplitIn::nTuples, palloc0_object, palloc_array, palloc_object, PG_GETARG_POINTER, PG_RETURN_VOID, PointPGetDatum(), spgPickSplitOut::prefixDatum, qsort, Point::x, x_cmp(), Point::y, and y_cmp().