15
15
16
16
#include < string>
17
17
#include < map>
18
- #include < climits > // For INT_MAX
18
+ #include < memory >
19
19
20
20
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
21
21
struct sqlite3 ;
@@ -51,8 +51,6 @@ extern const int OK; ///< SQLITE_OK
51
51
*/
52
52
class Statement
53
53
{
54
- friend class Column ; // For access to Statement::Ptr inner class
55
-
56
54
public:
57
55
/* *
58
56
* @brief Compile and register the SQL query for the provided SQLite Database Connection
@@ -62,7 +60,7 @@ class Statement
62
60
*
63
61
* Exception is thrown in case of error, then the Statement object is NOT constructed.
64
62
*/
65
- Statement (Database& aDatabase, const char * apQuery);
63
+ Statement (const Database& aDatabase, const char * apQuery);
66
64
67
65
/* *
68
66
* @brief Compile and register the SQL query for the provided SQLite Database Connection
@@ -72,7 +70,7 @@ class Statement
72
70
*
73
71
* Exception is thrown in case of error, then the Statement object is NOT constructed.
74
72
*/
75
- Statement (Database & aDatabase, const std::string& aQuery) :
73
+ Statement (const Database& aDatabase, const std::string& aQuery) :
76
74
Statement (aDatabase, aQuery.c_str())
77
75
{}
78
76
@@ -82,6 +80,7 @@ class Statement
82
80
* @param[in] aStatement Statement to move
83
81
*/
84
82
Statement (Statement&& aStatement) noexcept ;
83
+ Statement& operator =(Statement&& aStatement) noexcept = default ;
85
84
86
85
// Statement is non-copyable
87
86
Statement (const Statement&) = delete ;
@@ -123,39 +122,20 @@ class Statement
123
122
// => if you know what you are doing, use bindNoCopy() instead of bind()
124
123
125
124
SQLITECPP_PURE_FUNC
126
- int getIndex (const char * const apName);
125
+ int getIndex (const char * const apName) const ;
127
126
128
127
/* *
129
128
* @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
130
129
*/
131
- void bind (const int aIndex, const int aValue);
130
+ void bind (const int aIndex, const int32_t aValue);
132
131
/* *
133
132
* @brief Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
134
133
*/
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);
155
135
/* *
156
136
* @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
157
137
*/
158
- void bind (const int aIndex, const long long aValue);
138
+ void bind (const int aIndex, const int64_t aValue);
159
139
/* *
160
140
* @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
161
141
*/
@@ -210,39 +190,21 @@ class Statement
210
190
/* *
211
191
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
212
192
*/
213
- void bind (const char * apName, const int aValue)
193
+ void bind (const char * apName, const int32_t aValue)
214
194
{
215
195
bind (getIndex (apName), aValue);
216
196
}
217
197
/* *
218
198
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
219
199
*/
220
- void bind (const char * apName, const unsigned aValue)
200
+ void bind (const char * apName, const uint32_t aValue)
221
201
{
222
202
bind (getIndex (apName), aValue);
223
203
}
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
242
204
/* *
243
205
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
244
206
*/
245
- void bind (const char * apName, const long long aValue)
207
+ void bind (const char * apName, const int64_t aValue)
246
208
{
247
209
bind (getIndex (apName), aValue);
248
210
}
@@ -325,46 +287,28 @@ class Statement
325
287
/* *
326
288
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
327
289
*/
328
- void bind (const std::string& aName, const int aValue)
290
+ void bind (const std::string& aName, const int32_t aValue)
329
291
{
330
292
bind (aName.c_str (), aValue);
331
293
}
332
294
/* *
333
295
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
334
296
*/
335
- void bind (const std::string& aName, const unsigned aValue)
297
+ void bind (const std::string& aName, const uint32_t aValue)
336
298
{
337
299
bind (aName.c_str (), aValue);
338
300
}
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
357
301
/* *
358
302
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
359
303
*/
360
- void bind (const std::string& aName, const long long aValue)
304
+ void bind (const std::string& aName, const int64_t aValue)
361
305
{
362
306
bind (aName.c_str (), aValue);
363
307
}
364
308
/* *
365
309
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
366
310
*/
367
- void bind (const std::string& aName, const double aValue)
311
+ void bind (const std::string& aName, const double aValue)
368
312
{
369
313
bind (aName.c_str (), aValue);
370
314
}
@@ -519,7 +463,7 @@ class Statement
519
463
* Thus, you should instead extract immediately its data (getInt(), getText()...)
520
464
* and use or copy this data for any later usage.
521
465
*/
522
- Column getColumn (const int aIndex);
466
+ Column getColumn (const int aIndex) const ;
523
467
524
468
/* *
525
469
* @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
550
494
*
551
495
* Throw an exception if the specified name is not one of the aliased name of the columns in the result.
552
496
*/
553
- Column getColumn (const char * apName);
497
+ Column getColumn (const char * apName) const ;
554
498
555
499
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015
556
500
/* *
@@ -673,7 +617,7 @@ class Statement
673
617
}
674
618
675
619
// 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 ;
677
621
678
622
// / Return the number of columns in the result set returned by the prepared statement
679
623
int getColumnCount () const
@@ -701,52 +645,8 @@ class Statement
701
645
// / Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
702
646
const char * getErrorMsg () const noexcept ;
703
647
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>;
750
650
751
651
private:
752
652
/* *
@@ -758,7 +658,7 @@ class Statement
758
658
{
759
659
if (SQLite::OK != aRet)
760
660
{
761
- throw SQLite::Exception (mStmtPtr , aRet);
661
+ throw SQLite::Exception (mpSQLite , aRet);
762
662
}
763
663
}
764
664
@@ -784,17 +684,30 @@ class Statement
784
684
}
785
685
}
786
686
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 ();
790
693
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 {};
798
711
};
799
712
800
713
0 commit comments