Index: src/shell.c ================================================================== --- src/shell.c +++ src/shell.c @@ -612,10 +612,11 @@ sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ int autoExplain; /* Automatically turn on .explain mode */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ int statsOn; /* True to display memory stats before each finalize */ + int vmstepsOn; /* Display VM steps before each finalize */ int scanstatsOn; /* True to display scan stats before each finalize */ int countChanges; /* True to display change counts */ int backslashOn; /* Resolve C-style \x escapes in SQL input text */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ @@ -1994,10 +1995,16 @@ /* print usage stats if stats on */ if( pArg && pArg->statsOn ){ display_stats(db, pArg, 0); } + + if( pArg && pArg->vmstepsOn && pStmt ){ + int iCur = sqlite3_stmt_status(pStmt, SQLITE_STMTSTATUS_VM_STEP, 0); + FILE *out = pArg->traceOut ? pArg->traceOut : pArg->out; + raw_printf(out, "VM steps: %d\n", iCur); + } /* print loop-counters if required */ if( pArg && pArg->scanstatsOn ){ display_scanstats(db, pArg); } @@ -5336,10 +5343,20 @@ utf8_printf(p->out, "%s\n", zVfsName); sqlite3_free(zVfsName); } } }else + + if( c=='v' && strncmp(azArg[0], "vmsteps", n)==0 ){ + if( nArg==2 ){ + p->vmstepsOn = booleanValue(azArg[1]); + }else{ + raw_printf(stderr, "Usage: .vmsteps ?on|off?\n"); + rc = 1; + } + }else + #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){ sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; }else Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -958,10 +958,29 @@ pFrame = p->pFrame; p->pFrame = pFrame->pParent; p->nFrame--; sqlite3VdbeSetChanges(db, p->nChange); pcx = sqlite3VdbeFrameRestore(pFrame); +#ifdef SQLITE_TRACE_TRIGGER + if( (db->mTrace & SQLITE_TRACE_STMT) && aOp[0].p4.z ){ + int nTotal = nVmStep - pFrame->nVmStep; + char *zTrace; + assert( nTotal>=0 ); + assert( db->xTrace ); + zTrace = sqlite3_mprintf("%.*s%s completed (VM steps: total=%d self=%d)", + p->nFrame, " :", + aOp[0].p4.z, nTotal, nVmStep - pFrame->nVmStepAdj + ); + if( zTrace ){ + (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, 0, zTrace); + sqlite3_free(zTrace); + } + if( p->pFrame ){ + p->pFrame->nVmStepAdj += nTotal; + } + } +#endif lastRowid = db->lastRowid; if( pOp->p2==OE_Ignore ){ /* Instruction pcx is the OP_Program that invoked the sub-program ** currently being halted. If the p2 instruction of this OP_Halt ** instruction is set to OE_Ignore, then the sub-program is throwing @@ -5852,10 +5871,14 @@ pFrame->lastRowid = lastRowid; pFrame->nChange = p->nChange; pFrame->nDbChange = p->db->nChange; assert( pFrame->pAuxData==0 ); pFrame->pAuxData = p->pAuxData; +#ifdef SQLITE_TRACE_TRIGGER + pFrame->nVmStep = nVmStep; + pFrame->nVmStepAdj = nVmStep; +#endif p->pAuxData = 0; p->nChange = 0; p->pFrame = pFrame; p->aMem = aMem = VdbeFrameMem(pFrame); p->nMem = pFrame->nChildMem; @@ -6887,10 +6910,21 @@ void (*x)(void*,const char*) = (void(*)(void*,const char*))db->xTrace; char *z = sqlite3VdbeExpandSql(p, zTrace); x(db->pTraceArg, z); sqlite3_free(z); }else +#endif +#ifdef SQLITE_TRACE_TRIGGER + if( p->pFrame ){ + zTrace = sqlite3_mprintf("%.*s%s", p->nFrame-1, + " :", zTrace + ); + if( zTrace ){ + (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace); + sqlite3_free(zTrace); + } + }else #endif { (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace); } } Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -173,10 +173,14 @@ int nMem; /* Number of entries in aMem */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ int nChange; /* Statement changes (Vdbe.nChange) */ int nDbChange; /* Value of db->nChange */ +#ifdef SQLITE_TRACE_TRIGGER + int nVmStep; /* Value of nVmStep at start of program */ + int nVmStepAdj; /* Adjusted for nested programs */ +#endif }; #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) /*