]> granicus.if.org Git - postgresql/commitdiff
There are some bugs about backward scanning using
authorBruce Momjian <bruce@momjian.us>
Tue, 13 Apr 1999 17:18:29 +0000 (17:18 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 13 Apr 1999 17:18:29 +0000 (17:18 +0000)
indexes.

1. Index Scan using plural indexids never scan backward
   as to the order of indexids.
2. The cursor using Index scan is not usable after moving
   past the end.

This patch solves above bugs.
Moreover the change of _bt_first() would be useful to extend
ORDER BY patch by Jan Wieck for all descending order cases.

Hiroshi Inoue

src/backend/access/nbtree/nbtsearch.c
src/backend/access/nbtree/nbtutils.c
src/backend/executor/nodeIndexscan.c

index 593a5453bc5e47033a4fa3533df67cf6508fc3c0..1ea080abd721638aad7da2cbbe2db0c59aff0107 100644 (file)
@@ -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);
index 193a2f7e714e544c17c9101d92b034753060d08f..39a722bb074f129986eb8e1fe7396b536470c417 100644 (file)
@@ -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)
                {
index cdf13c5e19e0a10286fa3a7162aa27737e5334f8..16bb4f23b410158450986460d021bf9a2e0d1cd0 100644 (file)
@@ -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);