-C Improved\sfiltering\sof\sinput\sfor\sfuzzershell\sfor\smodes\sother\sthan\sgeneric.
-D 2015-04-22T13:16:46.644
+C Prototype\sfor\san\ssqlite3_db_log()\sinterface.
+D 2015-04-22T14:41:19.758
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in faaf75b89840659d74501bea269c7e33414761c1
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/expr.c 5555f768c05d7d4a7840c6c2e72ad7aecbe0fe54
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
-F src/func.c 1414c24c873c48796ad45942257a179a423ba42f
+F src/func.c e6b4680d0b6c901365e1ea5a6e75710e9479b70d
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
-F src/main.c 40e333960d53f7d50ee8ce09d40431c87ea653f2
+F src/main.c 453ae1a35c044cb5baa6b11697d722766d3f1569
F src/malloc.c 6a370b83d54e4bbf6f94021221c2a311cff26a18
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f
F src/prepare.c 1fffbdcd6f8a0173a8f70d71f22528f4c0e1e3d3
-F src/printf.c 08fa675c200aac29e561c6153f91f909ed17612f
+F src/printf.c 9753790eed39d7863a3e33567199f382d980fc28
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 53486a98c17b7ae09b8c2b398013e973ce4c1aae
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 35433ea8894ac42594ddc31eb0165a6d6401cfe5
F src/shell.c 78eabce4c16c45e36fea2368f95118116399ba8a
-F src/sqlite.h.in ca27603a36fcacdaac5a19d8ee35aaff8ce8516f
+F src/sqlite.h.in 3fb08b501d0155b4ba3ae8ef99c6f08491135dcb
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
-F src/sqliteInt.h 8abcea1295138f10ef8f7ed38db5f1b573b93ece
+F src/sqliteInt.h 823549bbcb0131e09c4a324080309d049a80e258
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
F src/tclsqlite.c 14f1992dd6100bfeb1a3dec7e7f449e1c814b8ee
-F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585
+F src/test1.c 94efc685eb2e3dda4eb476670eeffaeaf05bead9
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
-F src/tokenize.c b7fb584c2be5ec39b6fdf04b185e7c6f33f8dc15
+F src/tokenize.c 8fa8a62632f6f3916bfb6f7b10e1ffbd36de71f0
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c a6431c92803b975b7322724a7b433e538d243539
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
-F src/vdbe.c f0cf3cf527d5a40b8d5d2324fdbb31da6c90cd8b
+F src/vdbe.c 4f4af7239261189393ca2752a3bf9977c14cb024
F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d
F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0
-F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75
-F src/vdbeaux.c 03591cca98ec50e1493043f0ff7abbece0b9c83d
+F src/vdbeapi.c d4c9945b2a53b0b71d2a16843bb8d054ce513276
+F src/vdbeaux.c aa9b179cc9e6e3e75f8f28e366bb0aafab9d710e
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
F src/vdbemem.c b5256445b318b0f2b3bc429028469cfbb08f19a5
F src/vdbesort.c 2e7f683464fd5db3be4beaa1ff2d39e24fcb64b8
F src/wal.c 753995db83247f20361a8e8a874990b21a75abd9
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
-F src/where.c 32fe265e3dc74ef3b27deb9e6eb5fc3c71409612
+F src/where.c ba0839e75f989dba622809716daabeb9c7fbd3c5
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
+F test/errlog01.test 112ea4cd0f2974a63d60fe96d322af0f383045d4
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 1cceefa7c6585bca786fe9f7118f7beb829ad709
-R cbbdf393d38b0307d153eda6dc2aba63
+P 025e8370dde2918b66683f8d7fa9c7d23d03c9b4
+R 065b478bd5e153421f77ec0bbb390aae
+T *branch * sqlite3_db_log
+T *sym-sqlite3_db_log *
+T -sym-trunk *
U drh
-Z 11145234dd05700bee32abe646d63f11
+Z cb2dffa7a83d63dde4f8c28d3e4ea48d
-025e8370dde2918b66683f8d7fa9c7d23d03c9b4
\ No newline at end of file
+658e20f55467a90bcebe5e01cf9f252dbe8bd690
\ No newline at end of file
/*
** Implementation of the sqlite_log() function. This is a wrapper around
-** sqlite3_log(). The return value is NULL. The function exists purely for
-** its side-effects.
+** sqlite3_db_log(). The return value is NULL. The function exists purely
+** for its side-effects.
*/
static void errlogFunc(
sqlite3_context *context,
){
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(context);
- sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1]));
+ sqlite3_db_log(sqlite3_context_db_handle(context),
+ sqlite3_value_int(argv[0]),
+ "%s", sqlite3_value_text(argv[1]));
}
/*
rc = setupLookaside(db, pBuf, sz, cnt);
break;
}
+ case SQLITE_DBCONFIG_LOG: {
+ /* MSVC is picky about pulling func ptrs from va lists.
+ ** http://support.microsoft.com/kb/47961 */
+ typedef void(*LOGFUNC_t)(void*,int,const char*);
+ db->xLog = va_arg(ap, LOGFUNC_t);
+ db->pLogArg = va_arg(ap, void*);
+ break;
+ }
default: {
static const struct {
int op; /* The opcode */
** allocate memory because it might be called while the memory allocator
** mutex is held.
*/
-static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
+static void renderLogMsg(
+ void (*xLog)(void*,int,const char*), /* Logging function */
+ void *pArg, /* First argument to xLog */
+ int iErrCode, /* Error code */
+ const char *zFormat, /* Format string for error message */
+ va_list ap /* Arguments to format string */
+){
StrAccum acc; /* String accumulator */
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
acc.useMalloc = 0;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
- sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
- sqlite3StrAccumFinish(&acc));
+ xLog(pArg, iErrCode, sqlite3StrAccumFinish(&acc));
}
/*
va_list ap; /* Vararg list */
if( sqlite3GlobalConfig.xLog ){
va_start(ap, zFormat);
- renderLogMsg(iErrCode, zFormat, ap);
+ renderLogMsg(sqlite3GlobalConfig.xLog, sqlite3GlobalConfig.pLogArg,
+ iErrCode, zFormat, ap);
+ va_end(ap);
+ }
+}
+void sqlite3_db_log(sqlite3 *db, int iErrCode, const char *zFormat, ...){
+ va_list ap; /* Vararg list */
+ if( db && db->xLog ){
+ va_start(ap, zFormat);
+ renderLogMsg(db->xLog, db->pLogArg, iErrCode, zFormat, ap);
+ va_end(ap);
+ }else if( sqlite3GlobalConfig.xLog ){
+ va_start(ap, zFormat);
+ renderLogMsg(sqlite3GlobalConfig.xLog, sqlite3GlobalConfig.pLogArg,
+ iErrCode, zFormat, ap);
va_end(ap);
}
}
** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_LOG]] <dt>SQLITE_DBCONFIG_LOG</dt>
+** <dd> The SQLITE_DBCONFIG_LOG option is used to configure the SQLite
+** [error log] for a specific database connection. See also the
+** [SQLITE_CONFIG_LOG] option to [sqlite3_config()] for the global log
+** callback.
+** (^The SQLITE_DBCONFIG_LOG option takes two arguments: a pointer to a
+** function with a call signature of void(*)(void*,int,const char*),
+** and a pointer to void. ^If the function pointer is not NULL, it is
+** invoked by [sqlite3_db_log()] to process each logging event. ^If the
+** function pointer is NULL, then calls to [sqlite3_db_log()] interface try
+** to use the [SQLITE_CONFIG_LOG|global error log]. If both the connection
+** and global error log callbacks are NULL then [sqlite3_db_log()] is a
+** harmless no-op.
+** ^The void pointer that is the second argument to SQLITE_DBCONFIG_LOG is
+** passed through as the first parameter to the application-defined logger
+** function whenever that function is invoked. ^The second parameter to
+** the logger function is a copy of the second parameter to the corresponding
+** [sqlite3_db_log()] call and is intended to be a [result code] or an
+** [extended result code]. ^The third parameter passed to the logger is
+** log message after formatting via [sqlite3_snprintf()].
+** The SQLite logging interface is not reentrant; the logger function
+** supplied by the application must not invoke any SQLite interface.
+** </dd>
+**
** </dl>
*/
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
+#define SQLITE_DBCONFIG_LOG 1004 /* xFunc, void* */
/*
**
** ^The [sqlite3_log()] interface writes a message into the [error log]
** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
+** ^The [sqlite3_db_log()] interface writes a message into the [error log]
+** established by the [SQLITE_DBCONFIG_LOG] option to [sqlite3_db_config()].
** ^If logging is enabled, the zFormat string and subsequent arguments are
** used with [sqlite3_snprintf()] to generate the final output string.
**
-** The sqlite3_log() interface is intended for use by extensions such as
+** ^The [sqlite3_db_log()] interface writes error and warning information
+** to the callback identified by the [SQLITE_DBCONFIG_LOG] option if that
+** callback is not NULL, falling back to the [SQLITE_CONFIG_LOG] callback
+** if the first parameter to [sqlite3_db_log()] is NULL or if the
+** [SQLITE_DBCONFIG_LOG] callback is NULL.
+**
+** The sqlite3_log() and sqlite3_db_log() interfaces are intended for
+** use by extensions such as
** virtual tables, collating functions, and SQL functions. While there is
** nothing to prevent an application from calling sqlite3_log(), doing so
** is considered bad form.
** buffer.
*/
void sqlite3_log(int iErrCode, const char *zFormat, ...);
+void sqlite3_db_log(sqlite3*, int iErrCode, const char *zFormat, ...);
/*
** CAPI3REF: Write-Ahead Log Commit Hook
double notUsed1; /* Spacer */
} u1;
Lookaside lookaside; /* Lookaside malloc configuration */
+ void (*xLog)(void*,int,const char*); /* Function for logging */
+ void *pLogArg; /* First argument to xLog() */
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth; /* Access authorization function */
void *pAuthArg; /* 1st argument to the access auth function */
logcallback.pInterp = 0;
sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
}
- if( objc>1 ){
+ if( objc==2 ){
logcallback.pObj = objv[1];
Tcl_IncrRefCount(logcallback.pObj);
logcallback.pInterp = interp;
}
return TCL_OK;
}
+static int test_sqlite3_db_log(
+ ClientData clientData,
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ sqlite3 *db;
+ if( objc<1 || objc>3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ if( logcallback.pObj ){
+ Tcl_DecrRefCount(logcallback.pObj);
+ logcallback.pObj = 0;
+ logcallback.pInterp = 0;
+ sqlite3_db_config(db, SQLITE_DBCONFIG_LOG, 0, 0);
+ }
+ if( objc==3 ){
+ logcallback.pObj = objv[2];
+ Tcl_IncrRefCount(logcallback.pObj);
+ logcallback.pInterp = interp;
+ sqlite3_db_config(db, SQLITE_DBCONFIG_LOG, xLogcallback, 0);
+ }
+ return TCL_OK;
+}
/*
** tcl_objproc COMMANDNAME ARGS...
{ "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
{ "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 },
{ "test_sqlite3_log", test_sqlite3_log, 0 },
+ { "test_sqlite3_db_log", test_sqlite3_db_log, 0 },
#ifndef SQLITE_OMIT_EXPLAIN
{ "print_explain_query_plan", test_print_eqp, 0 },
#endif
assert( pzErrMsg!=0 );
if( pParse->zErrMsg ){
*pzErrMsg = pParse->zErrMsg;
- sqlite3_log(pParse->rc, "%s", *pzErrMsg);
+ sqlite3_db_log(db, pParse->rc, "%s", *pzErrMsg);
pParse->zErrMsg = 0;
nErr++;
}
}else{
sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType);
}
- sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg);
+ sqlite3_db_log(db, pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
assert( rc );
p->rc = rc;
testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(rc, "statement aborts at %d: [%s] %s",
+ sqlite3_db_log(db, rc, "statement aborts at %d: [%s] %s",
(int)(pOp - aOp), p->zSql, p->zErrMsg);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
sqlite3_mutex_enter(p->db->mutex);
if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE);
- sqlite3_mutex_leave(p->db->mutex);
- sqlite3_log(SQLITE_MISUSE,
+ sqlite3_db_log(p->db, SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
+ sqlite3_mutex_leave(p->db->mutex);
return SQLITE_MISUSE_BKPT;
}
if( i<1 || i>p->nVar ){
u32 iRandom;
if( retryCount ){
if( retryCount>100 ){
- sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
+ sqlite3_db_log(db, SQLITE_FULL, "MJ delete: %s", zMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
break;
}else if( retryCount==1 ){
- sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster);
+ sqlite3_db_log(db, SQLITE_FULL, "MJ collide: %s", zMaster);
}
}
retryCount++;
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
if( !sentWarning ){
- sqlite3_log(SQLITE_WARNING_AUTOINDEX,
+ sqlite3_db_log(pParse->db, SQLITE_WARNING_AUTOINDEX,
"automatic index on %s(%s)", pTable->zName,
pTable->aCol[iCol].zName);
sentWarning = 1;
--- /dev/null
+# 2015-04-22
+#
+# 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.
+#
+#*************************************************************************
+# Test cases for the sqlite3_log() and sqlite3_db_log() interfaces.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+unset -nocomplain log
+set log {}
+do_test errlog01-1.0 {
+ test_sqlite3_db_log db [list lappend ::log]
+ db eval {SELECT sqlite_log(7,'simulated error')}
+} {{}}
+do_test errlog01-1.1 {
+ set ::log
+} {SQLITE_NOMEM {simulated error}}
+do_test errlog01-1.2 {
+ sqlite3 db2 :memory:
+ set ::log {}
+ db2 eval {SELECT sqlite_log(7,'simulated error')}
+} {{}}
+do_test errlog01-1.3 {
+ set ::log
+} {}
+
+
+
+finish_test