dodo  0.0.1
A C++ library to create containerized Linux services
sqlite.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of the dodo library (https://github.com/jmspit/dodo).
3  * Copyright (c) 2019 Jan-Marten Spit.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /**
19  * @file
20  * SQLite3 wrapper c++ header file.
21  */
22 
23 #ifndef dodo_persist_sqlite_hpp
24 #define dodo_persist_sqlite_hpp
25 
26 #include <string>
27 #include <sqlite3.h>
28 #include <common/bytes.hpp>
29 
30 namespace dodo::persist {
31 
32  /**
33  * C++ API to SQLite.
34  *
35  * An example of the basics (src/examples/sqlite/sqlite.cpp):
36  * @include sqlite/sqlite.cpp
37  */
38  namespace sqlite {
39 
40  /**
41  * Prototype for wait/busy handlers.
42  */
43  typedef int(*WaitHandler)(void*,int);
44 
45  /**
46  * A STL friendly wrapper around the great sqlite3.
47  * A few extension functions are added for use in SQL
48  * - power(double x,double y) gives base x to the power y (x^y)
49  * - floor(double x) gives the nearest integer downwards
50  * - ceil(double x) gives the nearest integer upwards
51  */
52  class Database {
53  public:
54 
55  /**
56  * Constructor with explicit wait handler.
57  * @param filename the database filename
58  * @param handler the wait handler
59  */
60  Database( const std::string &filename, WaitHandler handler = 0 );
61 
62  /**
63  * Destructor.
64  */
65  ~Database();
66 
67  /**
68  * Begin a transaction.
69  * @see https://sqlite.org/lang_transaction.html
70  */
71  void beginTransaction();
72 
73  /**
74  * Begin an immediate transaction.
75  * @see https://sqlite.org/lang_transaction.html
76  */
78 
79  /**
80  * Begin an exclusive transaction.
81  * @see https://sqlite.org/lang_transaction.html
82  */
84 
85  /**
86  * Issue a full checpoint.
87  */
88  void checkPointFull();
89 
90  /**
91  * Issue a passive checpoint.
92  */
93  void checkPointPassive();
94 
95  /**
96  * Issue a (WAL) truncate checpoint.
97  */
98  void checkPointTruncate();
99 
100  /** Commit a transaction. */
101  void commit();
102 
103  /**
104  * Disable foreign key constraints.
105  */
106  void disableForeignKeys();
107 
108  /**
109  * Enable foreign key constraints.
110  */
111  void enableForeignKeys();
112 
113  /**
114  * Enable triggers.
115  */
116  void enableTriggers();
117 
118  /**
119  * Return the database filename.
120  * @return The file name.
121  */
122  std::string getFileName() const { return sqlite3_db_filename( database_, "main" ); };
123 
124  /**
125  * Return database handle.
126  * @return the sqlite3 database handle.
127  */
128  sqlite3* getDB() const { return database_; };
129 
130  /**
131  * get the current user_version pragma (a user defined database schema version)
132  * @return The user version.
133  */
134  int getUserVersion() const;
135 
136  /**
137  * Get the rowid of the last inserted row.
138  * @return The last rowid
139  */
140  int64_t lastInsertRowid() const;
141 
142  /**
143  * Get memory in use by the SQLite library.
144  * @return the amount of memory used.
145  */
146  static int64_t memUsed() {
147  return sqlite3_memory_used();
148  }
149 
150  /**
151  * Get memory highwater by the SQLite library.
152  * @return The max memory ever used.
153  */
154  static int64_t memHighWater() {
155  return sqlite3_memory_highwater(0);
156  }
157 
158  /**
159  * Release a savepoint.
160  * @param sp the savepoint name
161  */
162  void releaseSavepoint( const std::string &sp );
163 
164  /**
165  * Have SQLite attempt to release a much memory as possible.
166  */
167  void releaseMemory();
168 
169  /** Rollback a transaction. */
170  void rollback();
171 
172  /**
173  * Create a named savepoint.
174  * @param sp the savepoint name
175  * @see release, rollback
176  */
177  void createSavepoint( const std::string &sp );
178 
179  /**
180  * Rollback to a savepoint.
181  * @param sp the savepoint name
182  */
183  void rollback( const std::string &sp );
184 
185  /**
186  * set the user_version pragma
187  * @param version The user version to set.
188  */
189  void setUserVersion( int version );
190 
191  /**
192  * Set the SQLite soft heap limit - ask SQLite to strive to limit its memory use (caching).
193  * A value of 0 disables the limit.
194  * @param limit The limit to set.
195  * @return The previous soft heap limit.
196  * @see https://www.sqlite.org/c3ref/hard_heap_limit64.html
197  */
198  static int64_t softHeapLimit( int64_t limit ) {
199  return sqlite3_soft_heap_limit64( limit );
200  }
201 
202  protected:
203  /** The SQLite database handle. */
204  sqlite3 *database_;
205  };
206 
207  /**
208  * Generic SQL Statement.
209  */
210  class Statement {
211  public:
212 
213  /**
214  * Constructor.
215  * @param db The database context of the statement.
216  */
217  Statement( const Database& db );
218 
219  /**
220  * Destructor.
221  * Virtual so that this destructor will be called when
222  * descendants are deleted.
223  */
224  virtual ~Statement();
225 
226  /**
227  * Prepare a SQL statement.
228  * @param sql the SQL statement.
229  */
230  void prepare( const std::string &sql );
231 
232  /**
233  * Reset a SQL statement for re-execute or even re-prepare.
234  * @param clear If true (default), unbind the bind variables. If the statement is going to be
235  * re-executed, new bind calls must be made. If the satemetn is going to be re-executed with
236  * the same bind values, cler can be set to false and no re-binding is required.
237  */
238  void reset( bool clear = true );
239 
240  /**
241  * A statement handle can be explicitly closed without deleting
242  * the Statement object itself. This frees the resources in SQLite,
243  * . it's allowed to call prepare() again.
244  */
245  void close();
246 
247  protected:
248 
249  /** statement handle. */
250  sqlite3_stmt *stmt_;
251 
252  /** database handle on which the stmt_ is created. */
253  sqlite3 *database_;
254 
255  };
256 
257  /**
258  * Data Definition Language, SQL that takes no parameters,
259  * returns no data such as CREATE TABLE.
260  */
261  class DDL : public Statement {
262  public:
263 
264  /**
265  * Constructor.
266  * @param db Yhe database context.
267  */
268  DDL( const Database& db ) : Statement( db ) {};
269 
270  /**
271  * Destructor.
272  * @param db Yhe database context.
273  */
274  virtual ~DDL() {};
275 
276  /**
277  * execute, throws Oops on error.
278  * @see execute_r
279  */
280  void execute();
281 
282  /**
283  * execute and return result code.
284  * @return the SQLite error code.
285  * @see execute
286  */
287  int execute_r();
288  };
289 
290  /**
291  * Data Modification Language statements can take bind values.
292  * Note that calling reset leaves set bind values intact.
293  */
294  class DML : public Statement {
295  public:
296 
297  /**
298  * Constructor.
299  * @param db Yhe database context.
300  */
301  DML( const Database& db );
302 
303  /** Destructor. */
304  virtual ~DML() {};
305 
306  /**
307  * Execute and return the number of rows affected.
308  * @return The number of rows affected by the DML statement.
309  */
310  int execute();
311 
312  /**
313  * Bind a double value to the bind at position.
314  * @param position the bind position in the SQL (start with 1)
315  * @param value the value to bind.
316  */
317  void bind( int position, double value );
318 
319  /**
320  * Bind an int value to the bind at position.
321  * @param position the bind position in the SQL (start with 1)
322  * @param value the value to bind.
323  */
324  void bind( int position, int value );
325 
326  /**
327  * Bind a int64_t value to the bind at position.
328  * @param position the bind position in the SQL (start with 1)
329  * @param value the value to bind.
330  */
331  void bind( int position, int64_t value );
332 
333  /**
334  * Bind a string value to the bind at position.
335  * @param position the bind position in the SQL (start with 1)
336  * @param value the value to bind.
337  */
338  void bind( int position, const std::string &value );
339 
340  /**
341  * Bind an Bytes value to the bind at position.
342  * @param position the bind position in the SQL (start with 1)
343  * @param value the value to bind.
344  */
345  void bind( int position, const common::Bytes &value );
346 
347  /**
348  * Bind a string value to the bind by name. Note that this is less efficient than binding by index/position.
349  * @param name The name of the bind parameter.
350  * @param value the value to bind.
351  */
352  void bind( const std::string &name, double value );
353 
354  /**
355  * Bind a string value to the bind by name. Note that this is less efficient than binding by index/position.
356  * @param name The name of the bind parameter.
357  * @param value the value to bind.
358  */
359  void bind( const std::string &name, int value );
360 
361  /**
362  * Bind a string value to the bind by name. Note that this is less efficient than binding by index/position.
363  * @param name The name of the bind parameter.
364  * @param value the value to bind.
365  */
366  void bind( const std::string &name, int64_t value );
367 
368  /**
369  * Bind a string value to the bind by name. Note that this is less efficient than binding by index/position.
370  * @param name The name of the bind parameter.
371  * @param value the value to bind.
372  */
373  void bind( const std::string &name, const std::string &value );
374 
375  /**
376  * Bind a string value to the bind by name. Note that this is less efficient than binding by index/position.
377  * @param name The name of the bind parameter.
378  * @param value the value to bind.
379  */
380  void bind( const std::string &name, const common::Bytes &value );
381 
382  };
383 
384  /**
385  * Queries can take bind values and return select lists.
386  */
387  class Query : public DML {
388  public:
389 
390  /**
391  * The data type of a select-list value.
392  */
393  enum DataType {
394  dtInteger = SQLITE_INTEGER, /**< (1) Integer type (int64_t) */
395  dtFloat = SQLITE_FLOAT, /**< (2) Floating point type (double) */
396  dtText = SQLITE3_TEXT, /**< (3) Text type (string) */
397  dtBlob = SQLITE_BLOB, /**< (4) Binary data type (Bytes) */
398  dtNull = SQLITE_NULL, /**< (5) NULL type (unset and undefined) */
399  dtUnknown = 91, /**< Used to indicate a DataType that could not be determined */
400  };
401 
402  /**
403  * Constructor.
404  * @param db Yhe database context.
405  */
406  Query( const Database& db ) : DML( db ) {};
407 
408  /** Destructor. */
409  virtual ~Query() {};
410 
411  /**
412  * Step the result list, end of list returns false.
413  * @return true as long as there are more rows.
414  */
415  bool step();
416 
417  /**
418  * Test if the result is NULL
419  * @param col the select list column (start with 0).
420  * @return true if the col holds a NULL value
421  */
422  bool isNull( int col ) const;
423 
424  /**
425  * Get the dataype of a select list column.
426  * @param col The column index (start with 0).
427  * @return The Dataype of the select list column.
428  */
429  DataType getDataType( int col ) const;
430 
431  /**
432  * Get int value from select list.
433  * @param col the select list column (start with 0).
434  * @return the select list value.
435  */
436  int getInt( int col ) const;
437 
438  /**
439  * Get int64_t value from select list.
440  * @param col the select list column (start with 0).
441  * @return the select list value.
442  */
443  int64_t getInt64( int col ) const;
444 
445  /**
446  * Get double value from select list.
447  * @param col the select list column (start with 0).
448  * @return the select list value.
449  */
450  double getDouble( int col ) const;
451 
452  /**
453  * Get string value from select list.
454  * @param col the select list column (start with 0).
455  * @return the select list value.
456  */
457  std::string getText( int col ) const;
458 
459  /**
460  * Get Bytes value from select list.
461  * @param col the select list column (start with 0).
462  * @param bytes The Bytes value to get.
463  */
464  void getBytes( int col, common::Bytes &bytes ) const;
465 
466  /**
467  * get the number of columns in the query result set.
468  * @return the number of columns
469  */
470  int getColumnCount() const;
471  };
472 
473 
474  }; // namespace persist
475 
476 }; // namespace leanux
477 
478 #endif
dodo::persist::sqlite::Statement::~Statement
virtual ~Statement()
Destructor.
Definition: sqlite.cpp:353
dodo::persist::sqlite::Database::softHeapLimit
static int64_t softHeapLimit(int64_t limit)
Set the SQLite soft heap limit - ask SQLite to strive to limit its memory use (caching).
Definition: sqlite.hpp:198
dodo::persist::sqlite::Database::rollback
void rollback()
Rollback a transaction.
Definition: sqlite.cpp:255
dodo::persist::sqlite::Database::checkPointTruncate
void checkPointTruncate()
Issue a (WAL) truncate checpoint.
Definition: sqlite.cpp:313
dodo::persist::sqlite::Database::lastInsertRowid
int64_t lastInsertRowid() const
Get the rowid of the last inserted row.
Definition: sqlite.cpp:287
dodo::persist::sqlite::Database::enableTriggers
void enableTriggers()
Enable triggers.
Definition: sqlite.cpp:215
dodo::persist::sqlite::Statement
Generic SQL Statement.
Definition: sqlite.hpp:210
dodo::persist::sqlite::Query::Query
Query(const Database &db)
Constructor.
Definition: sqlite.hpp:406
dodo::persist::sqlite::Database::commit
void commit()
Commit a transaction.
Definition: sqlite.cpp:247
dodo::persist::sqlite::Query
Queries can take bind values and return select lists.
Definition: sqlite.hpp:387
dodo::common::Bytes
An array of Octets with size elements.
Definition: bytes.hpp:44
dodo::persist::sqlite::Query::~Query
virtual ~Query()
Destructor.
Definition: sqlite.hpp:409
dodo::persist::sqlite::Database::~Database
~Database()
Destructor.
Definition: sqlite.cpp:194
dodo::persist::sqlite::Query::dtUnknown
@ dtUnknown
Used to indicate a DataType that could not be determined.
Definition: sqlite.hpp:399
dodo::persist::sqlite::Query::getText
std::string getText(int col) const
Get string value from select list.
Definition: sqlite.cpp:504
dodo::persist::sqlite::Database::enableForeignKeys
void enableForeignKeys()
Enable foreign key constraints.
Definition: sqlite.cpp:199
dodo::persist::sqlite::WaitHandler
int(* WaitHandler)(void *, int)
Prototype for wait/busy handlers.
Definition: sqlite.hpp:43
dodo::persist::sqlite::Database::disableForeignKeys
void disableForeignKeys()
Disable foreign key constraints.
Definition: sqlite.cpp:207
dodo::persist::sqlite::DDL::~DDL
virtual ~DDL()
Destructor.
Definition: sqlite.hpp:274
dodo::persist::sqlite::Query::dtInteger
@ dtInteger
(1) Integer type (int64_t)
Definition: sqlite.hpp:394
dodo::persist::sqlite::Database::releaseMemory
void releaseMemory()
Have SQLite attempt to release a much memory as possible.
Definition: sqlite.cpp:344
dodo::persist::sqlite::Query::getColumnCount
int getColumnCount() const
get the number of columns in the query result set.
Definition: sqlite.cpp:516
dodo::persist::sqlite::Query::DataType
DataType
The data type of a select-list value.
Definition: sqlite.hpp:393
dodo::persist::sqlite::Query::step
bool step()
Step the result list, end of list returns false.
Definition: sqlite.cpp:476
dodo::persist::sqlite::Database::beginExclusiveTransaction
void beginExclusiveTransaction()
Begin an exclusive transaction.
Definition: sqlite.cpp:239
dodo::persist::sqlite::Statement::database_
sqlite3 * database_
database handle on which the stmt_ is created.
Definition: sqlite.hpp:253
dodo::persist::sqlite::Query::getDataType
DataType getDataType(int col) const
Get the dataype of a select list column.
Definition: sqlite.cpp:488
dodo::persist::sqlite::DDL::execute_r
int execute_r()
execute and return result code.
Definition: sqlite.cpp:396
dodo::persist::sqlite::Query::isNull
bool isNull(int col) const
Test if the result is NULL.
Definition: sqlite.cpp:484
dodo::persist::sqlite::Database::checkPointPassive
void checkPointPassive()
Issue a passive checpoint.
Definition: sqlite.cpp:304
dodo::persist::sqlite::Database::getDB
sqlite3 * getDB() const
Return database handle.
Definition: sqlite.hpp:128
dodo::persist::sqlite::Database::beginTransaction
void beginTransaction()
Begin a transaction.
Definition: sqlite.cpp:223
dodo::persist::sqlite::Statement::close
void close()
A statement handle can be explicitly closed without deleting the Statement object itself.
Definition: sqlite.cpp:381
dodo::persist::sqlite::Database::setUserVersion
void setUserVersion(int version)
set the user_version pragma
Definition: sqlite.cpp:326
dodo::persist
Persistent storage structures.
Definition: kvstore.hpp:35
dodo::persist::sqlite::DML::DML
DML(const Database &db)
Constructor.
Definition: sqlite.cpp:400
dodo::persist::sqlite::DML
Data Modification Language statements can take bind values.
Definition: sqlite.hpp:294
dodo::persist::sqlite::DML::bind
void bind(int position, double value)
Bind a double value to the bind at position.
Definition: sqlite.cpp:411
dodo::persist::sqlite::Statement::prepare
void prepare(const std::string &sql)
Prepare a SQL statement.
Definition: sqlite.cpp:357
dodo::persist::sqlite::Database::memUsed
static int64_t memUsed()
Get memory in use by the SQLite library.
Definition: sqlite.hpp:146
dodo::persist::sqlite::Query::dtFloat
@ dtFloat
(2) Floating point type (double)
Definition: sqlite.hpp:395
dodo::persist::sqlite::Statement::Statement
Statement(const Database &db)
Constructor.
Definition: sqlite.cpp:348
dodo::persist::sqlite::DML::execute
int execute()
Execute and return the number of rows affected.
Definition: sqlite.cpp:403
dodo::persist::sqlite::DML::~DML
virtual ~DML()
Destructor.
Definition: sqlite.hpp:304
dodo::persist::sqlite::Database::getUserVersion
int getUserVersion() const
get the current user_version pragma (a user defined database schema version)
Definition: sqlite.cpp:334
dodo::persist::sqlite::Query::getInt64
int64_t getInt64(int col) const
Get int64_t value from select list.
Definition: sqlite.cpp:496
dodo::persist::sqlite::Query::dtNull
@ dtNull
(5) NULL type (unset and undefined)
Definition: sqlite.hpp:398
dodo::persist::sqlite::Statement::reset
void reset(bool clear=true)
Reset a SQL statement for re-execute or even re-prepare.
Definition: sqlite.cpp:368
dodo::persist::sqlite::Database::getFileName
std::string getFileName() const
Return the database filename.
Definition: sqlite.hpp:122
dodo::persist::sqlite::Database::releaseSavepoint
void releaseSavepoint(const std::string &sp)
Release a savepoint.
Definition: sqlite.cpp:271
dodo::persist::sqlite::Database::beginImmediateTransaction
void beginImmediateTransaction()
Begin an immediate transaction.
Definition: sqlite.cpp:231
dodo::persist::sqlite::Database
A STL friendly wrapper around the great sqlite3.
Definition: sqlite.hpp:52
dodo::persist::sqlite::Database::database_
sqlite3 * database_
The SQLite database handle.
Definition: sqlite.hpp:204
dodo::persist::sqlite::DDL
Data Definition Language, SQL that takes no parameters, returns no data such as CREATE TABLE.
Definition: sqlite.hpp:261
dodo::persist::sqlite::Query::getDouble
double getDouble(int col) const
Get double value from select list.
Definition: sqlite.cpp:500
dodo::persist::sqlite::Query::dtText
@ dtText
(3) Text type (string)
Definition: sqlite.hpp:396
dodo::persist::sqlite::Database::Database
Database(const std::string &filename, WaitHandler handler=0)
Constructor with explicit wait handler.
Definition: sqlite.cpp:131
dodo::persist::sqlite::DDL::execute
void execute()
execute, throws Oops on error.
Definition: sqlite.cpp:389
dodo::persist::sqlite::DDL::DDL
DDL(const Database &db)
Constructor.
Definition: sqlite.hpp:268
dodo::persist::sqlite::Query::getBytes
void getBytes(int col, common::Bytes &bytes) const
Get Bytes value from select list.
Definition: sqlite.cpp:509
dodo::persist::sqlite::Statement::stmt_
sqlite3_stmt * stmt_
statement handle.
Definition: sqlite.hpp:250
dodo::persist::sqlite::Query::dtBlob
@ dtBlob
(4) Binary data type (Bytes)
Definition: sqlite.hpp:397
dodo::persist::sqlite::Database::checkPointFull
void checkPointFull()
Issue a full checpoint.
Definition: sqlite.cpp:295
dodo::persist::sqlite::Query::getInt
int getInt(int col) const
Get int value from select list.
Definition: sqlite.cpp:492
bytes.hpp
dodo::persist::sqlite::Database::memHighWater
static int64_t memHighWater()
Get memory highwater by the SQLite library.
Definition: sqlite.hpp:154
dodo::persist::sqlite::Database::createSavepoint
void createSavepoint(const std::string &sp)
Create a named savepoint.
Definition: sqlite.cpp:263