1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Have sqlite3_stmt_scanstatus_v2() return an NCYCLE value for all loops, not just virtual tables ones. The value returned is the sum of the NCYCLE counts for the various opcodes that move or read data from the table or index cursor associated with the loop.

FossilOrigin-Name: 9499b2f51e8174c6b8a67840c92ba23b7dd1dc8dc2b91fca0c5dc07b71662149
This commit is contained in:
dan
2022-12-06 18:48:06 +00:00
parent 29226fc023
commit 2adb309ead
7 changed files with 95 additions and 63 deletions

View File

@@ -2780,7 +2780,7 @@ case OP_Offset: { /* out3 */
** typeof() function or the IS NULL or IS NOT NULL operators or the
** equivalent. In this case, all content loading can be omitted.
*/
case OP_Column: {
case OP_Column: { /* ncycle */
u32 p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
BtCursor *pCrsr; /* The B-Tree cursor corresponding to pC */
@@ -4132,7 +4132,7 @@ case OP_SetCookie: {
**
** See also: OP_OpenRead, OP_ReopenIdx
*/
case OP_ReopenIdx: {
case OP_ReopenIdx: { /* ncycle */
int nField;
KeyInfo *pKeyInfo;
u32 p2;
@@ -4153,7 +4153,7 @@ case OP_ReopenIdx: {
}
/* If the cursor is not currently open or is open on a different
** index, then fall through into OP_OpenRead to force a reopen */
case OP_OpenRead:
case OP_OpenRead: /* ncycle */
case OP_OpenWrite:
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
@@ -4247,7 +4247,7 @@ open_cursor_set_hints:
**
** Duplicate ephemeral cursors are used for self-joins of materialized views.
*/
case OP_OpenDup: {
case OP_OpenDup: { /* ncycle */
VdbeCursor *pOrig; /* The original cursor to be duplicated */
VdbeCursor *pCx; /* The new cursor */
@@ -4309,8 +4309,8 @@ case OP_OpenDup: {
** by this opcode will be used for automatically created transient
** indices in joins.
*/
case OP_OpenAutoindex:
case OP_OpenEphemeral: {
case OP_OpenAutoindex: /* ncycle */
case OP_OpenEphemeral: { /* ncycle */
VdbeCursor *pCx;
KeyInfo *pKeyInfo;
@@ -4468,7 +4468,7 @@ case OP_OpenPseudo: {
** Close a cursor previously opened as P1. If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
case OP_Close: { /* ncycle */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
p->apCsr[pOp->p1] = 0;
@@ -4585,10 +4585,10 @@ case OP_ColumnsUsed: {
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLT: /* jump, in3, group */
case OP_SeekLE: /* jump, in3, group */
case OP_SeekGE: /* jump, in3, group */
case OP_SeekGT: { /* jump, in3, group */
case OP_SeekLT: /* jump, in3, group, ncycle */
case OP_SeekLE: /* jump, in3, group, ncycle */
case OP_SeekGE: /* jump, in3, group, ncycle */
case OP_SeekGT: { /* jump, in3, group, ncycle */
int res; /* Comparison result */
int oc; /* Opcode */
VdbeCursor *pC; /* The cursor to seek */
@@ -4854,7 +4854,7 @@ seek_not_found:
** jump to SeekOP.P2 if This.P5==0 or to This.P2 if This.P5>0.
** </ol>
*/
case OP_SeekScan: {
case OP_SeekScan: { /* ncycle */
VdbeCursor *pC;
int res;
int nStep;
@@ -4976,7 +4976,7 @@ case OP_SeekScan: {
**
** P1 must be a valid b-tree cursor.
*/
case OP_SeekHit: {
case OP_SeekHit: { /* ncycle */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
@@ -5108,7 +5108,7 @@ case OP_IfNotOpen: { /* jump */
**
** See also: NotFound, Found, NotExists
*/
case OP_IfNoHope: { /* jump, in3 */
case OP_IfNoHope: { /* jump, in3, ncycle */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
@@ -5122,9 +5122,9 @@ case OP_IfNoHope: { /* jump, in3 */
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
case OP_NoConflict: /* jump, in3, ncycle */
case OP_NotFound: /* jump, in3, ncycle */
case OP_Found: { /* jump, in3, ncycle */
int alreadyExists;
int ii;
VdbeCursor *pC;
@@ -5254,7 +5254,7 @@ case OP_Found: { /* jump, in3 */
**
** See also: Found, NotFound, NoConflict, SeekRowid
*/
case OP_SeekRowid: { /* jump, in3 */
case OP_SeekRowid: { /* jump, in3, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
@@ -5279,7 +5279,7 @@ case OP_SeekRowid: { /* jump, in3 */
}
/* Fall through into OP_NotExists */
/* no break */ deliberate_fall_through
case OP_NotExists: /* jump, in3 */
case OP_NotExists: /* jump, in3, ncycle */
pIn3 = &aMem[pOp->p3];
assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -5903,7 +5903,7 @@ case OP_RowData: {
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
case OP_Rowid: { /* out2 */
case OP_Rowid: { /* out2, ncycle */
VdbeCursor *pC;
i64 v;
sqlite3_vtab *pVtab;
@@ -6002,8 +6002,8 @@ case OP_NullRow: {
** from the end toward the beginning. In other words, the cursor is
** configured to use Prev, not Next.
*/
case OP_SeekEnd:
case OP_Last: { /* jump */
case OP_SeekEnd: /* ncycle */
case OP_Last: { /* jump, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
@@ -6108,7 +6108,7 @@ case OP_Sort: { /* jump */
** from the beginning toward the end. In other words, the cursor is
** configured to use Next, not Prev.
*/
case OP_Rewind: { /* jump */
case OP_Rewind: { /* jump, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
@@ -6202,7 +6202,7 @@ case OP_SorterNext: { /* jump */
rc = sqlite3VdbeSorterNext(db, pC);
goto next_tail;
case OP_Prev: /* jump */
case OP_Prev: /* jump, ncycle */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5==0
|| pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
@@ -6217,7 +6217,7 @@ case OP_Prev: /* jump */
rc = sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3);
goto next_tail;
case OP_Next: /* jump */
case OP_Next: /* jump, ncycle */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5==0
|| pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
@@ -6409,8 +6409,8 @@ case OP_IdxDelete: {
**
** See also: Rowid, MakeRecord.
*/
case OP_DeferredSeek:
case OP_IdxRowid: { /* out2 */
case OP_DeferredSeek: /* ncycle */
case OP_IdxRowid: { /* out2, ncycle */
VdbeCursor *pC; /* The P1 index cursor */
VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */
i64 rowid; /* Rowid that P1 current points to */
@@ -6472,8 +6472,8 @@ case OP_IdxRowid: { /* out2 */
** seek operation now, without further delay. If the cursor seek has
** already occurred, this instruction is a no-op.
*/
case OP_FinishSeek: {
VdbeCursor *pC; /* The P1 index cursor */
case OP_FinishSeek: { /* ncycle */
VdbeCursor *pC; /* The P1 index cursor */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
@@ -6528,10 +6528,10 @@ case OP_FinishSeek: {
** If the P1 index entry is less than or equal to the key value then jump
** to P2. Otherwise fall through to the next instruction.
*/
case OP_IdxLE: /* jump */
case OP_IdxGT: /* jump */
case OP_IdxLT: /* jump */
case OP_IdxGE: { /* jump */
case OP_IdxLE: /* jump, ncycle */
case OP_IdxGT: /* jump, ncycle */
case OP_IdxLT: /* jump, ncycle */
case OP_IdxGE: { /* jump, ncycle */
VdbeCursor *pC;
int res;
UnpackedRecord r;
@@ -7952,7 +7952,7 @@ case OP_VDestroy: {
** P1 is a cursor number. This opcode opens a cursor to the virtual
** table and stores that cursor in P1.
*/
case OP_VOpen: {
case OP_VOpen: { /* ncycle */
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVCur;
sqlite3_vtab *pVtab;
@@ -7999,7 +7999,7 @@ case OP_VOpen: {
** cursor. Register P3 is used to hold the values returned by
** sqlite3_vtab_in_first() and sqlite3_vtab_in_next().
*/
case OP_VInitIn: { /* out2 */
case OP_VInitIn: { /* out2, ncycle */
VdbeCursor *pC; /* The cursor containing the RHS values */
ValueList *pRhs; /* New ValueList object to put in reg[P2] */
@@ -8036,7 +8036,7 @@ case OP_VInitIn: { /* out2 */
**
** A jump is made to P2 if the result set after filtering would be empty.
*/
case OP_VFilter: { /* jump */
case OP_VFilter: { /* jump, ncycle */
int nArg;
int iQuery;
const sqlite3_module *pModule;
@@ -8096,7 +8096,7 @@ case OP_VFilter: { /* jump */
** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are
** unused by OP_VColumn.
*/
case OP_VColumn: {
case OP_VColumn: { /* ncycle */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
@@ -8148,7 +8148,7 @@ case OP_VColumn: {
** jump to instruction P2. Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: { /* jump */
case OP_VNext: { /* jump, ncycle */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;