From: drh Date: Wed, 25 Nov 2009 18:03:42 +0000 (+0000) Subject: Initial check-in of code that inserts tokenizations of the values X-Git-Tag: version-3.7.2~794 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c7bc4fde3c5ed76ec4dae4e5f5f1be8e8901703d;p=thirdparty%2Fsqlite.git Initial check-in of code that inserts tokenizations of the values for bound parameters into the output of sqlite3_trace(). FossilOrigin-Name: 545cfb3b63f482036ae152e6ebcce86d373585a8 --- diff --git a/Makefile.in b/Makefile.in index 3e769071e3..3bc5d8fda3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -175,7 +175,7 @@ OBJS0 = alter.lo analyze.lo attach.lo auth.lo backup.lo bitvec.lo btmutex.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 \ + 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. @@ -272,6 +272,7 @@ SRC = \ $(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 \ @@ -361,6 +362,7 @@ TESTSRC2 = \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbemem.c \ + $(TOP)/src/vdbetrace.c \ $(TOP)/src/where.c \ parse.c @@ -729,6 +731,9 @@ vdbeblob.lo: $(TOP)/src/vdbeblob.c $(HDR) 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 diff --git a/main.mk b/main.mk index d135af3253..ff9fb677b2 100644 --- a/main.mk +++ b/main.mk @@ -65,7 +65,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.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 \ + vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbetrace.o \ walker.o where.o utf.o vtab.o @@ -154,6 +154,7 @@ SRC = \ $(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 \ diff --git a/manifest b/manifest index 099aa62bc9..3840423987 100644 --- a/manifest +++ b/manifest @@ -1,10 +1,10 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Enhance\sthe\s%q,\s%Q,\sand\s%w\sprintf\sconversions\sso\sthat\sthe\sprecisions\s\nspecifies\sthe\slength\sof\sthe\sinput. -D 2009-11-25T16:53:38 +C Initial\scheck-in\sof\scode\sthat\sinserts\stokenizations\sof\sthe\svalues\nfor\sbound\sparameters\sinto\sthe\soutput\sof\ssqlite3_trace(). +D 2009-11-25T18:03:43 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 -F Makefile.in 7f6c6aa7feeeb5e26e01b344161d9aa1b5d64177 +F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.vxworks 10010ddbf52e2503c7c49c7c0b7c7a096f8638a6 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 @@ -91,7 +91,7 @@ F ext/rtree/tkt3363.test 2bf324f7908084a5f463de3109db9c6e607feb1b F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 -F main.mk 3f64bbfc5605584fe551305406991f7e02791fef +F main.mk 4323353d807bcbe769d4c245b9f433a5e9ddf132 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac @@ -161,7 +161,7 @@ F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache1.c 2bb2261190b42a348038f5b1c285c8cef415fcc8 F src/pragma.c 6936d7df5e04b9f996f8f320d15e65b6944b2caa F src/prepare.c ad90970bba3aead154266d8bb6faf9fbb5233b94 -F src/printf.c 51c3b010c6f1bd8bb07d7ea84147eb8f63ce1238 +F src/printf.c 644bc7d59df3dc56d6d8b9a510914bfc6b51bc69 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c c52d9e52e11058f4113f6644adc20d3f85141b1d F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 @@ -169,7 +169,7 @@ F src/select.c 2f9ed7482e7a25b0b127fc41693bbdbe1caf5647 F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828 F src/sqlite.h.in 4464e9772122f0447305d425e04d122b6f1bffec F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 -F src/sqliteInt.h 8ee7b66de2169dc958744e036b3b1550710a7b6e +F src/sqliteInt.h 7577de4b889b2842fc98069a13eb6b4eaecb4971 F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6 F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -212,13 +212,14 @@ F src/update.c 8efeb09822886e33c265dd96d29a3d865ea6dcf2 F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052 F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592 F src/vacuum.c 03309a08d549f9389cc3a3589afd4fadbdaf0679 -F src/vdbe.c 343175b0f5d8ad1dc018c52b3a4c428029cead92 -F src/vdbe.h 5f35750615163d1064052785b4a9f0eb004a720d +F src/vdbe.c 91b65712dcc35c80856ced6d64350059750dacc4 +F src/vdbe.h bea1f0cd530775bdb58a340265f3cf3ee920e9b2 F src/vdbeInt.h d7ea821ac7813c9bea0fe87558c35e07b2c7c44d F src/vdbeapi.c 17680ab7a75ec938c5ba039a6c87489d01faf2cb F src/vdbeaux.c 0981dcb5b933b74ae7bc9bfa7770df5e4da849b3 F src/vdbeblob.c 84f924700a7a889152aeebef77ca5f4e3875ffb4 F src/vdbemem.c 1e16e3a16e55f4c3452834f0e041726021aa66e0 +F src/vdbetrace.c 0c0c85de878afa593d129e96035844fb9cb66538 F src/vtab.c 456fc226614569f0e46f216e33265bea268bd917 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f F src/where.c 11b5b00c49d53e767a7eb855bc60790edeca6185 @@ -690,7 +691,7 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 -F test/trace.test 19ffbc09885c3321d56358a5738feae8587fb377 +F test/trace.test 1e194d4aa28072866d65b4522d61439156673cbe F test/trans.test d887cb07630dc39879a322d958ad8b006137485c F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22 F test/trans3.test d728abaa318ca364dc370e06576aa7e5fbed7e97 @@ -758,7 +759,7 @@ F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/mkkeywordhash.c 9216336085e7a7c226a35c0bd780239968f8304f F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 -F tool/mksqlite3c.tcl 24e8f32d406259135bbd23b5bb2adead51338a74 +F tool/mksqlite3c.tcl c2d2ec2fef48417c31d6da9ce2992619ab35bbc5 F tool/mksqlite3h.tcl eb100dce83f24b501b325b340f8b5eb8e5106b3b F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87 F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a @@ -776,14 +777,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P cb74b81bb0322efdd66146d7de466c14564b18fd -R d2fd7cc9116d60ea3bf83caab579713e +P 3ba773132d3baeb87acaee538b8fb0b0f4293673 +R 083042b00e5c6f135e16a26d8597a9b9 U drh -Z bb155b9f1ed8f5cc73b48ffe4ac5abca +Z dc2a97232842ecfec2bf765bdef955e5 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFLDWEVoxKgR168RlERAjrAAKCB/VKRKhYLK3n+HL8zd1duNxwkxQCfbc2N -c9b72fb+mD/lcn1IAqU+NZQ= -=Av30 +iD8DBQFLDXGFoxKgR168RlERAjnNAJ4s92jZVLjoWiP2AFZjoGmznb2KLgCcDqhv +qcS6kVAJAbCr5+upcVo5F4g= +=mEiC -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 54c9fe62fa..99c192899d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3ba773132d3baeb87acaee538b8fb0b0f4293673 \ No newline at end of file +545cfb3b63f482036ae152e6ebcce86d373585a8 \ No newline at end of file diff --git a/src/printf.c b/src/printf.c index fdd1222c22..17edb09070 100644 --- a/src/printf.c +++ b/src/printf.c @@ -957,3 +957,15 @@ void sqlite3DebugPrintf(const char *zFormat, ...){ 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 diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a3980a0715..3adba1c62b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2517,6 +2517,9 @@ 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*,...); diff --git a/src/vdbe.c b/src/vdbe.c index 35916ea471..97a98b316f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5632,7 +5632,9 @@ case OP_Trace: { zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); if( zTrace ){ if( db->xTrace ){ - db->xTrace(db->pTraceArg, zTrace); + char *z = sqlite3VdbeExpandSql(p, zTrace); + db->xTrace(db->pTraceArg, z); + sqlite3DbFree(db, z); } #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 ){ diff --git a/src/vdbe.h b/src/vdbe.h index 3ac85eafd4..f67e903b85 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -203,6 +203,9 @@ 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*); diff --git a/src/vdbetrace.c b/src/vdbetrace.c new file mode 100644 index 0000000000..f43fe5532d --- /dev/null +++ b/src/vdbetrace.c @@ -0,0 +1,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(inOp); 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; in; i++){ + sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); + } + sqlite3StrAccumAppend(&out, "'", 1); + } + } + return sqlite3StrAccumFinish(&out); +} + +#endif /* #ifndef SQLITE_OMIT_TRACE */ diff --git a/test/trace.test b/test/trace.test index 762c1d738b..b0b0fea2b0 100644 --- a/test/trace.test +++ b/test/trace.test @@ -168,4 +168,20 @@ ifcapable trigger { } {{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 diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 9a395d8320..0ef3ce46e7 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -250,6 +250,7 @@ foreach file { vdbemem.c vdbeaux.c vdbeapi.c + vdbetrace.c vdbe.c vdbeblob.c journal.c