SQLiteC++  0.5.0
SQLiteC++ is a smart and easy to use C++ SQLite3 wrapper.
 All Classes Namespaces Files Functions Friends Macros
Statement.h
Go to the documentation of this file.
1 /**
2  * @file Statement.h
3  * @brief A prepared SQLite Statement is a compiled SQL query ready to be executed, pointing to a row of result.
4  *
5  * Copyright (c) 2012-2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
6  *
7  * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
8  * or copy at http://opensource.org/licenses/MIT)
9  */
10 #pragma once
11 
12 #include <sqlite3.h>
13 #include "Exception.h"
14 
15 namespace SQLite
16 {
17 
18 // Forward declaration
19 class Database;
20 class Column;
21 
22 /**
23  * @brief RAII encapsulation of a prepared SQLite Statement.
24  *
25  * A Statement is a compiled SQL query ready to be executed step by step
26  * to provide results one row at a time.
27  *
28  * Resource Acquisition Is Initialization (RAII) means that the Statement
29  * is compiled in the constructor and finalized in the destructor, so that there is
30  * no need to worry about memory management or the validity of the underlying SQLite Statement.
31  */
32 class Statement
33 {
34 public:
35  class Ptr;
36 
37  /**
38  * @brief Compile and register the SQL query for the provided SQLite Database Connection
39  *
40  * @param[in] aDatabase the SQLite Database Connection
41  * @param[in] apQuery an UTF-8 encoded query string
42  *
43  * Exception is thrown in case of error, then the Statement object is NOT constructed.
44  */
45  Statement(Database& aDatabase, const char* apQuery); // throw(SQLite::Exception);
46 
47  /**
48  * @brief Finalize and unregister the SQL query from the SQLite Database Connection.
49  */
50  virtual ~Statement(void) throw(); // nothrow
51 
52  /**
53  * @brief Reset the statement to make it ready for a new execution.
54  */
55  void reset(void); // throw(SQLite::Exception);
56 
57  ////////////////////////////////////////////////////////////////////////////
58  // Bind a value to a parameter of the SQL statement,
59  // in the form "?" (unnamed), "?NNN", ":VVV", "@VVV" or "$VVV".
60  //
61  // Can use the parameter index, starting from "1", to the higher NNN value,
62  // or the complete parameter name "?NNN", ":VVV", "@VVV" or "$VVV"
63  // (prefixed with the corresponding sign "?", ":", "@" or "$")
64  //
65  // Note that for text and blob values, the SQLITE_TRANSIENT flag is used,
66  // which tell the sqlite library to make its own copy of the data before the bind() call returns.
67  // This choice is done to prevent any common misuses, like passing a pointer to a
68  // dynamic allocated and temporary variable (a std::string for instance).
69  // This is under-optimized for static data (a static text define in code)
70  // as well as for dynamic allocated buffer which could be transfer to sqlite
71  // instead of being copied.
72 
73  /**
74  * @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
75  */
76  void bind(const int aIndex, const int& aValue) ; // throw(SQLite::Exception);
77  /**
78  * @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
79  */
80  void bind(const int aIndex, const sqlite3_int64& aValue) ; // throw(SQLite::Exception);
81  /**
82  * @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
83  */
84  void bind(const int aIndex, const double& aValue) ; // throw(SQLite::Exception);
85  /**
86  * @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
87  *
88  * @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
89  */
90  void bind(const int aIndex, const std::string& aValue) ; // throw(SQLite::Exception);
91  /**
92  * @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
93  *
94  * @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
95  */
96  void bind(const int aIndex, const char* apValue) ; // throw(SQLite::Exception);
97  /**
98  * @brief Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
99  *
100  * @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
101  */
102  void bind(const int aIndex, const void* apValue, const int aSize) ; // throw(SQLite::Exception);
103  /**
104  * @brief Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
105  */
106  void bind(const int aIndex); // throw(SQLite::Exception);
107 
108  /**
109  * @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
110  */
111  void bind(const char* apName, const int& aValue) ; // throw(SQLite::Exception);
112  /**
113  * @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
114  */
115  void bind(const char* apName, const sqlite3_int64& aValue) ; // throw(SQLite::Exception);
116  /**
117  * @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
118  */
119  void bind(const char* apName, const double& aValue) ; // throw(SQLite::Exception);
120  /**
121  * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
122  *
123  * @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
124  */
125  void bind(const char* apName, const std::string& aValue) ; // throw(SQLite::Exception);
126  /**
127  * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
128  *
129  * @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
130  */
131  void bind(const char* apName, const char* apValue) ; // throw(SQLite::Exception);
132  /**
133  * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
134  *
135  * @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
136  */
137  void bind(const char* apName, const void* apValue, const int aSize) ; // throw(SQLite::Exception);
138  /**
139  * @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
140  */
141  void bind(const char* apName); // throw(SQLite::Exception); // bind NULL value
142 
143  ////////////////////////////////////////////////////////////////////////////
144 
145  /**
146  * @brief Execute a step of the prepared query to fetch one row of results.
147  *
148  * While true is returned, a row of results is available, and can be accessed
149  * thru the getColumn() method
150  *
151  * @see exec() execute a one-step prepared statement with no expected result
152  * @see Database::exec() is a shortcut to execute one or multiple statements without results
153  *
154  * @return - true (SQLITE_ROW) if there is another row ready : you can call getColumn(N) to get it
155  * then you have to call executeStep() again to fetch more rows until the query is finished
156  * - false (SQLITE_DONE) if the query has finished executing : there is no (more) row of result
157  * (case of a query with no result, or after N rows fetched successfully)
158  *
159  * @throw SQLite::Exception in case of error
160  */
161  bool executeStep(void); // throw(SQLite::Exception);
162 
163  /**
164  * @brief Execute a one-step query with no expected result.
165  *
166  * This method is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
167  * - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
168  * - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
169  * - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
170  *
171  * It is similar to Database::exec(), but using a precompiled statement, it adds :
172  * - the ability to bind() arguments to it (best way to insert data),
173  * - reusing it allows for better performances (efficent for multiple insersion).
174  *
175  * @see executeStep() execute a step of the prepared query to fetch one row of results
176  * @see Database::exec() is a shortcut to execute one or multiple statements without results
177  *
178  * @return number of row modified by this SQL statement (INSERT, UPDATE or DELETE)
179  *
180  * @throw SQLite::Exception in case of error, or if row of results are returned !
181  */
182  int exec(void); // throw(SQLite::Exception);
183 
184  ////////////////////////////////////////////////////////////////////////////
185 
186  /**
187  * @brief Return a copie of the column data specified by its index
188  *
189  * Can be used to access the data of the current row of result when applicable,
190  * while the executeStep() method returns true.
191  *
192  * Throw an exception if there is no row to return a Column from :
193  * - before any executeStep() call
194  * - after the last executeStep() returned false
195  * - after a reset() call
196  *
197  * Throw an exception if the specified index is out of the [0, getColumnCount()) range.
198  *
199  * @param[in] aIndex Index of the column, starting at 0
200  *
201  * @note This method is no more const, starting in v0.5,
202  * which reflects the fact that the returned Column object will
203  * share the ownership of the underlying sqlite3_stmt.
204  *
205  * @warning The resulting Column object must not be memorized "as-is".
206  * Is is only a wrapper arround the current result row, so it is only valid
207  * while the row from the Statement remains valid, that is only until next executeStep() call.
208  * Thus, you should instead extract immediately its data (getInt(), getText()...)
209  * and use or copy this data for any later usage.
210  */
211  Column getColumn(const int aIndex); // throw(SQLite::Exception);
212 
213  /**
214  * @brief Test if the column value is NULL
215  *
216  * @param[in] aIndex Index of the column, starting at 0
217  *
218  * @return true if the column value is NULL
219  */
220  bool isColumnNull(const int aIndex) const; // throw(SQLite::Exception);
221 
222  ////////////////////////////////////////////////////////////////////////////
223 
224  /// @brief Return the UTF-8 SQL Query.
225  inline const std::string& getQuery(void) const
226  {
227  return mQuery;
228  }
229  /// @brief Return the number of columns in the result set returned by the prepared statement
230  inline int getColumnCount(void) const
231  {
232  return mColumnCount;
233  }
234  /// @brief true when a row has been fetched with executeStep()
235  inline bool isOk(void) const
236  {
237  return mbOk;
238  }
239  /// @brief true when the last executeStep() had no more row to fetch
240  inline bool isDone(void) const
241  {
242  return mbDone;
243  }
244  /// @brief Return UTF-8 encoded English language explanation of the most recent error.
245  inline const char* errmsg(void) const
246  {
247  return sqlite3_errmsg(mStmtPtr);
248  }
249 
250 public:
251  /**
252  * @brief Shared pointer to the sqlite3_stmt SQLite Statement Object.
253  *
254  * Manage the finalization of the sqlite3_stmt with a reference counter.
255  *
256  * This is a internal class, not part of the API (hence full documentation is in the cpp).
257  */
258  class Ptr
259  {
260  public:
261  // Prepare the statement and initialize its reference counter
262  Ptr(sqlite3* apSQLite, std::string& aQuery);
263  // Copy constructor increments the ref counter
264  Ptr(const Ptr& aPtr);
265  // Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
266  ~Ptr(void) throw(); // nothrow (no virtual destructor needed here)
267 
268  /// @brief Inline cast operator returning the pointer to SQLite Database Connection Handle
269  inline operator sqlite3*() const
270  {
271  return mpSQLite;
272  }
273 
274  /// @brief Inline cast operator returning the pointer to SQLite Statement Object
275  inline operator sqlite3_stmt*() const
276  {
277  return mpStmt;
278  }
279 
280  private:
281  /// @{ Unused/forbidden copy operator
282  Ptr& operator=(const Ptr& aPtr);
283  /// @}
284 
285  private:
286  sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
287  sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object
288  unsigned int* mpRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt (to share it with Column objects)
289  };
290 
291 private:
292  /// @{ Statement must be non-copyable
293  Statement(const Statement&);
294  Statement& operator=(const Statement&);
295  /// @}
296 
297  /**
298  * @brief Check if a return code equals SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
299  *
300  * @param[in] SQLite return code to test against the SQLITE_OK expected value
301  */
302  void check(const int aRet) const; // throw(SQLite::Exception);
303 
304 private:
305  std::string mQuery; //!< UTF-8 SQL Query
306  Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object
307  int mColumnCount; //!< Number of columns in the result of the prepared statement
308  bool mbOk; //!< true when a row has been fetched with executeStep()
309  bool mbDone; //!< true when the last executeStep() had no more row to fetch
310 };
311 
312 } // namespace SQLite