]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Merge the implementation of OP_IdxRowid and OP_Seek so that OP_Seek no longer
authordrh <drh@noemail.net>
Sat, 30 Jan 2016 16:59:56 +0000 (16:59 +0000)
committerdrh <drh@noemail.net>
Sat, 30 Jan 2016 16:59:56 +0000 (16:59 +0000)
requires the rowid register and a separate OP_IdxRowid call.  Shorter and
faster prepared statements result.

FossilOrigin-Name: 9bec50a1e7796a6e038db9b1cc7cc1e7e350bf74

manifest
manifest.uuid
src/vdbe.c
src/wherecode.c

index df7711094d155eefa70b39ac044849edb1443752..d850d9282ed917f92a91f41e108d8cb4b52c1f30 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Only\shonor\sthe\sregister\ssubtype\svalue\sif\sthe\sMEM_Subtype\sflag\sis\sset.\nRevised\sand\simproved\sfix\sfor\sticket\s[f45ac567eaa9f9].
-D 2016-01-30T15:52:39.136
+C Merge\sthe\simplementation\sof\sOP_IdxRowid\sand\sOP_Seek\sso\sthat\sOP_Seek\sno\slonger\nrequires\sthe\srowid\sregister\sand\sa\sseparate\sOP_IdxRowid\scall.\s\sShorter\sand\nfaster\sprepared\sstatements\sresult.
+D 2016-01-30T16:59:56.592
 F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 72b7858f02017611c3ac1ddc965251017fed0845
@@ -412,7 +412,7 @@ F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3
 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18
 F src/util.c 72d40df0a52d3f30b462a15f0e094fcbade6dc82
 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
-F src/vdbe.c 49e0a224526f4307ab80e9d3a63697b28cf0cb21
+F src/vdbe.c 73f0f61eb5556e430487671a557d032ecac52240
 F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337
 F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79
 F src/vdbeapi.c 9d640d5efd9a140a6bda8da53b220aa258167993
@@ -428,7 +428,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
 F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
 F src/where.c af9bf5dcec1a0e52726c550924aa91d837166251
 F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a
-F src/wherecode.c ef0d7019029624625416cdf32cc86604c970416f
+F src/wherecode.c 7ea737b14e7a35d7f55cbad589a29aa49dfe3f7a
 F src/whereexpr.c 197a448b52073aee43eca3a2233fc113369eb2d4
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -1422,8 +1422,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 96b780209cc95c3f3769bb880591380d94bfe38d 2e9fb1295cd31fc29c97444c3dec82fef68e939f
-R bd3d63263e82ae4209cc8f920c59f1ec
-T +closed 2e9fb1295cd31fc29c97444c3dec82fef68e939f
+P 1f4c667f37d63fc3ef2e8f2581ecd3a66c054426
+R c807c9436e91d8aabdffdea0ecd68c4e
 U drh
-Z 5703eae66c478a55119b68d54c8bb9ef
+Z a3f05d9c2a4721d817f24f533822e83f
index f4551f775a5e29aff7621914e34e04ac0f15c5e9..01040f34b0e4e2237c0f4d2a2bdf0ab5ebbe30ad 100644 (file)
@@ -1 +1 @@
-1f4c667f37d63fc3ef2e8f2581ecd3a66c054426
\ No newline at end of file
+9bec50a1e7796a6e038db9b1cc7cc1e7e350bf74
\ No newline at end of file
index c6ae836a2855f62127aae0b911e864e85e804d3c..a1e59e1170dc8b54e37435a276824fd9ac2fafd3 100644 (file)
@@ -3857,42 +3857,6 @@ seek_not_found:
   }
   break;
 }
-
-/* Opcode: Seek P1 P2 P3 P4 *
-** Synopsis:  intkey=r[P2]
-**
-** P1 is an open table cursor and P2 is a rowid integer.  Arrange
-** for P1 to move so that it points to the rowid given by P2.
-**
-** This is actually a deferred seek.  Nothing actually happens until
-** the cursor is used to read a record.  That way, if no reads
-** occur, no unnecessary I/O happens.
-**
-** P4 may contain an array of integers (type P4_INTARRAY) containing
-** one entry for each column in the table P1 is open on. If so, then
-** parameter P3 is a cursor open on a database index. If array entry
-** a[i] is non-zero, then reading column (a[i]-1) from cursor P3 is 
-** equivalent to performing the deferred seek and then reading column i 
-** from P1.
-*/
-case OP_Seek: {    /* in2 */
-  VdbeCursor *pC;
-
-  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  pC = p->apCsr[pOp->p1];
-  assert( pC!=0 );
-  assert( pC->eCurType==CURTYPE_BTREE );
-  assert( pC->uc.pCursor!=0 );
-  assert( pC->isTable );
-  pC->nullRow = 0;
-  pIn2 = &aMem[pOp->p2];
-  pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
-  pC->deferredMoveto = 1;
-  assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
-  pC->aAltMap = pOp->p4.ai;
-  pC->pAltCursor = p->apCsr[pOp->p3];
-  break;
-}
   
 
 /* Opcode: Found P1 P2 P3 P4 *
@@ -4987,6 +4951,25 @@ case OP_IdxDelete: {
   break;
 }
 
+/* Opcode: Seek P1 * P3 P4 *
+** Synopsis:  Move P3 to P1.rowid
+**
+** P1 is an open index cursor and P3 is a cursor on the corresponding
+** table.  This opcode does a deferred seek of the P3 table cursor
+** to the row that corresponds to the current row of P1.
+**
+** This is a deferred seek.  Nothing actually happens until
+** the cursor is used to read a record.  That way, if no reads
+** occur, no unnecessary I/O happens.
+**
+** P4 may be an array of integers (type P4_INTARRAY) containing
+** one entry for each column in the P3 table.  If array entry a[i]
+** is non-zero, then reading column (a[i]-1) from cursor P3 is 
+** equivalent to performing the deferred seek and then reading column i 
+** from P1.  This information is stored in P3 and used to redirect
+** reads against P3 over to P1, thus possibly avoiding the need to
+** seek and read cursor P3.
+*/
 /* Opcode: IdxRowid P1 P2 * * *
 ** Synopsis: r[P2]=rowid
 **
@@ -4996,37 +4979,57 @@ case OP_IdxDelete: {
 **
 ** See also: Rowid, MakeRecord.
 */
+case OP_Seek:
 case OP_IdxRowid: {              /* out2 */
-  BtCursor *pCrsr;
-  VdbeCursor *pC;
-  i64 rowid;
+  VdbeCursor *pC;                /* The P1 index cursor */
+  VdbeCursor *pTabCur;           /* The P2 table cursor (OP_Seek only) */
+  i64 rowid;                     /* Rowid that P1 current points to */
 
-  pOut = out2Prerelease(p, pOp);
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   pC = p->apCsr[pOp->p1];
   assert( pC!=0 );
   assert( pC->eCurType==CURTYPE_BTREE );
-  pCrsr = pC->uc.pCursor;
-  assert( pCrsr!=0 );
-  pOut->flags = MEM_Null;
+  assert( pC->uc.pCursor!=0 );
   assert( pC->isTable==0 );
   assert( pC->deferredMoveto==0 );
+  assert( !pC->nullRow || pOp->opcode==OP_IdxRowid );
 
-  /* sqlite3VbeCursorRestore() can only fail if the record has been deleted
-  ** out from under the cursor.  That will never happend for an IdxRowid
-  ** opcode, hence the NEVER() arround the check of the return value.
-  */
+  /* The IdxRowid and Seek opcodes are combined because of the commonality
+  ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */
   rc = sqlite3VdbeCursorRestore(pC);
+
+  /* sqlite3VbeCursorRestore() can only fail if the record has been deleted
+  ** out from under the cursor.  That will never happens for an IdxRowid
+  ** or Seek opcode */
   if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
 
   if( !pC->nullRow ){
     rowid = 0;  /* Not needed.  Only used to silence a warning. */
-    rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid);
+    rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid);
     if( rc!=SQLITE_OK ){
       goto abort_due_to_error;
     }
-    pOut->u.i = rowid;
-    pOut->flags = MEM_Int;
+    if( pOp->opcode==OP_Seek ){
+      assert( pOp->p3>=0 && pOp->p3<p->nCursor );
+      pTabCur = p->apCsr[pOp->p3];
+      assert( pTabCur!=0 );
+      assert( pTabCur->eCurType==CURTYPE_BTREE );
+      assert( pTabCur->uc.pCursor!=0 );
+      assert( pTabCur->isTable );
+      pTabCur->nullRow = 0;
+      pTabCur->movetoTarget = rowid;
+      pTabCur->deferredMoveto = 1;
+      assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
+      pTabCur->aAltMap = pOp->p4.ai;
+      pTabCur->pAltCursor = pC;
+    }else{
+      pOut = out2Prerelease(p, pOp);
+      pOut->u.i = rowid;
+      pOut->flags = MEM_Int;
+    }
+  }else{
+    assert( pOp->opcode==OP_IdxRowid );
+    sqlite3VdbeMemSetNull(&aMem[pOp->p2]);
   }
   break;
 }
index d5902031554d35576a4a92037ce48a15815c1180..3fbd198e31a085aec3e3cd305b361693a5b8f06f 100644 (file)
@@ -768,7 +768,6 @@ static void codeDeferredSeek(
   WhereInfo *pWInfo,              /* Where clause context */
   Index *pIdx,                    /* Index scan is using */
   int iCur,                       /* Cursor for IPK b-tree */
-  int iRowid,                     /* Register containing rowid to seek to */
   int iIdxCur                     /* Index cursor */
 ){
   Parse *pParse = pWInfo->pParse; /* Parse context */
@@ -777,7 +776,7 @@ static void codeDeferredSeek(
   assert( iIdxCur>0 );
   assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
   
-  sqlite3VdbeAddOp3(v, OP_Seek, iCur, iRowid, iIdxCur);
+  sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur);
   if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)
    && sqlite3ParseToplevel(pParse)->writeMask==0 
   ){
@@ -1274,14 +1273,14 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     if( omitTable ){
       /* pIdx is a covering index.  No need to access the main table. */
     }else if( HasRowid(pIdx->pTable) ){
-      iRowidReg = ++pParse->nMem;
-      sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
-      sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
       if( pWInfo->eOnePass!=ONEPASS_OFF ){
+        iRowidReg = ++pParse->nMem;
+        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
+        sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
         sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
         VdbeCoverage(v);
       }else{
-        codeDeferredSeek(pWInfo, pIdx, iCur, iRowidReg, iIdxCur);
+        codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
       }
     }else if( iCur!=iIdxCur ){
       Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);