PostgreSQL Source Code git master
Loading...
Searching...
No Matches
rangetypes_spgist.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * rangetypes_spgist.c
4 * implementation of quad tree over ranges mapped to 2d-points for SP-GiST.
5 *
6 * Quad tree is a data structure similar to a binary tree, but is adapted to
7 * 2d data. Each inner node of a quad tree contains a point (centroid) which
8 * divides the 2d-space into 4 quadrants. Each quadrant is associated with a
9 * child node.
10 *
11 * Ranges are mapped to 2d-points so that the lower bound is one dimension,
12 * and the upper bound is another. By convention, we visualize the lower bound
13 * to be the horizontal axis, and upper bound the vertical axis.
14 *
15 * One quirk with this mapping is the handling of empty ranges. An empty range
16 * doesn't have lower and upper bounds, so it cannot be mapped to 2d space in
17 * a straightforward way. To cope with that, the root node can have a 5th
18 * quadrant, which is reserved for empty ranges. Furthermore, there can be
19 * inner nodes in the tree with no centroid. They contain only two child nodes,
20 * one for empty ranges and another for non-empty ones. Such a node can appear
21 * as the root node, or in the tree under the 5th child of the root node (in
22 * which case it will only contain empty nodes).
23 *
24 * The SP-GiST picksplit function uses medians along both axes as the centroid.
25 * This implementation only uses the comparison function of the range element
26 * datatype, therefore it works for any range type.
27 *
28 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
29 * Portions Copyright (c) 1994, Regents of the University of California
30 *
31 * IDENTIFICATION
32 * src/backend/utils/adt/rangetypes_spgist.c
33 *
34 *-------------------------------------------------------------------------
35 */
36
37#include "postgres.h"
38
39#include "access/spgist.h"
40#include "access/stratnum.h"
41#include "catalog/pg_type.h"
42#include "utils/datum.h"
43#include "utils/fmgrprotos.h"
44#include "utils/rangetypes.h"
45
46static int16 getQuadrant(TypeCacheEntry *typcache, const RangeType *centroid,
47 const RangeType *tst);
48static int bound_cmp(const void *a, const void *b, void *arg);
49
50static int adjacent_inner_consistent(TypeCacheEntry *typcache,
51 const RangeBound *arg, const RangeBound *centroid,
52 const RangeBound *prev);
53static int adjacent_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *arg,
54 const RangeBound *centroid);
55
56/*
57 * SP-GiST 'config' interface function.
58 */
61{
62#ifdef NOT_USED
64#endif
66
68 cfg->labelType = VOIDOID; /* we don't need node labels */
69 cfg->canReturnData = true;
70 cfg->longValuesOK = false;
72}
73
74/*----------
75 * Determine which quadrant a 2d-mapped range falls into, relative to the
76 * centroid.
77 *
78 * Quadrants are numbered like this:
79 *
80 * 4 | 1
81 * ----+----
82 * 3 | 2
83 *
84 * Where the lower bound of range is the horizontal axis and upper bound the
85 * vertical axis.
86 *
87 * Ranges on one of the axes are taken to lie in the quadrant with higher value
88 * along perpendicular axis. That is, a value on the horizontal axis is taken
89 * to belong to quadrant 1 or 4, and a value on the vertical axis is taken to
90 * belong to quadrant 1 or 2. A range equal to centroid is taken to lie in
91 * quadrant 1.
92 *
93 * Empty ranges are taken to lie in the special quadrant 5.
94 *----------
95 */
96static int16
98{
101 bool centroidEmpty;
103 upper;
104 bool empty;
105
108 range_deserialize(typcache, tst, &lower, &upper, &empty);
109
110 if (empty)
111 return 5;
112
113 if (range_cmp_bounds(typcache, &lower, &centroidLower) >= 0)
114 {
115 if (range_cmp_bounds(typcache, &upper, &centroidUpper) >= 0)
116 return 1;
117 else
118 return 2;
119 }
120 else
121 {
122 if (range_cmp_bounds(typcache, &upper, &centroidUpper) >= 0)
123 return 4;
124 else
125 return 3;
126 }
127}
128
129/*
130 * Choose SP-GiST function: choose path for addition of new range.
131 */
132Datum
134{
138 *centroid;
140 TypeCacheEntry *typcache;
141
142 if (in->allTheSame)
143 {
145 /* nodeN will be set by core */
146 out->result.matchNode.levelAdd = 0;
149 }
150
151 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(inRange));
152
153 /*
154 * A node with no centroid divides ranges purely on whether they're empty
155 * or not. All empty ranges go to child node 0, all non-empty ranges go to
156 * node 1.
157 */
158 if (!in->hasPrefix)
159 {
162 out->result.matchNode.nodeN = 0;
163 else
164 out->result.matchNode.nodeN = 1;
165 out->result.matchNode.levelAdd = 1;
168 }
169
171 quadrant = getQuadrant(typcache, centroid, inRange);
172
174
175 /* Select node matching to quadrant number */
177 out->result.matchNode.nodeN = quadrant - 1;
178 out->result.matchNode.levelAdd = 1;
180
182}
183
184/*
185 * Bound comparison for sorting.
186 */
187static int
188bound_cmp(const void *a, const void *b, void *arg)
189{
190 const RangeBound *ba = a;
191 const RangeBound *bb = b;
192 TypeCacheEntry *typcache = arg;
193
194 return range_cmp_bounds(typcache, ba, bb);
195}
196
197/*
198 * Picksplit SP-GiST function: split ranges into nodes. Select "centroid"
199 * range and distribute ranges according to quadrants.
200 */
201Datum
203{
206 int i;
207 int j;
208 int nonEmptyCount;
210 bool empty;
211 TypeCacheEntry *typcache;
212
213 /* Use the median values of lower and upper bounds as the centroid range */
216
217 typcache = range_get_typcache(fcinfo,
219
220 /* Allocate memory for bounds */
223 j = 0;
224
225 /* Deserialize bounds of ranges, count non-empty ranges */
226 for (i = 0; i < in->nTuples; i++)
227 {
229 &lowerBounds[j], &upperBounds[j], &empty);
230 if (!empty)
231 j++;
232 }
234
235 /*
236 * All the ranges are empty. The best we can do is to construct an inner
237 * node with no centroid, and put all ranges into node 0. If non-empty
238 * ranges are added later, they will be routed to node 1.
239 */
240 if (nonEmptyCount == 0)
241 {
242 out->nNodes = 2;
243 out->hasPrefix = false;
244 /* Prefix is empty */
246 out->nodeLabels = NULL;
247
248 out->mapTuplesToNodes = palloc_array(int, in->nTuples);
250
251 /* Place all ranges into node 0 */
252 for (i = 0; i < in->nTuples; i++)
253 {
255
257 out->mapTuplesToNodes[i] = 0;
258 }
260 }
261
262 /* Sort range bounds in order to find medians */
264 bound_cmp, typcache);
266 bound_cmp, typcache);
267
268 /* Construct "centroid" range from medians of lower and upper bounds */
270 &upperBounds[nonEmptyCount / 2], false, NULL);
271 out->hasPrefix = true;
273
274 /* Create node for empty ranges only if it is a root node */
275 out->nNodes = (in->level == 0) ? 5 : 4;
276 out->nodeLabels = NULL; /* we don't need node labels */
277
278 out->mapTuplesToNodes = palloc_array(int, in->nTuples);
280
281 /*
282 * Assign ranges to corresponding nodes according to quadrants relative to
283 * "centroid" range.
284 */
285 for (i = 0; i < in->nTuples; i++)
286 {
289
291 out->mapTuplesToNodes[i] = quadrant - 1;
292 }
293
295}
296
297/*
298 * SP-GiST consistent function for inner nodes: check which nodes are
299 * consistent with given set of queries.
300 */
301Datum
303{
306 int which;
307 int i;
309
310 /*
311 * For adjacent search we need also previous centroid (if any) to improve
312 * the precision of the consistent check. In this case needPrevious flag
313 * is set and centroid is passed into traversalValue.
314 */
315 bool needPrevious = false;
316
317 if (in->allTheSame)
318 {
319 /* Report that all nodes should be visited */
320 out->nNodes = in->nNodes;
321 out->nodeNumbers = palloc_array(int, in->nNodes);
322 for (i = 0; i < in->nNodes; i++)
323 out->nodeNumbers[i] = i;
325 }
326
327 if (!in->hasPrefix)
328 {
329 /*
330 * No centroid on this inner node. Such a node has two child nodes,
331 * the first for empty ranges, and the second for non-empty ones.
332 */
333 Assert(in->nNodes == 2);
334
335 /*
336 * Nth bit of which variable means that (N - 1)th node should be
337 * visited. Initially all bits are set. Bits of nodes which should be
338 * skipped will be unset.
339 */
340 which = (1 << 1) | (1 << 2);
341 for (i = 0; i < in->nkeys; i++)
342 {
343 StrategyNumber strategy = in->scankeys[i].sk_strategy;
344 bool empty;
345
346 /*
347 * The only strategy when second argument of operator is not range
348 * is RANGESTRAT_CONTAINS_ELEM.
349 */
350 if (strategy != RANGESTRAT_CONTAINS_ELEM)
352 else
353 empty = false;
354
355 switch (strategy)
356 {
361 case RANGESTRAT_AFTER:
363 /* These strategies return false if any argument is empty */
364 if (empty)
365 which = 0;
366 else
367 which &= (1 << 2);
368 break;
369
371
372 /*
373 * All ranges contain an empty range. Only non-empty
374 * ranges can contain a non-empty range.
375 */
376 if (!empty)
377 which &= (1 << 2);
378 break;
379
381
382 /*
383 * Only an empty range is contained by an empty range.
384 * Both empty and non-empty ranges can be contained by a
385 * non-empty range.
386 */
387 if (empty)
388 which &= (1 << 1);
389 break;
390
392 which &= (1 << 2);
393 break;
394
395 case RANGESTRAT_EQ:
396 if (empty)
397 which &= (1 << 1);
398 else
399 which &= (1 << 2);
400 break;
401
402 default:
403 elog(ERROR, "unrecognized range strategy: %d", strategy);
404 break;
405 }
406 if (which == 0)
407 break; /* no need to consider remaining conditions */
408 }
409 }
410 else
411 {
414 bool centroidEmpty;
415 TypeCacheEntry *typcache;
417
418 /* This node has a centroid. Fetch it. */
420 typcache = range_get_typcache(fcinfo,
424
425 Assert(in->nNodes == 4 || in->nNodes == 5);
426
427 /*
428 * Nth bit of which variable means that (N - 1)th node (Nth quadrant)
429 * should be visited. Initially all bits are set. Bits of nodes which
430 * can be skipped will be unset.
431 */
432 which = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
433
434 for (i = 0; i < in->nkeys; i++)
435 {
436 StrategyNumber strategy;
438 upper;
439 bool empty;
441
444 prevUpper;
445 bool prevEmpty;
446
447 /* Restrictions on range bounds according to scan strategy */
449 *maxLower = NULL,
450 *minUpper = NULL,
451 *maxUpper = NULL;
452
453 /* Are the restrictions on range bounds inclusive? */
454 bool inclusive = true;
455 bool strictEmpty = true;
456 int cmp,
457 which1,
458 which2;
459
460 strategy = in->scankeys[i].sk_strategy;
461
462 /*
463 * RANGESTRAT_CONTAINS_ELEM is just like RANGESTRAT_CONTAINS, but
464 * the argument is a single element. Expand the single element to
465 * a range containing only the element, and treat it like
466 * RANGESTRAT_CONTAINS.
467 */
468 if (strategy == RANGESTRAT_CONTAINS_ELEM)
469 {
470 lower.inclusive = true;
471 lower.infinite = false;
472 lower.lower = true;
473 lower.val = in->scankeys[i].sk_argument;
474
475 upper.inclusive = true;
476 upper.infinite = false;
477 upper.lower = false;
478 upper.val = in->scankeys[i].sk_argument;
479
480 empty = false;
481
482 strategy = RANGESTRAT_CONTAINS;
483 }
484 else
485 {
487 range_deserialize(typcache, range, &lower, &upper, &empty);
488 }
489
490 /*
491 * Most strategies are handled by forming a bounding box from the
492 * search key, defined by a minLower, maxLower, minUpper,
493 * maxUpper. Some modify 'which' directly, to specify exactly
494 * which quadrants need to be visited.
495 *
496 * For most strategies, nothing matches an empty search key, and
497 * an empty range never matches a non-empty key. If a strategy
498 * does not behave like that wrt. empty ranges, set strictEmpty to
499 * false.
500 */
501 switch (strategy)
502 {
504
505 /*
506 * Range A is before range B if upper bound of A is lower
507 * than lower bound of B.
508 */
509 maxUpper = &lower;
510 inclusive = false;
511 break;
512
514
515 /*
516 * Range A is overleft to range B if upper bound of A is
517 * less than or equal to upper bound of B.
518 */
519 maxUpper = &upper;
520 break;
521
523
524 /*
525 * Non-empty ranges overlap, if lower bound of each range
526 * is lower or equal to upper bound of the other range.
527 */
528 maxLower = &upper;
529 minUpper = &lower;
530 break;
531
533
534 /*
535 * Range A is overright to range B if lower bound of A is
536 * greater than or equal to lower bound of B.
537 */
538 minLower = &lower;
539 break;
540
541 case RANGESTRAT_AFTER:
542
543 /*
544 * Range A is after range B if lower bound of A is greater
545 * than upper bound of B.
546 */
547 minLower = &upper;
548 inclusive = false;
549 break;
550
552 if (empty)
553 break; /* Skip to strictEmpty check. */
554
555 /*
556 * Previously selected quadrant could exclude possibility
557 * for lower or upper bounds to be adjacent. Deserialize
558 * previous centroid range if present for checking this.
559 */
560 if (in->traversalValue)
561 {
565 }
566
567 /*
568 * For a range's upper bound to be adjacent to the
569 * argument's lower bound, it will be found along the line
570 * adjacent to (and just below) Y=lower. Therefore, if the
571 * argument's lower bound is less than the centroid's
572 * upper bound, the line falls in quadrants 2 and 3; if
573 * greater, the line falls in quadrants 1 and 4. (see
574 * adjacent_cmp_bounds for description of edge cases).
575 */
579 if (cmp > 0)
580 which1 = (1 << 1) | (1 << 4);
581 else if (cmp < 0)
582 which1 = (1 << 2) | (1 << 3);
583 else
584 which1 = 0;
585
586 /*
587 * Also search for ranges's adjacent to argument's upper
588 * bound. They will be found along the line adjacent to
589 * (and just right of) X=upper, which falls in quadrants 3
590 * and 4, or 1 and 2.
591 */
595 if (cmp > 0)
596 which2 = (1 << 1) | (1 << 2);
597 else if (cmp < 0)
598 which2 = (1 << 3) | (1 << 4);
599 else
600 which2 = 0;
601
602 /* We must chase down ranges adjacent to either bound. */
603 which &= which1 | which2;
604
605 needPrevious = true;
606 break;
607
609
610 /*
611 * Non-empty range A contains non-empty range B if lower
612 * bound of A is lower or equal to lower bound of range B
613 * and upper bound of range A is greater than or equal to
614 * upper bound of range A.
615 *
616 * All non-empty ranges contain an empty range.
617 */
618 strictEmpty = false;
619 if (!empty)
620 {
621 which &= (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
622 maxLower = &lower;
623 minUpper = &upper;
624 }
625 break;
626
628 /* The opposite of contains. */
629 strictEmpty = false;
630 if (empty)
631 {
632 /* An empty range is only contained by an empty range */
633 which &= (1 << 5);
634 }
635 else
636 {
637 minLower = &lower;
638 maxUpper = &upper;
639 }
640 break;
641
642 case RANGESTRAT_EQ:
643
644 /*
645 * Equal range can be only in the same quadrant where
646 * argument would be placed to.
647 */
648 strictEmpty = false;
649 which &= (1 << getQuadrant(typcache, centroid, range));
650 break;
651
652 default:
653 elog(ERROR, "unrecognized range strategy: %d", strategy);
654 break;
655 }
656
657 if (strictEmpty)
658 {
659 if (empty)
660 {
661 /* Scan key is empty, no branches are satisfying */
662 which = 0;
663 break;
664 }
665 else
666 {
667 /* Shouldn't visit tree branch with empty ranges */
668 which &= (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
669 }
670 }
671
672 /*
673 * Using the bounding box, see which quadrants we have to descend
674 * into.
675 */
676 if (minLower)
677 {
678 /*
679 * If the centroid's lower bound is less than or equal to the
680 * minimum lower bound, anything in the 3rd and 4th quadrants
681 * will have an even smaller lower bound, and thus can't
682 * match.
683 */
684 if (range_cmp_bounds(typcache, &centroidLower, minLower) <= 0)
685 which &= (1 << 1) | (1 << 2) | (1 << 5);
686 }
687 if (maxLower)
688 {
689 /*
690 * If the centroid's lower bound is greater than the maximum
691 * lower bound, anything in the 1st and 2nd quadrants will
692 * also have a greater than or equal lower bound, and thus
693 * can't match. If the centroid's lower bound is equal to the
694 * maximum lower bound, we can still exclude the 1st and 2nd
695 * quadrants if we're looking for a value strictly greater
696 * than the maximum.
697 */
698
700 if (cmp > 0 || (!inclusive && cmp == 0))
701 which &= (1 << 3) | (1 << 4) | (1 << 5);
702 }
703 if (minUpper)
704 {
705 /*
706 * If the centroid's upper bound is less than or equal to the
707 * minimum upper bound, anything in the 2nd and 3rd quadrants
708 * will have an even smaller upper bound, and thus can't
709 * match.
710 */
711 if (range_cmp_bounds(typcache, &centroidUpper, minUpper) <= 0)
712 which &= (1 << 1) | (1 << 4) | (1 << 5);
713 }
714 if (maxUpper)
715 {
716 /*
717 * If the centroid's upper bound is greater than the maximum
718 * upper bound, anything in the 1st and 4th quadrants will
719 * also have a greater than or equal upper bound, and thus
720 * can't match. If the centroid's upper bound is equal to the
721 * maximum upper bound, we can still exclude the 1st and 4th
722 * quadrants if we're looking for a value strictly greater
723 * than the maximum.
724 */
725
727 if (cmp > 0 || (!inclusive && cmp == 0))
728 which &= (1 << 2) | (1 << 3) | (1 << 5);
729 }
730
731 if (which == 0)
732 break; /* no need to consider remaining conditions */
733 }
734 }
735
736 /* We must descend into the quadrant(s) identified by 'which' */
737 out->nodeNumbers = palloc_array(int, in->nNodes);
738 if (needPrevious)
739 out->traversalValues = palloc_array(void *, in->nNodes);
740 out->nNodes = 0;
741
742 /*
743 * Elements of traversalValues should be allocated in
744 * traversalMemoryContext
745 */
747
748 for (i = 1; i <= in->nNodes; i++)
749 {
750 if (which & (1 << i))
751 {
752 /* Save previous prefix if needed */
753 if (needPrevious)
754 {
756
757 /*
758 * We know, that in->prefixDatum in this place is varlena,
759 * because it's range
760 */
761 previousCentroid = datumCopy(in->prefixDatum, false, -1);
763 }
764 out->nodeNumbers[out->nNodes] = i - 1;
765 out->nNodes++;
766 }
767 }
768
770
772}
773
774/*
775 * adjacent_cmp_bounds
776 *
777 * Given an argument and centroid bound, this function determines if any
778 * bounds that are adjacent to the argument are smaller than, or greater than
779 * or equal to centroid. For brevity, we call the arg < centroid "left", and
780 * arg >= centroid case "right". This corresponds to how the quadrants are
781 * arranged, if you imagine that "left" is equivalent to "down" and "right"
782 * is equivalent to "up".
783 *
784 * For the "left" case, returns -1, and for the "right" case, returns 1.
785 */
786static int
788 const RangeBound *centroid)
789{
790 int cmp;
791
792 Assert(arg->lower != centroid->lower);
793
794 cmp = range_cmp_bounds(typcache, arg, centroid);
795
796 if (centroid->lower)
797 {
798 /*------
799 * The argument is an upper bound, we are searching for adjacent lower
800 * bounds. A matching adjacent lower bound must be *larger* than the
801 * argument, but only just.
802 *
803 * The following table illustrates the desired result with a fixed
804 * argument bound, and different centroids. The CMP column shows
805 * the value of 'cmp' variable, and ADJ shows whether the argument
806 * and centroid are adjacent, per bounds_adjacent(). (N) means we
807 * don't need to check for that case, because it's implied by CMP.
808 * With the argument range [..., 500), the adjacent range we're
809 * searching for is [500, ...):
810 *
811 * ARGUMENT CENTROID CMP ADJ
812 * [..., 500) [498, ...) > (N) [500, ...) is to the right
813 * [..., 500) [499, ...) = (N) [500, ...) is to the right
814 * [..., 500) [500, ...) < Y [500, ...) is to the right
815 * [..., 500) [501, ...) < N [500, ...) is to the left
816 *
817 * So, we must search left when the argument is smaller than, and not
818 * adjacent, to the centroid. Otherwise search right.
819 *------
820 */
821 if (cmp < 0 && !bounds_adjacent(typcache, *arg, *centroid))
822 return -1;
823 else
824 return 1;
825 }
826 else
827 {
828 /*------
829 * The argument is a lower bound, we are searching for adjacent upper
830 * bounds. A matching adjacent upper bound must be *smaller* than the
831 * argument, but only just.
832 *
833 * ARGUMENT CENTROID CMP ADJ
834 * [500, ...) [..., 499) > (N) [..., 500) is to the right
835 * [500, ...) [..., 500) > (Y) [..., 500) is to the right
836 * [500, ...) [..., 501) = (N) [..., 500) is to the left
837 * [500, ...) [..., 502) < (N) [..., 500) is to the left
838 *
839 * We must search left when the argument is smaller than or equal to
840 * the centroid. Otherwise search right. We don't need to check
841 * whether the argument is adjacent with the centroid, because it
842 * doesn't matter.
843 *------
844 */
845 if (cmp <= 0)
846 return -1;
847 else
848 return 1;
849 }
850}
851
852/*----------
853 * adjacent_inner_consistent
854 *
855 * Like adjacent_cmp_bounds, but also takes into account the previous
856 * level's centroid. We might've traversed left (or right) at the previous
857 * node, in search for ranges adjacent to the other bound, even though we
858 * already ruled out the possibility for any matches in that direction for
859 * this bound. By comparing the argument with the previous centroid, and
860 * the previous centroid with the current centroid, we can determine which
861 * direction we should've moved in at previous level, and which direction we
862 * actually moved.
863 *
864 * If there can be any matches to the left, returns -1. If to the right,
865 * returns 1. If there can be no matches below this centroid, because we
866 * already ruled them out at the previous level, returns 0.
867 *
868 * XXX: Comparing just the previous and current level isn't foolproof; we
869 * might still search some branches unnecessarily. For example, imagine that
870 * we are searching for value 15, and we traverse the following centroids
871 * (only considering one bound for the moment):
872 *
873 * Level 1: 20
874 * Level 2: 50
875 * Level 3: 25
876 *
877 * At this point, previous centroid is 50, current centroid is 25, and the
878 * target value is to the left. But because we already moved right from
879 * centroid 20 to 50 in the first level, there cannot be any values < 20 in
880 * the current branch. But we don't know that just by looking at the previous
881 * and current centroid, so we traverse left, unnecessarily. The reason we are
882 * down this branch is that we're searching for matches with the *other*
883 * bound. If we kept track of which bound we are searching for explicitly,
884 * instead of deducing that from the previous and current centroid, we could
885 * avoid some unnecessary work.
886 *----------
887 */
888static int
890 const RangeBound *centroid, const RangeBound *prev)
891{
892 if (prev)
893 {
894 int prevcmp;
895 int cmp;
896
897 /*
898 * Which direction were we supposed to traverse at previous level,
899 * left or right?
900 */
901 prevcmp = adjacent_cmp_bounds(typcache, arg, prev);
902
903 /* and which direction did we actually go? */
904 cmp = range_cmp_bounds(typcache, centroid, prev);
905
906 /* if the two don't agree, there's nothing to see here */
907 if ((prevcmp < 0 && cmp >= 0) || (prevcmp > 0 && cmp < 0))
908 return 0;
909 }
910
911 return adjacent_cmp_bounds(typcache, arg, centroid);
912}
913
914/*
915 * SP-GiST consistent function for leaf nodes: check leaf value against query
916 * using corresponding function.
917 */
918Datum
920{
924 TypeCacheEntry *typcache;
925 bool res;
926 int i;
927
928 /* all tests are exact */
929 out->recheck = false;
930
931 /* leafDatum is what it is... */
932 out->leafValue = in->leafDatum;
933
934 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(leafRange));
935
936 /* Perform the required comparison(s) */
937 res = true;
938 for (i = 0; i < in->nkeys; i++)
939 {
941
942 /* Call the function corresponding to the scan strategy */
943 switch (in->scankeys[i].sk_strategy)
944 {
946 res = range_before_internal(typcache, leafRange,
948 break;
950 res = range_overleft_internal(typcache, leafRange,
952 break;
954 res = range_overlaps_internal(typcache, leafRange,
956 break;
958 res = range_overright_internal(typcache, leafRange,
960 break;
961 case RANGESTRAT_AFTER:
962 res = range_after_internal(typcache, leafRange,
964 break;
966 res = range_adjacent_internal(typcache, leafRange,
968 break;
970 res = range_contains_internal(typcache, leafRange,
972 break;
976 break;
979 keyDatum);
980 break;
981 case RANGESTRAT_EQ:
982 res = range_eq_internal(typcache, leafRange,
984 break;
985 default:
986 elog(ERROR, "unrecognized range strategy: %d",
987 in->scankeys[i].sk_strategy);
988 break;
989 }
990
991 /*
992 * If leaf datum doesn't match to a query key, no need to check
993 * subsequent keys.
994 */
995 if (!res)
996 break;
997 }
998
999 PG_RETURN_BOOL(res);
1000}
#define Assert(condition)
Definition c.h:873
int16_t int16
Definition c.h:541
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define PG_RETURN_VOID()
Definition fmgr.h:350
#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
int b
Definition isn.c:74
int a
Definition isn.c:73
int j
Definition isn.c:78
int i
Definition isn.c:77
Datum lower(PG_FUNCTION_ARGS)
Datum upper(PG_FUNCTION_ARGS)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
void * arg
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
static int fb(int x)
int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:706
bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
Definition rangetypes.c:761
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:845
bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:668
bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:932
bool range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val)
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:577
bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:802
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:891
#define RANGESTRAT_OVERLAPS
Definition rangetypes.h:98
#define RANGESTRAT_AFTER
Definition rangetypes.h:100
static RangeType * DatumGetRangeTypeP(Datum X)
Definition rangetypes.h:73
#define RANGESTRAT_BEFORE
Definition rangetypes.h:96
#define RANGESTRAT_OVERRIGHT
Definition rangetypes.h:99
#define RANGESTRAT_OVERLEFT
Definition rangetypes.h:97
#define RANGESTRAT_CONTAINED_BY
Definition rangetypes.h:103
#define RangeIsEmpty(r)
Definition rangetypes.h:55
static Datum RangeTypePGetDatum(const RangeType *X)
Definition rangetypes.h:85
#define RANGESTRAT_EQ
Definition rangetypes.h:105
#define RANGESTRAT_ADJACENT
Definition rangetypes.h:101
#define RANGESTRAT_CONTAINS_ELEM
Definition rangetypes.h:104
#define RANGESTRAT_CONTAINS
Definition rangetypes.h:102
#define RangeTypeGetOid(r)
Definition rangetypes.h:35
static int adjacent_inner_consistent(TypeCacheEntry *typcache, const RangeBound *arg, const RangeBound *centroid, const RangeBound *prev)
Datum spg_range_quad_config(PG_FUNCTION_ARGS)
Datum spg_range_quad_leaf_consistent(PG_FUNCTION_ARGS)
Datum spg_range_quad_picksplit(PG_FUNCTION_ARGS)
static int adjacent_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *arg, const RangeBound *centroid)
Datum spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
Datum spg_range_quad_choose(PG_FUNCTION_ARGS)
static int bound_cmp(const void *a, const void *b, void *arg)
static int16 getQuadrant(TypeCacheEntry *typcache, const RangeType *centroid, const RangeType *tst)
static int cmp(const chr *x, const chr *y, size_t len)
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
@ spgMatchNode
Definition spgist.h:69
uint16 StrategyNumber
Definition stratnum.h:22
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
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
bool longValuesOK
Definition spgist.h:47
bool canReturnData
Definition spgist.h:46
Oid labelType
Definition spgist.h:44
Oid prefixType
Definition spgist.h:43
void * traversalValue
Definition spgist.h:141
MemoryContext traversalMemoryContext
Definition spgist.h:142
void ** traversalValues
Definition spgist.h:160
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