Header And Logo

PostgreSQL
| The world's most advanced open source database.

rangetypes_spgist.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * rangetypes_spgist.c
00004  *    implementation of quad tree over ranges mapped to 2d-points for SP-GiST.
00005  *
00006  * Quad tree is a data structure similar to a binary tree, but is adapted to
00007  * 2d data. Each inner node of a quad tree contains a point (centroid) which
00008  * divides the 2d-space into 4 quadrants. Each quadrant is associated with a
00009  * child node.
00010  *
00011  * Ranges are mapped to 2d-points so that the lower bound is one dimension,
00012  * and the upper bound is another. By convention, we visualize the lower bound
00013  * to be the horizontal axis, and upper bound the vertical axis.
00014  *
00015  * One quirk with this mapping is the handling of empty ranges. An empty range
00016  * doesn't have lower and upper bounds, so it cannot be mapped to 2d space in
00017  * a straightforward way. To cope with that, the root node can have a 5th
00018  * quadrant, which is reserved for empty ranges. Furthermore, there can be
00019  * inner nodes in the tree with no centroid. They contain only two child nodes,
00020  * one for empty ranges and another for non-empty ones. Such a node can appear
00021  * as the root node, or in the tree under the 5th child of the root node (in
00022  * which case it will only contain empty nodes).
00023  *
00024  * The SP-GiST picksplit function uses medians along both axes as the centroid.
00025  * This implementation only uses the comparison function of the range element
00026  * datatype, therefore it works for any range type.
00027  *
00028  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00029  * Portions Copyright (c) 1994, Regents of the University of California
00030  *
00031  * IDENTIFICATION
00032  *          src/backend/utils/adt/rangetypes_spgist.c
00033  *
00034  *-------------------------------------------------------------------------
00035  */
00036 
00037 #include "postgres.h"
00038 
00039 #include "access/spgist.h"
00040 #include "access/skey.h"
00041 #include "catalog/pg_type.h"
00042 #include "utils/builtins.h"
00043 #include "utils/datum.h"
00044 #include "utils/rangetypes.h"
00045 
00046 /* SP-GiST API functions */
00047 Datum       spg_range_quad_config(PG_FUNCTION_ARGS);
00048 Datum       spg_range_quad_choose(PG_FUNCTION_ARGS);
00049 Datum       spg_range_quad_picksplit(PG_FUNCTION_ARGS);
00050 Datum       spg_range_quad_inner_consistent(PG_FUNCTION_ARGS);
00051 Datum       spg_range_quad_leaf_consistent(PG_FUNCTION_ARGS);
00052 
00053 static int16 getQuadrant(TypeCacheEntry *typcache, RangeType *centroid,
00054             RangeType *tst);
00055 static int  bound_cmp(const void *a, const void *b, void *arg);
00056 
00057 /*
00058  * SP-GiST 'config' interface function.
00059  */
00060 Datum
00061 spg_range_quad_config(PG_FUNCTION_ARGS)
00062 {
00063     /* spgConfigIn *cfgin = (spgConfigIn *) PG_GETARG_POINTER(0); */
00064     spgConfigOut *cfg = (spgConfigOut *) PG_GETARG_POINTER(1);
00065 
00066     cfg->prefixType = ANYRANGEOID;
00067     cfg->labelType = VOIDOID;   /* we don't need node labels */
00068     cfg->canReturnData = true;
00069     cfg->longValuesOK = false;
00070     PG_RETURN_VOID();
00071 }
00072 
00073 /*----------
00074  * Determine which quadrant a 2d-mapped range falls into, relative to the
00075  * centroid.
00076  *
00077  * Quadrants are numbered like this:
00078  *
00079  *   4  |  1
00080  *  ----+----
00081  *   3  |  2
00082  *
00083  * Where the lower bound of range is the horizontal axis and upper bound the
00084  * vertical axis.
00085  *
00086  * Ranges on one of the axes are taken to lie in the quadrant with higher value
00087  * along perpendicular axis. That is, a value on the horizontal axis is taken
00088  * to belong to quadrant 1 or 4, and a value on the vertical axis is taken to
00089  * belong to quadrant 1 or 2. A range equal to centroid is taken to lie in
00090  * quadrant 1.
00091  *
00092  * Empty ranges are taken to lie in the special quadrant 5.
00093  *----------
00094  */
00095 static int16
00096 getQuadrant(TypeCacheEntry *typcache, RangeType *centroid, RangeType *tst)
00097 {
00098     RangeBound  centroidLower,
00099                 centroidUpper;
00100     bool        centroidEmpty;
00101     RangeBound  lower,
00102                 upper;
00103     bool        empty;
00104 
00105     range_deserialize(typcache, centroid, &centroidLower, &centroidUpper,
00106                       &centroidEmpty);
00107     range_deserialize(typcache, tst, &lower, &upper, &empty);
00108 
00109     if (empty)
00110         return 5;
00111 
00112     if (range_cmp_bounds(typcache, &lower, &centroidLower) >= 0)
00113     {
00114         if (range_cmp_bounds(typcache, &upper, &centroidUpper) >= 0)
00115             return 1;
00116         else
00117             return 2;
00118     }
00119     else
00120     {
00121         if (range_cmp_bounds(typcache, &upper, &centroidUpper) >= 0)
00122             return 4;
00123         else
00124             return 3;
00125     }
00126 }
00127 
00128 /*
00129  * Choose SP-GiST function: choose path for addition of new range.
00130  */
00131 Datum
00132 spg_range_quad_choose(PG_FUNCTION_ARGS)
00133 {
00134     spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
00135     spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
00136     RangeType  *inRange = DatumGetRangeType(in->datum),
00137                *centroid;
00138     int16       quadrant;
00139     TypeCacheEntry *typcache;
00140 
00141     if (in->allTheSame)
00142     {
00143         out->resultType = spgMatchNode;
00144         /* nodeN will be set by core */
00145         out->result.matchNode.levelAdd = 0;
00146         out->result.matchNode.restDatum = RangeTypeGetDatum(inRange);
00147         PG_RETURN_VOID();
00148     }
00149 
00150     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(inRange));
00151 
00152     /*
00153      * A node with no centroid divides ranges purely on whether they're empty
00154      * or not. All empty ranges go to child node 0, all non-empty ranges go
00155      * to node 1.
00156      */
00157     if (!in->hasPrefix)
00158     {
00159         out->resultType = spgMatchNode;
00160         if (RangeIsEmpty(inRange))
00161             out->result.matchNode.nodeN = 0;
00162         else
00163             out->result.matchNode.nodeN = 1;
00164         out->result.matchNode.levelAdd = 1;
00165         out->result.matchNode.restDatum = RangeTypeGetDatum(inRange);
00166         PG_RETURN_VOID();
00167     }
00168 
00169     centroid = DatumGetRangeType(in->prefixDatum);
00170     quadrant = getQuadrant(typcache, centroid, inRange);
00171 
00172     Assert(quadrant <= in->nNodes);
00173 
00174     /* Select node matching to quadrant number */
00175     out->resultType = spgMatchNode;
00176     out->result.matchNode.nodeN = quadrant - 1;
00177     out->result.matchNode.levelAdd = 1;
00178     out->result.matchNode.restDatum = RangeTypeGetDatum(inRange);
00179 
00180     PG_RETURN_VOID();
00181 }
00182 
00183 /*
00184  * Bound comparison for sorting.
00185  */
00186 static int
00187 bound_cmp(const void *a, const void *b, void *arg)
00188 {
00189     RangeBound *ba = (RangeBound *) a;
00190     RangeBound *bb = (RangeBound *) b;
00191     TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
00192 
00193     return range_cmp_bounds(typcache, ba, bb);
00194 }
00195 
00196 /*
00197  * Picksplit SP-GiST function: split ranges into nodes. Select "centroid"
00198  * range and distribute ranges according to quadrants.
00199  */
00200 Datum
00201 spg_range_quad_picksplit(PG_FUNCTION_ARGS)
00202 {
00203     spgPickSplitIn *in = (spgPickSplitIn *) PG_GETARG_POINTER(0);
00204     spgPickSplitOut *out = (spgPickSplitOut *) PG_GETARG_POINTER(1);
00205     int         i;
00206     int         j;
00207     int         nonEmptyCount;
00208     RangeType  *centroid;
00209     bool        empty;
00210     TypeCacheEntry *typcache;
00211 
00212     /* Use the median values of lower and upper bounds as the centroid range */
00213     RangeBound *lowerBounds,
00214                *upperBounds;
00215 
00216     typcache = range_get_typcache(fcinfo,
00217                           RangeTypeGetOid(DatumGetRangeType(in->datums[0])));
00218 
00219     /* Allocate memory for bounds */
00220     lowerBounds = palloc(sizeof(RangeBound) * in->nTuples);
00221     upperBounds = palloc(sizeof(RangeBound) * in->nTuples);
00222     j = 0;
00223 
00224     /* Deserialize bounds of ranges, count non-empty ranges */
00225     for (i = 0; i < in->nTuples; i++)
00226     {
00227         range_deserialize(typcache, DatumGetRangeType(in->datums[i]),
00228                           &lowerBounds[j], &upperBounds[j], &empty);
00229         if (!empty)
00230             j++;
00231     }
00232     nonEmptyCount = j;
00233 
00234     /*
00235      * All the ranges are empty. The best we can do is to construct an inner
00236      * node with no centroid, and put all ranges into node 0. If non-empty
00237      * ranges are added later, they will be routed to node 1.
00238      */
00239     if (nonEmptyCount == 0)
00240     {
00241         out->nNodes = 2;
00242         out->hasPrefix = false;
00243         /* Prefix is empty */
00244         out->prefixDatum = PointerGetDatum(NULL);
00245         out->nodeLabels = NULL;
00246 
00247         out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
00248         out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
00249 
00250         /* Place all ranges into node 0 */
00251         for (i = 0; i < in->nTuples; i++)
00252         {
00253             RangeType  *range = DatumGetRangeType(in->datums[i]);
00254 
00255             out->leafTupleDatums[i] = RangeTypeGetDatum(range);
00256             out->mapTuplesToNodes[i] = 0;
00257         }
00258         PG_RETURN_VOID();
00259     }
00260 
00261     /* Sort range bounds in order to find medians */
00262     qsort_arg(lowerBounds, nonEmptyCount, sizeof(RangeBound),
00263               bound_cmp, typcache);
00264     qsort_arg(upperBounds, nonEmptyCount, sizeof(RangeBound),
00265               bound_cmp, typcache);
00266 
00267     /* Construct "centroid" range from medians of lower and upper bounds */
00268     centroid = range_serialize(typcache, &lowerBounds[nonEmptyCount / 2],
00269                                &upperBounds[nonEmptyCount / 2], false);
00270     out->hasPrefix = true;
00271     out->prefixDatum = RangeTypeGetDatum(centroid);
00272 
00273     /* Create node for empty ranges only if it is a root node */
00274     out->nNodes = (in->level == 0) ? 5 : 4;
00275     out->nodeLabels = NULL;     /* we don't need node labels */
00276 
00277     out->mapTuplesToNodes = palloc(sizeof(int) * in->nTuples);
00278     out->leafTupleDatums = palloc(sizeof(Datum) * in->nTuples);
00279 
00280     /*
00281      * Assign ranges to corresponding nodes according to quadrants relative to
00282      * "centroid" range.
00283      */
00284     for (i = 0; i < in->nTuples; i++)
00285     {
00286         RangeType  *range = DatumGetRangeType(in->datums[i]);
00287         int16       quadrant = getQuadrant(typcache, centroid, range);
00288 
00289         out->leafTupleDatums[i] = RangeTypeGetDatum(range);
00290         out->mapTuplesToNodes[i] = quadrant - 1;
00291     }
00292 
00293     PG_RETURN_VOID();
00294 }
00295 
00296 /*
00297  * SP-GiST consistent function for inner nodes: check which nodes are
00298  * consistent with given set of queries.
00299  */
00300 Datum
00301 spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
00302 {
00303     spgInnerConsistentIn *in = (spgInnerConsistentIn *) PG_GETARG_POINTER(0);
00304     spgInnerConsistentOut *out = (spgInnerConsistentOut *) PG_GETARG_POINTER(1);
00305     int         which;
00306     int         i;
00307 
00308     /*
00309      * For adjacent search we need also previous centroid (if any) to improve
00310      * the precision of the consistent check. In this case needPrevious flag is
00311      * set and centroid is passed into reconstructedValues. This is not the
00312      * intended purpose of reconstructedValues (because we already have the
00313      * full value available at the leaf), but it's a convenient place to store
00314      * state while traversing the tree.
00315      */
00316     bool        needPrevious = false;
00317 
00318     if (in->allTheSame)
00319     {
00320         /* Report that all nodes should be visited */
00321         out->nNodes = in->nNodes;
00322         out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
00323         for (i = 0; i < in->nNodes; i++)
00324             out->nodeNumbers[i] = i;
00325         PG_RETURN_VOID();
00326     }
00327 
00328     if (!in->hasPrefix)
00329     {
00330         /*
00331          * No centroid on this inner node. Such a node has two child nodes,
00332          * the first for empty ranges, and the second for non-empty ones.
00333          */
00334         Assert(in->nNodes == 2);
00335 
00336         /*
00337          * Nth bit of which variable means that (N - 1)th node should be
00338          * visited. Initially all bits are set. Bits of nodes which should be
00339          * skipped will be unset.
00340          */
00341         which = (1 << 1) | (1 << 2);
00342         for (i = 0; i < in->nkeys; i++)
00343         {
00344             StrategyNumber strategy = in->scankeys[i].sk_strategy;
00345             bool        empty;
00346 
00347             /*
00348              * The only strategy when second argument of operator is not range
00349              * is RANGESTRAT_CONTAINS_ELEM.
00350              */
00351             if (strategy != RANGESTRAT_CONTAINS_ELEM)
00352                 empty = RangeIsEmpty(
00353                              DatumGetRangeType(in->scankeys[i].sk_argument));
00354             else
00355                 empty = false;
00356 
00357             switch (strategy)
00358             {
00359                 case RANGESTRAT_BEFORE:
00360                 case RANGESTRAT_OVERLEFT:
00361                 case RANGESTRAT_OVERLAPS:
00362                 case RANGESTRAT_OVERRIGHT:
00363                 case RANGESTRAT_AFTER:
00364                 case RANGESTRAT_ADJACENT:
00365                     /* These strategies return false if any argument is empty */
00366                     if (empty)
00367                         which = 0;
00368                     else
00369                         which &= (1 << 2);
00370                     break;
00371 
00372                 case RANGESTRAT_CONTAINS:
00373                     /*
00374                      * All ranges contain an empty range. Only non-empty ranges
00375                      * can contain a non-empty range.
00376                      */
00377                     if (!empty)
00378                         which &= (1 << 2);
00379                     break;
00380 
00381                 case RANGESTRAT_CONTAINED_BY:
00382                     /*
00383                      * Only an empty range is contained by an empty range. Both
00384                      * empty and non-empty ranges can be contained by a
00385                      * non-empty range.
00386                      */
00387                     if (empty)
00388                         which &= (1 << 1);
00389                     break;
00390 
00391                 case RANGESTRAT_CONTAINS_ELEM:
00392                     which &= (1 << 2);
00393                     break;
00394 
00395                 case RANGESTRAT_EQ:
00396                     if (empty)
00397                         which &= (1 << 1);
00398                     else
00399                         which &= (1 << 2);
00400                     break;
00401 
00402                 default:
00403                     elog(ERROR, "unrecognized range strategy: %d", strategy);
00404                     break;
00405             }
00406             if (which == 0)
00407                 break;          /* no need to consider remaining conditions */
00408         }
00409     }
00410     else
00411     {
00412         RangeBound  centroidLower,
00413                     centroidUpper;
00414         bool        centroidEmpty;
00415         TypeCacheEntry *typcache;
00416         RangeType  *centroid;
00417 
00418         /* This node has a centroid. Fetch it. */
00419         centroid = DatumGetRangeType(in->prefixDatum);
00420         typcache = range_get_typcache(fcinfo,
00421                                RangeTypeGetOid(DatumGetRangeType(centroid)));
00422         range_deserialize(typcache, centroid, &centroidLower, &centroidUpper,
00423                           &centroidEmpty);
00424 
00425         Assert(in->nNodes == 4 || in->nNodes == 5);
00426 
00427         /*
00428          * Nth bit of which variable means that (N - 1)th node (Nth quadrant)
00429          * should be visited. Initially all bits are set. Bits of nodes which
00430          * can be skipped will be unset.
00431          */
00432         which = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
00433 
00434         for (i = 0; i < in->nkeys; i++)
00435         {
00436             StrategyNumber strategy;
00437             RangeBound  lower,
00438                         upper;
00439             bool        empty;
00440             RangeType  *range = NULL;
00441             /* Restrictions on range bounds according to scan strategy */
00442             RangeBound *minLower = NULL,
00443                        *maxLower = NULL,
00444                        *minUpper = NULL,
00445                        *maxUpper = NULL;
00446             /* Are the restrictions on range bounds inclusive? */
00447             bool        inclusive = true;
00448             bool        strictEmpty = true;
00449             int         cmp,
00450                         which1,
00451                         which2;
00452 
00453             strategy = in->scankeys[i].sk_strategy;
00454 
00455             /*
00456              * RANGESTRAT_CONTAINS_ELEM is just like RANGESTRAT_CONTAINS, but
00457              * the argument is a single element. Expand the single element to
00458              * a range containing only the element, and treat it like
00459              * RANGESTRAT_CONTAINS.
00460              */
00461             if (strategy == RANGESTRAT_CONTAINS_ELEM)
00462             {
00463                 lower.inclusive = true;
00464                 lower.infinite = false;
00465                 lower.lower = true;
00466                 lower.val = in->scankeys[i].sk_argument;
00467 
00468                 upper.inclusive = true;
00469                 upper.infinite = false;
00470                 upper.lower = false;
00471                 upper.val = in->scankeys[i].sk_argument;
00472 
00473                 empty = false;
00474 
00475                 strategy = RANGESTRAT_CONTAINS;
00476             }
00477             else
00478             {
00479                 range = DatumGetRangeType(in->scankeys[i].sk_argument);
00480                 range_deserialize(typcache, range, &lower, &upper, &empty);
00481             }
00482 
00483             /*
00484              * Most strategies are handled by forming a bounding box from the
00485              * search key, defined by a minLower, maxLower, minUpper, maxUpper.
00486              * Some modify 'which' directly, to specify exactly which quadrants
00487              * need to be visited.
00488              *
00489              * For most strategies, nothing matches an empty search key, and
00490              * an empty range never matches a non-empty key. If a strategy
00491              * does not behave like that wrt. empty ranges, set strictEmpty to
00492              * false.
00493              */
00494             switch (strategy)
00495             {
00496                 case RANGESTRAT_BEFORE:
00497                     /*
00498                      * Range A is before range B if upper bound of A is lower
00499                      * than lower bound of B.
00500                      */
00501                     maxUpper = &lower;
00502                     inclusive = false;
00503                     break;
00504 
00505                 case RANGESTRAT_OVERLEFT:
00506                     /*
00507                      * Range A is overleft to range B if upper bound of A is
00508                      * less or equal to upper bound of B.
00509                      */
00510                     maxUpper = &upper;
00511                     break;
00512 
00513                 case RANGESTRAT_OVERLAPS:
00514                     /*
00515                      * Non-empty ranges overlap, if lower bound of each range
00516                      * is lower or equal to upper bound of the other range.
00517                      */
00518                     maxLower = &upper;
00519                     minUpper = &lower;
00520                     break;
00521 
00522                 case RANGESTRAT_OVERRIGHT:
00523                     /*
00524                      * Range A is overright to range B if lower bound of A is
00525                      * greater or equal to lower bound of B.
00526                      */
00527                     minLower = &lower;
00528                     break;
00529 
00530                 case RANGESTRAT_AFTER:
00531                     /*
00532                      * Range A is after range B if lower bound of A is greater
00533                      * than upper bound of B.
00534                      */
00535                     minLower = &upper;
00536                     inclusive = false;
00537                     break;
00538 
00539                 case RANGESTRAT_ADJACENT:
00540                     if (empty)
00541                         break;              /* Skip to strictEmpty check. */
00542 
00543                     /*
00544                      * which1 is bitmask for possibility to be adjacent with
00545                      * lower bound of argument. which2 is bitmask for
00546                      * possibility to be adjacent with upper bound of argument.
00547                      */
00548                     which1 = which2 = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
00549 
00550                     /*
00551                      * Previously selected quadrant could exclude possibility
00552                      * for lower or upper bounds to be adjacent. Deserialize
00553                      * previous centroid range if present for checking this.
00554                      */
00555                     if (in->reconstructedValue != (Datum) 0)
00556                     {
00557                         RangeType  *prevCentroid;
00558                         RangeBound  prevLower,
00559                                     prevUpper;
00560                         bool        prevEmpty;
00561                         int         cmp1,
00562                                     cmp2;
00563 
00564                         prevCentroid = DatumGetRangeType(in->reconstructedValue);
00565                         range_deserialize(typcache, prevCentroid,
00566                                           &prevLower, &prevUpper, &prevEmpty);
00567 
00568                         /*
00569                          * Check if lower bound of argument is not in a
00570                          * quadrant we visited in the previous step.
00571                          */
00572                         cmp1 = range_cmp_bounds(typcache, &lower, &prevUpper);
00573                         cmp2 = range_cmp_bounds(typcache, &centroidUpper,
00574                                                 &prevUpper);
00575                         if ((cmp2 < 0 && cmp1 > 0) || (cmp2 > 0 && cmp1 < 0))
00576                             which1 = 0;
00577 
00578                         /*
00579                          * Check if upper bound of argument is not in a
00580                          * quadrant we visited in the previous step.
00581                          */
00582                         cmp1 = range_cmp_bounds(typcache, &upper, &prevLower);
00583                         cmp2 = range_cmp_bounds(typcache, &centroidLower,
00584                                                 &prevLower);
00585                         if ((cmp2 < 0 && cmp1 > 0) || (cmp2 > 0 && cmp1 < 0))
00586                             which2 = 0;
00587                     }
00588 
00589                     if (which1)
00590                     {
00591                         /*
00592                          * For a range's upper bound to be adjacent to the
00593                          * argument's lower bound, it will be found along the
00594                          * line adjacent to (and just below) Y=lower.
00595                          * Therefore, if the argument's lower bound is less
00596                          * than the centroid's upper bound, the line falls in
00597                          * quadrants 2 and 3; if greater, the line falls in
00598                          * quadrants 1 and 4.
00599                          *
00600                          * The above is true even when the argument's lower
00601                          * bound is greater and adjacent to the centroid's
00602                          * upper bound. If the argument's lower bound is
00603                          * greater than the centroid's upper bound, then the
00604                          * lowest value that an adjacent range could have is
00605                          * that of the centroid's upper bound, which still
00606                          * falls in quadrants 1 and 4.
00607                          *
00608                          * In the edge case, where the argument's lower bound
00609                          * is equal to the cetroid's upper bound, there may be
00610                          * adjacent ranges in any quadrant.
00611                          */
00612                         cmp = range_cmp_bounds(typcache, &lower,
00613                                                &centroidUpper);
00614                         if (cmp < 0)
00615                             which1 &= (1 << 2) | (1 << 3);
00616                         else if (cmp > 0)
00617                             which1 &= (1 << 1) | (1 << 4);
00618                     }
00619 
00620                     if (which2)
00621                     {
00622                         /*
00623                          * For a range's lower bound to be adjacent to the
00624                          * argument's upper bound, it will be found along the
00625                          * line adjacent to (and just right of)
00626                          * X=upper. Therefore, if the argument's upper bound is
00627                          * less than (and not adjacent to) the centroid's upper
00628                          * bound, the line falls in quadrants 3 and 4; if
00629                          * greater or equal to, the line falls in quadrants 1
00630                          * and 2.
00631                          *
00632                          * The edge case is when the argument's upper bound is
00633                          * less than and adjacent to the centroid's lower
00634                          * bound. In that case, adjacent ranges may be in any
00635                          * quadrant.
00636                          */
00637                         cmp = range_cmp_bounds(typcache, &lower,
00638                                                &centroidUpper);
00639                         if (cmp < 0 &&
00640                             !bounds_adjacent(typcache, upper, centroidLower))
00641                             which1 &= (1 << 3) | (1 << 4);
00642                         else if (cmp > 0)
00643                             which1 &= (1 << 1) | (1 << 2);
00644                     }
00645 
00646                     which &= which1 | which2;
00647 
00648                     needPrevious = true;
00649                     break;
00650 
00651                 case RANGESTRAT_CONTAINS:
00652                     /*
00653                      * Non-empty range A contains non-empty range B if lower
00654                      * bound of A is lower or equal to lower bound of range B
00655                      * and upper bound of range A is greater or equal to upper
00656                      * bound of range A.
00657                      *
00658                      * All non-empty ranges contain an empty range.
00659                      */
00660                     strictEmpty = false;
00661                     if (!empty)
00662                     {
00663                         which &= (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
00664                         maxLower = &lower;
00665                         minUpper = &upper;
00666                     }
00667                     break;
00668 
00669                 case RANGESTRAT_CONTAINED_BY:
00670                     /* The opposite of contains. */
00671                     strictEmpty = false;
00672                     if (empty)
00673                     {
00674                         /* An empty range is only contained by an empty range */
00675                         which &= (1 << 5);
00676                     }
00677                     else
00678                     {
00679                         minLower = &lower;
00680                         maxUpper = &upper;
00681                     }
00682                     break;
00683 
00684                 case RANGESTRAT_EQ:
00685                     /*
00686                      * Equal range can be only in the same quadrant where
00687                      * argument would be placed to.
00688                      */
00689                     strictEmpty = false;
00690                     which &= (1 << getQuadrant(typcache, centroid, range));
00691                     break;
00692 
00693                 default:
00694                     elog(ERROR, "unrecognized range strategy: %d", strategy);
00695                     break;
00696             }
00697 
00698             if (strictEmpty)
00699             {
00700                 if (empty)
00701                 {
00702                     /* Scan key is empty, no branches are satisfying */
00703                     which = 0;
00704                     break;
00705                 }
00706                 else
00707                 {
00708                     /* Shouldn't visit tree branch with empty ranges */
00709                     which &= (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
00710                 }
00711             }
00712 
00713             /*
00714              * Using the bounding box, see which quadrants we have to descend
00715              * into.
00716              */
00717             if (minLower)
00718             {
00719                 /*
00720                  * If the centroid's lower bound is less than or equal to
00721                  * the minimum lower bound, anything in the 3rd and 4th
00722                  * quadrants will have an even smaller lower bound, and thus
00723                  * can't match.
00724                  */
00725                 if (range_cmp_bounds(typcache, &centroidLower, minLower) <= 0)
00726                     which &= (1 << 1) | (1 << 2) | (1 << 5);
00727             }
00728             if (maxLower)
00729             {
00730                 /*
00731                  * If the centroid's lower bound is greater than the maximum
00732                  * lower bound, anything in the 1st and 2nd quadrants will
00733                  * also have a greater than or equal lower bound, and thus
00734                  * can't match. If the centroid's lower bound is equal to
00735                  * the maximum lower bound, we can still exclude the 1st and
00736                  * 2nd quadrants if we're looking for a value strictly greater
00737                  * than the maximum.
00738                  */
00739                 int         cmp;
00740 
00741                 cmp = range_cmp_bounds(typcache, &centroidLower, maxLower);
00742                 if (cmp > 0 || (!inclusive && cmp == 0))
00743                     which &= (1 << 3) | (1 << 4) | (1 << 5);
00744             }
00745             if (minUpper)
00746             {
00747                 /*
00748                  * If the centroid's upper bound is less than or equal to
00749                  * the minimum upper bound, anything in the 2nd and 3rd
00750                  * quadrants will have an even smaller upper bound, and thus
00751                  * can't match.
00752                  */
00753                 if (range_cmp_bounds(typcache, &centroidUpper, minUpper) <= 0)
00754                     which &= (1 << 1) | (1 << 4) | (1 << 5);
00755             }
00756             if (maxUpper)
00757             {
00758                 /*
00759                  * If the centroid's upper bound is greater than the maximum
00760                  * upper bound, anything in the 1st and 4th quadrants will
00761                  * also have a greater than or equal upper bound, and thus
00762                  * can't match. If the centroid's upper bound is equal to
00763                  * the maximum upper bound, we can still exclude the 1st and
00764                  * 4th quadrants if we're looking for a value strictly greater
00765                  * than the maximum.
00766                  */
00767                 int         cmp;
00768 
00769                 cmp = range_cmp_bounds(typcache, &centroidUpper, maxUpper);
00770                 if (cmp > 0 || (!inclusive && cmp == 0))
00771                     which &= (1 << 2) | (1 << 3) | (1 << 5);
00772             }
00773 
00774             if (which == 0)
00775                 break;          /* no need to consider remaining conditions */
00776         }
00777     }
00778 
00779     /* We must descend into the quadrant(s) identified by 'which' */
00780     out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
00781     if (needPrevious)
00782         out->reconstructedValues = (Datum *) palloc(sizeof(Datum) * in->nNodes);
00783     out->nNodes = 0;
00784     for (i = 1; i <= in->nNodes; i++)
00785     {
00786         if (which & (1 << i))
00787         {
00788             /* Save previous prefix if needed */
00789             if (needPrevious)
00790                 out->reconstructedValues[out->nNodes] = in->prefixDatum;
00791             out->nodeNumbers[out->nNodes++] = i - 1;
00792         }
00793     }
00794 
00795     PG_RETURN_VOID();
00796 }
00797 
00798 /*
00799  * SP-GiST consistent function for leaf nodes: check leaf value against query
00800  * using corresponding function.
00801  */
00802 Datum
00803 spg_range_quad_leaf_consistent(PG_FUNCTION_ARGS)
00804 {
00805     spgLeafConsistentIn *in = (spgLeafConsistentIn *) PG_GETARG_POINTER(0);
00806     spgLeafConsistentOut *out = (spgLeafConsistentOut *) PG_GETARG_POINTER(1);
00807     RangeType  *leafRange = DatumGetRangeType(in->leafDatum);
00808     TypeCacheEntry *typcache;
00809     bool        res;
00810     int         i;
00811 
00812     /* all tests are exact */
00813     out->recheck = false;
00814 
00815     /* leafDatum is what it is... */
00816     out->leafValue = in->leafDatum;
00817 
00818     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(leafRange));
00819 
00820     /* Perform the required comparison(s) */
00821     res = true;
00822     for (i = 0; i < in->nkeys; i++)
00823     {
00824         Datum       keyDatum = in->scankeys[i].sk_argument;
00825 
00826         /* Call the function corresponding to the scan strategy */
00827         switch (in->scankeys[i].sk_strategy)
00828         {
00829             case RANGESTRAT_BEFORE:
00830                 res = range_before_internal(typcache, leafRange,
00831                                             DatumGetRangeType(keyDatum));
00832                 break;
00833             case RANGESTRAT_OVERLEFT:
00834                 res = range_overleft_internal(typcache, leafRange,
00835                                               DatumGetRangeType(keyDatum));
00836                 break;
00837             case RANGESTRAT_OVERLAPS:
00838                 res = range_overlaps_internal(typcache, leafRange,
00839                                               DatumGetRangeType(keyDatum));
00840                 break;
00841             case RANGESTRAT_OVERRIGHT:
00842                 res = range_overright_internal(typcache, leafRange,
00843                                                DatumGetRangeType(keyDatum));
00844                 break;
00845             case RANGESTRAT_AFTER:
00846                 res = range_after_internal(typcache, leafRange,
00847                                            DatumGetRangeType(keyDatum));
00848                 break;
00849             case RANGESTRAT_ADJACENT:
00850                 res = range_adjacent_internal(typcache, leafRange,
00851                                            DatumGetRangeType(keyDatum));
00852                 break;
00853             case RANGESTRAT_CONTAINS:
00854                 res = range_contains_internal(typcache, leafRange,
00855                                               DatumGetRangeType(keyDatum));
00856                 break;
00857             case RANGESTRAT_CONTAINED_BY:
00858                 res = range_contained_by_internal(typcache, leafRange,
00859                                                 DatumGetRangeType(keyDatum));
00860                 break;
00861             case RANGESTRAT_CONTAINS_ELEM:
00862                 res = range_contains_elem_internal(typcache, leafRange,
00863                                                    keyDatum);
00864                 break;
00865             case RANGESTRAT_EQ:
00866                 res = range_eq_internal(typcache, leafRange,
00867                                         DatumGetRangeType(keyDatum));
00868                 break;
00869             default:
00870                 elog(ERROR, "unrecognized range strategy: %d",
00871                      in->scankeys[i].sk_strategy);
00872                 break;
00873         }
00874 
00875         /*
00876          * If leaf datum doesn't match to a query key, no need to check
00877          * subsequent keys.
00878          */
00879         if (!res)
00880             break;
00881     }
00882 
00883     PG_RETURN_BOOL(res);
00884 }