/ Check-in [6089d5db]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Change the definition of the BtCursor.skipNext field so that it is undefined for states CURSOR_VALID and CURSOR_INVALID.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6089d5dba73437d787259033e94a38cf1b0c87cac4a89c27e69d8239c22f496e
User & Date: drh 2019-01-28 00:42:06
Context
2019-01-28
11:54
Add a new test case to fuzzdata8.db. check-in: ce8e279a user: drh tags: trunk
00:42
Change the definition of the BtCursor.skipNext field so that it is undefined for states CURSOR_VALID and CURSOR_INVALID. check-in: 6089d5db user: drh tags: trunk
2019-01-27
19:50
Improvements to the ".eqp trace" command in the CLI so that it ensures that the schema has been read prior to activing the tracing feature, to avoid cluttering the output with a trace of the schema parse. check-in: 42687d45 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

   841    841     }
   842    842     pCur->eState = CURSOR_INVALID;
   843    843     rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
   844    844     if( rc==SQLITE_OK ){
   845    845       sqlite3_free(pCur->pKey);
   846    846       pCur->pKey = 0;
   847    847       assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
   848         -    pCur->skipNext |= skipNext;
          848  +    if( skipNext ) pCur->skipNext = skipNext;
   849    849       if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
   850    850         pCur->eState = CURSOR_SKIPNEXT;
   851    851       }
   852    852     }
   853    853     return rc;
   854    854   }
   855    855   
................................................................................
   911    911     if( rc ){
   912    912       *pDifferentRow = 1;
   913    913       return rc;
   914    914     }
   915    915     if( pCur->eState!=CURSOR_VALID ){
   916    916       *pDifferentRow = 1;
   917    917     }else{
   918         -    assert( pCur->skipNext==0 );
   919    918       *pDifferentRow = 0;
   920    919     }
   921    920     return SQLITE_OK;
   922    921   }
   923    922   
   924    923   #ifdef SQLITE_ENABLE_CURSOR_HINTS
   925    924   /*
................................................................................
  5330   5329           *pRes = -1;
  5331   5330           return SQLITE_OK;
  5332   5331         }
  5333   5332         /* If the requested key is one more than the previous key, then
  5334   5333         ** try to get there using sqlite3BtreeNext() rather than a full
  5335   5334         ** binary search.  This is an optimization only.  The correct answer
  5336   5335         ** is still obtained without this case, only a little more slowely */
  5337         -      if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
         5336  +      if( pCur->info.nKey+1==intKey ){
  5338   5337           *pRes = 0;
  5339   5338           rc = sqlite3BtreeNext(pCur, 0);
  5340   5339           if( rc==SQLITE_OK ){
  5341   5340             getCellInfo(pCur);
  5342   5341             if( pCur->info.nKey==intKey ){
  5343   5342               return SQLITE_OK;
  5344   5343             }
................................................................................
  5604   5603   */
  5605   5604   static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
  5606   5605     int rc;
  5607   5606     int idx;
  5608   5607     MemPage *pPage;
  5609   5608   
  5610   5609     assert( cursorOwnsBtShared(pCur) );
  5611         -  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  5612   5610     if( pCur->eState!=CURSOR_VALID ){
  5613   5611       assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
  5614   5612       rc = restoreCursorPosition(pCur);
  5615   5613       if( rc!=SQLITE_OK ){
  5616   5614         return rc;
  5617   5615       }
  5618   5616       if( CURSOR_INVALID==pCur->eState ){
  5619   5617         return SQLITE_DONE;
  5620   5618       }
  5621         -    if( pCur->skipNext ){
  5622         -      assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
         5619  +    if( pCur->eState==CURSOR_SKIPNEXT ){
  5623   5620         pCur->eState = CURSOR_VALID;
  5624         -      if( pCur->skipNext>0 ){
  5625         -        pCur->skipNext = 0;
  5626         -        return SQLITE_OK;
  5627         -      }
  5628         -      pCur->skipNext = 0;
         5621  +      if( pCur->skipNext>0 ) return SQLITE_OK;
  5629   5622       }
  5630   5623     }
  5631   5624   
  5632   5625     pPage = pCur->pPage;
  5633   5626     idx = ++pCur->ix;
  5634   5627     if( !pPage->isInit ){
  5635   5628       /* The only known way for this to happen is for there to be a
................................................................................
  5676   5669     }
  5677   5670   }
  5678   5671   int sqlite3BtreeNext(BtCursor *pCur, int flags){
  5679   5672     MemPage *pPage;
  5680   5673     UNUSED_PARAMETER( flags );  /* Used in COMDB2 but not native SQLite */
  5681   5674     assert( cursorOwnsBtShared(pCur) );
  5682   5675     assert( flags==0 || flags==1 );
  5683         -  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  5684   5676     pCur->info.nSize = 0;
  5685   5677     pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
  5686   5678     if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
  5687   5679     pPage = pCur->pPage;
  5688   5680     if( (++pCur->ix)>=pPage->nCell ){
  5689   5681       pCur->ix--;
  5690   5682       return btreeNext(pCur);
................................................................................
  5717   5709   ** use this hint, but COMDB2 does.
  5718   5710   */
  5719   5711   static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
  5720   5712     int rc;
  5721   5713     MemPage *pPage;
  5722   5714   
  5723   5715     assert( cursorOwnsBtShared(pCur) );
  5724         -  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  5725   5716     assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
  5726   5717     assert( pCur->info.nSize==0 );
  5727   5718     if( pCur->eState!=CURSOR_VALID ){
  5728   5719       rc = restoreCursorPosition(pCur);
  5729   5720       if( rc!=SQLITE_OK ){
  5730   5721         return rc;
  5731   5722       }
  5732   5723       if( CURSOR_INVALID==pCur->eState ){
  5733   5724         return SQLITE_DONE;
  5734   5725       }
  5735         -    if( pCur->skipNext ){
  5736         -      assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
         5726  +    if( CURSOR_SKIPNEXT==pCur->eState ){
  5737   5727         pCur->eState = CURSOR_VALID;
  5738         -      if( pCur->skipNext<0 ){
  5739         -        pCur->skipNext = 0;
  5740         -        return SQLITE_OK;
  5741         -      }
  5742         -      pCur->skipNext = 0;
         5728  +      if( pCur->skipNext<0 ) return SQLITE_OK;
  5743   5729       }
  5744   5730     }
  5745   5731   
  5746   5732     pPage = pCur->pPage;
  5747   5733     assert( pPage->isInit );
  5748   5734     if( !pPage->leaf ){
  5749   5735       int idx = pCur->ix;
................................................................................
  5770   5756       }
  5771   5757     }
  5772   5758     return rc;
  5773   5759   }
  5774   5760   int sqlite3BtreePrevious(BtCursor *pCur, int flags){
  5775   5761     assert( cursorOwnsBtShared(pCur) );
  5776   5762     assert( flags==0 || flags==1 );
  5777         -  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  5778   5763     UNUSED_PARAMETER( flags );  /* Used in COMDB2 but not native SQLite */
  5779   5764     pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
  5780   5765     pCur->info.nSize = 0;
  5781   5766     if( pCur->eState!=CURSOR_VALID
  5782   5767      || pCur->ix==0
  5783   5768      || pCur->pPage->leaf==0
  5784   5769     ){
................................................................................
  8766   8751     ** the cursor to the largest entry in the tree that is smaller than
  8767   8752     ** the entry being deleted. This cell will replace the cell being deleted
  8768   8753     ** from the internal node. The 'previous' entry is used for this instead
  8769   8754     ** of the 'next' entry, as the previous entry is always a part of the
  8770   8755     ** sub-tree headed by the child page of the cell being deleted. This makes
  8771   8756     ** balancing the tree following the delete operation easier.  */
  8772   8757     if( !pPage->leaf ){
  8773         -    pCur->skipNext = 0;
  8774   8758       rc = sqlite3BtreePrevious(pCur, 0);
  8775   8759       assert( rc!=SQLITE_DONE );
  8776   8760       if( rc ) return rc;
  8777   8761     }
  8778   8762   
  8779   8763     /* Save the positions of any other cursors open on this table before
  8780   8764     ** making any modifications.  */

Changes to src/btreeInt.h.

   490    490   ** but cursors cannot be shared.  Each cursor is associated with a
   491    491   ** particular database connection identified BtCursor.pBtree.db.
   492    492   **
   493    493   ** Fields in this structure are accessed under the BtShared.mutex
   494    494   ** found at self->pBt->mutex. 
   495    495   **
   496    496   ** skipNext meaning:
   497         -**    eState==SKIPNEXT && skipNext>0:  Next sqlite3BtreeNext() is no-op.
   498         -**    eState==SKIPNEXT && skipNext<0:  Next sqlite3BtreePrevious() is no-op.
   499         -**    eState==FAULT:                   Cursor fault with skipNext as error code.
          497  +** The meaning of skipNext depends on the value of eState:
          498  +**
          499  +**   eState            Meaning of skipNext
          500  +**   VALID             skipNext is meaningless and is ignored
          501  +**   INVALID           skipNext is meaningless and is ignored
          502  +**   SKIPNEXT          sqlite3BtreeNext() is a no-op if skipNext>0 and
          503  +**                     sqlite3BtreePrevious() is no-op if skipNext<0.
          504  +**   REQUIRESEEK       restoreCursorPosition() restores the cursor to
          505  +**                     eState=SKIPNEXT if skipNext!=0
          506  +**   FAULT             skipNext holds the cursor fault error code.
   500    507   */
   501    508   struct BtCursor {
   502    509     u8 eState;                /* One of the CURSOR_XXX constants (see below) */
   503    510     u8 curFlags;              /* zero or more BTCF_* flags defined below */
   504    511     u8 curPagerFlags;         /* Flags to send to sqlite3PagerGet() */
   505    512     u8 hints;                 /* As configured by CursorSetHints() */
   506    513     int skipNext;    /* Prev() is noop if negative. Next() is noop if positive.