diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 12 | ||||
-rw-r--r-- | src/sqlite.h.in | 71 | ||||
-rw-r--r-- | src/sqlite3ext.h | 5 | ||||
-rw-r--r-- | src/sqliteInt.h | 2 | ||||
-rw-r--r-- | src/test1.c | 21 | ||||
-rw-r--r-- | src/vdbe.c | 24 | ||||
-rw-r--r-- | src/vdbeapi.c | 2 | ||||
-rw-r--r-- | src/vdbeaux.c | 15 | ||||
-rw-r--r-- | src/vdbetrace.c | 2 |
9 files changed, 97 insertions, 57 deletions
diff --git a/src/main.c b/src/main.c index 5969738f6..2e996b554 100644 --- a/src/main.c +++ b/src/main.c @@ -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) ){ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 07d85b254..8b9aa7402 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -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 diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index 8bcfc6852..4d5023292 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -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) diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 225d7b287..0be494751 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 */ diff --git a/src/test1.c b/src/test1.c index 5ce818bf7..a1fdcb5cf 100644 --- a/src/test1.c +++ b/src/test1.c @@ -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 }, diff --git a/src/vdbe.c b/src/vdbe.c index 788353602..cdbd7301b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index a602fad38..883e5c95b 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -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; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 63609d72d..355021e97 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -73,6 +73,21 @@ const char *sqlite3_sql(sqlite3_stmt *pStmt){ } /* +** 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. */ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ diff --git a/src/vdbetrace.c b/src/vdbetrace.c index 07235c931..7311bc35c 100644 --- a/src/vdbetrace.c +++ b/src/vdbetrace.c @@ -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 ){ |