1515
1616#include < string>
1717#include < map>
18- #include < climits > // For INT_MAX
18+ #include < memory >
1919
2020// Forward declarations to avoid inclusion of <sqlite3.h> in a header
2121struct sqlite3 ;
@@ -51,8 +51,6 @@ extern const int OK; ///< SQLITE_OK
5151 */
5252class Statement
5353{
54- friend class Column ; // For access to Statement::Ptr inner class
55-
5654public:
5755 /* *
5856 * @brief Compile and register the SQL query for the provided SQLite Database Connection
@@ -62,7 +60,7 @@ class Statement
6260 *
6361 * Exception is thrown in case of error, then the Statement object is NOT constructed.
6462 */
65- Statement (Database& aDatabase, const char * apQuery);
63+ Statement (const Database& aDatabase, const char * apQuery);
6664
6765 /* *
6866 * @brief Compile and register the SQL query for the provided SQLite Database Connection
@@ -72,7 +70,7 @@ class Statement
7270 *
7371 * Exception is thrown in case of error, then the Statement object is NOT constructed.
7472 */
75- Statement (Database & aDatabase, const std::string& aQuery) :
73+ Statement (const Database& aDatabase, const std::string& aQuery) :
7674 Statement (aDatabase, aQuery.c_str())
7775 {}
7876
@@ -82,6 +80,7 @@ class Statement
8280 * @param[in] aStatement Statement to move
8381 */
8482 Statement (Statement&& aStatement) noexcept ;
83+ Statement& operator =(Statement&& aStatement) noexcept = default ;
8584
8685 // Statement is non-copyable
8786 Statement (const Statement&) = delete ;
@@ -123,39 +122,20 @@ class Statement
123122 // => if you know what you are doing, use bindNoCopy() instead of bind()
124123
125124 SQLITECPP_PURE_FUNC
126- int getIndex (const char * const apName);
125+ int getIndex (const char * const apName) const ;
127126
128127 /* *
129128 * @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
130129 */
131- void bind (const int aIndex, const int aValue);
130+ void bind (const int aIndex, const int32_t aValue);
132131 /* *
133132 * @brief Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
134133 */
135- void bind (const int aIndex, const unsigned aValue);
136-
137- #if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
138- /* *
139- * @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
140- */
141- void bind (const int aIndex, const long aValue)
142- {
143- bind (aIndex, static_cast <int >(aValue));
144- }
145- #else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
146- /* *
147- * @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
148- */
149- void bind (const int aIndex, const long aValue)
150- {
151- bind (aIndex, static_cast <long long >(aValue));
152- }
153- #endif
154-
134+ void bind (const int aIndex, const uint32_t aValue);
155135 /* *
156136 * @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
157137 */
158- void bind (const int aIndex, const long long aValue);
138+ void bind (const int aIndex, const int64_t aValue);
159139 /* *
160140 * @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
161141 */
@@ -210,39 +190,21 @@ class Statement
210190 /* *
211191 * @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
212192 */
213- void bind (const char * apName, const int aValue)
193+ void bind (const char * apName, const int32_t aValue)
214194 {
215195 bind (getIndex (apName), aValue);
216196 }
217197 /* *
218198 * @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
219199 */
220- void bind (const char * apName, const unsigned aValue)
200+ void bind (const char * apName, const uint32_t aValue)
221201 {
222202 bind (getIndex (apName), aValue);
223203 }
224-
225- #if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
226- /* *
227- * @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
228- */
229- void bind (const char * apName, const long aValue)
230- {
231- bind (apName, static_cast <int >(aValue));
232- }
233- #else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
234- /* *
235- * @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
236- */
237- void bind (const char * apName, const long aValue)
238- {
239- bind (apName, static_cast <long long >(aValue));
240- }
241- #endif
242204 /* *
243205 * @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
244206 */
245- void bind (const char * apName, const long long aValue)
207+ void bind (const char * apName, const int64_t aValue)
246208 {
247209 bind (getIndex (apName), aValue);
248210 }
@@ -325,46 +287,28 @@ class Statement
325287 /* *
326288 * @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
327289 */
328- void bind (const std::string& aName, const int aValue)
290+ void bind (const std::string& aName, const int32_t aValue)
329291 {
330292 bind (aName.c_str (), aValue);
331293 }
332294 /* *
333295 * @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
334296 */
335- void bind (const std::string& aName, const unsigned aValue)
297+ void bind (const std::string& aName, const uint32_t aValue)
336298 {
337299 bind (aName.c_str (), aValue);
338300 }
339-
340- #if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
341- /* *
342- * @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
343- */
344- void bind (const std::string& aName, const long aValue)
345- {
346- bind (aName.c_str (), static_cast <int >(aValue));
347- }
348- #else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
349- /* *
350- * @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
351- */
352- void bind (const std::string& aName, const long aValue)
353- {
354- bind (aName.c_str (), static_cast <long long >(aValue));
355- }
356- #endif
357301 /* *
358302 * @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
359303 */
360- void bind (const std::string& aName, const long long aValue)
304+ void bind (const std::string& aName, const int64_t aValue)
361305 {
362306 bind (aName.c_str (), aValue);
363307 }
364308 /* *
365309 * @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
366310 */
367- void bind (const std::string& aName, const double aValue)
311+ void bind (const std::string& aName, const double aValue)
368312 {
369313 bind (aName.c_str (), aValue);
370314 }
@@ -519,7 +463,7 @@ class Statement
519463 * Thus, you should instead extract immediately its data (getInt(), getText()...)
520464 * and use or copy this data for any later usage.
521465 */
522- Column getColumn (const int aIndex);
466+ Column getColumn (const int aIndex) const ;
523467
524468 /* *
525469 * @brief Return a copy of the column data specified by its column name (less efficient than using an index)
@@ -550,7 +494,7 @@ class Statement
550494 *
551495 * Throw an exception if the specified name is not one of the aliased name of the columns in the result.
552496 */
553- Column getColumn (const char * apName);
497+ Column getColumn (const char * apName) const ;
554498
555499#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015
556500 /* *
@@ -673,7 +617,7 @@ class Statement
673617 }
674618
675619 // Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
676- std::string getExpandedSQL ();
620+ std::string getExpandedSQL () const ;
677621
678622 // / Return the number of columns in the result set returned by the prepared statement
679623 int getColumnCount () const
@@ -701,52 +645,8 @@ class Statement
701645 // / Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
702646 const char * getErrorMsg () const noexcept ;
703647
704- private:
705- /* *
706- * @brief Shared pointer to the sqlite3_stmt SQLite Statement Object.
707- *
708- * Manage the finalization of the sqlite3_stmt with a reference counter.
709- *
710- * This is a internal class, not part of the API (hence full documentation is in the cpp).
711- */
712- // TODO Convert this whole custom pointer to a C++11 std::shared_ptr with a custom deleter
713- class Ptr
714- {
715- public:
716- // Prepare the statement and initialize its reference counter
717- Ptr (sqlite3* apSQLite, std::string& aQuery);
718- // Copy constructor increments the ref counter
719- Ptr (const Ptr& aPtr);
720-
721- // Move constructor
722- Ptr (Ptr&& aPtr);
723-
724- // Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
725- ~Ptr ();
726-
727- // / Inline cast operator returning the pointer to SQLite Database Connection Handle
728- operator sqlite3*() const
729- {
730- return mpSQLite;
731- }
732-
733- // / Inline cast operator returning the pointer to SQLite Statement Object
734- operator sqlite3_stmt*() const
735- {
736- return mpStmt;
737- }
738-
739- private:
740- // / @{ Unused/forbidden copy/assignment operator
741- Ptr& operator =(const Ptr& aPtr);
742- // / @}
743-
744- private:
745- sqlite3* mpSQLite; // !< Pointer to SQLite Database Connection Handle
746- sqlite3_stmt* mpStmt; // !< Pointer to SQLite Statement Object
747- unsigned int * mpRefCount; // !< Pointer to the heap allocated reference counter of the sqlite3_stmt
748- // !< (to share it with Column objects)
749- };
648+ // / Shared pointer to SQLite Prepared Statement Object
649+ using TStatementPtr = std::shared_ptr<sqlite3_stmt>;
750650
751651private:
752652 /* *
@@ -758,7 +658,7 @@ class Statement
758658 {
759659 if (SQLite::OK != aRet)
760660 {
761- throw SQLite::Exception (mStmtPtr , aRet);
661+ throw SQLite::Exception (mpSQLite , aRet);
762662 }
763663 }
764664
@@ -784,17 +684,30 @@ class Statement
784684 }
785685 }
786686
787- private:
788- // / Map of columns index by name (mutable so getColumnIndex can be const)
789- typedef std::map<std::string, int > TColumnNames;
687+ /* *
688+ * @brief Prepare statement object.
689+ *
690+ * @return Shared pointer to prepared statement object
691+ */
692+ TStatementPtr prepareStatement ();
790693
791- private:
792- std::string mQuery ; // !< UTF-8 SQL Query
793- Ptr mStmtPtr ; // !< Shared Pointer to the prepared SQLite Statement Object
794- int mColumnCount ; // !< Number of columns in the result of the prepared statement
795- mutable TColumnNames mColumnNames ; // !< Map of columns index by name (mutable so getColumnIndex can be const)
796- bool mbHasRow; // !< true when a row has been fetched with executeStep()
797- bool mbDone; // !< true when the last executeStep() had no more row to fetch
694+ /* *
695+ * @brief Return a prepared statement object.
696+ *
697+ * Throw an exception if the statement object was not prepared.
698+ * @return raw pointer to Prepared Statement Object
699+ */
700+ sqlite3_stmt* getPreparedStatement () const ;
701+
702+ std::string mQuery ; // !< UTF-8 SQL Query
703+ sqlite3* mpSQLite; // !< Pointer to SQLite Database Connection Handle
704+ TStatementPtr mpPreparedStatement; // !< Shared Pointer to the prepared SQLite Statement Object
705+ int mColumnCount {0 }; // !< Number of columns in the result of the prepared statement
706+ bool mbHasRow{false }; // !< true when a row has been fetched with executeStep()
707+ bool mbDone{false }; // !< true when the last executeStep() had no more row to fetch
708+
709+ // / Map of columns index by name (mutable so getColumnIndex can be const)
710+ mutable std::map<std::string, int > mColumnNames {};
798711};
799712
800713
0 commit comments