我正在用C编写一个使用sqlite3的应用程序。我希望将所有查询和错误被动地记录到stderr进行调试。
说我有这个代码(省略错误处理):
void main(void)
{
sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, NULL);
sqlite3 *db = NULL;
sqlite3_open_v2("main.db3", &db, SQLITE_OPEN_READWRITE, NULL);
sqlite3_trace_v2(db, SQLITE_TRACE_STMT, tracer, NULL);
// this code cannot change
sqlite3_exec(db, "SELECT * FROM users", NULL, NULL, NULL);
sqlite3_exec(db, "SELECT * FROM users_nonexistant", NULL, NULL, NULL);
}
static void errorLogCallback(void *, int iErrCode, const char *zMsg)
{
fprintf(stderr, "(%d) %s\n", iErrCode, zMsg);
}
static int tracer(unsigned, void*, void *p, void*)
{
sqlite3_stmt *stmt = (sqlite3_stmt*)p;
char *sql = sqlite3_expanded_sql(stmt);
fprintf(stderr, "%s\n", sql);
sqlite3_free(sql);
return 0;
}
输出:
SELECT * FROM users
(1) no such table: users_nonexistant
如何让它输出?
SELECT * FROM users
SELECT * FROM users_nonexisant
(1) no such table: users_nonexistant
答案 0 :(得分:2)
阅读sqlite3_config的文档会导致page about Configuration Options,
SQLITE_CONFIG_LOG
SQLITE_CONFIG_LOG选项用于配置SQLite全局错误日志。 (SQLITE_CONFIG_LOG选项有两个参数:一个指向函数的指针,调用签名为void()(void ,int,const char *),指向void的指针。如果函数指针不是NULL,由sqlite3_log()调用它来处理每个日志事件。如果函数指针为NULL,则sqlite3_log()接口变为无操作。作为SQLITE_CONFIG_LOG的第二个参数的void指针被传递为每当调用该函数时,应用程序定义的记录器函数的第一个参数。记录器函数的第二个参数是相应的sqlite3_log()调用的第一个参数的副本,用于结果代码或传递给记录器的第三个参数是通过sqlite3_snprintf()格式化后的日志消息.SQLite日志记录界面不可重入;应用程序提供的记录器函数不能调用任何SQLite接口。在多线程应用程序中, 应用程序-defined logger函数必须是线程安全的。
这意味着你可以传递一个char** pStatement
,它将指向要执行的char*
sql语句。
//...
int main(void)
{
char** pStatement=NULL;
sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, pStatement);
sqlite3 *db = NULL;
sqlite3_open_v2("main.db3", &db, SQLITE_OPEN_READWRITE, NULL);
sqlite3_trace_v2(db, SQLITE_TRACE_STMT, tracer, NULL);
const char *statement="SELECT * FROM users";
pStatement=(char**)&statement;
sqlite3_exec(db,statement , NULL, NULL, NULL);
const char *faultyStatement="SELECT * FROM users_nonexistant";
pStatement=(char**)&faultyStatement;
sqlite3_exec(db, faultyStatement, NULL, NULL, NULL);
}
static void errorLogCallback(void * pStatement, int iErrCode, const char *zMsg
{
fprintf(stderr, "%s\n(%d) %s\n",*(char**)pStatement, iErrCode, zMsg);
}
//...
免责声明:我还没有测试过代码!
答案 1 :(得分:1)
仅对实际运行的语句调用语句跟踪器。
在编译SQL语句之前,没有内置机制来记录它们。
如果您无法修改sqlite3_exec
调用,则必须更改SQLite的源代码并在那里添加日志调用。