1 /* 2 ** 2009 November 25 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** 13 ** This file contains code used to insert the values of host parameters 14 ** (aka "wildcards") into the SQL text output by sqlite3_trace(). 15 ** 16 ** The Vdbe parse-tree explainer is also found here. 17 */ 18 #include "sqliteInt.h" 19 #include "vdbeInt.h" 20 21 #ifndef SQLITE_OMIT_TRACE 22 23 /* 24 ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of 25 ** bytes in this text up to but excluding the first character in 26 ** a host parameter. If the text contains no host parameters, return 27 ** the total number of bytes in the text. 28 */ 29 static int findNextHostParameter(const char *zSql, int *pnToken){ 30 int tokenType; 31 int nTotal = 0; 32 int n; 33 34 *pnToken = 0; 35 while( zSql[0] ){ 36 n = sqlite3GetToken((u8*)zSql, &tokenType); 37 assert( n>0 && tokenType!=TK_ILLEGAL ); 38 if( tokenType==TK_VARIABLE ){ 39 *pnToken = n; 40 break; 41 } 42 nTotal += n; 43 zSql += n; 44 } 45 return nTotal; 46 } 47 48 /* 49 ** This function returns a pointer to a nul-terminated string in memory 50 ** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the 51 ** string contains a copy of zRawSql but with host parameters expanded to 52 ** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1, 53 ** then the returned string holds a copy of zRawSql with "-- " prepended 54 ** to each line of text. 55 ** 56 ** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then 57 ** then long strings and blobs are truncated to that many bytes. This 58 ** can be used to prevent unreasonably large trace strings when dealing 59 ** with large (multi-megabyte) strings and blobs. 60 ** 61 ** The calling function is responsible for making sure the memory returned 62 ** is eventually freed. 63 ** 64 ** ALGORITHM: Scan the input string looking for host parameters in any of 65 ** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within 66 ** string literals, quoted identifier names, and comments. For text forms, 67 ** the host parameter index is found by scanning the perpared 68 ** statement for the corresponding OP_Variable opcode. Once the host 69 ** parameter index is known, locate the value in p->aVar[]. Then render 70 ** the value as a literal in place of the host parameter name. 71 */ 72 char *sqlite3VdbeExpandSql( 73 Vdbe *p, /* The prepared statement being evaluated */ 74 const char *zRawSql /* Raw text of the SQL statement */ 75 ){ 76 sqlite3 *db; /* The database connection */ 77 int idx = 0; /* Index of a host parameter */ 78 int nextIndex = 1; /* Index of next ? host parameter */ 79 int n; /* Length of a token prefix */ 80 int nToken; /* Length of the parameter token */ 81 int i; /* Loop counter */ 82 Mem *pVar; /* Value of a host parameter */ 83 StrAccum out; /* Accumulate the output here */ 84 char zBase[100]; /* Initial working space */ 85 86 db = p->db; 87 sqlite3StrAccumInit(&out, zBase, sizeof(zBase), 88 db->aLimit[SQLITE_LIMIT_LENGTH]); 89 out.db = db; 90 if( db->nVdbeExec>1 ){ 91 while( *zRawSql ){ 92 const char *zStart = zRawSql; 93 while( *(zRawSql++)!='\n' && *zRawSql ); 94 sqlite3StrAccumAppend(&out, "-- ", 3); 95 assert( (zRawSql - zStart) > 0 ); 96 sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); 97 } 98 }else{ 99 while( zRawSql[0] ){ 100 n = findNextHostParameter(zRawSql, &nToken); 101 assert( n>0 ); 102 sqlite3StrAccumAppend(&out, zRawSql, n); 103 zRawSql += n; 104 assert( zRawSql[0] || nToken==0 ); 105 if( nToken==0 ) break; 106 if( zRawSql[0]=='?' ){ 107 if( nToken>1 ){ 108 assert( sqlite3Isdigit(zRawSql[1]) ); 109 sqlite3GetInt32(&zRawSql[1], &idx); 110 }else{ 111 idx = nextIndex; 112 } 113 }else{ 114 assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); 115 testcase( zRawSql[0]==':' ); 116 testcase( zRawSql[0]=='$' ); 117 testcase( zRawSql[0]=='@' ); 118 idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); 119 assert( idx>0 ); 120 } 121 zRawSql += nToken; 122 nextIndex = idx + 1; 123 assert( idx>0 && idx<=p->nVar ); 124 pVar = &p->aVar[idx-1]; 125 if( pVar->flags & MEM_Null ){ 126 sqlite3StrAccumAppend(&out, "NULL", 4); 127 }else if( pVar->flags & MEM_Int ){ 128 sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); 129 }else if( pVar->flags & MEM_Real ){ 130 sqlite3XPrintf(&out, 0, "%!.15g", pVar->r); 131 }else if( pVar->flags & MEM_Str ){ 132 int nOut; /* Number of bytes of the string text to include in output */ 133 #ifndef SQLITE_OMIT_UTF16 134 u8 enc = ENC(db); 135 Mem utf8; 136 if( enc!=SQLITE_UTF8 ){ 137 memset(&utf8, 0, sizeof(utf8)); 138 utf8.db = db; 139 sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); 140 sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); 141 pVar = &utf8; 142 } 143 #endif 144 nOut = pVar->n; 145 #ifdef SQLITE_TRACE_SIZE_LIMIT 146 if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ 147 nOut = SQLITE_TRACE_SIZE_LIMIT; 148 while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } 149 } 150 #endif 151 sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z); 152 #ifdef SQLITE_TRACE_SIZE_LIMIT 153 if( nOut<pVar->n ){ 154 sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); 155 } 156 #endif 157 #ifndef SQLITE_OMIT_UTF16 158 if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); 159 #endif 160 }else if( pVar->flags & MEM_Zero ){ 161 sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero); 162 }else{ 163 int nOut; /* Number of bytes of the blob to include in output */ 164 assert( pVar->flags & MEM_Blob ); 165 sqlite3StrAccumAppend(&out, "x'", 2); 166 nOut = pVar->n; 167 #ifdef SQLITE_TRACE_SIZE_LIMIT 168 if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; 169 #endif 170 for(i=0; i<nOut; i++){ 171 sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff); 172 } 173 sqlite3StrAccumAppend(&out, "'", 1); 174 #ifdef SQLITE_TRACE_SIZE_LIMIT 175 if( nOut<pVar->n ){ 176 sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); 177 } 178 #endif 179 } 180 } 181 } 182 return sqlite3StrAccumFinish(&out); 183 } 184 185 #endif /* #ifndef SQLITE_OMIT_TRACE */ 186 187 /***************************************************************************** 188 ** The following code implements the data-structure explaining logic 189 ** for the Vdbe. 190 */ 191 192 #if defined(SQLITE_ENABLE_TREE_EXPLAIN) 193 194 /* 195 ** Allocate a new Explain object 196 */ 197 void sqlite3ExplainBegin(Vdbe *pVdbe){ 198 if( pVdbe ){ 199 Explain *p; 200 sqlite3BeginBenignMalloc(); 201 p = (Explain *)sqlite3MallocZero( sizeof(Explain) ); 202 if( p ){ 203 p->pVdbe = pVdbe; 204 sqlite3_free(pVdbe->pExplain); 205 pVdbe->pExplain = p; 206 sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase), 207 SQLITE_MAX_LENGTH); 208 p->str.useMalloc = 2; 209 }else{ 210 sqlite3EndBenignMalloc(); 211 } 212 } 213 } 214 215 /* 216 ** Return true if the Explain ends with a new-line. 217 */ 218 static int endsWithNL(Explain *p){ 219 return p && p->str.zText && p->str.nChar 220 && p->str.zText[p->str.nChar-1]=='\n'; 221 } 222 223 /* 224 ** Append text to the indentation 225 */ 226 void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){ 227 Explain *p; 228 if( pVdbe && (p = pVdbe->pExplain)!=0 ){ 229 va_list ap; 230 if( p->nIndent && endsWithNL(p) ){ 231 int n = p->nIndent; 232 if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent); 233 sqlite3AppendSpace(&p->str, p->aIndent[n-1]); 234 } 235 va_start(ap, zFormat); 236 sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap); 237 va_end(ap); 238 } 239 } 240 241 /* 242 ** Append a '\n' if there is not already one. 243 */ 244 void sqlite3ExplainNL(Vdbe *pVdbe){ 245 Explain *p; 246 if( pVdbe && (p = pVdbe->pExplain)!=0 && !endsWithNL(p) ){ 247 sqlite3StrAccumAppend(&p->str, "\n", 1); 248 } 249 } 250 251 /* 252 ** Push a new indentation level. Subsequent lines will be indented 253 ** so that they begin at the current cursor position. 254 */ 255 void sqlite3ExplainPush(Vdbe *pVdbe){ 256 Explain *p; 257 if( pVdbe && (p = pVdbe->pExplain)!=0 ){ 258 if( p->str.zText && p->nIndent<ArraySize(p->aIndent) ){ 259 const char *z = p->str.zText; 260 int i = p->str.nChar-1; 261 int x; 262 while( i>=0 && z[i]!='\n' ){ i--; } 263 x = (p->str.nChar - 1) - i; 264 if( p->nIndent && x<p->aIndent[p->nIndent-1] ){ 265 x = p->aIndent[p->nIndent-1]; 266 } 267 p->aIndent[p->nIndent] = x; 268 } 269 p->nIndent++; 270 } 271 } 272 273 /* 274 ** Pop the indentation stack by one level. 275 */ 276 void sqlite3ExplainPop(Vdbe *p){ 277 if( p && p->pExplain ) p->pExplain->nIndent--; 278 } 279 280 /* 281 ** Free the indentation structure 282 */ 283 void sqlite3ExplainFinish(Vdbe *pVdbe){ 284 if( pVdbe && pVdbe->pExplain ){ 285 sqlite3_free(pVdbe->zExplain); 286 sqlite3ExplainNL(pVdbe); 287 pVdbe->zExplain = sqlite3StrAccumFinish(&pVdbe->pExplain->str); 288 sqlite3_free(pVdbe->pExplain); 289 pVdbe->pExplain = 0; 290 sqlite3EndBenignMalloc(); 291 } 292 } 293 294 /* 295 ** Return the explanation of a virtual machine. 296 */ 297 const char *sqlite3VdbeExplanation(Vdbe *pVdbe){ 298 return (pVdbe && pVdbe->zExplain) ? pVdbe->zExplain : 0; 299 } 300 #endif /* defined(SQLITE_DEBUG) */ 301