]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Initial check-in of code that inserts tokenizations of the values
authordrh <drh@noemail.net>
Wed, 25 Nov 2009 18:03:42 +0000 (18:03 +0000)
committerdrh <drh@noemail.net>
Wed, 25 Nov 2009 18:03:42 +0000 (18:03 +0000)
for bound parameters into the output of sqlite3_trace().

FossilOrigin-Name: 545cfb3b63f482036ae152e6ebcce86d373585a8

Makefile.in
main.mk
manifest
manifest.uuid
src/printf.c
src/sqliteInt.h
src/vdbe.c
src/vdbe.h
src/vdbetrace.c [new file with mode: 0644]
test/trace.test
tool/mksqlite3c.tcl

index 3e769071e31418821176b35cbf83fcfc7bcc78e5..3bc5d8fda33a20137c980b60c1aacb01a958353f 100644 (file)
@@ -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 d135af3253e40f6de63915f11ec097b45583b6ff..ff9fb677b23e52276457c9f1daaf04a178167090 100644 (file)
--- 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 \
index 099aa62bc9bb4e7f5b8e62da934dc877d3db3bae..3840423987d71172452087060b8fc958c7146ff9 100644 (file)
--- 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-----
index 54c9fe62fa70531a3e483d68dabef09db900003e..99c192899d874f718b86d9961cf5a00fda39ad5e 100644 (file)
@@ -1 +1 @@
-3ba773132d3baeb87acaee538b8fb0b0f4293673
\ No newline at end of file
+545cfb3b63f482036ae152e6ebcce86d373585a8
\ No newline at end of file
index fdd1222c229b08db0beb5968bbb5769261481c00..17edb0907045b878226343dd073711c9b71f776a 100644 (file)
@@ -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
index a3980a071550bf61c4f3be0e6f886bad6fb6c6b4..3adba1c62b77a820e528971af96ea2d1a4452184 100644 (file)
@@ -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*,...);
index 35916ea4716b79b90822f67643827d2ab097c56c..97a98b316f6805e1e4e57cd9acb8cb9923027abb 100644 (file)
@@ -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 ){
index 3ac85eafd41e4711a36d3a82a73a70e5119a6586..f67e903b85730daa76fa3f20d68feb6ba0c4eb5a 100644 (file)
@@ -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 (file)
index 0000000..f43fe55
--- /dev/null
@@ -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(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 */
index 762c1d738bf3e0419176e4ca5e30aa4080005b27..b0b0fea2b015f54b4f8675893a3fe3e28c5f2d29 100644 (file)
@@ -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
index 9a395d83203791504c2944f1a3b0a43826976c66..0ef3ce46e77b393e6033edd5a0826b529c6c0716 100644 (file)
@@ -250,6 +250,7 @@ foreach file {
    vdbemem.c
    vdbeaux.c
    vdbeapi.c
+   vdbetrace.c
    vdbe.c
    vdbeblob.c
    journal.c