mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Add the OP_IfNoHope and OP_SeekHit opcodes used to reduce the number of
unnecessary sqlite3BtreeMovetoUnpacked() calls when checking for an early exit on IN-operator loops. Futher optimizations are likely possible here. FossilOrigin-Name: 6bf251af4347165a470d39457d61ab6d2a06c206db8f30bd8be5dbb388ae8a5b
This commit is contained in:
56
src/vdbe.c
56
src/vdbe.c
@@ -4034,6 +4034,25 @@ seek_not_found:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SeekHit P1 P2 * * *
|
||||
** Synopsis: seekHit=P2
|
||||
**
|
||||
** Set the seekHit flag on cursor P1 to the value in P2.
|
||||
** The seekHit flag is used by the IfNoHope opcode.
|
||||
**
|
||||
** P1 must be a valid b-tree cursor. P2 must be a boolean value,
|
||||
** either 0 or 1.
|
||||
*/
|
||||
case OP_SeekHit: {
|
||||
VdbeCursor *pC;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( pOp->p2==0 || pOp->p2==1 );
|
||||
pC->seekHit = pOp->p2 & 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Found P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
**
|
||||
@@ -4068,7 +4087,34 @@ seek_not_found:
|
||||
** advanced in either direction. In other words, the Next and Prev
|
||||
** opcodes do not work after this operation.
|
||||
**
|
||||
** See also: Found, NotExists, NoConflict
|
||||
** See also: Found, NotExists, NoConflict, IfNoHope
|
||||
*/
|
||||
/* Opcode: IfNoHope P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
**
|
||||
** Register P3 is the first of P4 registers that form an unpacked
|
||||
** record.
|
||||
**
|
||||
** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then
|
||||
** this opcode is a no-op. But if the seekHit flag of P1 is clear, then
|
||||
** check to see if there is any entry in P1 that matches the
|
||||
** prefix identified by P3 and P4. If no entry matches the prefix,
|
||||
** jump to P2. Otherwise fall through.
|
||||
**
|
||||
** This opcode behaves like OP_NotFound if the seekHit
|
||||
** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
|
||||
**
|
||||
** This opcode is used in IN clause processing for a multi-column key.
|
||||
** If an IN clause is attached to an element of the key other than the
|
||||
** left-most element, and if there are no matches on the most recent
|
||||
** seek over the whole key, then it might be that one of the key element
|
||||
** to the left is prohibiting a match, and hence there is "no hope" of
|
||||
** any match regardless of how many IN clause elements are checked.
|
||||
** In such a case, we abandon the IN clause search early, using this
|
||||
** opcode. The opcode name comes from the fact that the
|
||||
** jump is taken if there is "no hope" of achieving a match.
|
||||
**
|
||||
** See also: NotFound, SeekHit
|
||||
*/
|
||||
/* Opcode: NoConflict P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
@@ -4093,6 +4139,14 @@ seek_not_found:
|
||||
**
|
||||
** See also: NotFound, Found, NotExists
|
||||
*/
|
||||
case OP_IfNoHope: { /* jump, in3 */
|
||||
VdbeCursor *pC;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
if( pC->seekHit ) break;
|
||||
/* Fall through into OP_NotFound */
|
||||
}
|
||||
case OP_NoConflict: /* jump, in3 */
|
||||
case OP_NotFound: /* jump, in3 */
|
||||
case OP_Found: { /* jump, in3 */
|
||||
|
Reference in New Issue
Block a user