I'm trying to code a function that creates a zSQL database from a file of commands, using SQLite. The code of my function is as follows :
bool createDatabaseFromFile(Database& db, std::istream &commandFile, const char* dbName, std::ostream* err, bool multilineQueries)
{
Statement stmt;
std::string lineStr;
std::string queryStr;
bool end = false;
if (!dbName) // if the adress of the database isn't given, we get it from the first line of the command file
{
std::getline(commandFile, lineStr);
dbName = lineStr.c_str();
}
bool noError = db.open(dbName, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, err); // if the database didn't open, the following loops aren't used
while (std::getline(commandFile, lineStr) && (!end) && noError) // adds all lines of the file until either the end of the file or the keyword "#END"
{
if (lineStr.substr(0,4) == "#END")
end = true;
else if (lineStr.substr(0,2) != "//") // skips the commented lines
queryStr += lineStr;
if (!multilineQueries) // if all lines are considered as a single query
queryStr += ";";
}
std::string::size_type start_query = 0;
std::string::size_type end_query;
std::string query;
while (start_query != std::string::npos && !noError) //continue until all queries of the string are executed or there is an error
{
end_query = queryStr.find_first_of(';', start_query);
query = queryStr.substr(start_query, end_query);
if (db.prepare(query.c_str(), lineStr.size(), stmt)) // returns true if sql3_prepare didn't return an error
{
noError = stmt.makeAllSteps();
}
else
noError = false;
start_query = end_query;
if (start_query != std::string::npos)
start_query ++; // else the "cursors" stay on the same ';' over and over
}
return noError;
}
The Stmt class is basically a wrapper around sqlite3_stmt. When it's destroyed at the end of the code, it calls sqlite3_finalize, which causes a segfault for a reason I can't understand. What's the issue ?
The call stack of the error is this :
sqlite3_finalize(pStmt=0x3)
sql3::Statement::erase(this=0x28f9e0)
sql3::Statement::~Statement(this=0x28f9e0, __in_chrg=<optimized out>)
sql3::createDatabaseFromFile(db=..., commandFile=..., dbName=0x51e057 "Ressources\\DatabaseFile.txt", err=0x533cc0, multilineQueries=true)
Here is the destructor's code :
void sql3::Statement::erase()
{
if (p_stmt)
testCode(sqlite3_finalize(p_stmt), USING_INCORRECT_STATEMENT, nullptr, std::cerr);
//testCode is a const function, so the above is equivalent to :
if (p_stmt)
sqlite3_finalize(p_stmt);
p_stmt = nullptr;
}
sql3::Statement::~Statement()
{
erase();
}
Also, not sure what this mean, but I don't have any error if I call Statement::erase() just after Statement::makeAllSteps(). EDIT : apparently, it means that the while (start_query != std::string::npos && !noError) loop is skipped for some reason.
EDIT 2 : found it, it's because of !noError. I'll post an answer when I'm allowed.