-
Notifications
You must be signed in to change notification settings - Fork 397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve error checking in SQLite database connection (again) #10553
Improve error checking in SQLite database connection (again) #10553
Conversation
After calling sqlite3_close(), the call to sqlite3_errmsg() is guaranteed to yield useless message "bad parameter or other API misuse"
Creating a journal file could decrease the character limit for folder paths on Windows. Currently, the only inheriting class uses journal_mode = OFF, so it is not necessary to test for access to create and lock a journal file. Confer SQLite::SQLite().
sqlite3 *m_connection; | ||
std::shared_ptr<sqlite3> m_db; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that m_db
is a shared pointer to m_connection
, created in the SQLiteProcedures constructor. There is no need to store m_connection
for direct access.
@@ -2803,7 +2808,7 @@ int SQLiteProcedures::sqliteResetCommand(sqlite3_stmt *stmt) | |||
|
|||
bool SQLiteProcedures::sqliteWithinTransaction() | |||
{ | |||
return (sqlite3_get_autocommit(m_connection) == 0); | |||
return (sqlite3_get_autocommit(m_db.get()) == 0); | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use the shared_ptr instead of the pointer it owns.
SQLiteProcedures::SQLiteProcedures(std::shared_ptr<std::ostream> const &errorStream, std::shared_ptr<sqlite3> const &db) | ||
: m_writeOutputToSQLite(true), m_errorStream(errorStream), m_connection(nullptr), m_db(db) | ||
: m_writeOutputToSQLite(true), m_errorStream(errorStream), m_db(db) | ||
{ | ||
} | ||
|
||
SQLiteProcedures::SQLiteProcedures(std::shared_ptr<std::ostream> const &errorStream, | ||
bool writeOutputToSQLite, | ||
fs::path const &dbName, | ||
fs::path const &errorFilePath) | ||
: m_writeOutputToSQLite(writeOutputToSQLite), m_errorStream(errorStream), m_connection(nullptr) | ||
: m_writeOutputToSQLite(writeOutputToSQLite), m_errorStream(errorStream) | ||
{ | ||
sqlite3 *m_connection = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of initializing member variable, initialize m_connection
as a local variable.
sqlite3_close(m_connection); | ||
if (rc) { | ||
*m_errorStream << "SQLite3 message, can't get exclusive lock to edit database: " << sqlite3_errmsg(m_connection) << std::endl; | ||
*m_errorStream << "SQLite3 message, can't get exclusive lock to edit database: " << zErrMsg << std::endl; | ||
ok = false; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After sqlite3_close()
, we should not call sqlite3_errmsg()
. Instead, the error message was already returned by a previous function call.
rc = sqlite3_exec(m_connection, "PRAGMA journal_mode = OFF;", nullptr, 0, &zErrMsg); | ||
if (!rc) { | ||
rc = sqlite3_exec(m_connection, "CREATE TABLE Test(x INTEGER PRIMARY KEY)", nullptr, 0, &zErrMsg); | ||
} | ||
sqlite3_close(m_connection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we turn off the journal mode then execute a query.
Thanks for the PR. I looked at some of the CI testing diffs, and it seems like this branch's fixes are:
|
I guess the CI tests do not merge the develop branch? My local copy of the develop branch is out of date, so I'll merge in the latest develop branch. Otherwise, the commits are only related to SQLiteProcedures class and do not impact any other features. |
Merge NREL/EnergyPlus:develop
CI does not automatically merge the latest develop branch. We've had several PRs merged in recent days, which probably caused test diffs. Now this branch is up to date, and all CI testing looks good. This seems like a good addition to enhance SQLite database connection error checking. |
This PR looks fully clean and ready to go. @Myoldmopar |
Pull request overview
sqlite3_errmsg
aftersqlite3_close
. Such a call sequence always yields the unhelpful error message "bad parameter or other API misuse".Suggested tag: Defect
Discussion
The SQliteProcedures constructor tests for access to create/write/lock a sqlite3 database file. Unless the calling code sets
journal_mode = OFF
, the first call tosqlite3_exec
opens a database file (dbName
) and a journal file atdbName + "-journal"
. However, testing access to the journal file is not necessary since the inheriting class SQLite setsjournal_mode = OFF
and never uses it. In some cases, failing to turn off the journal file could lead to an error. Namely, on Windows, file paths may be limited to 260 characters, depending on registry settings. While the database file may be within the path length limit, the journal file may exceed it. Then, EnergyPlus would return an error message blaming sqlite.Pull Request Author
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Reviewer
This will not be exhaustively relevant to every PR.