我正在用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

最佳答案

阅读sqlite3_config的文档会导致此page about Configuration Options
SQLITE配置日志
SQLITE配置日志选项用于配置SQLITE全局错误日志。(SQLITE_CONFIG_LOG选项有两个参数:指向调用签名为void()的函数的指针(void,int,const char*)和指向void的指针。如果函数指针不为空,sqlite3_log()将调用它来处理每个日志事件。如果函数指针为空,则sqlite3_log()接口将变为no-op。每当调用该函数时,作为SQLITE_CONFIG_log的第二个参数的void指针将作为第一个参数传递给应用程序定义的记录器函数。logger函数的第二个参数是第一个参数到对应的sqlite3_log()调用的副本,目的是作为结果代码或扩展结果代码。传递给记录器的第三个参数是通过sqlite3_snprintf()格式化后的日志消息。SQLite日志记录接口不可重入;应用程序提供的记录器函数不能调用任何SQLite接口。在多线程应用程序中,应用程序定义的记录器函数必须是线程安全的。
这意味着您可以传递一个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);
}
//...

免责声明:我还没有测试代码!

关于c - 产生错误的sqlite日志查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39302374/

10-11 22:19
查看更多