Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -1760,10 +1760,29 @@ db->xTrace = xTrace; db->pTraceArg = pArg; sqlite3_mutex_leave(db->mutex); return pOld; } +/* +** Return the current trace function and argument. +*/ +int sqlite3_get_trace( + const sqlite3 *db, + void (**pxTrace)(void*,const char*), + void **ppArg +){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || pxTrace==0 || ppArg==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + sqlite3_mutex_enter(db->mutex); + *pxTrace = db->xTrace; + *ppArg = db->pTraceArg; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} /* ** Register a profile function. The pArg from the previously registered ** profile function is returned. ** ** A NULL profile function means that no profiling is executes. A non-NULL @@ -1788,10 +1807,29 @@ db->xProfile = xProfile; db->pProfileArg = pArg; sqlite3_mutex_leave(db->mutex); return pOld; } +/* +** Return the current profile function and argument. +*/ +int sqlite3_get_profile( + const sqlite3 *db, + void (**pxProfile)(void*,const char*,sqlite3_uint64), + void **ppArg +){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || pxProfile==0 || ppArg==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + sqlite3_mutex_enter(db->mutex); + *pxProfile = db->xProfile; + *ppArg = db->pProfileArg; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} #endif /* SQLITE_OMIT_TRACE */ /* ** Register a function to be invoked when a transaction commits. ** If the invoked function returns non-zero, then the commit becomes a Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -2670,20 +2670,24 @@ /* ** CAPI3REF: Tracing And Profiling Functions ** METHOD: sqlite3 ** -** These routines register callback functions that can be used for +** These routines control callback functions that can be used for ** tracing and profiling the execution of SQL statements. ** ** ^The callback function registered by sqlite3_trace() is invoked at ** various times when an SQL statement is being run by [sqlite3_step()]. ** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the ** SQL statement text as the statement first begins executing. ** ^(Additional sqlite3_trace() callbacks might occur ** as each triggered subprogram is entered. The callbacks for triggers ** contain a UTF-8 SQL comment that identifies the trigger.)^ +** +** ^The [sqlite3_get_trace(D,X,P)] interface writes into X and P the +** values of the trace callback and pointer set by the most recent +** [sqlite3_trace()] call on the same [database connection] D. ** ** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit ** the length of [bound parameter] expansion in the output of sqlite3_trace(). ** ** ^The callback function registered by sqlite3_profile() is invoked @@ -2691,17 +2695,25 @@ ** the original statement text and an estimate of wall-clock time ** of how long that statement took to run. ^The profile callback ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite -** might provide greater resolution on the profiler callback. The -** sqlite3_profile() function is considered experimental and is -** subject to change in future versions of SQLite. +** might provide greater resolution on the profiler callback. +** +** ^The [sqlite3_get_profile(D,X,P)] interface writes into X and P the +** values of the profile callback and pointer set by the most recent +** [sqlite3_profile()] call on the same [database connection] D. +** +** All of the tracing and profile interfaces are omitted when the +** [SQLITE_OMIT_TRACE] compile-time option is used. */ void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, +void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite3_uint64), void*); +int sqlite3_get_trace(const sqlite3*, void(**)(void*,const char*),void**); +int sqlite3_get_profile(const sqlite3*, + void(**)(void*,const char*,sqlite3_uint64),void**); /* ** CAPI3REF: Query Progress Callbacks ** METHOD: sqlite3 ** Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -3382,12 +3382,12 @@ void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); void sqlite3RegisterBuiltinFunctions(sqlite3*); void sqlite3RegisterDateTimeFunctions(void); void sqlite3RegisterGlobalFunctions(void); -int sqlite3SafetyCheckOk(sqlite3*); -int sqlite3SafetyCheckSickOrOk(sqlite3*); +int sqlite3SafetyCheckOk(const sqlite3*); +int sqlite3SafetyCheckSickOrOk(const sqlite3*); void sqlite3ChangeCookie(Parse*, int); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) void sqlite3MaterializeView(Parse*, Table*, Expr*, int); #endif Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -1155,11 +1155,11 @@ ** sqlite3SafetyCheckOk() requires that the db pointer be valid for ** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to ** open properly and is not fit for general use but which can be ** used as an argument to sqlite3_errmsg() or sqlite3_close(). */ -int sqlite3SafetyCheckOk(sqlite3 *db){ +int sqlite3SafetyCheckOk(const sqlite3 *db){ u32 magic; if( db==0 ){ logBadConnection("NULL"); return 0; } @@ -1172,11 +1172,11 @@ return 0; }else{ return 1; } } -int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ +int sqlite3SafetyCheckSickOrOk(const sqlite3 *db){ u32 magic; magic = db->magic; if( magic!=SQLITE_MAGIC_SICK && magic!=SQLITE_MAGIC_OPEN && magic!=SQLITE_MAGIC_BUSY ){