aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtsearch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/nbtree/nbtsearch.c')
-rw-r--r--src/backend/access/nbtree/nbtsearch.c72
1 files changed, 60 insertions, 12 deletions
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 593a5453bc5..1ea080abd72 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.42 1999/03/28 20:31:58 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.43 1999/04/13 17:18:28 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -733,7 +733,8 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
return res;
}
- } while (keysok >= so->numberOfFirstKeys);
+ } while (keysok >= so->numberOfFirstKeys ||
+ (keysok == -1 && ScanDirectionIsBackward(dir)));
ItemPointerSetInvalid(current);
so->btso_curbuf = InvalidBuffer;
@@ -775,6 +776,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
BTScanOpaque so;
ScanKeyData skdata;
Size keysok;
+ int i;
+ int nKeyIndex = -1;
rel = scan->relation;
so = (BTScanOpaque) scan->opaque;
@@ -790,11 +793,34 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
{
_bt_orderkeys(rel, so);
- strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
+ if (ScanDirectionIsBackward(dir))
+ {
+ for (i=0; i<so->numberOfKeys; i++)
+ {
+ if (so->keyData[i].sk_attno != 1)
+ break;
+ strat = _bt_getstrat(rel, so->keyData[i].sk_attno,
+ so->keyData[i].sk_procedure);
+ if (strat == BTLessStrategyNumber ||
+ strat == BTLessEqualStrategyNumber||
+ strat == BTEqualStrategyNumber)
+ {
+ nKeyIndex = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
- /* NOTE: it assumes ForwardScanDirection */
- if (strat == BTLessStrategyNumber ||
- strat == BTLessEqualStrategyNumber)
+ if (strat == BTLessStrategyNumber ||
+ strat == BTLessEqualStrategyNumber)
+ ;
+ else
+ nKeyIndex = 0;
+ }
+ if (nKeyIndex < 0)
scan->scanFromEnd = true;
}
else
@@ -823,8 +849,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
return (RetrieveIndexResult) NULL;
}
proc = index_getprocid(rel, 1, BTORDER_PROC);
- ScanKeyEntryInitialize(&skdata, so->keyData[0].sk_flags, 1, proc,
- so->keyData[0].sk_argument);
+ ScanKeyEntryInitialize(&skdata, so->keyData[nKeyIndex].sk_flags,
+ 1, proc, so->keyData[nKeyIndex].sk_argument);
stack = _bt_search(rel, 1, &skdata, &buf);
_bt_freestack(stack);
@@ -897,7 +923,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
/* it's yet other place to add some code latter for is(not)null */
- strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
+ strat = _bt_getstrat(rel, 1, so->keyData[nKeyIndex].sk_procedure);
switch (strat)
{
@@ -914,9 +940,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
} while (result <= 0);
- /* if this is true, the key we just looked at is gone */
- if (result > 0)
- _bt_twostep(scan, &buf, ForwardScanDirection);
}
break;
@@ -946,6 +969,21 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
ItemPointerSetInvalid(&(scan->currentItemData));
return (RetrieveIndexResult) NULL;
}
+ else if (ScanDirectionIsBackward(dir))
+ {
+ do
+ {
+ if (!_bt_twostep(scan, &buf, ForwardScanDirection))
+ break;
+
+ offnum = ItemPointerGetOffsetNumber(current);
+ page = BufferGetPage(buf);
+ result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+ } while (result == 0);
+
+ if (result < 0)
+ _bt_twostep(scan, &buf, BackwardScanDirection);
+ }
break;
case BTGreaterEqualStrategyNumber:
@@ -1026,6 +1064,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
so->btso_curbuf = buf;
return _bt_next(scan, dir);
}
+ else if (keysok == -1 && ScanDirectionIsBackward(dir))
+ {
+ so->btso_curbuf = buf;
+ return _bt_next(scan, dir);
+ }
else
{
ItemPointerSetInvalid(current);
@@ -1495,6 +1538,11 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
so->btso_curbuf = buf;
return _bt_next(scan, dir);
}
+ else if (keysok == -1 && ScanDirectionIsBackward(dir))
+ {
+ so->btso_curbuf = buf;
+ return _bt_next(scan, dir);
+ }
else
{
ItemPointerSetInvalid(current);