mirror of
https://github.com/cuberite/SQLiteCpp.git
synced 2025-08-04 17:56:13 -04:00
Adding an encapsulation to the statement ref counter : a shared pointer class
This commit is contained in:
parent
c94fe1fb4b
commit
d535ccb09f
2
TODO.txt
2
TODO.txt
@ -1,6 +1,6 @@
|
|||||||
C++11 explicit support
|
C++11 explicit support
|
||||||
|
|
||||||
Adding an encapsulation to the statement ref counter
|
Adding mpSQLite to the statement Shared Pointer
|
||||||
|
|
||||||
=> V0.5.0
|
=> V0.5.0
|
||||||
|
|
||||||
|
@ -15,72 +15,40 @@ namespace SQLite
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Encapsulation of a Column in a Row of the result.
|
// Encapsulation of a Column in a Row of the result.
|
||||||
Column::Column(sqlite3* apSQLite, sqlite3_stmt* apStmt, unsigned int* apStmtRefCount, int aIndex) throw() : // nothrow
|
Column::Column(Statement::Ptr aStmtPtr, int aIndex) throw() : // nothrow
|
||||||
mpSQLite (apSQLite),
|
mStmtPtr (aStmtPtr),
|
||||||
mpStmt (apStmt),
|
mIndex (aIndex)
|
||||||
mpStmtRefCount (apStmtRefCount),
|
|
||||||
mIndex (aIndex)
|
|
||||||
{
|
{
|
||||||
// Increment the reference counter of the sqlite3_stmt,
|
|
||||||
// telling the Statement object not to finalize the sqlite3_stmt during the lifetime of this Column objet
|
|
||||||
(*mpStmtRefCount)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy constructor
|
|
||||||
Column::Column(const Column& copy) throw() : // nothrow
|
|
||||||
mpSQLite (copy.mpSQLite),
|
|
||||||
mpStmt (copy.mpStmt),
|
|
||||||
mpStmtRefCount (copy.mpStmtRefCount),
|
|
||||||
mIndex (copy.mIndex)
|
|
||||||
{
|
|
||||||
// Increment the reference counter of the sqlite3_stmt,
|
|
||||||
// telling the Statement object not to finalize the sqlite3_stmt during the lifetime of this Column objet
|
|
||||||
(*mpStmtRefCount)++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize and unregister the SQL query from the SQLite Database Connection.
|
// Finalize and unregister the SQL query from the SQLite Database Connection.
|
||||||
Column::~Column(void) throw() // nothrow
|
Column::~Column(void) throw() // nothrow
|
||||||
{
|
{
|
||||||
// Decrement and check the reference counter of the sqlite3_stmt
|
// the finalization will be done by the destructor of the last shared pointer
|
||||||
(*mpStmtRefCount)--;
|
|
||||||
if (0 == *mpStmtRefCount)
|
|
||||||
{
|
|
||||||
// When count reaches zero, finalize the sqlite3_stmt, as no Column nor Statement object use it any more
|
|
||||||
int ret = sqlite3_finalize(mpStmt);
|
|
||||||
// Never throw an exception in a destructor
|
|
||||||
//std::cout << sqlite3_errmsg(mpSQLite) << std::endl;
|
|
||||||
SQLITE_CPP_ASSERT (SQLITE_OK == ret);
|
|
||||||
|
|
||||||
mpStmt = NULL;
|
|
||||||
|
|
||||||
// and delete the reference counter
|
|
||||||
delete mpStmtRefCount;
|
|
||||||
}
|
|
||||||
// else, the finalization will be done by the Statement or another Column object (the last one)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the integer value of the column specified by its index starting at 0
|
// Return the integer value of the column specified by its index starting at 0
|
||||||
int Column::getInt(void) const throw() // nothrow
|
int Column::getInt(void) const throw() // nothrow
|
||||||
{
|
{
|
||||||
return sqlite3_column_int(mpStmt, mIndex);
|
return sqlite3_column_int(mStmtPtr, mIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the 64bits integer value of the column specified by its index starting at 0
|
// Return the 64bits integer value of the column specified by its index starting at 0
|
||||||
sqlite3_int64 Column::getInt64(void) const throw() // nothrow
|
sqlite3_int64 Column::getInt64(void) const throw() // nothrow
|
||||||
{
|
{
|
||||||
return sqlite3_column_int64(mpStmt, mIndex);
|
return sqlite3_column_int64(mStmtPtr, mIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the double value of the column specified by its index starting at 0
|
// Return the double value of the column specified by its index starting at 0
|
||||||
double Column::getDouble(void) const throw() // nothrow
|
double Column::getDouble(void) const throw() // nothrow
|
||||||
{
|
{
|
||||||
return sqlite3_column_double(mpStmt, mIndex);
|
return sqlite3_column_double(mStmtPtr, mIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0
|
// Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0
|
||||||
const char* Column::getText(void) const throw() // nothrow
|
const char* Column::getText(void) const throw() // nothrow
|
||||||
{
|
{
|
||||||
return (const char*)sqlite3_column_text(mpStmt, mIndex);
|
return (const char*)sqlite3_column_text(mStmtPtr, mIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#include "Exception.h"
|
#include "Exception.h"
|
||||||
|
#include "Statement.h"
|
||||||
|
|
||||||
namespace SQLite
|
namespace SQLite
|
||||||
{
|
{
|
||||||
@ -24,15 +25,12 @@ namespace SQLite
|
|||||||
class Column
|
class Column
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/// Encapsulation of a Column in a Row of the result.
|
||||||
* @brief Compile and register the SQL query for the provided SQLite Database Connection
|
explicit Column(Statement::Ptr aStmtPtr, int aIndex) throw(); // nothrow
|
||||||
*/
|
|
||||||
explicit Column(sqlite3* apSQLite, sqlite3_stmt* apStmt, unsigned int* apStmtRefCount, int aIndex) throw(); // nothrow
|
|
||||||
/// Simple destructor
|
/// Simple destructor
|
||||||
virtual ~Column(void) throw(); // nothrow
|
virtual ~Column(void) throw(); // nothrow
|
||||||
|
|
||||||
/// @brief copy constructor : only way to copy a valid instance
|
// default copy constructor and asignement operator are enough
|
||||||
Column(const Column& aOther) throw(); // nothrow
|
|
||||||
|
|
||||||
/// Return the integer value of the column.
|
/// Return the integer value of the column.
|
||||||
int getInt (void) const throw();
|
int getInt (void) const throw();
|
||||||
@ -79,16 +77,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Forbid default constructor and assignment operator (no implementation)
|
Statement::Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object
|
||||||
// so that there is no way of having a Column instance not initialized
|
int mIndex; //!< Index of the column in the row of result
|
||||||
Column(void);
|
|
||||||
Column& operator=(const Column&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
|
|
||||||
sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object
|
|
||||||
unsigned int* mpStmtRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt (shared with the Statement object)
|
|
||||||
int mIndex; //!< Index of the column in the row of result
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Standard std::ostream inserter
|
/// Standard std::ostream inserter
|
||||||
|
@ -17,42 +17,20 @@ 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)
|
||||||
mpStmt(NULL),
|
|
||||||
mpStmtRefCount(NULL),
|
|
||||||
mpSQLite(aDatabase.mpSQLite), // need Database friendship
|
mpSQLite(aDatabase.mpSQLite), // need Database friendship
|
||||||
mQuery(apQuery),
|
mQuery(apQuery),
|
||||||
|
mStmtPtr(mpSQLite, mQuery), // prepare the SQL query, and ref count
|
||||||
mColumnCount(0),
|
mColumnCount(0),
|
||||||
mbOk(false),
|
mbOk(false),
|
||||||
mbDone(false)
|
mbDone(false)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_prepare_v2(mpSQLite, mQuery.c_str(), mQuery.size(), &mpStmt, NULL);
|
mColumnCount = sqlite3_column_count(mStmtPtr);
|
||||||
check(ret);
|
|
||||||
mColumnCount = sqlite3_column_count(mpStmt);
|
|
||||||
// Initialize the reference counter of the sqlite3_stmt : used to share the mpStmt with Column objects;
|
|
||||||
// This is needed to enable Column objects to live longer than the Statement objet it refers to.
|
|
||||||
mpStmtRefCount = new unsigned int;
|
|
||||||
*mpStmtRefCount = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize and unregister the SQL query from the SQLite Database Connection.
|
// Finalize and unregister the SQL query from the SQLite Database Connection.
|
||||||
Statement::~Statement(void) throw() // nothrow
|
Statement::~Statement(void) throw() // nothrow
|
||||||
{
|
{
|
||||||
// Decrement and check the reference counter of the sqlite3_stmt
|
// the finalization will be done by the destructor of the last shared pointer
|
||||||
(*mpStmtRefCount)--;
|
|
||||||
if (0 == *mpStmtRefCount)
|
|
||||||
{
|
|
||||||
// If count reaches zero, finalize the sqlite3_stmt, as no Column objet use it anymore
|
|
||||||
int ret = sqlite3_finalize(mpStmt);
|
|
||||||
// Never throw an exception in a destructor
|
|
||||||
//std::cout << sqlite3_errmsg(mpSQLite) << std::endl;
|
|
||||||
SQLITE_CPP_ASSERT (SQLITE_OK == ret);
|
|
||||||
|
|
||||||
mpStmt = NULL;
|
|
||||||
|
|
||||||
// and delete the reference counter
|
|
||||||
delete mpStmtRefCount;
|
|
||||||
}
|
|
||||||
// else, the finalization will be done by the last Column object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the statement to make it ready for a new execution
|
// Reset the statement to make it ready for a new execution
|
||||||
@ -60,49 +38,49 @@ void Statement::reset(void) // throw(SQLite::Exception)
|
|||||||
{
|
{
|
||||||
mbOk = false;
|
mbOk = false;
|
||||||
mbDone = false;
|
mbDone = false;
|
||||||
int ret = sqlite3_reset(mpStmt);
|
int ret = sqlite3_reset(mStmtPtr);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const int aIndex, const int& aValue) // throw(SQLite::Exception)
|
void Statement::bind(const int aIndex, const int& aValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_int(mpStmt, aIndex, aValue);
|
int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const int aIndex, const sqlite3_int64& aValue) // throw(SQLite::Exception)
|
void Statement::bind(const int aIndex, const sqlite3_int64& aValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_int64(mpStmt, aIndex, aValue);
|
int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const int aIndex, const double& aValue) // throw(SQLite::Exception)
|
void Statement::bind(const int aIndex, const double& aValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_double(mpStmt, aIndex, aValue);
|
int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const int aIndex, const std::string& aValue) // throw(SQLite::Exception)
|
void Statement::bind(const int aIndex, const std::string& aValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_text(mpStmt, aIndex, aValue.c_str(), aValue.size(), SQLITE_TRANSIENT);
|
int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), aValue.size(), SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const int aIndex, const char* apValue) // throw(SQLite::Exception)
|
void Statement::bind(const int aIndex, const char* apValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_text(mpStmt, aIndex, apValue, -1, SQLITE_TRANSIENT);
|
int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const int aIndex) // throw(SQLite::Exception)
|
void Statement::bind(const int aIndex) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_null(mpStmt, aIndex);
|
int ret = sqlite3_bind_null(mStmtPtr, aIndex);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,48 +88,48 @@ void Statement::bind(const int aIndex) // throw(SQLite::Exception)
|
|||||||
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName, const int& aValue) // throw(SQLite::Exception)
|
void Statement::bind(const char* apName, const int& aValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mpStmt, apName);
|
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_int(mpStmt, index, aValue);
|
int ret = sqlite3_bind_int(mStmtPtr, index, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName, const sqlite3_int64& aValue) // throw(SQLite::Exception)
|
void Statement::bind(const char* apName, const sqlite3_int64& aValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mpStmt, apName);
|
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_int64(mpStmt, index, aValue);
|
int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName, const double& aValue) // throw(SQLite::Exception)
|
void Statement::bind(const char* apName, const double& aValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mpStmt, apName);
|
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_double(mpStmt, index, aValue);
|
int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName, const std::string& aValue) // throw(SQLite::Exception)
|
void Statement::bind(const char* apName, const std::string& aValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mpStmt, apName);
|
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_text(mpStmt, index, aValue.c_str(), aValue.size(), SQLITE_TRANSIENT);
|
int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), aValue.size(), SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName, const char* apValue) // throw(SQLite::Exception)
|
void Statement::bind(const char* apName, const char* apValue) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mpStmt, apName);
|
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_text(mpStmt, index, apValue, -1, SQLITE_TRANSIENT);
|
int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName) // throw(SQLite::Exception)
|
void Statement::bind(const char* apName) // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mpStmt, apName);
|
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_null(mpStmt, index);
|
int ret = sqlite3_bind_null(mStmtPtr, index);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +139,7 @@ bool Statement::executeStep(void) // throw(SQLite::Exception)
|
|||||||
{
|
{
|
||||||
if (false == mbDone)
|
if (false == mbDone)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_step(mpStmt);
|
int ret = sqlite3_step(mStmtPtr);
|
||||||
if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it
|
if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it
|
||||||
{
|
{
|
||||||
mbOk = true;
|
mbOk = true;
|
||||||
@ -191,7 +169,7 @@ int Statement::exec(void) // throw(SQLite::Exception)
|
|||||||
{
|
{
|
||||||
if (false == mbDone)
|
if (false == mbDone)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_step(mpStmt);
|
int ret = sqlite3_step(mStmtPtr);
|
||||||
if (SQLITE_DONE == ret) // the statement has finished executing successfully
|
if (SQLITE_DONE == ret) // the statement has finished executing successfully
|
||||||
{
|
{
|
||||||
mbOk = false;
|
mbOk = false;
|
||||||
@ -233,7 +211,7 @@ Column Statement::getColumn(const int aIndex) const // throw(SQLite::Exception)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Share the Statement Object handle with the new Column created
|
// Share the Statement Object handle with the new Column created
|
||||||
return Column(mpSQLite, mpStmt, mpStmtRefCount, aIndex);
|
return Column(mStmtPtr, aIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if the column is NULL
|
// Test if the column is NULL
|
||||||
@ -248,10 +226,9 @@ bool Statement::isColumnNull(const int aIndex) const // throw(SQLite::Exception)
|
|||||||
throw SQLite::Exception("Column index out of range");
|
throw SQLite::Exception("Column index out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (SQLITE_NULL == sqlite3_column_type(mpStmt, aIndex));
|
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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 Statement::check(const int aRet) const // throw(SQLite::Exception)
|
void Statement::check(const int aRet) const // throw(SQLite::Exception)
|
||||||
{
|
{
|
||||||
@ -261,4 +238,73 @@ void Statement::check(const int aRet) const // throw(SQLite::Exception)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepare the statement and initialize its reference counter
|
||||||
|
*
|
||||||
|
* @param[in] apSQLite The sqlite3 database connexion
|
||||||
|
* @param[in] aQuery The SQL query string to prepare
|
||||||
|
*/
|
||||||
|
Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) :
|
||||||
|
mpStmt(NULL),
|
||||||
|
mpRefCount(NULL)
|
||||||
|
{
|
||||||
|
int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), aQuery.size(), &mpStmt, NULL);
|
||||||
|
if (SQLITE_OK != ret)
|
||||||
|
{
|
||||||
|
throw SQLite::Exception(sqlite3_errmsg(apSQLite));
|
||||||
|
}
|
||||||
|
// Initialize the reference counter of the sqlite3_stmt :
|
||||||
|
// used to share the mStmtPtr between Statement and Column objects;
|
||||||
|
// This is needed to enable Column objects to live longer than the Statement objet it refers to.
|
||||||
|
mpRefCount = new unsigned int(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor increments the ref counter
|
||||||
|
*
|
||||||
|
* @param[in] aPtr Pointer to copy
|
||||||
|
*/
|
||||||
|
Statement::Ptr::Ptr (const Statement::Ptr& aPtr) :
|
||||||
|
mpStmt(aPtr.mpStmt),
|
||||||
|
mpRefCount(aPtr.mpRefCount)
|
||||||
|
{
|
||||||
|
assert(NULL != mpRefCount);
|
||||||
|
assert(0 != *mpRefCount);
|
||||||
|
|
||||||
|
// Increment the reference counter of the sqlite3_stmt,
|
||||||
|
// asking not to finalize the sqlite3_stmt during the lifetime of the new objet
|
||||||
|
++(*mpRefCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
|
||||||
|
Statement::Ptr::~Ptr(void)
|
||||||
|
{
|
||||||
|
assert(NULL != mpRefCount);
|
||||||
|
assert(0 != *mpRefCount);
|
||||||
|
|
||||||
|
// Decrement and check the reference counter of the sqlite3_stmt
|
||||||
|
--(*mpRefCount);
|
||||||
|
if (0 == *mpRefCount)
|
||||||
|
{
|
||||||
|
// If count reaches zero, finalize the sqlite3_stmt,
|
||||||
|
// as no Statement not Column objet use it anymore
|
||||||
|
int ret = sqlite3_finalize(mpStmt);
|
||||||
|
// Never throw an exception in a destructor
|
||||||
|
// TODO : Add mpSQLite to the pointer ?
|
||||||
|
//std::cout << sqlite3_errmsg(mpSQLite) << std::endl;
|
||||||
|
SQLITE_CPP_ASSERT (SQLITE_OK == ret);
|
||||||
|
|
||||||
|
// and delete the reference counter
|
||||||
|
delete mpRefCount;
|
||||||
|
mpRefCount = NULL;
|
||||||
|
mpStmt = NULL;
|
||||||
|
}
|
||||||
|
// else, the finalization will be done later, by the last object
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SQLite
|
} // namespace SQLite
|
||||||
|
@ -32,6 +32,8 @@ class Column;
|
|||||||
class Statement
|
class Statement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class Ptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compile and register the SQL query for the provided SQLite Database Connection
|
* @brief Compile and register the SQL query for the provided SQLite Database Connection
|
||||||
*
|
*
|
||||||
@ -191,6 +193,34 @@ public:
|
|||||||
return mbDone;
|
return mbDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 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)
|
||||||
|
*/
|
||||||
|
class Statement::Ptr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Prepare the statement and initialize its reference counter
|
||||||
|
Ptr(sqlite3* apSQLite, std::string& aQuery);
|
||||||
|
// Copy constructor increments the ref counter
|
||||||
|
Ptr(const Ptr& aPtr);
|
||||||
|
// Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
|
||||||
|
~Ptr(void) throw(); // nothrow (no virtual destructor needed here)
|
||||||
|
|
||||||
|
/// Inline cast operator returning the pointer to SQLite Statement Object
|
||||||
|
inline operator sqlite3_stmt*() const { return mpStmt; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Unused/forbidden copy operator
|
||||||
|
Ptr& operator=(const Ptr& aPtr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Statement must not be copyable
|
// Statement must not be copyable
|
||||||
Statement(void);
|
Statement(void);
|
||||||
@ -203,10 +233,9 @@ private:
|
|||||||
void check(const int aRet) const; // throw(SQLite::Exception);
|
void check(const int aRet) const; // throw(SQLite::Exception);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object
|
|
||||||
unsigned int* mpStmtRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt (to share it with Column objects)
|
|
||||||
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
|
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
|
||||||
int mColumnCount; //!< Number of column in the result of the prepared statement
|
int mColumnCount; //!< Number of column in the result of the prepared statement
|
||||||
bool mbOk; //!< True when a row has been fetched with executeStep()
|
bool mbOk; //!< True when a row has been fetched with executeStep()
|
||||||
bool mbDone; //!< True when the last executeStep() had no more row to fetch
|
bool mbDone; //!< True when the last executeStep() had no more row to fetch
|
||||||
|
Loading…
x
Reference in New Issue
Block a user