Skip to content

Commit 9a09248

Browse files
committed
Fix rtree and contrib/rtree_gist search behavior for the 1-D box and
polygon operators (<<, &<, >>, &>). Per ideas originally put forward by andrew@supernews and later rediscovered by moi. This patch just fixes the existing opclasses, and does not add any new behavior as I proposed earlier; that can be sorted out later. In principle this could be back-patched, since it changes only search behavior and not system catalog entries nor rtree index contents. I'm not currently planning to do that, though, since I think it could use more testing.
1 parent dea4117 commit 9a09248

File tree

6 files changed

+75
-33
lines changed

6 files changed

+75
-33
lines changed

contrib/rtree_gist/rtree_gist.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
*
33
* rtree_gist.c
44
* pg_amproc entries for GiSTs over 2-D boxes.
5-
* This gives R-tree behavior, with Guttman's poly-time split algorithm.
65
*
6+
* This gives R-tree behavior, with Guttman's poly-time split algorithm.
77
*
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/contrib/rtree_gist/rtree_gist.c,v 1.12 2005/05/25 21:40:40 momjian Exp $
10+
* $PostgreSQL: pgsql/contrib/rtree_gist/rtree_gist.c,v 1.13 2005/06/24 00:18:52 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -78,7 +78,7 @@ gbox_consistent(PG_FUNCTION_ARGS)
7878
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
7979

8080
/*
81-
* * if entry is not leaf, use gbox_internal_consistent, * else use
81+
* if entry is not leaf, use rtree_internal_consistent, else use
8282
* gbox_leaf_consistent
8383
*/
8484
if (!(DatumGetPointer(entry->key) != NULL && query))
@@ -509,8 +509,9 @@ gpoly_consistent(PG_FUNCTION_ARGS)
509509
bool result;
510510

511511
/*
512-
* * if entry is not leaf, use gbox_internal_consistent, * else use
513-
* gbox_leaf_consistent
512+
* Since the operators are marked lossy anyway, we can just use
513+
* rtree_internal_consistent even at leaf nodes. (This works
514+
* in part because the index entries are bounding Boxes not polygons.)
514515
*/
515516
if (!(DatumGetPointer(entry->key) != NULL && query))
516517
PG_RETURN_BOOL(FALSE);
@@ -536,15 +537,19 @@ rtree_internal_consistent(BOX *key,
536537
switch (strategy)
537538
{
538539
case RTLeftStrategyNumber:
540+
retval = !DatumGetBool(DirectFunctionCall2(box_overright, PointerGetDatum(key), PointerGetDatum(query)));
541+
break;
539542
case RTOverLeftStrategyNumber:
540-
retval = DatumGetBool(DirectFunctionCall2(box_overleft, PointerGetDatum(key), PointerGetDatum(query)));
543+
retval = !DatumGetBool(DirectFunctionCall2(box_right, PointerGetDatum(key), PointerGetDatum(query)));
541544
break;
542545
case RTOverlapStrategyNumber:
543546
retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query)));
544547
break;
545548
case RTOverRightStrategyNumber:
549+
retval = !DatumGetBool(DirectFunctionCall2(box_left, PointerGetDatum(key), PointerGetDatum(query)));
550+
break;
546551
case RTRightStrategyNumber:
547-
retval = DatumGetBool(DirectFunctionCall2(box_right, PointerGetDatum(key), PointerGetDatum(query)));
552+
retval = !DatumGetBool(DirectFunctionCall2(box_overleft, PointerGetDatum(key), PointerGetDatum(query)));
548553
break;
549554
case RTSameStrategyNumber:
550555
case RTContainsStrategyNumber:

src/backend/access/common/indexvalid.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/common/indexvalid.c,v 1.33 2004/12/31 21:59:07 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/common/indexvalid.c,v 1.34 2005/06/24 00:18:52 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -59,8 +59,16 @@ index_keytest(IndexTuple tuple,
5959

6060
test = FunctionCall2(&key->sk_func, datum, key->sk_argument);
6161

62-
if (!DatumGetBool(test))
63-
return false;
62+
if (key->sk_flags & SK_NEGATE)
63+
{
64+
if (DatumGetBool(test))
65+
return false;
66+
}
67+
else
68+
{
69+
if (!DatumGetBool(test))
70+
return false;
71+
}
6472

6573
key++;
6674
scanKeySize--;

src/backend/access/rtree/rtscan.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.58 2005/03/29 00:16:53 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.59 2005/06/24 00:18:52 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -125,27 +125,36 @@ rtrescan(PG_FUNCTION_ARGS)
125125
* Scans on internal pages use different operators than they do on
126126
* leaf pages. For example, if the user wants all boxes that
127127
* exactly match (x1,y1,x2,y2), then on internal pages we need to
128-
* find all boxes that contain (x1,y1,x2,y2).
128+
* find all boxes that contain (x1,y1,x2,y2). rtstrat.c knows
129+
* how to pick the opclass member to use for internal pages.
130+
* In some cases we need to negate the result of the opclass member.
129131
*/
130132
for (i = 0; i < s->numberOfKeys; i++)
131133
{
132134
AttrNumber attno = s->keyData[i].sk_attno;
133135
Oid opclass;
136+
Oid subtype;
137+
StrategyNumber orig_strategy;
134138
StrategyNumber int_strategy;
135139
Oid int_oper;
136140
RegProcedure int_proc;
141+
int int_flags;
137142

138143
opclass = s->indexRelation->rd_indclass->values[attno - 1];
139-
int_strategy = RTMapToInternalOperator(s->keyData[i].sk_strategy);
140-
int_oper = get_opclass_member(opclass,
141-
s->keyData[i].sk_subtype,
142-
int_strategy);
144+
subtype = s->keyData[i].sk_subtype;
145+
orig_strategy = s->keyData[i].sk_strategy;
146+
int_strategy = RTMapToInternalOperator(orig_strategy);
147+
int_oper = get_opclass_member(opclass, subtype, int_strategy);
148+
Assert(OidIsValid(int_oper));
143149
int_proc = get_opcode(int_oper);
150+
int_flags = s->keyData[i].sk_flags;
151+
if (RTMapToInternalNegate(orig_strategy))
152+
int_flags |= SK_NEGATE;
144153
ScanKeyEntryInitialize(&(p->s_internalKey[i]),
145-
s->keyData[i].sk_flags,
154+
int_flags,
146155
attno,
147156
int_strategy,
148-
s->keyData[i].sk_subtype,
157+
subtype,
149158
int_proc,
150159
s->keyData[i].sk_argument);
151160
}

src/backend/access/rtree/rtstrat.c

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/rtree/rtstrat.c,v 1.25 2004/12/31 21:59:26 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/rtree/rtstrat.c,v 1.26 2005/06/24 00:18:52 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -28,20 +28,31 @@
2828
* the leaf we search for equality.
2929
*
3030
* This array maps leaf search operators to the internal search operators.
31-
* We assume the normal ordering on operators:
32-
*
33-
* left, left-or-overlap, overlap, right-or-overlap, right, same,
34-
* contains, contained-by
3531
*/
3632
static const StrategyNumber RTOperMap[RTNStrategies] = {
37-
RTOverLeftStrategyNumber,
38-
RTOverLeftStrategyNumber,
39-
RTOverlapStrategyNumber,
40-
RTOverRightStrategyNumber,
41-
RTOverRightStrategyNumber,
42-
RTContainsStrategyNumber,
43-
RTContainsStrategyNumber,
44-
RTOverlapStrategyNumber
33+
RTOverRightStrategyNumber, /* left */
34+
RTRightStrategyNumber, /* overleft */
35+
RTOverlapStrategyNumber, /* overlap */
36+
RTLeftStrategyNumber, /* overright */
37+
RTOverLeftStrategyNumber, /* right */
38+
RTContainsStrategyNumber, /* same */
39+
RTContainsStrategyNumber, /* contains */
40+
RTOverlapStrategyNumber /* contained-by */
41+
};
42+
43+
/*
44+
* We may need to negate the result of the selected operator. (This could
45+
* be avoided by expanding the set of operators required for an opclass.)
46+
*/
47+
static const bool RTNegateMap[RTNStrategies] = {
48+
true, /* left */
49+
true, /* overleft */
50+
false, /* overlap */
51+
true, /* overright */
52+
true, /* right */
53+
false, /* same */
54+
false, /* contains */
55+
false /* contained-by */
4556
};
4657

4758

@@ -51,3 +62,10 @@ RTMapToInternalOperator(StrategyNumber strat)
5162
Assert(strat > 0 && strat <= RTNStrategies);
5263
return RTOperMap[strat - 1];
5364
}
65+
66+
bool
67+
RTMapToInternalNegate(StrategyNumber strat)
68+
{
69+
Assert(strat > 0 && strat <= RTNStrategies);
70+
return RTNegateMap[strat - 1];
71+
}

src/include/access/rtree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/access/rtree.h,v 1.39 2005/06/06 17:01:24 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/access/rtree.h,v 1.40 2005/06/24 00:18:52 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -136,5 +136,6 @@ extern void ReleaseResources_rtree(void);
136136

137137
/* rtstrat.c */
138138
extern StrategyNumber RTMapToInternalOperator(StrategyNumber strat);
139+
extern bool RTMapToInternalNegate(StrategyNumber strat);
139140

140141
#endif /* RTREE_H */

src/include/access/skey.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/access/skey.h,v 1.28 2004/12/31 22:03:21 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/include/access/skey.h,v 1.29 2005/06/24 00:18:52 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -72,6 +72,7 @@ typedef ScanKeyData *ScanKey;
7272
/* ScanKeyData sk_flags */
7373
#define SK_ISNULL 0x0001 /* sk_argument is NULL */
7474
#define SK_UNARY 0x0002 /* unary operator (currently unsupported) */
75+
#define SK_NEGATE 0x0004 /* must negate the function result */
7576

7677

7778
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy