]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the sqlite3_expanded_sql() interface. Refinements to the
authordrh <drh@noemail.net>
Thu, 14 Jul 2016 01:09:08 +0000 (01:09 +0000)
committerdrh <drh@noemail.net>
Thu, 14 Jul 2016 01:09:08 +0000 (01:09 +0000)
sqlite3_trace_v2() interface to make it more useful.

FossilOrigin-Name: 99ee7ee58d45b29a0000492306ddc0b90563ff51

manifest
manifest.uuid
src/main.c
src/sqlite.h.in
src/sqlite3ext.h
src/sqliteInt.h
src/test1.c
src/vdbe.c
src/vdbeapi.c
src/vdbeaux.c
src/vdbetrace.c

index a7725c09a7bab0fd3e410bad42159a3852a1e586..98c634e40070cbd872de1ba279a3ba13c3ac68a2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Legacy\stests\snow\spassing.
-D 2016-07-13T23:18:27.653
+C Add\sthe\ssqlite3_expanded_sql()\sinterface.\s\sRefinements\sto\sthe\nsqlite3_trace_v2()\sinterface\sto\smake\sit\smore\suseful.
+D 2016-07-14T01:09:08.369
 F Makefile.in 6c20d44f72d4564f11652b26291a214c8367e5db
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a
@@ -348,7 +348,7 @@ F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
 F src/insert.c 8f4e9fcbd8e95e85f15647ba8b413b18d556ec2b
 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
 F src/loadext.c 4237fd37ca589f1d90b3ea925dd9df20da8e0c84
-F src/main.c a3be9a816c72fe658838e33e42afabfff93526f2
+F src/main.c ade3b39f3bde9212b3fabcff2367d29052002df6
 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
@@ -385,15 +385,15 @@ F src/resolve.c cca3aa77b95706df5d635a2141a4d1de60ae6598
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c f3c6e9065fb34f6a23af27ec7f1f717ffbfc2ee4
 F src/shell.c a8a9e392a6a2777fabf5feb536931cb190f235e5
-F src/sqlite.h.in 0fde7379e6a9d900802976de51cb1256f0fdac59
+F src/sqlite.h.in 6ba80e88ee17b9071f35121271784ecef60df863
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h 3875aa5b3c4bb5d8d14c387628c5fe852b2846bf
-F src/sqliteInt.h 5b8a3e1dc92e7459b69954cce9f653bd2391deb8
+F src/sqlite3ext.h 6fb1639d41907544cb3905c69a348ee64c5da79e
+F src/sqliteInt.h 48cd97eb134665348393dfe277b4c14d1085bfc7
 F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
 F src/status.c 5b18f9526900f61189ab0b83f1ef41d9f871a2ab
 F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
 F src/tclsqlite.c 25fbbbb97f76dbfd113153fb63f52d7ecfac5dd0
-F src/test1.c 640f862c490c8eee09a9d02d0d128c6a8a75336d
+F src/test1.c 5124aff86fba753a6994e9621696ccfdc8bbf24e
 F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
 F src/test3.c c75c8af0eadb335236c9e61b51044c58a8f7dd59
 F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
@@ -449,15 +449,15 @@ F src/update.c 4f05ea8cddfa367d045e03589756c02199e8f9bd
 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
 F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d
 F src/vacuum.c 544ec90a66a4b0460b7c1baeadbc21b45e6ca0b6
-F src/vdbe.c c6bb62aa69a6faf1197eee36336c6de99bb4733f
+F src/vdbe.c 7b5570f77e32766949fd8f9478e4a9bb06e6ab24
 F src/vdbe.h 67bc551f7faf04c33493892e4b378aada823ed10
 F src/vdbeInt.h c59381049af5c7751a83456c39b80d1a6fde1f9d
-F src/vdbeapi.c a466743c8e6de100c11e044b693c9469d2cf598a
-F src/vdbeaux.c c90275b0e55a2b32c03dc09314194fe46f2429d8
+F src/vdbeapi.c 460b90f7f0894753d33df377702c1dc9cc5fa21b
+F src/vdbeaux.c 6083ff395021ac8c40e1b53798ee6483037e3fb7
 F src/vdbeblob.c 83d2d266383157b02e2b809350bb197e89d7895b
 F src/vdbemem.c 1ecaa5ee0caff07255f25d04e8dc88befb6f88d1
 F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c
-F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484
+F src/vdbetrace.c d0371769fe66fe4eb85bdcacf82b6f2af50feb9b
 F src/vtab.c 948d2d4984219eee37a7bf427d6667e21e6eb92e
 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c 02eeecc265f6ffd0597378f5d8ae9070b62a406a
@@ -1505,7 +1505,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P cb0062feb018f52689938a58cb76886d431c33f0
-R d7e93f0729616f164eba3e9e1862aa07
+P f33526a341132435cb4185149a784eef6b3a1a2d
+R b996b3134868ad007e1e44124ba2e740
 U drh
-Z a0be5e80cc5b797f562ce4c096d88be2
+Z 809ea44b43d6348d635e64228e5049a8
index 5103610b4fac68dbbf1a5667d039d3e2631950f8..6a7d48edff94057f2defd9baac9f204c070c1ad6 100644 (file)
@@ -1 +1 @@
-f33526a341132435cb4185149a784eef6b3a1a2d
\ No newline at end of file
+99ee7ee58d45b29a0000492306ddc0b90563ff51
\ No newline at end of file
index 5969738f6b3c3a304429824829981c3a82b9095e..2e996b554582995fc59495b703bfbc8e2aae7c6d 100644 (file)
@@ -1805,7 +1805,7 @@ int sqlite3_overload_function(
 ** SQL statement.
 */
 #ifndef SQLITE_OMIT_DEPRECATED
-void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
+void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){
   void *pOld;
 
 #ifdef SQLITE_ENABLE_API_ARMOR
@@ -1817,7 +1817,7 @@ void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
   sqlite3_mutex_enter(db->mutex);
   pOld = db->pTraceArg;
   db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0;
-  db->xTrace = (int(*)(u32,void*,void*,i64))xTrace;
+  db->xTrace = (int(*)(u32,void*,void*,void*))xTrace;
   db->pTraceArg = pArg;
   sqlite3_mutex_leave(db->mutex);
   return pOld;
@@ -1827,10 +1827,10 @@ void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
 /* Register a trace callback using the version-2 interface.
 */
 int sqlite3_trace_v2(
-  sqlite3 *db,                                       /* Trace this connection */
-  int(*xTrace)(unsigned,void*,void*,sqlite3_int64),  /* Callback to invoke */
-  unsigned mTrace,                                   /* OPs to be traced */
-  void *pArg                                         /* Context */
+  sqlite3 *db,                               /* Trace this connection */
+  unsigned mTrace,                           /* Mask of events to be traced */
+  int(*xTrace)(unsigned,void*,void*,void*),  /* Callback to invoke */
+  void *pArg                                 /* Context */
 ){
 #ifdef SQLITE_ENABLE_API_ARMOR
   if( !sqlite3SafetyCheckOk(db) ){
index 07d85b254d33e6dc6e7520bb6b0c6288001ea9c9..8b9aa7402d8435584ec1e92f4106f5f020c4e85a 100644 (file)
@@ -2804,33 +2804,25 @@ SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
 ** The T argument is one of the integer type codes above.
 ** The C argument is a copy of the context pointer passed in as the
 ** fourth argument to [sqlite3_trace_v2()].
-** The P argument is a pointer whose meaning depends on T.
-** The X argument is an 64-bit integer whose meaning also
-** depends on T.
+** The P and X arguments are pointers whose meanings depend on T.
 **
 ** <dl>
-** [[SQLITE_TRACE_SQL]] <dt>SQLITE_TRACE_SQL</dt>
-** <dd>An SQLITE_TRACE_SQL callback provides the same functionality
-** as the legacy [sqlite3_trace()] callback.
-** The P argument is a pointer to the constant UTF-8 string that is text
-** describing an SQL statement that is starting to run with all
-** [bound parameter] expanded.  The X argument is unused.  The size
-** of the expansion of [bound parameters] is limited by the
-** [SQLITE_TRACE_SIZE_LIMIT] compile-time option.
-**
 ** [[SQLITE_TRACE_STMT]] <dt>SQLITE_TRACE_STMT</dt>
-** <dd>An SQLITE_TRACE_STMT callback is invoked on the same occasions
-** as SQLITE_TRACE_SQL.  The difference is that the P argument is a
-** pointer to the [prepared statement] rather than an SQL string.
-** The X argument is unused.
+** <dd>An SQLITE_TRACE_STMT callback is invoked when a prepared statement
+** first begins running and possibly at other times during the
+** execution of the prepared statement, such as at the start of each
+** trigger subprogram.  The P argument is a pointer to the
+** [prepared statement].  The X argument is a pointer to a string which
+** is the expanded SQL text of the prepared statement or a comment that
+** indicates the invocation of a trigger.
 **
 ** [[SQLITE_TRACE_PROFILE]] <dt>SQLITE_TRACE_PROFILE</dt>
 ** <dd>An SQLITE_TRACE_PROFILE callback provides approximately the same
 ** information as is provided by the [sqlite3_profile()] callback.
 ** The P argument is a pointer to the [prepared statement] and the
-** X argument is an estimate of the number of nanosecond for which
-** the prepared statement ran.  The SQLITE_TRACE_PROFILE callback is
-** invoked when the statement finishes.
+** X argument points to a 64-bit integer which is the estimated of
+** the number of nanosecond that the prepared statement took to run.
+** The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes.
 **
 ** [[SQLITE_TRACE_ROW]] <dt>SQLITE_TRACE_ROW</dt>
 ** <dd>An SQLITE_TRACE_ROW callback is invoked whenever a prepared
@@ -2845,17 +2837,16 @@ SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
 ** and the X argument is unused.
 ** </dl>
 */
-#define SQLITE_TRACE_SQL        0x0001
-#define SQLITE_TRACE_STMT       0x0002
-#define SQLITE_TRACE_PROFILE    0x0004
-#define SQLITE_TRACE_ROW        0x0008
-#define SQLITE_TRACE_CLOSE      0x0010
+#define SQLITE_TRACE_STMT       0x01
+#define SQLITE_TRACE_PROFILE    0x02
+#define SQLITE_TRACE_ROW        0x04
+#define SQLITE_TRACE_CLOSE      0x08
 
 /*
 ** CAPI3REF: SQL Trace Hook
 ** METHOD: sqlite3
 **
-** The sqlite3_trace_v2(D,X,M,P) interface registers a trace callback
+** The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback
 ** function X against [database connection] D, using property mask M
 ** and context pointer P.  If the X callback is
 ** NULL or if the M mask is zero, then tracing is disabled.  The
@@ -2874,8 +2865,7 @@ SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
 ** The T argument is one of the [SQLITE_TRACE]
 ** constants to indicate why the callback was invoked.
 ** The C argument is a copy of the context pointer.
-** The P and X arguments are a pointer and a 64-bit integer
-** whose meanings depend on T.
+** The P and X arguments are pointers whose meanings depend on T.
 **
 ** The sqlite3_trace_v2() interface is intended to replace the legacy
 ** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which
@@ -2883,8 +2873,8 @@ SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
 */
 int sqlite3_trace_v2(
   sqlite3*,
-  int(*xCallback)(unsigned,void*,void*,sqlite3_int64),
   unsigned uMask,
+  int(*xCallback)(unsigned,void*,void*,void*),
   void *pCtx
 );
 
@@ -3506,11 +3496,30 @@ int sqlite3_prepare16_v2(
 ** CAPI3REF: Retrieving Statement SQL
 ** METHOD: sqlite3_stmt
 **
-** ^This interface can be used to retrieve a saved copy of the original
-** SQL text used to create a [prepared statement] if that statement was
-** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
+** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8
+** SQL text used to create [prepared statement] P if P was
+** created by either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
+** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
+** string containing the SQL text of prepared statement P with
+** [bound parameters] expanded.
+**
+** For example, if a prepared statement is created using the SQL
+** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345
+** and parameter :xyz is unbound, then sqlite3_sql() will return
+** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql()
+** will return "SELECT 2345,NULL".
+**
+** The [SQLITE_TRACE_SIZE_LIMIT] setting limits the size of a 
+** bound parameter expansion.
+**
+** ^The string returned by sqlite3_sql(P) is managed by SQLite and is
+** automatically freed when the prepared statement is finalized.
+** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
+** is obtained from [sqlite3_malloc()] and must be free by the application
+** by passing it to [sqlite3_free()].
 */
 const char *sqlite3_sql(sqlite3_stmt *pStmt);
+char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
 
 /*
 ** CAPI3REF: Determine If An SQL Statement Writes The Database
index 8bcfc68521d3e8ce9a97ed04bbf89791e1609ef5..4d5023292b6d344a16c0aec433704023bf85a802 100644 (file)
@@ -282,8 +282,8 @@ struct sqlite3_api_routines {
   /* Version 3.12.0 and later */
   int (*system_errno)(sqlite3*);
   /* Version 3.14.0 and later */
-  int (*trace_v2)(sqlite3*,int(*)(unsigned,void*,void*,sqlite3_uint64),
-      unsigned,void*);
+  int (*trace_v2)(sqlite3*,int(*)(unsigned,void*,void*,void*),unsigned,void*);
+  char *(*expanded_sql)(sqlite3_stmt*);
 };
 
 /*
@@ -531,6 +531,7 @@ struct sqlite3_api_routines {
 #define sqlite3_system_errno           sqlite3_api->system_errno
 /* Version 3.14.0 and later */
 #define sqlite3_trace_v2               sqlite3_api->trace_v2
+#define sqlite3_expanded_sql           sqlite3_api->expanded_sql
 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
 
 #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
index 225d7b2872b61397f685383e7b893920492e0a75..0be494751364863433a72b38d8315c6aa09beba7 100644 (file)
@@ -1300,7 +1300,7 @@ struct sqlite3 {
   int nVDestroy;                /* Number of active OP_VDestroy operations */
   int nExtension;               /* Number of loaded extensions */
   void **aExtension;            /* Array of shared library handles */
-  int (*xTrace)(u32,void*,void*,i64);      /* Trace function */
+  int (*xTrace)(u32,void*,void*,void*);     /* Trace function */
   void *pTraceArg;                          /* Argument to the trace function */
   void (*xProfile)(void*,const char*,u64);  /* Profiling function */
   void *pProfileArg;                        /* Argument to profile function */
index 5ce818bf747cd8cdba97f864208e548f114b334c..a1fdcb5cfb144ffac127f26194b9ef874c4f07d0 100644 (file)
@@ -4386,6 +4386,26 @@ static int test_sql(
   Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
   return TCL_OK;
 }
+static int test_ex_sql(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  sqlite3_stmt *pStmt;
+  char *z;
+
+  if( objc!=2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "STMT");
+    return TCL_ERROR;
+  }
+
+  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
+  z = sqlite3_expanded_sql(pStmt);
+  Tcl_SetResult(interp, z, TCL_VOLATILE);
+  sqlite3_free(z);
+  return TCL_OK;
+}
 
 /*
 ** Usage: sqlite3_column_count STMT 
@@ -7276,6 +7296,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_changes",               test_changes       ,0 },
      { "sqlite3_step",                  test_step          ,0 },
      { "sqlite3_sql",                   test_sql           ,0 },
+     { "sqlite3_expanded_sql",          test_ex_sql        ,0 },
      { "sqlite3_next_stmt",             test_next_stmt     ,0 },
      { "sqlite3_stmt_readonly",         test_stmt_readonly ,0 },
      { "sqlite3_stmt_busy",             test_stmt_busy     ,0 },
index 788353602880b6fc72db682607a04c6ae70ba552..cdbd7301b8a8b6746604d38627133df0261587a1 100644 (file)
@@ -6785,27 +6785,21 @@ case OP_Init: {          /* jump */
   char *z;
 
 #ifndef SQLITE_OMIT_TRACE
-  if( (db->mTrace & (SQLITE_TRACE_SQL|SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
+  if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
    && !p->doingRerun
    && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
   ){
-    if( db->mTrace & (SQLITE_TRACE_SQL|SQLITE_TRACE_LEGACY) ){
-      z = sqlite3VdbeExpandSql(p, zTrace);
+    z = sqlite3VdbeExpandSql(p, zTrace);
 #ifndef SQLITE_OMIT_DEPRECATED
-      if( SQLITE_TRACE_LEGACY ){
-        void (*x)(void*,const char*);
-        x = (void(*)(void*,const char*))db->xTrace;
-        x(db->pTraceArg, z);
-      }else
+    if( db->mTrace & SQLITE_TRACE_LEGACY ){
+      void (*x)(void*,const char*) = (void(*)(void*,const char*))db->xTrace;
+      x(db->pTraceArg, z);
+    }else
 #endif
-      {
-        db->xTrace(SQLITE_TRACE_SQL,db->pTraceArg,z,0);
-      }
-      sqlite3DbFree(db, z);
-    }
-    if( db->mTrace & SQLITE_TRACE_STMT ){
-      (void)db->xTrace(SQLITE_TRACE_STMT,db->pTraceArg,p,0);
+    {
+      (void)db->xTrace(SQLITE_TRACE_STMT,db->pTraceArg,p,z);
     }
+    sqlite3_free(z);
   }
 #ifdef SQLITE_USE_FCNTL_TRACE
   zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
index a602fad3836fab10ae1b6f38398e093941e7bc7e..883e5c95bf296a2923fcd16b9a74dc8afeccba75 100644 (file)
@@ -71,7 +71,7 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
     db->xProfile(db->pProfileArg, p->zSql, iElapse);
   }
   if( db->mTrace & SQLITE_TRACE_PROFILE ){
-    db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, iElapse);
+    db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
   }
   p->startTime = 0;
 }
index 63609d72dd9e5bfff087c61814eb34bb9b67719e..355021e970fe1e0f3fb26cc528cb12ca99b8b51b 100644 (file)
@@ -72,6 +72,21 @@ const char *sqlite3_sql(sqlite3_stmt *pStmt){
   return p ? p->zSql : 0;
 }
 
+/*
+** Return the SQL associated with a prepared statement with
+** bound parameters expanded.  Space to hold the returned string is
+** obtained from sqlite3_malloc().  The caller is responsible for
+** freeing the returned string by passing it to sqlite3_free().
+**
+** The SQLITE_TRACE_SIZE_LIMIT puts an upper bound on the size of
+** expanded bound parameters.
+*/
+char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
+  Vdbe *p = (Vdbe *)pStmt;
+  return p ? sqlite3VdbeExpandSql(p, p->zSql) : 0;
+  if( p->zSql==0 ) return 0;
+}
+
 /*
 ** Swap all content between two VDBE structures.
 */
index 07235c931b15ec230e3d4ffce56717694428f7aa..7311bc35c6ff2f2c46cc3c5cad9bb3bc13de293a 100644 (file)
@@ -84,7 +84,7 @@ char *sqlite3VdbeExpandSql(
   char zBase[100];         /* Initial working space */
 
   db = p->db;
-  sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase), 
+  sqlite3StrAccumInit(&out, 0, zBase, sizeof(zBase), 
                       db->aLimit[SQLITE_LIMIT_LENGTH]);
   if( db->nVdbeExec>1 ){
     while( *zRawSql ){