/ Check-in [66347385]
Login

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

Overview
Comment:Change the OP_Last opcode so that it is a no-op if the cursor is already pointing at the end of the b-tree.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 663473850c4274270445b3771911fa773a8c405f
User & Date: drh 2016-11-15 04:00:24
References
2017-08-01
18:21 New ticket [cb91bf42] Assertion fault following PRAGMA reverse_unordered_selects=ON. artifact: b9784104 user: drh
Context
2016-11-15
21:17
Add a needed #include to speedtest1.c. check-in: 77aeb705 user: drh tags: trunk
17:37
Experimental changes toward making snapshots serializable. check-in: b6a81fa1 user: drh tags: serializable-snapshot
04:00
Change the OP_Last opcode so that it is a no-op if the cursor is already pointing at the end of the b-tree. check-in: 66347385 user: drh tags: trunk
02:46
Make the VACUUM command about 9% faster by avoiding unnecessary calls to sqlite3BtreeMovetoUnpacked() while copying rowid tables. check-in: 5ed0bd38 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  4274   4274   ** that is currently pointing to a row in a (non-empty) table.
  4275   4275   ** This is a verification routine is used only within assert() statements.
  4276   4276   */
  4277   4277   int sqlite3BtreeCursorIsValid(BtCursor *pCur){
  4278   4278     return pCur && pCur->eState==CURSOR_VALID;
  4279   4279   }
  4280   4280   #endif /* NDEBUG */
         4281  +int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){
         4282  +  assert( pCur!=0 );
         4283  +  return pCur->eState==CURSOR_VALID;
         4284  +}
  4281   4285   
  4282   4286   /*
  4283   4287   ** Return the value of the integer key or "rowid" for a table btree.
  4284   4288   ** This routine is only valid for a cursor that is pointing into a
  4285   4289   ** ordinary table btree.  If the cursor points to an index btree or
  4286   4290   ** is invalid, the result of this routine is undefined.
  4287   4291   */

Changes to src/btree.h.

   306    306   int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
   307    307   int sqlite3BtreeIsReadonly(Btree *pBt);
   308    308   int sqlite3HeaderSizeBtree(void);
   309    309   
   310    310   #ifndef NDEBUG
   311    311   int sqlite3BtreeCursorIsValid(BtCursor*);
   312    312   #endif
          313  +int sqlite3BtreeCursorIsValidNN(BtCursor*);
   313    314   
   314    315   #ifndef SQLITE_OMIT_BTREECOUNT
   315    316   int sqlite3BtreeCount(BtCursor *, i64 *);
   316    317   #endif
   317    318   
   318    319   #ifdef SQLITE_TEST
   319    320   int sqlite3BtreeCursorInfo(BtCursor*, int*, int);

Changes to src/vdbe.c.

  4795   4795   ** If the table or index is empty and P2>0, then jump immediately to P2.
  4796   4796   ** If P2 is 0 or if the table or index is not empty, fall through
  4797   4797   ** to the following instruction.
  4798   4798   **
  4799   4799   ** This opcode leaves the cursor configured to move in reverse order,
  4800   4800   ** from the end toward the beginning.  In other words, the cursor is
  4801   4801   ** configured to use Prev, not Next.
         4802  +**
         4803  +** If P3 is -1, then the cursor is positioned at the end of the btree
         4804  +** for the purpose of appending a new entry onto the btree.  In that
         4805  +** case P2 must be 0.  It is assumed that the cursor is used only for
         4806  +** appending and so if the cursor is valid, then the cursor must already
         4807  +** be pointing at the end of the btree and so no changes are made to
         4808  +** the cursor.
  4802   4809   */
  4803   4810   case OP_Last: {        /* jump */
  4804   4811     VdbeCursor *pC;
  4805   4812     BtCursor *pCrsr;
  4806   4813     int res;
  4807   4814   
  4808   4815     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4809   4816     pC = p->apCsr[pOp->p1];
  4810   4817     assert( pC!=0 );
  4811   4818     assert( pC->eCurType==CURTYPE_BTREE );
  4812   4819     pCrsr = pC->uc.pCursor;
  4813   4820     res = 0;
  4814   4821     assert( pCrsr!=0 );
  4815         -  rc = sqlite3BtreeLast(pCrsr, &res);
  4816         -  pC->nullRow = (u8)res;
  4817         -  pC->deferredMoveto = 0;
  4818         -  pC->cacheStatus = CACHE_STALE;
  4819   4822     pC->seekResult = pOp->p3;
  4820   4823   #ifdef SQLITE_DEBUG
  4821   4824     pC->seekOp = OP_Last;
  4822   4825   #endif
  4823         -  if( rc ) goto abort_due_to_error;
  4824         -  if( pOp->p2>0 ){
  4825         -    VdbeBranchTaken(res!=0,2);
  4826         -    if( res ) goto jump_to_p2;
         4826  +  if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){
         4827  +    rc = sqlite3BtreeLast(pCrsr, &res);
         4828  +    pC->nullRow = (u8)res;
         4829  +    pC->deferredMoveto = 0;
         4830  +    pC->cacheStatus = CACHE_STALE;
         4831  +    if( rc ) goto abort_due_to_error;
         4832  +    if( pOp->p2>0 ){
         4833  +      VdbeBranchTaken(res!=0,2);
         4834  +      if( res ) goto jump_to_p2;
         4835  +    }
         4836  +  }else{
         4837  +    assert( pOp->p2==0 );
  4827   4838     }
  4828   4839     break;
  4829   4840   }
  4830   4841   
  4831   4842   
  4832   4843   /* Opcode: Sort P1 P2 * * *
  4833   4844   **