mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-15 11:41:13 +03:00
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
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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{
|
||||
|
||||
50
src/vdbe.c
50
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,14 +4068,21 @@ 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 );
|
||||
@@ -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().
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user