hmmm... it gives a schema changed because 'delete * from x' actually drops the table but I'm not sure why it gave an error since the prepare was done after the other change was committed...
program output: Opened the database. Opened the database. Failed to step statement: database schema has changed finalize failed: database schema has changed program code: #include <stdio.h> #include <stdlib.h> //#include <unistd.h> #include <sqlite3.h> int main(int argc, char** argv) { int rc; sqlite3* db1; sqlite3* db2; sqlite3_stmt *pStmt1; sqlite3_stmt *pStmt2; sqlite3_stmt *pStmt3; unlink("bug.db"); // for the test, we make sure we have a new database. // create first connection to the database: db1. rc = sqlite3_open("bug.db", &db1); if (rc) { printf("Cannot open database: %s\n", sqlite3_errmsg(db1)); exit(1); } printf("Opened the database.\n"); // create table bla using the first connection db1, inside a transaction. rc = sqlite3_exec(db1, "begin", 0, 0, 0); if (rc != SQLITE_OK) { printf("begin failed: %s\n", sqlite3_errmsg(db1)); exit(1); } rc = sqlite3_prepare(db1, // Database handle "create table bla(a int,b int)", -1, // Length of the statement &pStmt1, // OUT: Statement handle 0); // OUT: Pointer to unused portion // of the statement if (rc != SQLITE_OK) { printf("prepare failed: %s\n", sqlite3_errmsg(db1)); exit(1); } rc = sqlite3_step(pStmt1); if (rc != SQLITE_DONE) { // if we failed, we show it. printf("Failed to step statement: %s\n", sqlite3_errmsg(db1)); } rc = sqlite3_finalize(pStmt1); if (rc != SQLITE_OK) { printf("finalize failed: %s\n", sqlite3_errmsg(db1)); exit(1); } sqlite3_exec(db1, "commit", 0, 0, 0); // here we commit the transaction. if (rc != SQLITE_OK) { printf("commit failed: %s\n", sqlite3_errmsg(db1)); exit(1); } // now we suppose to have inside the database the table bla. // here we, optionally, create another connection to the same database, // and then create other table in a transaction. rc = sqlite3_open("bug.db", &db2); // create the second connection. if (rc) { printf("Cannot open database again: %s\n", sqlite3_errmsg(db2)); exit(1); } printf("Opened the database.\n"); // create table foo rc = sqlite3_exec(db2, "begin", 0, 0, 0); // start the transaction. if (rc != SQLITE_OK) { printf("begin failed: %s\n", sqlite3_errmsg(db2)); exit(1); } rc = sqlite3_prepare(db2, // Database handle "create table foo(c int,d int)", -1, // Length of the statement &pStmt2, // OUT: Statement handle 0); // OUT: Pointer to unused portion if (rc != SQLITE_OK) { printf("prepare failed: %s\n", sqlite3_errmsg(db2)); exit(1); } rc = sqlite3_step(pStmt2); if (rc != SQLITE_DONE) { // if we failed, we show it. printf("Failed to step statement: %s\n", sqlite3_errmsg(db2)); } rc = sqlite3_finalize(pStmt2); if (rc != SQLITE_OK) { printf("finalize failed: %s\n", sqlite3_errmsg(db2)); exit(1); } sqlite3_exec(db2, "commit", 0, 0, 0); if (rc != SQLITE_OK) { printf("commit failed: %s\n", sqlite3_errmsg(db2)); exit(1); } // delete from table bla using the first connection. sqlite3_exec(db1, "begin", 0, 0, 0); if (rc != SQLITE_OK) { printf("begin failed: %s\n", sqlite3_errmsg(db1)); exit(1); } rc = sqlite3_prepare(db1, // Database handle "delete from bla", -1, // Length of the statement &pStmt3, // OUT: Statement handle 0); // OUT: Pointer to unused portion // of the statement if (rc != SQLITE_OK) { printf("prepare failed: %s\n", sqlite3_errmsg(db1)); exit(1); } rc = sqlite3_step(pStmt3); if (rc != SQLITE_DONE) { // if we failed, we log it. printf("Failed to step statement: %s\n", sqlite3_errmsg(db1)); } else { printf("deleted all from bla successfully\n"); } rc = sqlite3_finalize(pStmt3); if (rc != SQLITE_OK) { printf("finalize failed: %s\n", sqlite3_errmsg(db1)); exit(1); } sqlite3_exec(db1, "commit", 0, 0, 0); if (rc != SQLITE_OK) { printf("commit failed: %s\n", sqlite3_errmsg(db1)); exit(1); } return 0; }