Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Initial check-in of code that inserts tokenizations of the values for bound parameters into the output of sqlite3_trace(). |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
545cfb3b63f482036ae152e6ebcce86d |
User & Date: | drh 2009-11-25 18:03:43.000 |
Context
2009-11-25
| ||
19:35 | Get trace with parameter insertion working for UTF16 databases. (check-in: 01d5451af0 user: drh tags: trunk) | |
18:03 | Initial check-in of code that inserts tokenizations of the values for bound parameters into the output of sqlite3_trace(). (check-in: 545cfb3b63 user: drh tags: trunk) | |
16:53 | Enhance the %q, %Q, and %w printf conversions so that the precisions specifies the length of the input. (check-in: 3ba773132d user: drh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
171 172 173 174 175 176 177 | memjournal.lo \ mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo select.lo status.lo \ table.lo tokenize.lo trigger.lo update.lo \ util.lo vacuum.lo \ | | | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | memjournal.lo \ mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo select.lo status.lo \ table.lo tokenize.lo trigger.lo update.lo \ util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbetrace.lo \ walker.lo where.lo utf.lo vtab.lo # Object files for the amalgamation. # OBJS1 = sqlite3.lo # Determine the real value of LIBOBJ based on the 'configure' script |
︙ | ︙ | |||
268 269 270 271 272 273 274 275 276 277 278 279 280 281 | $(TOP)/src/vacuum.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbeblob.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbeInt.h \ $(TOP)/src/vtab.c \ $(TOP)/src/walker.c \ $(TOP)/src/where.c # Generated source code files # | > | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | $(TOP)/src/vacuum.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbeblob.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbetrace.c \ $(TOP)/src/vdbeInt.h \ $(TOP)/src/vtab.c \ $(TOP)/src/walker.c \ $(TOP)/src/where.c # Generated source code files # |
︙ | ︙ | |||
357 358 359 360 361 362 363 364 365 366 367 368 369 370 | $(TOP)/src/tokenize.c \ $(TOP)/src/utf.c \ $(TOP)/src/util.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/where.c \ parse.c # Source code to the actual test files. # TESTSRC = \ $(TOP)/src/test1.c \ | > | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | $(TOP)/src/tokenize.c \ $(TOP)/src/utf.c \ $(TOP)/src/util.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbetrace.c \ $(TOP)/src/where.c \ parse.c # Source code to the actual test files. # TESTSRC = \ $(TOP)/src/test1.c \ |
︙ | ︙ | |||
725 726 727 728 729 730 731 732 733 734 735 736 737 738 | vdbeblob.lo: $(TOP)/src/vdbeblob.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbeblob.c vdbemem.lo: $(TOP)/src/vdbemem.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbemem.c vtab.lo: $(TOP)/src/vtab.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vtab.c walker.lo: $(TOP)/src/walker.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/walker.c where.lo: $(TOP)/src/where.c $(HDR) | > > > | 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 | vdbeblob.lo: $(TOP)/src/vdbeblob.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbeblob.c vdbemem.lo: $(TOP)/src/vdbemem.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbemem.c vdbetrace.lo: $(TOP)/src/vdbetrace.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbetrace.c vtab.lo: $(TOP)/src/vtab.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vtab.c walker.lo: $(TOP)/src/walker.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/walker.c where.lo: $(TOP)/src/where.c $(HDR) |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
61 62 63 64 65 66 67 | memjournal.o \ mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \ notify.o opcodes.o os.o os_os2.o os_unix.o os_win.o \ pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o select.o status.o \ table.o tokenize.o trigger.o \ update.o util.o vacuum.o \ | | | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | memjournal.o \ mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \ notify.o opcodes.o os.o os_os2.o os_unix.o os_win.o \ pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o select.o status.o \ table.o tokenize.o trigger.o \ update.o util.o vacuum.o \ vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbetrace.o \ walker.o where.o utf.o vtab.o # All of the source code files. # SRC = \ |
︙ | ︙ | |||
150 151 152 153 154 155 156 157 158 159 160 161 162 163 | $(TOP)/src/vacuum.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbeblob.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbeInt.h \ $(TOP)/src/vtab.c \ $(TOP)/src/walker.c \ $(TOP)/src/where.c # Source code for extensions # | > | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | $(TOP)/src/vacuum.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbeblob.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbetrace.c \ $(TOP)/src/vdbeInt.h \ $(TOP)/src/vtab.c \ $(TOP)/src/walker.c \ $(TOP)/src/where.c # Source code for extensions # |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
953 954 955 956 957 958 959 | sqlite3VXPrintf(&acc, 0, zFormat, ap); va_end(ap); sqlite3StrAccumFinish(&acc); fprintf(stdout,"%s", zBuf); fflush(stdout); } #endif | > > > > > > > > > > > > | 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 | sqlite3VXPrintf(&acc, 0, zFormat, ap); va_end(ap); sqlite3StrAccumFinish(&acc); fprintf(stdout,"%s", zBuf); fflush(stdout); } #endif #ifndef SQLITE_OMIT_TRACE /* ** variable-argument wrapper around sqlite3VXPrintf(). */ void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ va_list ap; va_start(ap,zFormat); sqlite3VXPrintf(p, 1, zFormat, ap); va_end(ap); } #endif |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 | int sqlite3StatusValue(int); void sqlite3StatusAdd(int, int); void sqlite3StatusSet(int, int); int sqlite3IsNaN(double); void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3VMPrintf(sqlite3*,const char*, va_list); char *sqlite3MAppendf(sqlite3*,char*,const char*,...); #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) | > > > | 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 | int sqlite3StatusValue(int); void sqlite3StatusAdd(int, int); void sqlite3StatusSet(int, int); int sqlite3IsNaN(double); void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); #ifndef SQLITE_OMIT_TRACE void sqlite3XPrintf(StrAccum*, const char*, ...); #endif char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3VMPrintf(sqlite3*,const char*, va_list); char *sqlite3MAppendf(sqlite3*,char*,const char*,...); #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
5628 5629 5630 5631 5632 5633 5634 | */ case OP_Trace: { char *zTrace; zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); if( zTrace ){ if( db->xTrace ){ | > | > | 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 | */ case OP_Trace: { char *zTrace; zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); if( zTrace ){ if( db->xTrace ){ char *z = sqlite3VdbeExpandSql(p, zTrace); db->xTrace(db->pTraceArg, z); sqlite3DbFree(db, z); } #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 ){ sqlite3DebugPrintf("SQL-trace: %s\n", zTrace); } #endif /* SQLITE_DEBUG */ } |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
199 200 201 202 203 204 205 206 207 208 209 210 211 212 | sqlite3 *sqlite3VdbeDb(Vdbe*); void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); void sqlite3VdbeSwap(Vdbe*,Vdbe*); VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); void sqlite3VdbeProgramDelete(sqlite3 *, SubProgram *, int); sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8); void sqlite3VdbeSetVarmask(Vdbe*, int); UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int); void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); #ifndef NDEBUG | > > > | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | sqlite3 *sqlite3VdbeDb(Vdbe*); void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); void sqlite3VdbeSwap(Vdbe*,Vdbe*); VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); void sqlite3VdbeProgramDelete(sqlite3 *, SubProgram *, int); sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8); void sqlite3VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE_OMIT_TRACE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int); void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); #ifndef NDEBUG |
︙ | ︙ |
Added src/vdbetrace.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | /* ** 2009 November 25 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to insert the values of host parameters ** (aka "wildcards") into the SQL text output by sqlite3_trace(). */ #include "sqliteInt.h" #include "vdbeInt.h" #ifndef SQLITE_OMIT_TRACE /* ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of ** bytes in this text up to but excluding the first character in ** a host parameter. If the text contains no host parameters, return ** the total number of bytes in the text. */ static int findNextHostParameter(const char *zSql){ int tokenType; int nTotal = 0; int n; while( zSql[0] ){ n = sqlite3GetToken((u8*)zSql, &tokenType); assert( n>0 && tokenType!=TK_ILLEGAL ); if( tokenType==TK_VARIABLE ) break; nTotal += n; zSql += n; } return nTotal; } /* ** Return a pointer to a string in memory obtained form sqlite3Malloc() which ** holds a copy of zRawSql but with host parameters expanded to their ** current values. ** ** The calling function is responsible for making sure the memory returned ** is eventually freed. ** ** ALGORITHM: Scan the input string looking for host parameters in any of ** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within ** string literals, quoted identifier names, and comments. For text forms, ** the host parameter index is found by scanning the perpared ** statement for the corresponding OP_Variable opcode. Once the host ** parameter index is known, locate the value in p->aVar[]. Then render ** the value as a literal in place of the host parameter name. */ char *sqlite3VdbeExpandSql( Vdbe *p, /* The prepared statement being evaluated */ const char *zRawSql /* Raw text of the SQL statement */ ){ sqlite3 *db; /* The database connection */ int idx; /* Index of a host parameter */ int nextIndex = 1; /* Index of next ? host parameter */ int n; /* Length of a token prefix */ int i; /* Loop counter */ int dummy; /* For holding a unused return value */ Mem *pVar; /* Value of a host parameter */ VdbeOp *pOp; /* For looping over opcodes */ StrAccum out; /* Accumulate the output here */ char zBase[100]; /* Initial working space */ db = p->db; sqlite3StrAccumInit(&out, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); out.db = db; while( zRawSql[0] ){ n = findNextHostParameter(zRawSql); assert( n>0 ); sqlite3StrAccumAppend(&out, zRawSql, n); zRawSql += n; if( zRawSql[0]==0 ) break; if( zRawSql[0]=='?' ){ zRawSql++; if( sqlite3Isdigit(zRawSql[0]) ){ idx = 0; while( sqlite3Isdigit(zRawSql[0]) ){ idx = idx*10 + zRawSql[0] - '0'; zRawSql++; } }else{ idx = nextIndex; } }else{ assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); n = sqlite3GetToken((u8*)zRawSql, &dummy); idx = 0; for(i=0, pOp=p->aOp; ALWAYS(i<p->nOp); i++, pOp++){ if( pOp->opcode!=OP_Variable ) continue; if( pOp->p3>1 ) continue; if( memcmp(pOp->p4.z, zRawSql, n)==0 && pOp->p4.z[n]==0 ){ idx = pOp->p1; break; } } assert( idx>0 ); zRawSql += n; } nextIndex = idx + 1; assert( idx>0 && idx<=p->nVar ); pVar = &p->aVar[idx-1]; if( pVar->flags & MEM_Null ){ sqlite3StrAccumAppend(&out, "NULL", 4); }else if( pVar->flags & MEM_Int ){ sqlite3XPrintf(&out, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ sqlite3XPrintf(&out, "%!.15g", pVar->r); }else if( pVar->flags & MEM_Str ){ sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z); }else{ assert( pVar->flags & MEM_Blob ); sqlite3StrAccumAppend(&out, "x'", 2); for(i=0; i<pVar->n; i++){ sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); } sqlite3StrAccumAppend(&out, "'", 1); } } return sqlite3StrAccumFinish(&out); } #endif /* #ifndef SQLITE_OMIT_TRACE */ |
Changes to test/trace.test.
︙ | ︙ | |||
163 164 165 166 167 168 169 170 171 | } db eval { UPDATE t1 SET a=a+1; } set TRACE_OUT } {{UPDATE t1 SET a=a+1;} {-- TRIGGER r1t1} {-- TRIGGER r1t2} {-- TRIGGER r1t1} {-- TRIGGER r1t2} {-- TRIGGER r1t1} {-- TRIGGER r1t2}} } finish_test | > > > > > > > > > > > > > > > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | } db eval { UPDATE t1 SET a=a+1; } set TRACE_OUT } {{UPDATE t1 SET a=a+1;} {-- TRIGGER r1t1} {-- TRIGGER r1t2} {-- TRIGGER r1t1} {-- TRIGGER r1t2} {-- TRIGGER r1t1} {-- TRIGGER r1t2}} } # With 3.6.21, we add the ability to expand host parameters in the trace # output. Test this feature. # do_test trace-6.1 { set ::t6int [expr {3+3}] set ::t6real [expr {1.5*4.0}] set ::t6str {test-six y'all} db eval {SELECT x'3031323334' AS x} {set ::t6blob $x} unset -nocomplain t6null set TRACE_OUT {} execsql {SELECT $::t6int, $::t6real, $t6str, $t6blob, $t6null} } {6 6.0 {test-six y'all} 01234 {}} do_test trace-6.2 { set TRACE_OUT } {{SELECT 6, 6.0, 'test-six y''all', x'3031323334', NULL}} finish_test |
Changes to tool/mksqlite3c.tcl.
︙ | ︙ | |||
246 247 248 249 250 251 252 253 254 255 256 257 258 259 | btmutex.c btree.c backup.c vdbemem.c vdbeaux.c vdbeapi.c vdbe.c vdbeblob.c journal.c memjournal.c walker.c resolve.c | > | 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | btmutex.c btree.c backup.c vdbemem.c vdbeaux.c vdbeapi.c vdbetrace.c vdbe.c vdbeblob.c journal.c memjournal.c walker.c resolve.c |
︙ | ︙ |