From 00a8e0a6428d05d2ad823a5c36ee8db2e324af41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rombauts?= Date: Mon, 2 Apr 2012 19:00:24 +0200 Subject: [PATCH] Moving Column to make it an inner class of Statement - Column must not be used directly, only as a temporary Adapter of Statement::getColumn - Adding an Object Oriented example in main.cpp --- src/SQLiteC++/Column.cpp | 63 -------------------------- src/SQLiteC++/Column.h | 90 ------------------------------------- src/SQLiteC++/Database.cpp | 2 +- src/SQLiteC++/Statement.cpp | 52 ++++++++++++++++++++- src/SQLiteC++/Statement.h | 74 +++++++++++++++++++++++++++++- src/example1/main.cpp | 89 ++++++++++++++++++++++++++++++++++-- 6 files changed, 210 insertions(+), 160 deletions(-) delete mode 100644 src/SQLiteC++/Column.cpp delete mode 100644 src/SQLiteC++/Column.h diff --git a/src/SQLiteC++/Column.cpp b/src/SQLiteC++/Column.cpp deleted file mode 100644 index b4e0bba..0000000 --- a/src/SQLiteC++/Column.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file Column.cpp - * @brief A SQLite Column is a result field in a certain row. - * - * Copyright (c) 2012 Sebastien Rombauts (sebastien dot rombauts at gmail dot com) - * - * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt - * or copy at http://opensource.org/licenses/MIT) - */ -#include "Column.h" - -#include "Database.h" -#include - -namespace SQLite -{ - -// Encapsulation of a Column in a Row of the result. -Column::Column(sqlite3* apSQLite, sqlite3_stmt* apStmt, int aIndex) throw() : // nothrow - mpSQLite(apSQLite), - mpStmt(apStmt), - mIndex(aIndex) -{ -} - -Column::~Column(void) throw() // nothrow -{ -} - -// Return the integer value of the column specified by its index starting at 0 -int Column::getInt(void) const // throw(SQLite::Exception) -{ - return sqlite3_column_int(mpStmt, mIndex); -} - -// Return the 64bits integer value of the column specified by its index starting at 0 -sqlite3_int64 Column::getInt64(void) const // throw(SQLite::Exception) -{ - return sqlite3_column_int64(mpStmt, mIndex); -} - -// Return the double value of the column specified by its index starting at 0 -double Column::getDouble(void) const // throw(SQLite::Exception) -{ - return sqlite3_column_double(mpStmt, mIndex); -} - -// Return the text value (NULL terminated string) of the column specified by its index starting at 0 -const char * Column::getText(void) const // throw(SQLite::Exception) -{ - return (const char*)sqlite3_column_text(mpStmt, mIndex); -} - - -}; // namespace SQLite - - -// Standard std::ostream inserter -std::ostream& operator<<(std::ostream &stream, SQLite::Column const& column) -{ - stream << column.getText(); - return stream; -} diff --git a/src/SQLiteC++/Column.h b/src/SQLiteC++/Column.h deleted file mode 100644 index 5d93836..0000000 --- a/src/SQLiteC++/Column.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file Column.h - * @brief A SQLite Column is a result field in a certain row. - * - * Copyright (c) 2012 Sebastien Rombauts (sebastien dot rombauts at gmail dot com) - * - * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt - * or copy at http://opensource.org/licenses/MIT) - */ -#pragma once - -#include -#include "Exception.h" - -namespace SQLite -{ - -// Forward declaration -class Database; - -/** - * @brief Encapsulation of a Column in a Row of the result. - * - * A Column is a particular field of SQLite data in the current row of result of the Statement. - * - * @warning A Column object must not be copied or memorized as it is only valid for a short time, - * only while the row from the Statement remains valid, that is only until next executeStep - */ -class Column -{ -public: - /** - * @brief Compile and register the SQL query for the provided SQLite Database Connection - */ - explicit Column(sqlite3* apSQLite, sqlite3_stmt* apStmt, int aIndex) throw(); // nothrow - /// Basic destructor - virtual ~Column(void) throw(); // nothrow - - /// Return the integer value of the column. - int getInt (void) const; // throw(SQLite::Exception); - // Return the 64bits integer value of the column. - sqlite3_int64 getInt64 (void) const; // throw(SQLite::Exception); - // Return the double (64bits float) value of the column. - double getDouble(void) const; // throw(SQLite::Exception); - // Return the text value (NULL terminated string) of the column. - const char* getText (void) const; // throw(SQLite::Exception); - - /// Inline cast operator to int - inline operator const int() const - { - return getInt(); - } - /// Inline cast operator to 64bits integer - inline operator const sqlite3_int64() const - { - return getInt64(); - } - /// Inline cast operator to double - inline operator const double() const - { - return getDouble(); - } - /// Inline cast operator to char* - inline operator const char*() const - { - return getText(); - } - /// Inline cast operator to std::string - inline operator const std::string() const - { - return getText(); - } - -private: - // Column is copyable, but copy should not be used elsewhere than in return form getColumn - Column(void); - Column& operator=(const Column&); - -private: - sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle - sqlite3_stmt* mpStmt; //!< Pointeur to SQLite Statement Object - int mIndex; //!< Index of the column in the row of result -}; - - -}; // namespace SQLite - - -/// Standard std::ostream inserter -std::ostream& operator<<(std::ostream &stream, SQLite::Column const& column); diff --git a/src/SQLiteC++/Database.cpp b/src/SQLiteC++/Database.cpp index 51ffb3d..6f485e0 100644 --- a/src/SQLiteC++/Database.cpp +++ b/src/SQLiteC++/Database.cpp @@ -39,7 +39,7 @@ Database::~Database(void) throw() // nothrow iStatement++) { // TODO (*iStatement)->Finalize(); ? - std::cout << "Unregistered statement: " << (*iStatement)->getQuery().c_str() << " !\n"; + //std::cout << "Unregistered statement: " << (*iStatement)->getQuery().c_str() << " !\n"; } int ret = sqlite3_close(mpSQLite); diff --git a/src/SQLiteC++/Statement.cpp b/src/SQLiteC++/Statement.cpp index c869937..5626a1e 100644 --- a/src/SQLiteC++/Statement.cpp +++ b/src/SQLiteC++/Statement.cpp @@ -118,7 +118,7 @@ bool Statement::executeStep(void) // throw(SQLite::Exception) } // Return a copy of the column data specified by its index starting at 0 -Column Statement::getColumn(const int aIndex) const // throw(SQLite::Exception) +Statement::Column Statement::getColumn(const int aIndex) const // throw(SQLite::Exception) { if (false == mbOk) { @@ -159,5 +159,55 @@ void Statement::check(const int aRet) const // throw(SQLite::Exception) } } +//////////////////////////////////////////////////////////////////////////////// +// Implementation of the inner class Statement::Column +// +// Warning : you should never try to use directly a Column object, nor copying it; +// is is only an Adapter class designed to convert the result value +// of Statement::getColumn() to the data type you want +// + +// Encapsulation of a Column in a Row of the result. +Statement::Column::Column(sqlite3* apSQLite, sqlite3_stmt* apStmt, int aIndex) throw() : // nothrow + mpSQLite(apSQLite), + mpStmt(apStmt), + mIndex(aIndex) +{ +} + +Statement::Column::~Column(void) throw() // nothrow +{ +} + +// Return the integer value of the column specified by its index starting at 0 +int Statement::Column::getInt(void) const throw() // nothrow +{ + return sqlite3_column_int(mpStmt, mIndex); +} + +// Return the 64bits integer value of the column specified by its index starting at 0 +sqlite3_int64 Statement::Column::getInt64(void) const throw() // nothrow +{ + return sqlite3_column_int64(mpStmt, mIndex); +} + +// Return the double value of the column specified by its index starting at 0 +double Statement::Column::getDouble(void) const throw() // nothrow +{ + return sqlite3_column_double(mpStmt, mIndex); +} + +// Return the text value (NULL terminated string) of the column specified by its index starting at 0 +const char * Statement::Column::getText(void) const throw() // nothrow +{ + return (const char*)sqlite3_column_text(mpStmt, mIndex); +} + +// Standard std::ostream inserter +std::ostream& operator<<(std::ostream &stream, const Statement::Column& column) +{ + stream << column.getText(); + return stream; +} }; // namespace SQLite diff --git a/src/SQLiteC++/Statement.h b/src/SQLiteC++/Statement.h index dd62e75..5c1c1ec 100644 --- a/src/SQLiteC++/Statement.h +++ b/src/SQLiteC++/Statement.h @@ -11,7 +11,6 @@ #include #include "Exception.h" -#include "Column.h" namespace SQLite { @@ -27,6 +26,10 @@ class Database; */ class Statement { +public: + // Forward declaration of the inner class "Column" + class Column; + public: /** * @brief Compile and register the SQL query for the provided SQLite Database Connection @@ -89,7 +92,6 @@ public: */ Column getColumn (const int aIndex) const; // throw(SQLite::Exception); - /** * @brief Test if the column is NULL */ @@ -129,6 +131,74 @@ public: return mbDone; } +public: + /** + * @brief Encapsulation of a Column in a Row of the result. + * + * A Column is a particular field of SQLite data in the current row of result of the Statement. + * + * @warning A Column object must not be copied or memorized as it is only valid for a short time, + * only while the row from the Statement remains valid, that is only until next executeStep + */ + class Column + { + /// Standard std::ostream inserter + friend std::ostream& operator<<(std::ostream &stream, const Column& column); + + public: + /** + * @brief Compile and register the SQL query for the provided SQLite Database Connection + */ + explicit Column(sqlite3* apSQLite, sqlite3_stmt* apStmt, int aIndex) throw(); // nothrow + /// Basic destructor + virtual ~Column(void) throw(); // nothrow + + /// Return the integer value of the column. + int getInt (void) const throw(); + // Return the 64bits integer value of the column. + sqlite3_int64 getInt64 (void) const throw(); + // Return the double (64bits float) value of the column. + double getDouble(void) const throw(); + // Return the text value (NULL terminated string) of the column. + const char* getText (void) const throw(); + + /// Inline cast operator to int + inline operator const int() const + { + return getInt(); + } + /// Inline cast operator to 64bits integer + inline operator const sqlite3_int64() const + { + return getInt64(); + } + /// Inline cast operator to double + inline operator const double() const + { + return getDouble(); + } + /// Inline cast operator to char* + inline operator const char*() const + { + return getText(); + } + /// Inline cast operator to std::string + inline operator const std::string() const + { + return getText(); + } + + private: + // Column is copyable, but copy should not be used elsewhere than in return form getColumn + Column(void); + Column& operator=(const Column&); + + private: + sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle + sqlite3_stmt* mpStmt; //!< Pointeur to SQLite Statement Object + int mIndex; //!< Index of the column in the row of result + }; + private: // Statement must not be copyable Statement(void); diff --git a/src/example1/main.cpp b/src/example1/main.cpp index 47ae027..5f0f8a2 100644 --- a/src/example1/main.cpp +++ b/src/example1/main.cpp @@ -1,8 +1,61 @@ +/** + * @file main.cpp + * @brief Two short examples in a row. + * + * Demonstrate how-to use the SQLite++ wrapper + * + * Copyright (c) 2012 Sebastien Rombauts (sebastien dot rombauts at gmail dot com) + * + * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt + * or copy at http://opensource.org/licenses/MIT) + */ + #include -#include "../SQLiteC++/SQLiteC++.h" + +#include "../SQLiteC++/Database.h" +#include "../SQLiteC++/Statement.h" + + +/// Object Oriented Basic example +class Example +{ +public: + Example(void) : + mDb("example.db3"), // Open a database file + mQuery(mDb, "SELECT * FROM test WHERE size > ?") // Compile a SQL query, containing one parameter (index 1) + { + } + virtual ~Example(void) + { + } + + // List the rows where the "size" column is greater than the provided aParamValue + void ListGreaterThan (const int aParamValue) + { + std::cout << "ListGreaterThan (" << aParamValue << ")\n"; + + // Bind the integer value provided to the first parameter of the SQL query + mQuery.bind(1, aParamValue); + + // Loop to execute the query step by step, to get one a row of results at a time + while (mQuery.executeStep()) + { + std::cout << "row : (" << mQuery.getColumn(0) << ", " << mQuery.getColumn(1) << ", " << mQuery.getColumn(2) << ")\n"; + } + + // Reset the query to be able to use it again later + mQuery.reset(); + } + +private: + SQLite::Database mDb; + SQLite::Statement mQuery; +}; + int main (void) { + // Basic example (1/2) : try { // Open a database file @@ -10,19 +63,32 @@ int main (void) std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n"; // Compile a SQL query, containing one parameter (index 1) - SQLite::Statement query(db, "SELECT * FROM test WHERE size>?"); + SQLite::Statement query(db, "SELECT * FROM test WHERE size > ?"); std::cout << "SQLite statement '" << query.getQuery().c_str() << "' compiled (" << query.getColumnCount () << " columns in the result)\n"; - // Bind an integer value "6" to the first parameter of the SQL query + // Bind the integer value 6 to the first parameter of the SQL query query.bind(1, 6); + // Loop to execute the query step by step, to get one a row of results at a time while (query.executeStep()) { + // Demonstrate how to get some typed column value int id = query.getColumn(0); // = query.getColumn(0).getInt() //const char* pvalue = query.getColumn(1); // = query.getColumn(1).getText() std::string value = query.getColumn(1); // = query.getColumn(1).getText() int size = query.getColumn(2); // = query.getColumn(2).getInt() std::cout << "row : (" << id << ", " << value << ", " << size << ")\n"; + } + + // Reset the query to use it again + query.reset(); + std::cout << "SQLite statement '" << query.getQuery().c_str() << "' reseted (" << query.getColumnCount () << " columns in the result)\n"; + // Bind the string value "6" to the first parameter of the SQL query + query.bind(1, "6"); + + while (query.executeStep()) + { + // Demonstrate that inserting column value in a std:ostream is natural std::cout << "row : (" << query.getColumn(0) << ", " << query.getColumn(1) << ", " << query.getColumn(2) << ")\n"; } } @@ -31,5 +97,22 @@ int main (void) std::cout << "SQLite exception: " << e.what() << std::endl; } + //////////////////////////////////////////////////////////////////////////// + // Object Oriented Basic example (2/2) : + try + { + // Open the database and compile the query + Example example; + + // Demonstrate the way to use the same query with different parameter values + example.ListGreaterThan(8); + example.ListGreaterThan(6); + example.ListGreaterThan(2); + } + catch (std::exception& e) + { + std::cout << "SQLite exception: " << e.what() << std::endl; + } + return 0; }