aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/nbtree/nbtsearch.c130
-rw-r--r--src/backend/access/nbtree/nbtutils.c10
2 files changed, 92 insertions, 48 deletions
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 3a5eda3ad8c..0ad8b4ab36f 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.53 1999/07/17 20:16:43 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.54 1999/09/27 18:20:21 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -727,11 +727,15 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
RegProcedure proc;
int result;
BTScanOpaque so;
- ScanKeyData skdata;
Size keysok;
- int i;
- int nKeyIndex = -1;
+ bool strategyCheck;
+ ScanKey scankeys = 0;
+ int keysCount = 0;
+ int *nKeyIs = 0;
+ int i, j;
+ StrategyNumber strat_total;
+
rel = scan->relation;
so = (BTScanOpaque) scan->opaque;
@@ -742,38 +746,57 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
so->numberOfFirstKeys = 0; /* may be changed by _bt_orderkeys */
so->qual_ok = 1; /* may be changed by _bt_orderkeys */
scan->scanFromEnd = false;
+ strategyCheck = false;
if (so->numberOfKeys > 0)
{
_bt_orderkeys(rel, so);
- if (ScanDirectionIsBackward(dir))
+ if (so->qual_ok)
+ strategyCheck = true;
+ }
+ strat_total = BTEqualStrategyNumber;
+ if (strategyCheck)
+ {
+ AttrNumber attno;
+
+ nKeyIs = (int *)palloc(so->numberOfKeys*sizeof(int));
+ for (i=0; i < so->numberOfKeys; i++)
{
- for (i = 0; i < so->numberOfKeys; i++)
+ attno = so->keyData[i].sk_attno;
+ if (attno == keysCount)
+ continue;
+ if (attno > keysCount + 1)
+ break;
+ strat = _bt_getstrat(rel, attno,
+ so->keyData[i].sk_procedure);
+ if (strat == strat_total ||
+ strat == BTEqualStrategyNumber)
{
- if (so->keyData[i].sk_attno != 1)
+ nKeyIs[keysCount++] = i;
+ continue;
+ }
+ if (ScanDirectionIsBackward(dir) &&
+ (strat == BTLessStrategyNumber ||
+ strat == BTLessEqualStrategyNumber) )
+ {
+ nKeyIs[keysCount++] = i;
+ strat_total = strat;
+ if (strat == BTLessStrategyNumber)
break;
- strat = _bt_getstrat(rel, so->keyData[i].sk_attno,
- so->keyData[i].sk_procedure);
- if (strat == BTLessStrategyNumber ||
- strat == BTLessEqualStrategyNumber ||
- strat == BTEqualStrategyNumber)
- {
- nKeyIndex = i;
+ continue;
+ }
+ if (ScanDirectionIsForward(dir) &&
+ (strat == BTGreaterStrategyNumber ||
+ strat == BTGreaterEqualStrategyNumber) )
+ {
+ nKeyIs[keysCount++] = i;
+ strat_total = strat;
+ if (strat == BTGreaterStrategyNumber)
break;
- }
+ continue;
}
}
- else
- {
- strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
-
- if (strat == BTLessStrategyNumber ||
- strat == BTLessEqualStrategyNumber)
- ;
- else
- nKeyIndex = 0;
- }
- if (nKeyIndex < 0)
+ if (!keysCount)
scan->scanFromEnd = true;
}
else
@@ -784,7 +807,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
/* if we just need to walk down one edge of the tree, do that */
if (scan->scanFromEnd)
+ {
+ if (nKeyIs)
+ pfree(nKeyIs);
return _bt_endpoint(scan, dir);
+ }
itupdesc = RelationGetDescr(rel);
current = &(scan->currentItemData);
@@ -796,16 +823,24 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
* at the right place in the scan.
*/
/* _bt_orderkeys disallows it, but it's place to add some code latter */
- if (so->keyData[0].sk_flags & SK_ISNULL)
+ scankeys = (ScanKey)palloc(keysCount*sizeof(ScanKeyData));
+ for (i=0; i < keysCount; i++)
{
- elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet");
- return (RetrieveIndexResult) NULL;
+ j = nKeyIs[i];
+ if (so->keyData[j].sk_flags & SK_ISNULL)
+ {
+ pfree(nKeyIs);
+ pfree(scankeys);
+ elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet");
+ return ((RetrieveIndexResult) NULL);
+ }
+ proc = index_getprocid(rel, i+1, BTORDER_PROC);
+ ScanKeyEntryInitialize(scankeys+i, so->keyData[j].sk_flags,
+ i+1, proc, so->keyData[j].sk_argument);
}
- proc = index_getprocid(rel, 1, BTORDER_PROC);
- ScanKeyEntryInitialize(&skdata, so->keyData[nKeyIndex].sk_flags,
- 1, proc, so->keyData[nKeyIndex].sk_argument);
+ if (nKeyIs) pfree(nKeyIs);
- stack = _bt_search(rel, 1, &skdata, &buf);
+ stack = _bt_search(rel, keysCount, scankeys, &buf);
_bt_freestack(stack);
blkno = BufferGetBlockNumber(buf);
@@ -823,6 +858,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
ItemPointerSetInvalid(current);
so->btso_curbuf = InvalidBuffer;
_bt_relbuf(rel, buf, BT_READ);
+ pfree(scankeys);
return (RetrieveIndexResult) NULL;
}
maxoff = PageGetMaxOffsetNumber(page);
@@ -835,7 +871,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
*/
while (maxoff == P_HIKEY && !P_RIGHTMOST(pop) &&
- _bt_skeycmp(rel, 1, &skdata, page,
+ _bt_skeycmp(rel, keysCount, scankeys, page,
PageGetItemId(page, P_HIKEY),
BTGreaterEqualStrategyNumber))
{
@@ -849,6 +885,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
ItemPointerSetInvalid(current);
so->btso_curbuf = InvalidBuffer;
_bt_relbuf(rel, buf, BT_READ);
+ pfree(scankeys);
return (RetrieveIndexResult) NULL;
}
maxoff = PageGetMaxOffsetNumber(page);
@@ -857,7 +894,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
/* find the nearest match to the manufactured scan key on the page */
- offnum = _bt_binsrch(rel, buf, 1, &skdata, BT_DESCENT);
+ offnum = _bt_binsrch(rel, buf, keysCount, scankeys, BT_DESCENT);
if (offnum > maxoff)
{
@@ -872,12 +909,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
* we're looking for minus the value we're looking at in the index.
*/
- result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+ result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
/* it's yet other place to add some code latter for is(not)null */
- strat = _bt_getstrat(rel, 1, so->keyData[nKeyIndex].sk_procedure);
-
+ strat = strat_total;
switch (strat)
{
case BTLessStrategyNumber:
@@ -890,7 +926,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
offnum = ItemPointerGetOffsetNumber(current);
page = BufferGetPage(buf);
- result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+ result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
} while (result <= 0);
}
@@ -906,12 +942,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
offnum = ItemPointerGetOffsetNumber(current);
page = BufferGetPage(buf);
- result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+ result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
} while (result >= 0);
-
- if (result < 0)
- _bt_twostep(scan, &buf, BackwardScanDirection);
}
+ if (result < 0)
+ _bt_twostep(scan, &buf, BackwardScanDirection);
break;
case BTEqualStrategyNumber:
@@ -920,6 +955,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
_bt_relbuf(scan->relation, buf, BT_READ);
so->btso_curbuf = InvalidBuffer;
ItemPointerSetInvalid(&(scan->currentItemData));
+ pfree(scankeys);
return (RetrieveIndexResult) NULL;
}
else if (ScanDirectionIsBackward(dir))
@@ -931,7 +967,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
offnum = ItemPointerGetOffsetNumber(current);
page = BufferGetPage(buf);
- result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+ result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
} while (result == 0);
if (result < 0)
@@ -950,6 +986,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
_bt_relbuf(scan->relation, buf, BT_READ);
so->btso_curbuf = InvalidBuffer;
ItemPointerSetInvalid(&(scan->currentItemData));
+ pfree(scankeys);
return (RetrieveIndexResult) NULL;
}
}
@@ -974,7 +1011,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
page = BufferGetPage(buf);
offnum = ItemPointerGetOffsetNumber(current);
- result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+ result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
} while (result < 0);
if (result > 0)
@@ -993,12 +1030,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
offnum = ItemPointerGetOffsetNumber(current);
page = BufferGetPage(buf);
- result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+ result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
} while (result >= 0);
}
break;
}
+ pfree(scankeys);
/* okay, current item pointer for the scan is right */
offnum = ItemPointerGetOffsetNumber(current);
page = BufferGetPage(buf);
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 2a5e7578d2f..ee0cd1483b4 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.32 1999/07/17 20:16:43 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.33 1999/09/27 18:20:21 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -101,6 +101,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
uint16 numberOfKeys = so->numberOfKeys;
uint16 new_numberOfKeys = 0;
AttrNumber attno = 1;
+ bool equalStrategyEnd, underEqualStrategy;
if (numberOfKeys < 1)
return;
@@ -136,6 +137,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
for (j = 0; j <= BTMaxStrategyNumber; j++)
init[j] = 0;
+ equalStrategyEnd = false;
+ underEqualStrategy = true;
/* check each key passed in */
for (i = 0;;)
{
@@ -150,6 +153,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
if (cur->sk_attno != attno + 1 && i < numberOfKeys)
elog(ERROR, "_bt_orderkeys: key(s) for attribute %d missed", attno + 1);
+ underEqualStrategy = (!equalStrategyEnd);
/*
* If = has been specified, no other key will be used. In case
* of key < 2 && key == 1 and so on we have to set qual_ok to
@@ -175,6 +179,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
init[BTGreaterEqualStrategyNumber - 1] = 0;
init[BTGreaterStrategyNumber - 1] = 0;
}
+ else
+ equalStrategyEnd = true;
/* only one of <, <= */
if (init[BTLessStrategyNumber - 1]
@@ -223,7 +229,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
if (init[j])
key[new_numberOfKeys++] = xform[j];
- if (attno == 1)
+ if (underEqualStrategy)
so->numberOfFirstKeys = new_numberOfKeys;
if (i == numberOfKeys)