diff --git a/include/SQLiteCpp/Database.h b/include/SQLiteCpp/Database.h index f64c995..b82ccc6 100644 --- a/include/SQLiteCpp/Database.h +++ b/include/SQLiteCpp/Database.h @@ -378,7 +378,7 @@ private: { if (SQLITE_OK != aRet) { - throw SQLite::Exception(sqlite3_errstr(aRet)); + throw SQLite::Exception(mpSQLite, aRet); } } diff --git a/include/SQLiteCpp/Exception.h b/include/SQLiteCpp/Exception.h index d58915e..e3a5ece 100644 --- a/include/SQLiteCpp/Exception.h +++ b/include/SQLiteCpp/Exception.h @@ -16,60 +16,6 @@ #include -namespace SQLite -{ - - -/** - * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. - */ -class Exception : public std::runtime_error -{ -public: - /** - * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. - * - * @param[in] aErrorMessage The string message describing the SQLite error - */ - explicit Exception(const std::string& 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; -}; - - -} // namespace SQLite - - /// Compatibility with non-clang compilers. #ifndef __has_feature #define __has_feature(x) 0 @@ -87,3 +33,91 @@ public: // Visual Studio 2013 does not support noexcept, and "throw()" is deprecated by C++11 #define noexcept #endif + + +namespace SQLite +{ + + +/** + * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. + */ +class Exception : public std::runtime_error +{ +public: + /** + * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. + * + * @param[in] aErrorMessage The string message describing the SQLite error + */ + explicit Exception(const std::string& aErrorMessage) : + std::runtime_error(aErrorMessage), + mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense + mExtendedErrcode(-1) + { + } + + /** + * @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. + */ + explicit Exception(sqlite3* apSQLite) : + std::runtime_error(sqlite3_errmsg(apSQLite)), + mErrcode(sqlite3_errcode(apSQLite)), + mExtendedErrcode(sqlite3_extended_errcode(apSQLite)) + { + } + + /** + * @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) : + std::runtime_error(sqlite3_errmsg(apSQLite)), + mErrcode(ret), + mExtendedErrcode(sqlite3_extended_errcode(apSQLite)) + { + } + + /** + * @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. + * @param[in] aErrorMessage String providing more context, added to the SQLite errmsg + */ + explicit Exception(sqlite3* apSQLite, int ret, const std::string &aErrorMessage) : + std::runtime_error(aErrorMessage + ": " + sqlite3_errmsg(apSQLite)), + mErrcode(ret), + mExtendedErrcode(sqlite3_extended_errcode(apSQLite)) + { + } + + /// @brief Return the result code (if any, otherwise -1). + inline int getErrorCode() const noexcept // nothrow + { + return mErrcode; + } + + /// @brief Return the extended numeric result code (if any, otherwise -1). + inline int getExtendedErrorCode() const noexcept // nothrow + { + return mExtendedErrcode; + } + + /// @brief Return a string, solely based on the error code + inline const char *getErrStr() const noexcept // nothrow + { + return sqlite3_errstr(mErrcode); + } + +private: + const int mErrcode; + const int mExtendedErrcode; +}; + + +} // namespace SQLite diff --git a/src/Backup.cpp b/src/Backup.cpp index ba8815a..c46ecfd 100644 --- a/src/Backup.cpp +++ b/src/Backup.cpp @@ -31,8 +31,7 @@ Backup::Backup(Database& aDestDatabase, apSrcDatabaseName); if (NULL == mpSQLiteBackup) { - std::string strerr = sqlite3_errmsg(aDestDatabase.getHandle()); - throw SQLite::Exception(strerr); + throw SQLite::Exception(aDestDatabase.getHandle()); } } diff --git a/src/Database.cpp b/src/Database.cpp index 2ce2183..f19dee9 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -36,9 +36,9 @@ Database::Database(const char* apFilename, const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs); if (SQLITE_OK != ret) { - std::string strerr = sqlite3_errstr(ret); + const SQLite::Exception exception(mpSQLite, ret); // must create before closing sqlite3_close(mpSQLite); // close is required even in case of error on opening - throw SQLite::Exception(strerr); + throw exception; } if (aBusyTimeoutMs > 0) @@ -58,9 +58,9 @@ Database::Database(const std::string& aFilename, const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? NULL : aVfs.c_str()); if (SQLITE_OK != ret) { - std::string strerr = sqlite3_errstr(ret); + const SQLite::Exception exception(mpSQLite, ret); // must create before closing sqlite3_close(mpSQLite); // close is required even in case of error on opening - throw SQLite::Exception(strerr); + throw exception; } if (aBusyTimeoutMs > 0) diff --git a/src/Statement.cpp b/src/Statement.cpp index f8db0c2..eec9a92 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -195,7 +195,7 @@ bool Statement::executeStep() { mbOk = false; mbDone = false; - throw SQLite::Exception(sqlite3_errstr(ret)); + throw SQLite::Exception(mStmtPtr, ret); } } else