c ++ sqlite3_exec由于未完成的语句而无法关闭

时间:2015-04-30 02:13:14

标签: c++ sql sqlite

我在Ubuntu(c ++)上使用Sqlite3有以下代码:

void test_function(dbHandler)
{
    char *retError = 0;

    std::string sql("INSERT INTO LOG (LAST_CHANGED_DATE_TIME) VALUES ('TEST');");

    int returnStatus = sqlite3_exec(dbHandler, sql.c_str(), 0, 0, &retError);

    std::cout << "RetStatus = " << returnStatus << "; " << retError << s

    if (returnStatus == SQLITE_OK)
        return sqlite3_changes(dbHandler);
    else
    {
        sqlite3_free(retError);
        sqlite3_close(dbHandler);
    }
}

sqlite3_exec语句sql在测试其失败行为时出错(在这种情况下,字段名称不匹配)。我从sqlite3_exec获得了正确的状态:

 Status = 1; table Log has no column named last_changed_date_time

由于这是一个错误,我需要释放错误消息(retError)并关闭数据库连接。这是我遇到问题的地方:

调用sqlite3_close时,我收到以下异常消息:

unable to close due to unfinalized statements or unfinished backups

我浏览了sqlite3文档并且无法找到我在这里发布的内容......

基于此我需要帮助:

a)修复上述代码。

b)了解在出现错误时从sqlite3_exec恢复的正确方法。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

a)应以std::endl;结尾的输出行。 dbHandler参数必须具有类型。 void函数不能返回值。但是,关于使用sqlite3 api,发布的代码是正确的。

b)如果出现错误,sqlite3_exec将进行恢复。您只需使用您已经在做的retError释放sqlite3_free指向的内存。

下面是一个最小的运行示例,其中我描述的3个错误已修复。它表明它是正确的(&#34;库程序不按顺序调用&#34;输出是因为你不能在一个封闭的数据库句柄上调用sqlite3_errmsg),因为它不会产生你描述的错误。因此,如果sqlite3_close失败,那是因为程序中的其他地方出现了错误。

您可以通过取消注释3个注释行来重现您描述的错误。 sqlite3_prepare调用后将由sqlite3_finalize创建的语句不会被清除,因此sqlite3_close将导致&#34;由于未完成的语句或未完成的备份而无法关闭#34;错误。您的错误可能是由类似的东西引起的。

#include <iostream>
#include <sqlite3.h>

void test_function(sqlite3 * dbHandler)
{
    char *retError = 0;

    std::string sql("INSERT INTO LOG (LAST_CHANGED_DATE_TIME) VALUES ('TEST');");

    int returnStatus = sqlite3_exec(dbHandler, sql.c_str(), 0, 0, &retError);

    std::cout << "RetStatus = " << returnStatus << "; " << retError << std::endl;

    if (returnStatus == SQLITE_OK)
        return; // sqlite3_changes(dbHandler);
    else
    {
        sqlite3_free(retError);
        sqlite3_close(dbHandler);
    }
}

int main() 
{
    sqlite3 * dbHandler;
    sqlite3_open("test.sqlite", &dbHandler);
    sqlite3_exec(dbHandler, "CREATE TABLE LOG (DUMMY);", 0, 0, 0);

    // sqlite3_stmt * test;
    // const char * sql = "INSERT INTO LOG (DUMMY) VALUES ('TEST');";
    // sqlite3_prepare(dbHandler, sql, -1, &test, 0);

    test_function(dbHandler);

    std::cout << "Last error: " << sqlite3_errmsg(dbHandler) << std::endl;
    return 0;
}

答案 1 :(得分:1)

由于我在10年后升级后重新访问sqlite3,因此我设法获得了上述消息。我做了一个sqlite3_open_v2然后一个sqlite3_close并得到了相同的消息。 sqlite3_close_v2可以避免此消息。

小而愚蠢的错误,但也许对某人有用。