*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
return res;
}
- } while (keysok >= so->numberOfFirstKeys);
+ } while (keysok >= so->numberOfFirstKeys ||
+ (keysok == -1 && ScanDirectionIsBackward(dir)));
ItemPointerSetInvalid(current);
so->btso_curbuf = InvalidBuffer;
BTScanOpaque so;
ScanKeyData skdata;
Size keysok;
+ int i;
+ int nKeyIndex = -1;
rel = scan->relation;
so = (BTScanOpaque) scan->opaque;
{
_bt_orderkeys(rel, so);
- strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
+ if (ScanDirectionIsBackward(dir))
+ {
+ for (i=0; inumberOfKeys; 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
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);
/* 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)
{
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;
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:
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);
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
Buffer buffer = InvalidBuffer;
int numIndices;
+ bool bBackward;
+ int indexNumber;
/* ----------------
* extract necessary information from index scan 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)
{
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
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 &&
*/
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;
indxid = node->indxid;
indxqual = node->indxqual;
numIndices = length(indxid);
- indexPtr = 0;
+ indexPtr = -1;
CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);