diff options
author | drh <drh@noemail.net> | 2016-05-26 20:56:38 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2016-05-26 20:56:38 +0000 |
commit | eeb9565a3e3397340a4dc79a8b693e35cdecfb7c (patch) | |
tree | a054e5793db17e2467c972bebaf97c3a7c72a3d8 | |
parent | ce3c5011d9325adf3546505c45d40243db6e7eee (diff) | |
download | sqlite-eeb9565a3e3397340a4dc79a8b693e35cdecfb7c.tar.gz sqlite-eeb9565a3e3397340a4dc79a8b693e35cdecfb7c.zip |
Add a new OP_SeekRowid opcode, that combines the functions of OP_MustBeInt
and OP_NotExists. This makes the code slightly smaller and faster.
FossilOrigin-Name: ffe80a1bfa014943a614fc6993c1749b9bfec4c1
-rw-r--r-- | manifest | 18 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/expr.c | 3 | ||||
-rw-r--r-- | src/pragma.c | 4 | ||||
-rw-r--r-- | src/vdbe.c | 50 | ||||
-rw-r--r-- | src/wherecode.c | 3 |
6 files changed, 57 insertions, 23 deletions
@@ -1,5 +1,5 @@ -C Add\sthe\slibvers.c\stool\sin\sthe\stool/\ssubdirectory. -D 2016-05-25T18:53:39.049 +C Add\sa\snew\sOP_SeekRowid\sopcode,\sthat\scombines\sthe\sfunctions\sof\sOP_MustBeInt\nand\sOP_NotExists.\s\sThis\smakes\sthe\scode\sslightly\ssmaller\sand\sfaster. +D 2016-05-26T20:56:38.450 F Makefile.in f59e0763ff448719fc1bd25513882b0567286317 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 306d73e854b1a92ea06e5d1e637faa5c44de53c7 @@ -333,7 +333,7 @@ F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39 F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f -F src/expr.c 8796c0739b2ad091e6779253f62aad6e767e2be1 +F src/expr.c 81bd7d87985746313770211183e900ed1ad28381 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb F src/func.c ef4c18c8a66143413ce41a58d582d2c14ddf78e1 @@ -372,7 +372,7 @@ F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e F src/pcache.c 5583c8ade4b05075a60ba953ef471d1c1a9c05df F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c 7f51d2b541aab57596adf62db2c4bb025d34f04d -F src/pragma.c 9fdce031ddcb57f0f56e4a8b421b7e7a77de73b0 +F src/pragma.c d98039af2deb5a4990f6635462b3f61f325a6c75 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c a5f0ca08ddede803c241266abb46356ec748ded1 @@ -445,7 +445,7 @@ F src/update.c 4f05ea8cddfa367d045e03589756c02199e8f9bd F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c f2706d5564d2b2887a27c909e8e1575250029503 +F src/vdbe.c 45e4da739187028281e342f79fae0f4145055bec F src/vdbe.h 5591b5add447096e31288b5a0a78ec5d7b5c5170 F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c @@ -461,7 +461,7 @@ F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 F src/where.c 0e54a03d11d4e99ad25528f42ff4c9a6fa7a23da F src/whereInt.h 6e18240be400bef8e4dbafea605251707c5dbf49 -F src/wherecode.c e3f18fcda2d7f8218a09dc33cf495dca0efa6e3e +F src/wherecode.c ba71a4e4bada29aa9842200e6299714bf18c812c F src/whereexpr.c eacc0e60d029a082b4fc0cc42ea98544add1319e F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd @@ -1495,7 +1495,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 41fd46e2962ba9a1e1f6867567499d1f6f5b8372 -R 871df33bb708dea5ddc1c61eb4854aa7 +P 2a41f098b2f0523b3d7e6eba6ae91cc0d30752df +R 810bd747b437c6e4e76eef1099520866 U drh -Z b20c30dd356053a2351766a3c882aef8 +Z 73ea989f24641ac606e6e6c2f5b60872 diff --git a/manifest.uuid b/manifest.uuid index b182bd8e8..9a103ac06 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2a41f098b2f0523b3d7e6eba6ae91cc0d30752df
\ No newline at end of file +ffe80a1bfa014943a614fc6993c1749b9bfec4c1
\ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 9e3b664e8..156db96fa 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2222,8 +2222,7 @@ static void sqlite3ExprCodeIN( if( eType==IN_INDEX_ROWID ){ /* In this case, the RHS is the ROWID of table b-tree */ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); + sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, r1); VdbeCoverage(v); }else{ /* In this case, the RHS is an index b-tree. diff --git a/src/pragma.c b/src/pragma.c index 330e99909..56823c724 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1334,12 +1334,10 @@ void sqlite3Pragma( sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); sqlite3ColumnDefault(v, pTab, iKey, regRow); sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, - sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); }else{ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); } - sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v); sqlite3VdbeGoto(v, addrOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); }else{ diff --git a/src/vdbe.c b/src/vdbe.c index d512c0bc7..d4392a89d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4023,6 +4023,30 @@ case OP_Found: { /* jump, in3 */ break; } +/* Opcode: SeekRowid P1 P2 P3 * * +** Synopsis: intkey=r[P3] +** +** P1 is the index of a cursor open on an SQL table btree (with integer +** keys). If register P3 does not contain an integer or if P1 does not +** contain a record with rowid P3 then jump immediately to P2. +** Or, if P2 is 0, raise an SQLITE_CORRUPT error. If P1 does contain +** a record with rowid P3 then +** leave the cursor pointing at that record and fall through to the next +** instruction. +** +** The OP_NotExists opcode performs the same operation, but with OP_NotExists +** the P3 register must be guaranteed to contain an integer value. With this +** opcode, register P3 might not contain an integer. +** +** The OP_NotFound opcode performs the same operation on index btrees +** (with arbitrary multi-value keys). +** +** This opcode leaves the cursor in a state where it cannot be advanced +** in either direction. In other words, the Next and Prev opcodes will +** not work following this opcode. +** +** See also: Found, NotFound, NoConflict, SeekRowid +*/ /* Opcode: NotExists P1 P2 P3 * * ** Synopsis: intkey=r[P3] ** @@ -4033,6 +4057,10 @@ case OP_Found: { /* jump, in3 */ ** leave the cursor pointing at that record and fall through to the next ** instruction. ** +** The OP_SeekRowid opcode performs the same operation but also allows the +** P3 register to contain a non-integer value, in which case the jump is +** always taken. This opcode requires that P3 always contain an integer. +** ** The OP_NotFound opcode performs the same operation on index btrees ** (with arbitrary multi-value keys). ** @@ -4040,15 +4068,22 @@ case OP_Found: { /* jump, in3 */ ** in either direction. In other words, the Next and Prev opcodes will ** not work following this opcode. ** -** See also: Found, NotFound, NoConflict +** See also: Found, NotFound, NoConflict, SeekRowid */ -case OP_NotExists: { /* jump, in3 */ +case OP_SeekRowid: { /* jump, in3 */ VdbeCursor *pC; BtCursor *pCrsr; int res; u64 iKey; pIn3 = &aMem[pOp->p3]; + if( (pIn3->flags & MEM_Int)==0 ){ + applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding); + if( (pIn3->flags & MEM_Int)==0 ) goto jump_to_p2; + } + /* Fall through into OP_NotExists */ +case OP_NotExists: /* jump, in3 */ + pIn3 = &aMem[pOp->p3]; assert( pIn3->flags & MEM_Int ); assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; @@ -4250,10 +4285,12 @@ case OP_NewRowid: { /* out2 */ ** sqlite3_last_insert_rowid() function (otherwise it is unmodified). ** ** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of -** the last seek operation (OP_NotExists) was a success, then this +** the last seek operation (OP_NotExists or OP_SeekRowid) was a success, +** then this ** operation will not attempt to find the appropriate row before doing ** the insert but will instead overwrite the row that the cursor is -** currently pointing to. Presumably, the prior OP_NotExists opcode +** currently pointing to. Presumably, the prior OP_NotExists or +** OP_SeekRowid opcode ** has already positioned the cursor correctly. This is an optimization ** that boosts performance by avoiding redundant seeks. ** @@ -4611,8 +4648,9 @@ case OP_RowData: { pCrsr = pC->uc.pCursor; /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or - ** OP_Rewind/Op_Next with no intervening instructions that might invalidate - ** the cursor. If this where not the case, on of the following assert()s + ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions + ** that might invalidate the cursor. + ** If this where not the case, on of the following assert()s ** would fail. Should this ever change (because of changes in the code ** generator) then the fix would be to insert a call to ** sqlite3VdbeCursorMoveto(). diff --git a/src/wherecode.c b/src/wherecode.c index 054b1b107..83ee48ac6 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -971,8 +971,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); addrNxt = pLevel->addrNxt; - sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); + sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); VdbeCoverage(v); sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); |