aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/nbtree/nbtsearch.c72
-rw-r--r--src/backend/access/nbtree/nbtutils.c10
-rw-r--r--src/backend/executor/nodeIndexscan.c42
3 files changed, 102 insertions, 22 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);
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 193a2f7e714..39a722bb074 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.25 1999/02/13 23:14:37 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.26 1999/04/13 17:18:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -367,8 +367,14 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, Size *keysok)
&isNull);
/* btree doesn't support 'A is null' clauses, yet */
- if (isNull || key[0].sk_flags & SK_ISNULL)
+ if (key[0].sk_flags & SK_ISNULL)
return false;
+ if (isNull)
+ {
+ if (*keysok < so->numberOfFirstKeys)
+ *keysok = -1;
+ return false;
+ }
if (key[0].sk_flags & SK_COMMUTE)
{
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index cdf13c5e19e..16bb4f23b41 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.33 1999/02/21 03:48:40 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.34 1999/04/13 17:18:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -96,6 +96,8 @@ IndexNext(IndexScan *node)
Buffer buffer = InvalidBuffer;
int numIndices;
+ bool bBackward;
+ int indexNumber;
/* ----------------
* extract necessary information from index scan node
* ----------------
@@ -151,8 +153,26 @@ IndexNext(IndexScan *node)
* appropriate heap tuple.. else return NULL.
* ----------------
*/
- while (indexstate->iss_IndexPtr < numIndices)
- {
+ bBackward = ScanDirectionIsBackward(direction);
+ if (bBackward)
+ {
+ indexNumber = numIndices - indexstate->iss_IndexPtr - 1;
+ if (indexNumber < 0)
+ {
+ indexNumber = 0;
+ indexstate->iss_IndexPtr = numIndices - 1;
+ }
+ }
+ else
+ {
+ if ((indexNumber = indexstate->iss_IndexPtr) < 0)
+ {
+ indexNumber = 0;
+ indexstate->iss_IndexPtr = 0;
+ }
+ }
+ while (indexNumber < numIndices)
+ {
scandesc = scanDescs[indexstate->iss_IndexPtr];
while ((result = index_getnext(scandesc, direction)) != NULL)
{
@@ -204,8 +224,14 @@ IndexNext(IndexScan *node)
if (BufferIsValid(buffer))
ReleaseBuffer(buffer);
}
- if (indexstate->iss_IndexPtr < numIndices)
- indexstate->iss_IndexPtr++;
+ if (indexNumber < numIndices)
+ {
+ indexNumber++;
+ if (bBackward)
+ indexstate->iss_IndexPtr--;
+ else
+ indexstate->iss_IndexPtr++;
+ }
}
/* ----------------
* if we get here it means the index scan failed so we
@@ -294,7 +320,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
indxqual = node->indxqual;
numScanKeys = indexstate->iss_NumScanKeys;
- indexstate->iss_IndexPtr = 0;
+ indexstate->iss_IndexPtr = -1;
/* If this is re-scanning of PlanQual ... */
if (estate->es_evTuple != NULL &&
@@ -611,7 +637,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
*/
indexstate = makeNode(IndexScanState);
indexstate->iss_NumIndices = 0;
- indexstate->iss_IndexPtr = 0;
+ indexstate->iss_IndexPtr = -1;
indexstate->iss_ScanKeys = NULL;
indexstate->iss_NumScanKeys = NULL;
indexstate->iss_RuntimeKeyInfo = NULL;
@@ -635,7 +661,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
indxid = node->indxid;
indxqual = node->indxqual;
numIndices = length(indxid);
- indexPtr = 0;
+ indexPtr = -1;
CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);