C ++ sqlite3_exec cannot be closed due to unfinalized statements

I have the following code snippet using Sqlite3 on Ubuntu (C ++):

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); } } 

The sqlite3_exec sql statement is erroneous to check its failure behavior (in this case, the field name does not match). I get the correct status from sqlite3_exec as:

  Status = 1; table Log has no column named last_changed_date_time 

As an error, I need to free the error message ( retError ) and close the database connection. And here I have a problem:

When sqlite3_close called, I get the following exception message:

 unable to close due to unfinalized statements or unfinished backups 

I was looking through sqlite3 docs and couldn't find out that I am not releasing here ...

Based on this, I need help:

a) Correct the above code.

b) Understand the correct recovery method from sqlite3_exec in case of an error.

Thanks for the help.

+5
source share
2 answers

a) The output string, which should end with std::endl; . The dbHandler argument must be of type. The void function cannot return a value. However, regarding the use of sqlite3 api, the published code is correct.

b) If sqlite3_exec fails, recovery will occur. You only need to free the memory pointed to by retError using sqlite3_free , which you already do.

Below is a minimal example with three bugs fixed by me. It shows that it is correct (the output is "library routine called from sequence" because you cannot call sqlite3_errmsg in the private database descriptor), since it does not generate the error you described. Therefore, if sqlite3_close fails, it is due to an error elsewhere in your program.

The error you are describing can be reproduced by uncommenting the three commented lines. The statement that sqlite3_prepare will then create will not be cleared by calling sqlite3_finalize , and therefore sqlite3_close will result in the error "could not be closed due to unfinalized statements or incomplete backups." Your error is probably caused by something similar.

 #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
source

Since I am reviewing sqlite3 from the moment of updating after 10 years, I managed to get the above message. I did sqlite3_open_v2 and then sqlite3_close and received the same message. sqlite3_close_v2 avoids the message.

A small, idiotic mistake, but perhaps useful to someone.

+1
source

All Articles