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" <root@ais.sable.krasnoyarsk.su>
This commit is contained in:
parent
e5e12f6405
commit
74cdf92868
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* and recorded in the opaque entry of the scan in order to avoid
|
||||||
* doing a ReadBuffer() for every tuple in the index. This avoids
|
* doing a ReadBuffer() for every tuple in the index. This avoids
|
||||||
* semop() calls, which are expensive.
|
* 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 {
|
typedef struct BTScanOpaqueData {
|
||||||
Buffer btso_curbuf;
|
Buffer btso_curbuf;
|
||||||
Buffer btso_mrkbuf;
|
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;
|
} BTScanOpaqueData;
|
||||||
|
|
||||||
typedef BTScanOpaqueData *BTScanOpaque;
|
typedef BTScanOpaqueData *BTScanOpaque;
|
||||||
@ -248,7 +254,7 @@ extern ScanKey _bt_mkscankey(Relation rel, IndexTuple itup);
|
|||||||
extern void _bt_freeskey(ScanKey skey);
|
extern void _bt_freeskey(ScanKey skey);
|
||||||
extern void _bt_freestack(BTStack stack);
|
extern void _bt_freestack(BTStack stack);
|
||||||
extern void _bt_orderkeys(Relation relation, uint16 *numberOfKeys,
|
extern void _bt_orderkeys(Relation relation, uint16 *numberOfKeys,
|
||||||
ScanKey key);
|
ScanKey key, uint16 *qual_ok);
|
||||||
extern bool _bt_checkqual(IndexScanDesc scan, IndexTuple itup);
|
extern bool _bt_checkqual(IndexScanDesc scan, IndexTuple itup);
|
||||||
extern BTItem _bt_formitem(IndexTuple itup);
|
extern BTItem _bt_formitem(IndexTuple itup);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* This file contains only the public interface routines.
|
* This file contains only the public interface routines.
|
||||||
@ -330,32 +330,9 @@ char *
|
|||||||
btbeginscan(Relation rel, bool fromEnd, uint16 keysz, ScanKey scankey)
|
btbeginscan(Relation rel, bool fromEnd, uint16 keysz, ScanKey scankey)
|
||||||
{
|
{
|
||||||
IndexScanDesc scan;
|
IndexScanDesc scan;
|
||||||
StrategyNumber strat;
|
|
||||||
BTScanOpaque so;
|
|
||||||
|
|
||||||
/* first order the keys in the qualification */
|
/* get the scan */
|
||||||
if (keysz > 1)
|
|
||||||
_bt_orderkeys(rel, &keysz, scankey);
|
|
||||||
|
|
||||||
/* now get the scan */
|
|
||||||
scan = RelationGetIndexScan(rel, fromEnd, keysz, scankey);
|
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 */
|
/* register scan in case we change pages it's using */
|
||||||
_bt_regscan(scan);
|
_bt_regscan(scan);
|
||||||
@ -371,6 +348,7 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
|
|||||||
{
|
{
|
||||||
ItemPointer iptr;
|
ItemPointer iptr;
|
||||||
BTScanOpaque so;
|
BTScanOpaque so;
|
||||||
|
StrategyNumber strat;
|
||||||
|
|
||||||
so = (BTScanOpaque) scan->opaque;
|
so = (BTScanOpaque) scan->opaque;
|
||||||
|
|
||||||
@ -388,12 +366,45 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
|
|||||||
ItemPointerSetInvalid(iptr);
|
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 */
|
/* reset the scan key */
|
||||||
|
so->numberOfKeys = scan->numberOfKeys;
|
||||||
|
so->qual_ok = 1; /* may be changed by _bt_orderkeys */
|
||||||
if (scan->numberOfKeys > 0) {
|
if (scan->numberOfKeys > 0) {
|
||||||
memmove(scan->keyData,
|
memmove(scan->keyData,
|
||||||
scankey,
|
scankey,
|
||||||
scan->numberOfKeys * sizeof(ScanKeyData));
|
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
|
void
|
||||||
@ -411,7 +422,8 @@ btmovescan(IndexScanDesc scan, Datum v)
|
|||||||
ItemPointerSetInvalid(iptr);
|
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 */
|
/* be tidy */
|
||||||
#ifdef PERFECT_MMGR
|
#ifdef PERFECT_MMGR
|
||||||
|
if ( so->keyData != (ScanKey) NULL )
|
||||||
|
pfree (so->keyData);
|
||||||
pfree (scan->opaque);
|
pfree (scan->opaque);
|
||||||
#endif /* PERFECT_MMGR */
|
#endif /* PERFECT_MMGR */
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
BTScanOpaque so;
|
||||||
ScanKeyData skdata;
|
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 we just need to walk down one edge of the tree, do that */
|
||||||
if (scan->scanFromEnd)
|
if (scan->scanFromEnd)
|
||||||
return (_bt_endpoint(scan, dir));
|
return (_bt_endpoint(scan, dir));
|
||||||
@ -611,7 +615,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
rel = scan->relation;
|
rel = scan->relation;
|
||||||
itupdesc = RelationGetTupleDescriptor(scan->relation);
|
itupdesc = RelationGetTupleDescriptor(scan->relation);
|
||||||
current = &(scan->currentItemData);
|
current = &(scan->currentItemData);
|
||||||
so = (BTScanOpaque) scan->opaque;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Okay, we want something more complicated. What we'll do is use
|
* 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);
|
proc = index_getprocid(rel, 1, BTORDER_PROC);
|
||||||
ScanKeyEntryInitialize(&skdata, 0x0, 1, proc,
|
ScanKeyEntryInitialize(&skdata, 0x0, 1, proc,
|
||||||
scan->keyData[0].sk_argument);
|
so->keyData[0].sk_argument);
|
||||||
|
|
||||||
stack = _bt_search(rel, 1, &skdata, &buf);
|
stack = _bt_search(rel, 1, &skdata, &buf);
|
||||||
_bt_freestack(stack);
|
_bt_freestack(stack);
|
||||||
@ -666,7 +669,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
|
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) {
|
switch (strat) {
|
||||||
case BTLessStrategyNumber:
|
case BTLessStrategyNumber:
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* more than one qual clauses using this index.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
|
_bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key, uint16 *qual_ok)
|
||||||
{
|
{
|
||||||
ScanKey xform;
|
ScanKey xform;
|
||||||
ScanKeyData *cur;
|
ScanKeyData *cur;
|
||||||
@ -133,6 +133,8 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
|
|||||||
cur->sk_argument, xform[j].sk_argument);
|
cur->sk_argument, xform[j].sk_argument);
|
||||||
if (test)
|
if (test)
|
||||||
xform[j].sk_argument = cur->sk_argument;
|
xform[j].sk_argument = cur->sk_argument;
|
||||||
|
else if ( j == (BTEqualStrategyNumber - 1) )
|
||||||
|
*qual_ok = 0; /* key == a && key == b, but a != b */
|
||||||
} else {
|
} else {
|
||||||
/* nope, use this value */
|
/* nope, use this value */
|
||||||
memmove(&xform[j], cur, sizeof(*cur));
|
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 */
|
/* 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]) {
|
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[BTLessStrategyNumber - 1] = 0;
|
||||||
init[BTLessEqualStrategyNumber - 1] = 0;
|
init[BTLessEqualStrategyNumber - 1] = 0;
|
||||||
init[BTGreaterEqualStrategyNumber - 1] = 0;
|
init[BTGreaterEqualStrategyNumber - 1] = 0;
|
||||||
@ -166,7 +191,7 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
|
|||||||
* in the correct way.
|
* 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)
|
if (test)
|
||||||
init[BTLessEqualStrategyNumber - 1] = 0;
|
init[BTLessEqualStrategyNumber - 1] = 0;
|
||||||
@ -184,12 +209,12 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key)
|
|||||||
ge = &xform[BTGreaterEqualStrategyNumber - 1];
|
ge = &xform[BTGreaterEqualStrategyNumber - 1];
|
||||||
|
|
||||||
/* see note above on function cache */
|
/* 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)
|
if (test)
|
||||||
init[BTGreaterStrategyNumber - 1] = 0;
|
|
||||||
else
|
|
||||||
init[BTGreaterEqualStrategyNumber - 1] = 0;
|
init[BTGreaterEqualStrategyNumber - 1] = 0;
|
||||||
|
else
|
||||||
|
init[BTGreaterStrategyNumber - 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* okay, reorder and count */
|
/* okay, reorder and count */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user