summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc G. Fournier1996-07-30 07:56:04 +0000
committerMarc G. Fournier1996-07-30 07:56:04 +0000
commit74cdf928687ac62db73b72509e1e11b9008a6bf2 (patch)
tree8e556818774c9f880bba2e307bb9492d6e101200
parente5e12f640571f1d1a440d868454afd543beb73fd (diff)
Fixes:
> INDEXED searches in some cases DO NOT WORK. > Although simple search expressions (i.e. with a constant value on > the right side of an operator) work, performing a join (by putting > a field of some other table on the right side of an operator) produces > empty output. > WITHOUT indices, everything works fine. > submitted by: "Vadim B. Mikheev" <[email protected]>
-rw-r--r--src/backend/access/nbtree.h10
-rw-r--r--src/backend/access/nbtree/nbtree.c66
-rw-r--r--src/backend/access/nbtree/nbtsearch.c11
-rw-r--r--src/backend/access/nbtree/nbtutils.c37
4 files changed, 86 insertions, 38 deletions
diff --git a/src/backend/access/nbtree.h b/src/backend/access/nbtree.h
index d5c37a23950..051fb8f6eb0 100644
--- a/src/backend/access/nbtree.h
+++ b/src/backend/access/nbtree.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: nbtree.h,v 1.1.1.1 1996/07/09 06:21:08 scrappy Exp $
+ * $Id: nbtree.h,v 1.2 1996/07/30 07:55:10 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -60,11 +60,17 @@ typedef BTPageOpaqueData *BTPageOpaque;
* and recorded in the opaque entry of the scan in order to avoid
* doing a ReadBuffer() for every tuple in the index. This avoids
* semop() calls, which are expensive.
+ *
+ * And it's used to remember actual scankey info (we need in it
+ * if some scankeys evaled at runtime.
*/
typedef struct BTScanOpaqueData {
Buffer btso_curbuf;
Buffer btso_mrkbuf;
+ uint16 qual_ok; /* 0 for quals like key == 1 && key > 2 */
+ uint16 numberOfKeys; /* number of key attributes */
+ ScanKey keyData; /* key descriptor */
} BTScanOpaqueData;
typedef BTScanOpaqueData *BTScanOpaque;
@@ -248,7 +254,7 @@ extern ScanKey _bt_mkscankey(Relation rel, IndexTuple itup);
extern void _bt_freeskey(ScanKey skey);
extern void _bt_freestack(BTStack stack);
extern void _bt_orderkeys(Relation relation, uint16 *numberOfKeys,
- ScanKey key);
+ ScanKey key, uint16 *qual_ok);
extern bool _bt_checkqual(IndexScanDesc scan, IndexTuple itup);
extern BTItem _bt_formitem(IndexTuple itup);
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 06016119964..5829e8afe07 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.1.1.1 1996/07/09 06:21:12 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.2 1996/07/30 07:56:00 scrappy Exp $
*
* NOTES
* This file contains only the public interface routines.
@@ -330,32 +330,9 @@ char *
btbeginscan(Relation rel, bool fromEnd, uint16 keysz, ScanKey scankey)
{
IndexScanDesc scan;
- StrategyNumber strat;
- BTScanOpaque so;
- /* first order the keys in the qualification */
- if (keysz > 1)
- _bt_orderkeys(rel, &keysz, scankey);
-
- /* now get the scan */
+ /* get the scan */
scan = RelationGetIndexScan(rel, fromEnd, keysz, scankey);
- so = (BTScanOpaque) palloc(sizeof(BTScanOpaqueData));
- so->btso_curbuf = so->btso_mrkbuf = InvalidBuffer;
- scan->opaque = so;
-
- /* finally, be sure that the scan exploits the tree order */
- scan->scanFromEnd = false;
- scan->flags = 0x0;
- if (keysz > 0) {
- strat = _bt_getstrat(scan->relation, 1 /* XXX */,
- scankey[0].sk_procedure);
-
- if (strat == BTLessStrategyNumber
- || strat == BTLessEqualStrategyNumber)
- scan->scanFromEnd = true;
- } else {
- scan->scanFromEnd = true;
- }
/* register scan in case we change pages it's using */
_bt_regscan(scan);
@@ -371,6 +348,7 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
{
ItemPointer iptr;
BTScanOpaque so;
+ StrategyNumber strat;
so = (BTScanOpaque) scan->opaque;
@@ -388,12 +366,45 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
ItemPointerSetInvalid(iptr);
}
+ if ( so == NULL ) /* if called from btbeginscan */
+ {
+ so = (BTScanOpaque) palloc(sizeof(BTScanOpaqueData));
+ so->btso_curbuf = so->btso_mrkbuf = InvalidBuffer;
+ so->keyData = (ScanKey) NULL;
+ if ( scan->numberOfKeys > 0)
+ so->keyData = (ScanKey) palloc (scan->numberOfKeys * sizeof(ScanKeyData));
+ scan->opaque = so;
+ scan->flags = 0x0;
+ }
+
/* reset the scan key */
+ so->numberOfKeys = scan->numberOfKeys;
+ so->qual_ok = 1; /* may be changed by _bt_orderkeys */
if (scan->numberOfKeys > 0) {
memmove(scan->keyData,
scankey,
scan->numberOfKeys * sizeof(ScanKeyData));
+ memmove(so->keyData,
+ scankey,
+ so->numberOfKeys * sizeof(ScanKeyData));
+ /* order the keys in the qualification */
+ if (so->numberOfKeys > 1)
+ _bt_orderkeys(scan->relation, &so->numberOfKeys, so->keyData, &so->qual_ok);
}
+
+ /* finally, be sure that the scan exploits the tree order */
+ scan->scanFromEnd = false;
+ if ( so->numberOfKeys > 0 ) {
+ strat = _bt_getstrat(scan->relation, 1 /* XXX */,
+ so->keyData[0].sk_procedure);
+
+ if (strat == BTLessStrategyNumber
+ || strat == BTLessEqualStrategyNumber)
+ scan->scanFromEnd = true;
+ } else {
+ scan->scanFromEnd = true;
+ }
+
}
void
@@ -411,7 +422,8 @@ btmovescan(IndexScanDesc scan, Datum v)
ItemPointerSetInvalid(iptr);
}
- scan->keyData[0].sk_argument = v;
+/* scan->keyData[0].sk_argument = v; */
+ so->keyData[0].sk_argument = v;
}
/*
@@ -445,6 +457,8 @@ btendscan(IndexScanDesc scan)
/* be tidy */
#ifdef PERFECT_MMGR
+ if ( so->keyData != (ScanKey) NULL )
+ pfree (so->keyData);
pfree (scan->opaque);
#endif /* PERFECT_MMGR */
}
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index d7a7fc7d62e..3756c2fc30c 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.1.1.1 1996/07/09 06:21:12 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.2 1996/07/30 07:56:02 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -604,6 +604,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
BTScanOpaque so;
ScanKeyData skdata;
+ so = (BTScanOpaque) scan->opaque;
+ if ( so->qual_ok == 0 ) /* may be set by _bt_orderkeys */
+ return ((RetrieveIndexResult) NULL);
+
/* if we just need to walk down one edge of the tree, do that */
if (scan->scanFromEnd)
return (_bt_endpoint(scan, dir));
@@ -611,7 +615,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
rel = scan->relation;
itupdesc = RelationGetTupleDescriptor(scan->relation);
current = &(scan->currentItemData);
- so = (BTScanOpaque) scan->opaque;
/*
* Okay, we want something more complicated. What we'll do is use
@@ -628,7 +631,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
*/
proc = index_getprocid(rel, 1, BTORDER_PROC);
ScanKeyEntryInitialize(&skdata, 0x0, 1, proc,
- scan->keyData[0].sk_argument);
+ so->keyData[0].sk_argument);
stack = _bt_search(rel, 1, &skdata, &buf);
_bt_freestack(stack);
@@ -666,7 +669,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
*/
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
- strat = _bt_getstrat(rel, 1, scan->keyData[0].sk_procedure);
+ strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
switch (strat) {
case BTLessStrategyNumber:
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 695a2b637c8..d06b857851e 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.1.1.1 1996/07/09 06:21:12 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.2 1996/07/30 07:56:04 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -82,7 +82,7 @@ _bt_freestack(BTStack stack)
* more than one qual clauses using this index.
*/
void
-_bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
+_bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key, uint16 *qual_ok)
{
ScanKey xform;
ScanKeyData *cur;
@@ -133,6 +133,8 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
cur->sk_argument, xform[j].sk_argument);
if (test)
xform[j].sk_argument = cur->sk_argument;
+ else if ( j == (BTEqualStrategyNumber - 1) )
+ *qual_ok = 0; /* key == a && key == b, but a != b */
} else {
/* nope, use this value */
memmove(&xform[j], cur, sizeof(*cur));
@@ -142,7 +144,30 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
}
/* if = has been specified, no other key will be used */
+ /*
+ * XXX
+ * But in case of key < 2 && key == 1 and so on
+ * we have to set qual_ok to 0
+ */
if (init[BTEqualStrategyNumber - 1]) {
+
+ ScanKeyData *eq, *chk;
+
+ eq = &xform[BTEqualStrategyNumber - 1];
+
+ for (j = BTMaxStrategyNumber; --j >= 0; )
+ {
+ if ( j == (BTEqualStrategyNumber - 1) || init[j] == 0 )
+ continue;
+
+ chk = &xform[j];
+
+ test = (long) fmgr(chk->sk_procedure, eq->sk_argument, chk->sk_argument);
+
+ if (!test)
+ *qual_ok = 0;
+ }
+
init[BTLessStrategyNumber - 1] = 0;
init[BTLessEqualStrategyNumber - 1] = 0;
init[BTGreaterEqualStrategyNumber - 1] = 0;
@@ -166,7 +191,7 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
* in the correct way.
*/
- test = (long) fmgr(le->sk_procedure, le->sk_argument, lt->sk_argument);
+ test = (long) fmgr(le->sk_procedure, lt->sk_argument, le->sk_argument);
if (test)
init[BTLessEqualStrategyNumber - 1] = 0;
@@ -184,12 +209,12 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
ge = &xform[BTGreaterEqualStrategyNumber - 1];
/* see note above on function cache */
- test = (long) fmgr(ge->sk_procedure, gt->sk_argument, gt->sk_argument);
+ test = (long) fmgr(ge->sk_procedure, gt->sk_argument, ge->sk_argument);
if (test)
- init[BTGreaterStrategyNumber - 1] = 0;
- else
init[BTGreaterEqualStrategyNumber - 1] = 0;
+ else
+ init[BTGreaterStrategyNumber - 1] = 0;
}
/* okay, reorder and count */