/ Check-in [ffe80a1b]
Login

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

Overview
Comment:Add a new OP_SeekRowid opcode, that combines the functions of OP_MustBeInt and OP_NotExists. This makes the code slightly smaller and faster.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ffe80a1bfa014943a614fc6993c1749b9bfec4c1
User & Date: drh 2016-05-26 20:56:38
Context
2016-05-27
01:07
Fix the Lemon-generated parser so that it compiles with -DYYSTACKDEPTH=0. It does compile now, but there are subtle issues still. check-in: 28d439f8 user: drh tags: trunk
2016-05-26
20:56
Add a new OP_SeekRowid opcode, that combines the functions of OP_MustBeInt and OP_NotExists. This makes the code slightly smaller and faster. check-in: ffe80a1b user: drh tags: trunk
2016-05-25
18:53
Add the libvers.c tool in the tool/ subdirectory. check-in: 2a41f098 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  2218   2218           sqlite3VdbeJumpHere(v, addr1);
  2219   2219         }
  2220   2220       }
  2221   2221     
  2222   2222       if( eType==IN_INDEX_ROWID ){
  2223   2223         /* In this case, the RHS is the ROWID of table b-tree
  2224   2224         */
  2225         -      sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
  2226         -      sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
         2225  +      sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, r1);
  2227   2226         VdbeCoverage(v);
  2228   2227       }else{
  2229   2228         /* In this case, the RHS is an index b-tree.
  2230   2229         */
  2231   2230         sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
  2232   2231     
  2233   2232         /* If the set membership test fails, then the result of the 

Changes to src/pragma.c.

  1330   1330           if( pParent && pIdx==0 ){
  1331   1331             int iKey = pFK->aCol[0].iFrom;
  1332   1332             assert( iKey>=0 && iKey<pTab->nCol );
  1333   1333             if( iKey!=pTab->iPKey ){
  1334   1334               sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
  1335   1335               sqlite3ColumnDefault(v, pTab, iKey, regRow);
  1336   1336               sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v);
  1337         -            sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, 
  1338         -               sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v);
  1339   1337             }else{
  1340   1338               sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
  1341   1339             }
  1342         -          sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v);
         1340  +          sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v);
  1343   1341             sqlite3VdbeGoto(v, addrOk);
  1344   1342             sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
  1345   1343           }else{
  1346   1344             for(j=0; j<pFK->nCol; j++){
  1347   1345               sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
  1348   1346                               aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
  1349   1347               sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);

Changes to src/vdbe.c.

  4019   4019     }else{
  4020   4020       VdbeBranchTaken(takeJump||alreadyExists==0,2);
  4021   4021       if( takeJump || !alreadyExists ) goto jump_to_p2;
  4022   4022     }
  4023   4023     break;
  4024   4024   }
  4025   4025   
         4026  +/* Opcode: SeekRowid P1 P2 P3 * *
         4027  +** Synopsis: intkey=r[P3]
         4028  +**
         4029  +** P1 is the index of a cursor open on an SQL table btree (with integer
         4030  +** keys).  If register P3 does not contain an integer or if P1 does not
         4031  +** contain a record with rowid P3 then jump immediately to P2.  
         4032  +** Or, if P2 is 0, raise an SQLITE_CORRUPT error. If P1 does contain
         4033  +** a record with rowid P3 then 
         4034  +** leave the cursor pointing at that record and fall through to the next
         4035  +** instruction.
         4036  +**
         4037  +** The OP_NotExists opcode performs the same operation, but with OP_NotExists
         4038  +** the P3 register must be guaranteed to contain an integer value.  With this
         4039  +** opcode, register P3 might not contain an integer.
         4040  +**
         4041  +** The OP_NotFound opcode performs the same operation on index btrees
         4042  +** (with arbitrary multi-value keys).
         4043  +**
         4044  +** This opcode leaves the cursor in a state where it cannot be advanced
         4045  +** in either direction.  In other words, the Next and Prev opcodes will
         4046  +** not work following this opcode.
         4047  +**
         4048  +** See also: Found, NotFound, NoConflict, SeekRowid
         4049  +*/
  4026   4050   /* Opcode: NotExists P1 P2 P3 * *
  4027   4051   ** Synopsis: intkey=r[P3]
  4028   4052   **
  4029   4053   ** P1 is the index of a cursor open on an SQL table btree (with integer
  4030   4054   ** keys).  P3 is an integer rowid.  If P1 does not contain a record with
  4031   4055   ** rowid P3 then jump immediately to P2.  Or, if P2 is 0, raise an
  4032   4056   ** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then 
  4033   4057   ** leave the cursor pointing at that record and fall through to the next
  4034   4058   ** instruction.
  4035   4059   **
         4060  +** The OP_SeekRowid opcode performs the same operation but also allows the
         4061  +** P3 register to contain a non-integer value, in which case the jump is
         4062  +** always taken.  This opcode requires that P3 always contain an integer.
         4063  +**
  4036   4064   ** The OP_NotFound opcode performs the same operation on index btrees
  4037   4065   ** (with arbitrary multi-value keys).
  4038   4066   **
  4039   4067   ** This opcode leaves the cursor in a state where it cannot be advanced
  4040   4068   ** in either direction.  In other words, the Next and Prev opcodes will
  4041   4069   ** not work following this opcode.
  4042   4070   **
  4043         -** See also: Found, NotFound, NoConflict
         4071  +** See also: Found, NotFound, NoConflict, SeekRowid
  4044   4072   */
  4045         -case OP_NotExists: {        /* jump, in3 */
         4073  +case OP_SeekRowid: {        /* jump, in3 */
  4046   4074     VdbeCursor *pC;
  4047   4075     BtCursor *pCrsr;
  4048   4076     int res;
  4049   4077     u64 iKey;
  4050   4078   
  4051   4079     pIn3 = &aMem[pOp->p3];
         4080  +  if( (pIn3->flags & MEM_Int)==0 ){
         4081  +    applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding);
         4082  +    if( (pIn3->flags & MEM_Int)==0 ) goto jump_to_p2;
         4083  +  }
         4084  +  /* Fall through into OP_NotExists */
         4085  +case OP_NotExists:          /* jump, in3 */
         4086  +  pIn3 = &aMem[pOp->p3];
  4052   4087     assert( pIn3->flags & MEM_Int );
  4053   4088     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4054   4089     pC = p->apCsr[pOp->p1];
  4055   4090     assert( pC!=0 );
  4056   4091   #ifdef SQLITE_DEBUG
  4057   4092     pC->seekOp = 0;
  4058   4093   #endif
................................................................................
  4246   4281   **
  4247   4282   ** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
  4248   4283   ** incremented (otherwise not).  If the OPFLAG_LASTROWID flag of P5 is set,
  4249   4284   ** then rowid is stored for subsequent return by the
  4250   4285   ** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
  4251   4286   **
  4252   4287   ** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of
  4253         -** the last seek operation (OP_NotExists) was a success, then this
         4288  +** the last seek operation (OP_NotExists or OP_SeekRowid) was a success,
         4289  +** then this
  4254   4290   ** operation will not attempt to find the appropriate row before doing
  4255   4291   ** the insert but will instead overwrite the row that the cursor is
  4256         -** currently pointing to.  Presumably, the prior OP_NotExists opcode
         4292  +** currently pointing to.  Presumably, the prior OP_NotExists or
         4293  +** OP_SeekRowid opcode
  4257   4294   ** has already positioned the cursor correctly.  This is an optimization
  4258   4295   ** that boosts performance by avoiding redundant seeks.
  4259   4296   **
  4260   4297   ** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
  4261   4298   ** UPDATE operation.  Otherwise (if the flag is clear) then this opcode
  4262   4299   ** is part of an INSERT operation.  The difference is only important to
  4263   4300   ** the update hook.
................................................................................
  4607   4644     assert( pC->isTable || pOp->opcode!=OP_RowData );
  4608   4645     assert( pC->isTable==0 || pOp->opcode==OP_RowData );
  4609   4646     assert( pC->nullRow==0 );
  4610   4647     assert( pC->uc.pCursor!=0 );
  4611   4648     pCrsr = pC->uc.pCursor;
  4612   4649   
  4613   4650     /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
  4614         -  ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
  4615         -  ** the cursor.  If this where not the case, on of the following assert()s
         4651  +  ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
         4652  +  ** that might invalidate the cursor.
         4653  +  ** If this where not the case, on of the following assert()s
  4616   4654     ** would fail.  Should this ever change (because of changes in the code
  4617   4655     ** generator) then the fix would be to insert a call to
  4618   4656     ** sqlite3VdbeCursorMoveto().
  4619   4657     */
  4620   4658     assert( pC->deferredMoveto==0 );
  4621   4659     assert( sqlite3BtreeCursorIsValid(pCrsr) );
  4622   4660   #if 0  /* Not required due to the previous to assert() statements */

Changes to src/wherecode.c.

   967    967       assert( pTerm->pExpr!=0 );
   968    968       assert( omitTable==0 );
   969    969       testcase( pTerm->wtFlags & TERM_VIRTUAL );
   970    970       iReleaseReg = ++pParse->nMem;
   971    971       iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
   972    972       if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
   973    973       addrNxt = pLevel->addrNxt;
   974         -    sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v);
   975         -    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
          974  +    sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
   976    975       VdbeCoverage(v);
   977    976       sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
   978    977       sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
   979    978       VdbeComment((v, "pk"));
   980    979       pLevel->op = OP_Noop;
   981    980     }else if( (pLoop->wsFlags & WHERE_IPK)!=0
   982    981            && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0