From 487e15dc239ccdb3344d1c99ce120e872bab4a74 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 20 Sep 2012 18:34:38 -0400 Subject: Imported Upstream version 2.0.6 --- src/vdbetrace.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) (limited to 'src/vdbetrace.c') diff --git a/src/vdbetrace.c b/src/vdbetrace.c index de123b5..c71a7c4 100644 --- a/src/vdbetrace.c +++ b/src/vdbetrace.c @@ -12,6 +12,8 @@ ** ** This file contains code used to insert the values of host parameters ** (aka "wildcards") into the SQL text output by sqlite3_trace(). +** +** The Vdbe parse-tree explainer is also found here. */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -152,3 +154,119 @@ char *sqlite3VdbeExpandSql( } #endif /* #ifndef SQLITE_OMIT_TRACE */ + +/***************************************************************************** +** The following code implements the data-structure explaining logic +** for the Vdbe. +*/ + +#if defined(SQLITE_ENABLE_TREE_EXPLAIN) + +/* +** Allocate a new Explain object +*/ +void sqlite3ExplainBegin(Vdbe *pVdbe){ + if( pVdbe ){ + Explain *p; + sqlite3BeginBenignMalloc(); + p = sqlite3_malloc( sizeof(Explain) ); + if( p ){ + memset(p, 0, sizeof(*p)); + p->pVdbe = pVdbe; + sqlite3_free(pVdbe->pExplain); + pVdbe->pExplain = p; + sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase), + SQLITE_MAX_LENGTH); + p->str.useMalloc = 2; + }else{ + sqlite3EndBenignMalloc(); + } + } +} + +/* +** Return true if the Explain ends with a new-line. +*/ +static int endsWithNL(Explain *p){ + return p && p->str.zText && p->str.nChar + && p->str.zText[p->str.nChar-1]=='\n'; +} + +/* +** Append text to the indentation +*/ +void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){ + Explain *p; + if( pVdbe && (p = pVdbe->pExplain)!=0 ){ + va_list ap; + if( p->nIndent && endsWithNL(p) ){ + int n = p->nIndent; + if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent); + sqlite3AppendSpace(&p->str, p->aIndent[n-1]); + } + va_start(ap, zFormat); + sqlite3VXPrintf(&p->str, 1, zFormat, ap); + va_end(ap); + } +} + +/* +** Append a '\n' if there is not already one. +*/ +void sqlite3ExplainNL(Vdbe *pVdbe){ + Explain *p; + if( pVdbe && (p = pVdbe->pExplain)!=0 && !endsWithNL(p) ){ + sqlite3StrAccumAppend(&p->str, "\n", 1); + } +} + +/* +** Push a new indentation level. Subsequent lines will be indented +** so that they begin at the current cursor position. +*/ +void sqlite3ExplainPush(Vdbe *pVdbe){ + Explain *p; + if( pVdbe && (p = pVdbe->pExplain)!=0 ){ + if( p->str.zText && p->nIndentaIndent) ){ + const char *z = p->str.zText; + int i = p->str.nChar-1; + int x; + while( i>=0 && z[i]!='\n' ){ i--; } + x = (p->str.nChar - 1) - i; + if( p->nIndent && xaIndent[p->nIndent-1] ){ + x = p->aIndent[p->nIndent-1]; + } + p->aIndent[p->nIndent] = x; + } + p->nIndent++; + } +} + +/* +** Pop the indentation stack by one level. +*/ +void sqlite3ExplainPop(Vdbe *p){ + if( p && p->pExplain ) p->pExplain->nIndent--; +} + +/* +** Free the indentation structure +*/ +void sqlite3ExplainFinish(Vdbe *pVdbe){ + if( pVdbe && pVdbe->pExplain ){ + sqlite3_free(pVdbe->zExplain); + sqlite3ExplainNL(pVdbe); + pVdbe->zExplain = sqlite3StrAccumFinish(&pVdbe->pExplain->str); + sqlite3_free(pVdbe->pExplain); + pVdbe->pExplain = 0; + sqlite3EndBenignMalloc(); + } +} + +/* +** Return the explanation of a virtual machine. +*/ +const char *sqlite3VdbeExplanation(Vdbe *pVdbe){ + return (pVdbe && pVdbe->zExplain) ? pVdbe->zExplain : 0; +} +#endif /* defined(SQLITE_DEBUG) */ -- cgit v1.2.3