Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 产生错误的sqlite日志查询_C_Sqlite - Fatal编程技术网

C 产生错误的sqlite日志查询

C 产生错误的sqlite日志查询,c,sqlite,C,Sqlite,我正在用C编写一个使用sqlite3的应用程序。我希望所有的查询和错误都被被动地记录到stderr进行调试 假设我有此代码(省略错误处理): 输出: SELECT * FROM users (1) no such table: users_nonexistant 我怎样才能让它输出这个 SELECT * FROM users SELECT * FROM users_nonexisant (1) no such table: users_nonexistant 阅读相关文档以了解导致此问题的原

我正在用C编写一个使用sqlite3的应用程序。我希望所有的查询和错误都被被动地记录到stderr进行调试

假设我有此代码(省略错误处理):

输出:

SELECT * FROM users
(1) no such table: users_nonexistant
我怎样才能让它输出这个

SELECT * FROM users
SELECT * FROM users_nonexisant
(1) no such table: users_nonexistant

阅读相关文档以了解导致此问题的原因

SQLITE_配置_日志 SQLITE_CONFIG_LOG选项用于配置SQLITE全局错误日志。(SQLITE_CONFIG_LOG选项有两个参数:一个指向调用签名为void()(void,int,const char*)的函数的指针,另一个指向void的指针。如果函数指针不为NULL,则sqlite3_LOG()将调用它来处理每个日志事件。如果函数指针为NULL,则sqlite3_LOG()将接口变为no-op。无论何时调用SQLITE_CONFIG_LOG函数,作为SQLITE_CONFIG_LOG第二个参数的void指针将作为第一个参数传递给应用程序定义的记录器函数。记录器函数的第二个参数是第一个参数到相应sqlite3_LOG()的副本调用并指定为结果代码或扩展结果代码。传递给记录器的第三个参数是通过sqlite3_snprintf()格式化后的日志消息。SQLite日志记录接口不可重入;应用程序提供的记录器函数不得调用任何SQLite接口。在多线程应用程序中,应用程序定义的记录器函数必须是线程安全的

这意味着您可以传递一个指向要执行的
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);
}
//...

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

仅对实际运行的语句调用语句跟踪程序

在编译SQL语句之前,没有内置的机制来记录它们。
如果您不能修改
sqlite3\u exec
调用,您必须更改SQLite的源代码并在那里添加日志调用。

谢谢您的回答。这肯定会打印出正确的信息,但我不想为每个
sqlite3\u exec
语句编写额外的代码。我添加了一条注释,
//此代码无法更改使这一点更加明显。
sqlite3_exec
本身已经是
prepare
step
finalize
的包装器,您可以编写一个包装器函数,还可以为当前语句设置指针是的,是的,我知道我可以为所有sqlite3调用编写一个包装器。但这是我无法做到的准确地更改所有100多个呼叫站点,并发送一封公司范围内的电子邮件,告诉所有人使用我的新API。我感谢您的帮助,但听起来我想要的是不可能的。感谢您提供的信息。我怀疑是这样的,但我希望不是这样。修补源代码是一种选择,但可能不值得,从维护角度来看。我将继续生活我所拥有的。
//...
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);
}
//...