Adding mpSQLite to the statement Shared Pointer for error reporting

This commit is contained in:
Sébastien Rombauts 2013-03-07 11:48:52 +01:00
parent d535ccb09f
commit 244a8bff60
7 changed files with 60 additions and 48 deletions

View File

@ -1,7 +1,5 @@
C++11 explicit support C++11 explicit support
Adding mpSQLite to the statement Shared Pointer
=> V0.5.0 => V0.5.0
Missing features in v0.4.0: Missing features in v0.4.0:

View File

@ -25,7 +25,7 @@ Database::Database(const char* apFilename, const int aFlags /*= SQLITE_OPEN_READ
if (SQLITE_OK != ret) if (SQLITE_OK != ret)
{ {
std::string strerr = sqlite3_errmsg(mpSQLite); std::string strerr = sqlite3_errmsg(mpSQLite);
sqlite3_close(mpSQLite); sqlite3_close(mpSQLite); // close is required even in case of error on opening
throw SQLite::Exception(strerr); throw SQLite::Exception(strerr);
} }
} }

View File

@ -112,23 +112,23 @@ public:
* *
* @param[in] aTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY * @param[in] aTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY
*/ */
inline int setBusyTimeout(int aTimeoutMs) // throw(); nothrow inline int setBusyTimeout(int aTimeoutMs) // throw(); nothrow
{ {
return sqlite3_busy_timeout(mpSQLite, aTimeoutMs); return sqlite3_busy_timeout(mpSQLite, aTimeoutMs);
} }
/** /**
* @brief Get the rowid of the most recent successful INSERT into the database from the current connection. * @brief Get the rowid of the most recent successful INSERT into the database from the current connection.
* *
* @return Rowid of the most recent successful INSERT into the database, or 0 if there was none. * @return Rowid of the most recent successful INSERT into the database, or 0 if there was none.
*/ */
inline sqlite3_int64 getLastInsertRowid(void) const // throw(); nothrow inline sqlite3_int64 getLastInsertRowid(void) const // throw(); nothrow
{ {
return sqlite3_last_insert_rowid(mpSQLite); return sqlite3_last_insert_rowid(mpSQLite);
} }
/** /**
* @brief Filename used to open the database * Return the filename used to open the database
*/ */
inline const std::string& getFilename(void) const inline const std::string& getFilename(void) const
{ {
@ -142,7 +142,7 @@ private:
Database& operator=(const Database&); Database& operator=(const Database&);
/** /**
* @brief Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message * Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
*/ */
void check(const int aRet) const; // throw(SQLite::Exception); void check(const int aRet) const; // throw(SQLite::Exception);

View File

@ -32,11 +32,14 @@ namespace SQLite
{ {
/** /**
* @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. * Encapsulation of the error message from SQLite3, based on std::runtime_error.
*/ */
class Exception : public std::runtime_error class Exception : public std::runtime_error
{ {
public: public:
/**
* Encapsulation of the error message from SQLite3, based on std::runtime_error.
*/
Exception(const std::string& aErrorMessage) : Exception(const std::string& aErrorMessage) :
std::runtime_error(aErrorMessage) std::runtime_error(aErrorMessage)
{ {

View File

@ -17,9 +17,8 @@ namespace SQLite
// Compile and register the SQL query for the provided SQLite Database Connection // Compile and register the SQL query for the provided SQLite Database Connection
Statement::Statement(Database &aDatabase, const char* apQuery) : // throw(SQLite::Exception) Statement::Statement(Database &aDatabase, const char* apQuery) : // throw(SQLite::Exception)
mpSQLite(aDatabase.mpSQLite), // need Database friendship
mQuery(apQuery), mQuery(apQuery),
mStmtPtr(mpSQLite, mQuery), // prepare the SQL query, and ref count mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0), mColumnCount(0),
mbOk(false), mbOk(false),
mbDone(false) mbDone(false)
@ -153,7 +152,7 @@ bool Statement::executeStep(void) // throw(SQLite::Exception)
{ {
mbOk = false; mbOk = false;
mbDone = false; mbDone = false;
throw SQLite::Exception(sqlite3_errmsg(mpSQLite)); throw SQLite::Exception(sqlite3_errmsg(mStmtPtr));
} }
} }
else else
@ -185,7 +184,7 @@ int Statement::exec(void) // throw(SQLite::Exception)
{ {
mbOk = false; mbOk = false;
mbDone = false; mbDone = false;
throw SQLite::Exception(sqlite3_errmsg(mpSQLite)); throw SQLite::Exception(sqlite3_errmsg(mStmtPtr));
} }
} }
else else
@ -194,7 +193,7 @@ int Statement::exec(void) // throw(SQLite::Exception)
} }
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE) // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE)
return sqlite3_changes(mpSQLite); return sqlite3_changes(mStmtPtr);
} }
// Return a copy of the column data specified by its index starting at 0 // Return a copy of the column data specified by its index starting at 0
@ -234,7 +233,7 @@ void Statement::check(const int aRet) const // throw(SQLite::Exception)
{ {
if (SQLITE_OK != aRet) if (SQLITE_OK != aRet)
{ {
throw SQLite::Exception(sqlite3_errmsg(mpSQLite)); throw SQLite::Exception(sqlite3_errmsg(mStmtPtr));
} }
} }
@ -250,13 +249,14 @@ void Statement::check(const int aRet) const // throw(SQLite::Exception)
* @param[in] aQuery The SQL query string to prepare * @param[in] aQuery The SQL query string to prepare
*/ */
Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) : Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) :
mpSQLite(apSQLite),
mpStmt(NULL), mpStmt(NULL),
mpRefCount(NULL) mpRefCount(NULL)
{ {
int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), aQuery.size(), &mpStmt, NULL); int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), aQuery.size(), &mpStmt, NULL);
if (SQLITE_OK != ret) if (SQLITE_OK != ret)
{ {
throw SQLite::Exception(sqlite3_errmsg(apSQLite)); throw SQLite::Exception(sqlite3_errmsg(mpSQLite));
} }
// Initialize the reference counter of the sqlite3_stmt : // Initialize the reference counter of the sqlite3_stmt :
// used to share the mStmtPtr between Statement and Column objects; // used to share the mStmtPtr between Statement and Column objects;
@ -270,6 +270,7 @@ Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) :
* @param[in] aPtr Pointer to copy * @param[in] aPtr Pointer to copy
*/ */
Statement::Ptr::Ptr (const Statement::Ptr& aPtr) : Statement::Ptr::Ptr (const Statement::Ptr& aPtr) :
mpSQLite(aPtr.mpSQLite),
mpStmt(aPtr.mpStmt), mpStmt(aPtr.mpStmt),
mpRefCount(aPtr.mpRefCount) mpRefCount(aPtr.mpRefCount)
{ {
@ -295,7 +296,6 @@ Statement::Ptr::~Ptr(void)
// as no Statement not Column objet use it anymore // as no Statement not Column objet use it anymore
int ret = sqlite3_finalize(mpStmt); int ret = sqlite3_finalize(mpStmt);
// Never throw an exception in a destructor // Never throw an exception in a destructor
// TODO : Add mpSQLite to the pointer ?
//std::cout << sqlite3_errmsg(mpSQLite) << std::endl; //std::cout << sqlite3_errmsg(mpSQLite) << std::endl;
SQLITE_CPP_ASSERT (SQLITE_OK == ret); SQLITE_CPP_ASSERT (SQLITE_OK == ret);

View File

@ -42,12 +42,12 @@ public:
explicit Statement(Database &aDatabase, const char* apQuery); // throw(SQLite::Exception); explicit Statement(Database &aDatabase, const char* apQuery); // throw(SQLite::Exception);
/** /**
* @brief Finalize and unregister the SQL query from the SQLite Database Connection. * Finalize and unregister the SQL query from the SQLite Database Connection.
*/ */
virtual ~Statement(void) throw(); // nothrow virtual ~Statement(void) throw(); // nothrow
/** /**
* @brief Reset the statement to make it ready for a new execution. * Reset the statement to make it ready for a new execution.
*/ */
void reset(void); // throw(SQLite::Exception); void reset(void); // throw(SQLite::Exception);
@ -60,52 +60,52 @@ public:
// (prefixed with the corresponding sign "?", ":", "@" or "$") // (prefixed with the corresponding sign "?", ":", "@" or "$")
/** /**
* @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const int aIndex, const int& aValue) ; // throw(SQLite::Exception); void bind(const int aIndex, const int& aValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const int aIndex, const sqlite3_int64& aValue) ; // throw(SQLite::Exception); void bind(const int aIndex, const sqlite3_int64& aValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const int aIndex, const double& aValue) ; // throw(SQLite::Exception); void bind(const int aIndex, const double& aValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const int aIndex, const std::string& aValue) ; // throw(SQLite::Exception); void bind(const int aIndex, const std::string& aValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const int aIndex, const char* apValue) ; // throw(SQLite::Exception); void bind(const int aIndex, const char* apValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const int aIndex); // throw(SQLite::Exception); void bind(const int aIndex); // throw(SQLite::Exception);
/** /**
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const char* apName, const int& aValue) ; // throw(SQLite::Exception); void bind(const char* apName, const int& aValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const char* apName, const sqlite3_int64& aValue) ; // throw(SQLite::Exception); void bind(const char* apName, const sqlite3_int64& aValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const char* apName, const double& aValue) ; // throw(SQLite::Exception); void bind(const char* apName, const double& aValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const char* apName, const std::string& aValue) ; // throw(SQLite::Exception); void bind(const char* apName, const std::string& aValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const char* apName, const char* apValue) ; // throw(SQLite::Exception); void bind(const char* apName, const char* apValue) ; // throw(SQLite::Exception);
/** /**
* @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) * Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/ */
void bind(const char* apName); // throw(SQLite::Exception); // bind NULL value void bind(const char* apName); // throw(SQLite::Exception); // bind NULL value
@ -155,14 +155,14 @@ public:
Column getColumn(const int aIndex) const; // throw(SQLite::Exception); Column getColumn(const int aIndex) const; // throw(SQLite::Exception);
/** /**
* @brief Test if the column is NULL * Test if the column is NULL
*/ */
bool isColumnNull(const int aIndex) const; // throw(SQLite::Exception); bool isColumnNull(const int aIndex) const; // throw(SQLite::Exception);
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
/** /**
* @brief UTF-8 SQL Query. * UTF-8 SQL Query.
*/ */
inline const std::string& getQuery(void) const inline const std::string& getQuery(void) const
{ {
@ -170,7 +170,7 @@ public:
} }
/** /**
* @brief Return the number of columns in the result set returned by the prepared statement * Return the number of columns in the result set returned by the prepared statement
*/ */
inline int getColumnCount(void) const inline int getColumnCount(void) const
{ {
@ -178,7 +178,7 @@ public:
} }
/** /**
* @brief True when the last row is fetched with executeStep(). * true when the last row is fetched with executeStep().
*/ */
inline bool isOk(void) const inline bool isOk(void) const
{ {
@ -186,7 +186,7 @@ public:
} }
/** /**
* @brief True when the last row is fetched with executeStep(). * true when the last row is fetched with executeStep().
*/ */
inline bool isDone(void) const inline bool isDone(void) const
{ {
@ -195,9 +195,11 @@ public:
public: public:
/** /**
* @brief Shared pointer to the sqlite3_stmt SQLite Statement Object * Shared pointer to the sqlite3_stmt SQLite Statement Object.
* *
* This is a internal class, not part of the API (hence full documentation is in the cpp) * Manage the finalization of the sqlite3_stmt with a reference counter.
*
* This is a internal class, not part of the API (hence full documentation is in the cpp).
*/ */
class Statement::Ptr class Statement::Ptr
{ {
@ -209,14 +211,24 @@ public:
// Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0 // Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
~Ptr(void) throw(); // nothrow (no virtual destructor needed here) ~Ptr(void) throw(); // nothrow (no virtual destructor needed here)
/// Inline cast operator returning the pointer to SQLite Database Connection Handle
inline operator sqlite3*() const
{
return mpSQLite;
}
/// Inline cast operator returning the pointer to SQLite Statement Object /// Inline cast operator returning the pointer to SQLite Statement Object
inline operator sqlite3_stmt*() const { return mpStmt; } inline operator sqlite3_stmt*() const
{
return mpStmt;
}
private: private:
// Unused/forbidden copy operator // Unused/forbidden copy operator
Ptr& operator=(const Ptr& aPtr); Ptr& operator=(const Ptr& aPtr);
private: private:
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object
unsigned int* mpRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt (to share it with Column objects) unsigned int* mpRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt (to share it with Column objects)
}; };
@ -228,12 +240,11 @@ private:
Statement& operator=(const Statement&); Statement& operator=(const Statement&);
/** /**
* @brief Check if a return code equals SQLITE_OK, else throw a SQLite::Exception with the SQLite error message * Check if a return code equals SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
*/ */
void check(const int aRet) const; // throw(SQLite::Exception); void check(const int aRet) const; // throw(SQLite::Exception);
private: private:
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
std::string mQuery; //!< UTF-8 SQL Query std::string mQuery; //!< UTF-8 SQL Query
Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object
int mColumnCount; //!< Number of column in the result of the prepared statement int mColumnCount; //!< Number of column in the result of the prepared statement

View File

@ -31,7 +31,7 @@ Transaction::~Transaction(void) throw() // nothrow
{ {
mDatabase.exec("ROLLBACK"); mDatabase.exec("ROLLBACK");
} }
catch (SQLite::Exception& e) catch (SQLite::Exception& /*e*/)
{ {
// Never throw an exception in a destructor // Never throw an exception in a destructor
//std::cout << e.what() << std::endl; //std::cout << e.what() << std::endl;