diff --git a/src/SQLiteC++/Statement.cpp b/src/SQLiteC++/Statement.cpp index b9e33ca..f0ea437 100644 --- a/src/SQLiteC++/Statement.cpp +++ b/src/SQLiteC++/Statement.cpp @@ -20,6 +20,7 @@ Statement::Statement(Database &aDatabase, const char* apQuery) : // throw(SQLite mpStmt(NULL), mDatabase(aDatabase), mQuery(apQuery), + mbOk(false), mbDone(false) { int ret = sqlite3_prepare_v2(mDatabase.mpSQLite, mQuery.c_str(), mQuery.size(), &mpStmt, NULL); @@ -27,6 +28,7 @@ Statement::Statement(Database &aDatabase, const char* apQuery) : // throw(SQLite { throw SQLite::Exception(sqlite3_errmsg(mDatabase.mpSQLite)); } + mColumnCount = sqlite3_column_count(mpStmt); mDatabase.registerStatement(*this); } @@ -45,6 +47,7 @@ Statement::~Statement(void) throw() // nothrow // Reset the statement to make it ready for a new execution void Statement::reset(void) // throw(SQLite::Exception) { + mbOk = false; mbDone = false; int ret = sqlite3_reset(mpStmt); if (SQLITE_OK != ret) @@ -117,18 +120,16 @@ void Statement::bind(const int aIndex) // throw(SQLite::Exception) // Execute a step of the query to fetch one row of results bool Statement::executeStep(void) // throw(SQLite::Exception) { - bool bOk = false; - if (false == mbDone) { int ret = sqlite3_step(mpStmt); if (SQLITE_ROW == ret) { - bOk = true; + mbOk = true; } else if (SQLITE_DONE == ret) { - bOk = false; + mbOk = false; mbDone = true; } else @@ -137,13 +138,83 @@ bool Statement::executeStep(void) // throw(SQLite::Exception) } } - return bOk; + return mbOk; } -// Return the number of columns in the result set returned by the prepared statement -int Statement::getColumnCount(void) const throw() // nothrow +// Return the integer value of the column specified by its index starting at 0 +int Statement::getColumnInt(const int aIndex) const // throw(SQLite::Exception) { - return sqlite3_column_count(mpStmt); + if (false == mbOk) + { + throw SQLite::Exception("No row to get a column from"); + } + else if ((aIndex < 0) || (aIndex >= mColumnCount)) + { + throw SQLite::Exception("Column index out of range"); + } + + return sqlite3_column_int(mpStmt, aIndex); +} + + +// Return the 64bits integer value of the column specified by its index starting at 0 +sqlite3_int64 Statement::getColumnInt64(const int aIndex) const // throw(SQLite::Exception) +{ + if (false == mbOk) + { + throw SQLite::Exception("No row to get a column from"); + } + else if ((aIndex < 0) || (aIndex >= mColumnCount)) + { + throw SQLite::Exception("Column index out of range"); + } + + return sqlite3_column_int64(mpStmt, aIndex); +} + +// Return the double value of the column specified by its index starting at 0 +double Statement::getColumnDouble(const int aIndex) const // throw(SQLite::Exception) +{ + if (false == mbOk) + { + throw SQLite::Exception("No row to get a column from"); + } + else if ((aIndex < 0) || (aIndex >= mColumnCount)) + { + throw SQLite::Exception("Column index out of range"); + } + + return sqlite3_column_double(mpStmt, aIndex); +} + +// Return the text value (NULL terminated string) of the column specified by its index starting at 0 +const char * Statement::getColumnText(const int aIndex) const // throw(SQLite::Exception) +{ + if (false == mbOk) + { + throw SQLite::Exception("No row to get a column from"); + } + else if ((aIndex < 0) || (aIndex >= mColumnCount)) + { + throw SQLite::Exception("Column index out of range"); + } + + return (const char*)sqlite3_column_text(mpStmt, aIndex); +} + +// Test if the column is NULL +bool Statement::isColumnNull(const int aIndex) const // throw(SQLite::Exception) +{ + if (false == mbOk) + { + throw SQLite::Exception("No row to get a column from"); + } + else if ((aIndex < 0) || (aIndex >= mColumnCount)) + { + throw SQLite::Exception("Column index out of range"); + } + + return (SQLITE_NULL == sqlite3_column_type(mpStmt, aIndex)); } }; // namespace SQLite diff --git a/src/SQLiteC++/Statement.h b/src/SQLiteC++/Statement.h index 7561ba1..522673b 100644 --- a/src/SQLiteC++/Statement.h +++ b/src/SQLiteC++/Statement.h @@ -44,40 +44,65 @@ public: */ void reset(void); // throw(SQLite::Exception); + //////////////////////////////////////////////////////////////////////////// + /** - * @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement + * @brief 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); /** - * @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement + * @brief 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); /** - * @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement + * @brief 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); /** - * @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement + * @brief 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); /** - * @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement + * @brief 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); /** - * @brief Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement + * @brief 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); // bind NULL value + //////////////////////////////////////////////////////////////////////////// + /** * @brief Execute a step of the query to fetch one row of results. */ bool executeStep(void); // throw(SQLite::Exception); + //////////////////////////////////////////////////////////////////////////// + /** - * @brief Return the number of columns in the result set returned by the prepared statement + * @brief Return the integer value of the column specified by its index starting at 0 (aIndex >= 0) */ - int getColumnCount(void) const throw(); // nothrow + int getColumnInt (const int aIndex) const; // throw(SQLite::Exception); + /** + * @brief Return the 64bits integer value of the column specified by its index starting at 0 (aIndex >= 0) + */ + sqlite3_int64 getColumnInt64 (const int aIndex) const; // throw(SQLite::Exception); + /** + * @brief Return the double (64bits float) value of the column specified by its index starting at 0 (aIndex >= 0) + */ + double getColumnDouble(const int aIndex) const; // throw(SQLite::Exception); + /** + * @brief Return the text value (NULL terminated string) of the column specified by its index starting at 0 (aIndex >= 0) + */ + const char* getColumnText (const int aIndex) const; // throw(SQLite::Exception); + + /** + * @brief Test if the column is NULL + */ + bool isColumnNull (const int aIndex) const; // throw(SQLite::Exception); + + //////////////////////////////////////////////////////////////////////////// /** * @brief UTF-8 SQL Query. @@ -87,6 +112,22 @@ public: return mQuery; } + /** + * @brief Return the number of columns in the result set returned by the prepared statement + */ + inline int getColumnCount(void) const + { + return mColumnCount; + } + + /** + * @brief True when the last row is fetched with executeStep(). + */ + inline bool isOk(void) const + { + return mbOk; + } + /** * @brief True when the last row is fetched with executeStep(). */ @@ -96,10 +137,12 @@ public: } private: - sqlite3_stmt* mpStmt; //!< Pointeur to SQLite Statement Object - Database& mDatabase; //!< Reference to the SQLite Database Connection - std::string mQuery; //!< UTF-8 SQL Query - bool mbDone; //!< True when the last row is fetched with executeStep() + sqlite3_stmt* mpStmt; //!< Pointeur to SQLite Statement Object + Database& mDatabase; //!< Reference to the SQLite Database Connection + std::string mQuery; //!< UTF-8 SQL Query + int mColumnCount; //!< Number of column in the result of the prepared statement + bool mbOk; //!< True when a row has been fetched with executeStep() + bool mbDone; //!< True when the last executeStep() had no more row to fetch }; diff --git a/src/example1/main.cpp b/src/example1/main.cpp index 3ebd7e4..e95387d 100644 --- a/src/example1/main.cpp +++ b/src/example1/main.cpp @@ -11,13 +11,13 @@ int main (void) // Compile a SQL query, containing one parameter (index 1) SQLite::Statement query(db, "SELECT * FROM test WHERE size>?"); - std::cout << "SQLite statement compiled (" << query.getColumnCount () << " collumns in the result)\n"; + std::cout << "SQLite statement '" << query.getQuery().c_str() << "' compiled (" << query.getColumnCount () << " collumns in the result)\n"; // Bind an integer value "6" to the first parameter of the SQL query query.bind(1, 6); while (query.executeStep()) { - std::cout << "executeStep\n"; + std::cout << "row : (" << query.getColumnInt(0) << ", " << query.getColumnText(1) << ", " << query.getColumnInt(2) << ")\n"; } } catch (std::exception& e)