diff options
Diffstat (limited to 'src/backend/access/spgist/spgquadtreeproc.c')
-rw-r--r-- | src/backend/access/spgist/spgquadtreeproc.c | 240 |
1 files changed, 118 insertions, 122 deletions
diff --git a/src/backend/access/spgist/spgquadtreeproc.c b/src/backend/access/spgist/spgquadtreeproc.c index 231749e992d..10fafe58643 100644 --- a/src/backend/access/spgist/spgquadtreeproc.c +++ b/src/backend/access/spgist/spgquadtreeproc.c @@ -190,45 +190,21 @@ spg_quad_picksplit(PG_FUNCTION_ARGS) } -/* Subroutine to fill out->nodeNumbers[] for spg_quad_inner_consistent */ -static void -setNodes(spgInnerConsistentOut *out, bool isAll, int first, int second) -{ - if (isAll) - { - out->nNodes = 4; - out->nodeNumbers[0] = 0; - out->nodeNumbers[1] = 1; - out->nodeNumbers[2] = 2; - out->nodeNumbers[3] = 3; - } - else - { - out->nNodes = 2; - out->nodeNumbers[0] = first - 1; - out->nodeNumbers[1] = second - 1; - } -} - - Datum spg_quad_inner_consistent(PG_FUNCTION_ARGS) { spgInnerConsistentIn *in = (spgInnerConsistentIn *) PG_GETARG_POINTER(0); spgInnerConsistentOut *out = (spgInnerConsistentOut *) PG_GETARG_POINTER(1); - Point *query, - *centroid; - BOX *boxQuery; + Point *centroid; + int which; + int i; - query = DatumGetPointP(in->query); Assert(in->hasPrefix); centroid = DatumGetPointP(in->prefixDatum); if (in->allTheSame) { /* Report that all nodes should be visited */ - int i; - out->nNodes = in->nNodes; out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes); for (i = 0; i < in->nNodes; i++) @@ -237,76 +213,86 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS) } Assert(in->nNodes == 4); - out->nodeNumbers = (int *) palloc(sizeof(int) * 4); - switch (in->strategy) + /* "which" is a bitmask of quadrants that satisfy all constraints */ + which = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4); + + for (i = 0; i < in->nkeys; i++) { - case RTLeftStrategyNumber: - setNodes(out, SPTEST(point_left, centroid, query), 3, 4); - break; - case RTRightStrategyNumber: - setNodes(out, SPTEST(point_right, centroid, query), 1, 2); - break; - case RTSameStrategyNumber: - out->nNodes = 1; - out->nodeNumbers[0] = getQuadrant(centroid, query) - 1; - break; - case RTBelowStrategyNumber: - setNodes(out, SPTEST(point_below, centroid, query), 2, 3); - break; - case RTAboveStrategyNumber: - setNodes(out, SPTEST(point_above, centroid, query), 1, 4); - break; - case RTContainedByStrategyNumber: - - /* - * For this operator, the query is a box not a point. We cheat to - * the extent of assuming that DatumGetPointP won't do anything - * that would be bad for a pointer-to-box. - */ - boxQuery = DatumGetBoxP(in->query); - - if (DatumGetBool(DirectFunctionCall2(box_contain_pt, - PointerGetDatum(boxQuery), - PointerGetDatum(centroid)))) - { - /* centroid is in box, so descend to all quadrants */ - setNodes(out, true, 0, 0); - } - else - { - /* identify quadrant(s) containing all corners of box */ - Point p; - int i, - r = 0; - - p = boxQuery->low; - r |= 1 << (getQuadrant(centroid, &p) - 1); - - p.y = boxQuery->high.y; - r |= 1 << (getQuadrant(centroid, &p) - 1); - - p = boxQuery->high; - r |= 1 << (getQuadrant(centroid, &p) - 1); - - p.x = boxQuery->low.x; - r |= 1 << (getQuadrant(centroid, &p) - 1); - - /* we must descend into those quadrant(s) */ - out->nNodes = 0; - for (i = 0; i < 4; i++) + Point *query = DatumGetPointP(in->scankeys[i].sk_argument); + BOX *boxQuery; + + switch (in->scankeys[i].sk_strategy) + { + case RTLeftStrategyNumber: + if (SPTEST(point_right, centroid, query)) + which &= (1 << 3) | (1 << 4); + break; + case RTRightStrategyNumber: + if (SPTEST(point_left, centroid, query)) + which &= (1 << 1) | (1 << 2); + break; + case RTSameStrategyNumber: + which &= (1 << getQuadrant(centroid, query)); + break; + case RTBelowStrategyNumber: + if (SPTEST(point_above, centroid, query)) + which &= (1 << 2) | (1 << 3); + break; + case RTAboveStrategyNumber: + if (SPTEST(point_below, centroid, query)) + which &= (1 << 1) | (1 << 4); + break; + case RTContainedByStrategyNumber: + + /* + * For this operator, the query is a box not a point. We + * cheat to the extent of assuming that DatumGetPointP won't + * do anything that would be bad for a pointer-to-box. + */ + boxQuery = DatumGetBoxP(in->scankeys[i].sk_argument); + + if (DatumGetBool(DirectFunctionCall2(box_contain_pt, + PointerGetDatum(boxQuery), + PointerGetDatum(centroid)))) { - if (r & (1 << i)) - { - out->nodeNumbers[out->nNodes] = i; - out->nNodes++; - } + /* centroid is in box, so all quadrants are OK */ } - } - break; - default: - elog(ERROR, "unrecognized strategy number: %d", in->strategy); - break; + else + { + /* identify quadrant(s) containing all corners of box */ + Point p; + int r = 0; + + p = boxQuery->low; + r |= 1 << getQuadrant(centroid, &p); + p.y = boxQuery->high.y; + r |= 1 << getQuadrant(centroid, &p); + p = boxQuery->high; + r |= 1 << getQuadrant(centroid, &p); + p.x = boxQuery->low.x; + r |= 1 << getQuadrant(centroid, &p); + + which &= r; + } + break; + default: + elog(ERROR, "unrecognized strategy number: %d", + in->scankeys[i].sk_strategy); + break; + } + + if (which == 0) + break; /* no need to consider remaining conditions */ + } + + /* We must descend into the quadrant(s) identified by which */ + out->nodeNumbers = (int *) palloc(sizeof(int) * 4); + out->nNodes = 0; + for (i = 1; i <= 4; i++) + { + if (which & (1 << i)) + out->nodeNumbers[out->nNodes++] = i - 1; } PG_RETURN_VOID(); @@ -318,9 +304,9 @@ spg_quad_leaf_consistent(PG_FUNCTION_ARGS) { spgLeafConsistentIn *in = (spgLeafConsistentIn *) PG_GETARG_POINTER(0); spgLeafConsistentOut *out = (spgLeafConsistentOut *) PG_GETARG_POINTER(1); - Point *query = DatumGetPointP(in->query); Point *datum = DatumGetPointP(in->leafDatum); bool res; + int i; /* all tests are exact */ out->recheck = false; @@ -328,35 +314,45 @@ spg_quad_leaf_consistent(PG_FUNCTION_ARGS) /* leafDatum is what it is... */ out->leafValue = in->leafDatum; - switch (in->strategy) + /* Perform the required comparison(s) */ + res = true; + for (i = 0; i < in->nkeys; i++) { - case RTLeftStrategyNumber: - res = SPTEST(point_left, datum, query); - break; - case RTRightStrategyNumber: - res = SPTEST(point_right, datum, query); - break; - case RTSameStrategyNumber: - res = SPTEST(point_eq, datum, query); - break; - case RTBelowStrategyNumber: - res = SPTEST(point_below, datum, query); - break; - case RTAboveStrategyNumber: - res = SPTEST(point_above, datum, query); - break; - case RTContainedByStrategyNumber: - - /* - * For this operator, the query is a box not a point. We cheat to - * the extent of assuming that DatumGetPointP won't do anything - * that would be bad for a pointer-to-box. - */ - res = SPTEST(box_contain_pt, query, datum); - break; - default: - elog(ERROR, "unrecognized strategy number: %d", in->strategy); - res = false; + Point *query = DatumGetPointP(in->scankeys[i].sk_argument); + + switch (in->scankeys[i].sk_strategy) + { + case RTLeftStrategyNumber: + res = SPTEST(point_left, datum, query); + break; + case RTRightStrategyNumber: + res = SPTEST(point_right, datum, query); + break; + case RTSameStrategyNumber: + res = SPTEST(point_eq, datum, query); + break; + case RTBelowStrategyNumber: + res = SPTEST(point_below, datum, query); + break; + case RTAboveStrategyNumber: + res = SPTEST(point_above, datum, query); + break; + case RTContainedByStrategyNumber: + + /* + * For this operator, the query is a box not a point. We + * cheat to the extent of assuming that DatumGetPointP won't + * do anything that would be bad for a pointer-to-box. + */ + res = SPTEST(box_contain_pt, query, datum); + break; + default: + elog(ERROR, "unrecognized strategy number: %d", + in->scankeys[i].sk_strategy); + break; + } + + if (!res) break; } |