From 832e89440f2586a2b027dfa56e5d14baf9ecd188 Mon Sep 17 00:00:00 2001 From: Douglas Heriot Date: Thu, 26 May 2016 00:34:34 +1000 Subject: [PATCH] Better exception messages when statements fail Added new constructor to Exception that takes sqlite3* pointer, allowing for getting more information out. Makes it much easier to debug syntax errors in prepared statements, for example. --- include/SQLiteCpp/Exception.h | 33 ++++++++++++++++++++++++++++++++- include/SQLiteCpp/Statement.h | 2 +- src/Statement.cpp | 4 ++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/include/SQLiteCpp/Exception.h b/include/SQLiteCpp/Exception.h index ae7a8ed..d58915e 100644 --- a/include/SQLiteCpp/Exception.h +++ b/include/SQLiteCpp/Exception.h @@ -12,6 +12,8 @@ #include #include +#include +#include namespace SQLite @@ -30,9 +32,38 @@ public: * @param[in] aErrorMessage The string message describing the SQLite error */ explicit Exception(const std::string& aErrorMessage) : - std::runtime_error(aErrorMessage) + std::runtime_error(aErrorMessage), + errcode(0), + extendedErrcode(0), + errstr(), + errmsg() { } + + /** + * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. + * + * @param[in] apSQLite The SQLite object, to obtain detailed error messages from. + * @param[in] ret Return value from function call that failed. + */ + explicit Exception(sqlite3* apSQLite, int ret) : + errcode(ret), + extendedErrcode(sqlite3_extended_errcode(apSQLite)), + errstr(sqlite3_errstr(ret)), + errmsg(sqlite3_errmsg(apSQLite)), + + std::runtime_error([apSQLite, ret](){ + std::ostringstream message; + message << sqlite3_errstr(ret) << ": " << sqlite3_errmsg(apSQLite); + return message.str(); + }()) + { + } + + const int errcode; + const int extendedErrcode; + const std::string errstr; + const std::string errmsg; }; diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index 3ee3162..dc44b6e 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -457,7 +457,7 @@ private: { if (SQLITE_OK != aRet) { - throw SQLite::Exception(sqlite3_errstr(aRet)); + throw SQLite::Exception(mStmtPtr, aRet); } } diff --git a/src/Statement.cpp b/src/Statement.cpp index 20d4bc5..f8db0c2 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -227,7 +227,7 @@ int Statement::exec() { mbOk = false; mbDone = false; - throw SQLite::Exception(sqlite3_errstr(ret)); + throw SQLite::Exception(mStmtPtr, ret); } } else @@ -317,7 +317,7 @@ Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) : const int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast(aQuery.size()), &mpStmt, NULL); if (SQLITE_OK != ret) { - throw SQLite::Exception(sqlite3_errstr(ret)); + throw SQLite::Exception(apSQLite, ret); } // Initialize the reference counter of the sqlite3_stmt : // used to share the mStmtPtr between Statement and Column objects;