# endif
#endif
+/*
+** These are the Selective Debugging macros, which give finer-grained debugging
+** than available via SQLITE_DEBUG. No use of SQLITE_DEBUG is disturbed
+** if code uses Selective Debugging. Selective Debugging introduces both
+** debug levels (ie a value for DEBUG_LEVEL) and also debug classes (for
+** example, DEBUG_VIRTUAL_MACHINE or DEBUG_STORAGE).
+**
+** Levels of Debugging Info, currently 3 levels 1-3
+**
+** Level 3 is the default, and applies if DEBUG_LEVEL is undefined
+**
+**
+** Level 1 status labels, such as "Flag status in Opcode XX is %s". Also
+** useful for ad-hoc debugging
+** Level 2 Level 1 plus flow labels, such as notification of
+** "Entering/Leaving Function X"
+** Level 3 Level 2 plus data structure dumps, and anything else
+*/
+
+
/*
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
** 0 means mutexes are permanently disable and the library is never
char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
-#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
+#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_SELECTIVE_DEBUG)
void sqlite3DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE_TEST)
void *sqlite3TestTextToPtr(const char*);
#endif
+#if defined(SQLITE_SELECTIVE_DEBUG)
+ #define SELECTIVE_DEBUG(l) DEBUG_ALL || (l)
+
+ #if !defined(DEBUG_LEVEL) /* default to 3 */
+ #define DEBUG_LEVEL 3
+ #endif
+
+ #if (DEBUG_LEVEL < 1) || (DEBUG_LEVEL > 3)
+ #error "DEBUG_LEVEL must be between 1 and 3. Default is 3"
+ #endif
+#else
+ #define SELECTIVE_DEBUG(l) 0
+
+ #if defined(DEBUG_ALL)
+ #error "DEBUG_ALL specified without SQLITE_SELECTIVE_DEBUG"
+ #endif
+
+ #if defined(DEBUG_LEVEL)
+ #error "DEBUG_LEVEL specified without SQLITE_SELECTIVE_DEBUG"
+ #endif
+
+#endif
+
+#if defined(SELECTIVE_DEBUG)
+
+ #define DEBUG_PRINT(level,x) \
+ if (level <= DEBUG_LEVEL) { \
+ sqlite3DebugPrintf("Level: %d file:%s line:%d %s\n",level,__FILE__,__LINE__,x); \
+ }
+
+#else
+ #define DEBUG_PRINT(x) do {} while (0)
+#endif
+
#if defined(SQLITE_DEBUG)
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
** be changed out from under the copy. This macro verifies that nothing
** like that ever happens.
*/
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
#else
# define memAboutToChange(P,M)
# define UPDATE_MAX_BLOBSIZE(P)
#endif
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/* This routine provides a convenient place to set a breakpoint during
** tracing with PRAGMA vdbe_trace=on. The breakpoint fires right after
** each opcode is printed. Variables "pc" (program counter) and pOp are
return 0;
}
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/*
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
}
#endif
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/*
** Print the value of a register for tracing purposes:
*/
}
#endif
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/*
** Show the values of all registers in the virtual machine. Used for
** interactive debugging.
#endif /* SQLITE_DEBUG */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
#else
# define REGISTER_TRACE(R,M)
){
Op *aOp = p->aOp; /* Copy of p->aOp */
Op *pOp = aOp; /* Current operation */
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) || defined(DEBUG_VIRTUAL_MACHINE)
Op *pOrigOp; /* Value of pOp at the top of the loop */
#endif
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */
#endif
int rc = SQLITE_OK; /* Value to return */
db->busyHandler.nBusy = 0;
if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
sqlite3VdbeIOTraceSql(p);
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
sqlite3BeginBenignMalloc();
if( p->pc==0
&& (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
if( p->anExec ) p->anExec[(int)(pOp-aOp)]++;
#endif
- /* Only allow tracing if SQLITE_DEBUG is defined.
+ /* Only allow tracing if SQLITE_DEBUG or DEBUG_VIRTUAL_MACHINE is defined.
*/
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( db->flags & SQLITE_VdbeTrace ){
sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp);
test_trace_breakpoint((int)(pOp - aOp),pOp,p);
#endif
/* Sanity checking on other operands */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
{
u8 opProperty = sqlite3OpcodeProperty[pOp->opcode];
if( (opProperty & OPFLG_IN1)!=0 ){
}
}
#endif
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) || defined(DEBUG_VIRTUAL_MACHINE)
pOrigOp = pOp;
#endif
*/
case OP_Goto: { /* jump */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/* In debuggging mode, when the p5 flags is set on an OP_Goto, that
** means we should really jump back to the preceeding OP_ReleaseReg
** instruction. */
*/
case OP_HaltIfNull: { /* in3 */
pIn3 = &aMem[pOp->p3];
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
if( (pIn3->flags & MEM_Null)==0 ) break;
int pcx;
pcx = (int)(pOp - aOp);
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
if( pOp->p1==SQLITE_OK && p->pFrame ){
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
pOut->n = 0;
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pOut->uTemp = 0;
#endif
while( cnt>0 ){
assert( memIsValid(pIn1) );
memAboutToChange(p, pOut);
sqlite3VdbeMemMove(pOut, pIn1);
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pIn1->pScopyFrom = 0;
{ int i;
for(i=1; i<p->nMem; i++){
memAboutToChange(p, pOut);
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
Deephemeralize(pOut);
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pOut->pScopyFrom = 0;
#endif
REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut);
pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pOut->pScopyFrom = pIn1;
pOut->mScopyFlags = pIn1->flags;
#endif
|| (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
sqlite3VdbeMemNulTerminate(&pMem[i]);
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/* The registers in the result will not be used again when the
** prepared statement restarts. This is because sqlite3_column()
** APIs might have caused type conversions of made other changes to
*/
case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/* Verify the preconditions of this opcode - that it follows an OP_Lt or
** OP_Gt with the SQLITE_STOREP2 flag set, with zero or more intervening
** OP_ReleaseReg opcodes */
assert( pKeyInfo!=0 );
p1 = pOp->p1;
p2 = pOp->p2;
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( aPermute ){
int k, mx = 0;
for(k=0; k<n; k++) if( aPermute[k]>(u32)mx ) mx = aPermute[k];
pCur->nullRow = 1;
pCur->isOrdered = 1;
pCur->pgnoRoot = p2;
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pCur->wrFlag = wrFlag;
#endif
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor);
oc = pOp->opcode;
eqOnly = 0;
pC->nullRow = 0;
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pC->seekOp = pOp->opcode;
#endif
assert( oc!=OP_SeekLT || r.default_rc==+1 );
r.aMem = &aMem[pOp->p3];
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
r.eqSeen = 0;
assert( pC->eCurType==CURTYPE_BTREE );
assert( !pC->isTable );
if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( db->flags&SQLITE_VdbeTrace ){
printf("... cursor not valid - fall through\n");
}
r.nField = (u16)pOp[1].p4.i;
r.default_rc = 0;
r.aMem = &aMem[pOp[1].p3];
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
{
int i;
for(i=0; i<r.nField; i++){
if( rc ) goto abort_due_to_error;
if( res>0 ){
seekscan_search_fail:
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( db->flags&SQLITE_VdbeTrace ){
printf("... %d steps and then skip\n", pOp->p1 - nStep);
}
goto jump_to_p2;
}
if( res==0 ){
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( db->flags&SQLITE_VdbeTrace ){
printf("... %d steps and then success\n", pOp->p1 - nStep);
}
break;
}
if( nStep<=0 ){
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( db->flags&SQLITE_VdbeTrace ){
printf("... fall through after %d steps\n", pOp->p1);
}
assert( pOp->p4type==P4_INT32 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pC->seekOp = pOp->opcode;
#endif
pIn3 = &aMem[pOp->p3];
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
r.aMem = pIn3;
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
for(ii=0; ii<r.nField; ii++){
assert( memIsValid(&r.aMem[ii]) );
assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
notExistsWithKey:
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid;
#endif
assert( pC->isTable );
assert( pC->deferredMoveto==0 );
sqlite3VdbeIncrWriteCounter(p, pC);
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( pOp->p4type==P4_TABLE
&& HasRowid(pOp->p4.pTab)
&& pOp->p5==0
assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION );
assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE );
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( p->pFrame==0 ){
if( pC->isEphemeral==0
&& (pOp->p5 & OPFLAG_AUXDELETE)==0
assert( pC->uc.pCursor!=0 );
sqlite3BtreeClearCursor(pC->uc.pCursor);
}
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( pC->seekOp==0 ) pC->seekOp = OP_NullRow;
#endif
break;
pCrsr = pC->uc.pCursor;
res = 0;
assert( pCrsr!=0 );
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pC->seekOp = pOp->opcode;
#endif
if( pOp->opcode==OP_SeekEnd ){
assert( pC!=0 );
assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
res = 1;
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pC->seekOp = OP_Rewind;
#endif
if( isSorter(pC) ){
r.default_rc = 0;
}
r.aMem = &aMem[pOp->p3];
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
{
int i;
for(i=0; i<r.nField; i++){
** on every btree. This is a prerequisite for invoking
** sqlite3InitCallback().
*/
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
for(iDb=0; iDb<db->nDb; iDb++){
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
}
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
pFrame->anExec = p->anExec;
#endif
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
pFrame->iFrameMagic = SQLITE_FRAME_MAGIC;
#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
p->anExec = 0;
#endif
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/* Verify that second and subsequent executions of the same trigger do not
** try to reuse register values from the first use. */
{
pCtx = pOp->p4.pCtx;
pMem = &aMem[pOp->p3];
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( pOp->p1 ){
/* This is an OP_AggInverse call. Verify that xStep has always
** been called at least once prior to any xInverse call. */
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
for(i=0; i<pCtx->argc; i++){
assert( memIsValid(pCtx->argv[i]) );
REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
assert( pCtx->pVdbe==p );
memAboutToChange(p, pOut);
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
for(i=0; i<pCtx->argc; i++){
assert( memIsValid(pCtx->argv[i]) );
REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
}
}
#endif /* SQLITE_USE_FCNTL_TRACE */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( (db->flags & SQLITE_SqlTrace)!=0
&& (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
){
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/* Opcode: Abortable * * * * *
**
** Verify that an Abort can happen. Assert if an Abort at this point
}
#endif
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
/* Opcode: ReleaseReg P1 P2 P3 * P5
** Synopsis: release r[P1@P2] mask P3
**
#ifndef NDEBUG
assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] );
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(DEBUG_VIRTUAL_MACHINE)
if( db->flags & SQLITE_VdbeTrace ){
u8 opProperty = sqlite3OpcodeProperty[pOrigOp->opcode];
if( rc!=0 ) printf("rc=%d\n",rc);