libdballe 9.13
sqlite.h
Go to the documentation of this file.
1
4#ifndef DBALLE_SQL_SQLITE_H
5#define DBALLE_SQL_SQLITE_H
6
7#include <dballe/core/error.h>
8#include <dballe/sql/sql.h>
9#include <functional>
10#include <sqlite3.h>
11#include <vector>
12
13namespace dballe {
14namespace sql {
15struct SQLiteStatement;
16
20struct error_sqlite : public dballe::error_db
21{
22 std::string msg;
23
24 error_sqlite(sqlite3* db, const std::string& msg);
25 error_sqlite(const std::string& dbmsg, const std::string& msg);
26 ~error_sqlite() noexcept {}
27
28 const char* what() const noexcept override { return msg.c_str(); }
29
30 static void throwf(sqlite3* db, const char* fmt, ...)
32};
33
35class SQLiteConnection : public Connection
36{
37protected:
39 std::string pathname;
41 int flags = 0;
43 sqlite3* db = nullptr;
45 bool forked = false;
46
47 void init_after_connect();
48 static void on_sqlite3_profile(void* arg, const char* query,
49 sqlite3_uint64 usecs);
50
51 SQLiteConnection();
52
53 void fork_prepare() override;
54 void fork_parent() override;
55 void fork_child() override;
56
57 void check_connection();
58
59 void reopen();
60
61public:
62 SQLiteConnection(const SQLiteConnection&) = delete;
63 SQLiteConnection(const SQLiteConnection&&) = delete;
64 ~SQLiteConnection();
65
66 static std::shared_ptr<SQLiteConnection> create();
67
68 SQLiteConnection& operator=(const SQLiteConnection&) = delete;
69
70 operator sqlite3*() { return db; }
71
72 void open_file(const std::string& pathname,
73 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
74 void open_memory(int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
75 void open_private_file(int flags = SQLITE_OPEN_READWRITE |
76 SQLITE_OPEN_CREATE);
77
78 std::unique_ptr<Transaction> transaction(bool readonly = false) override;
79 std::unique_ptr<SQLiteStatement> sqlitestatement(const std::string& query);
80
81 bool has_table(const std::string& name) override;
82 std::string get_setting(const std::string& key) override;
83 void set_setting(const std::string& key, const std::string& value) override;
84 void drop_settings() override;
85 void execute(const std::string& query) override;
86 void explain(const std::string& query, FILE* out) override;
87
91 void drop_table_if_exists(const char* name);
92
100
102 int changes();
103
105 void exec(const std::string& query);
106 void exec_nothrow(const std::string& query) noexcept;
107
108#if SQLITE_VERSION_NUMBER >= 3014000
114 void trace(unsigned mask = SQLITE_TRACE_STMT);
115#endif
116};
117
119struct SQLiteStatement
120{
121 SQLiteConnection& conn;
122 std::string query;
123 sqlite3_stmt* stm = nullptr;
124
125 SQLiteStatement(SQLiteConnection& conn, const std::string& query);
126 SQLiteStatement(const SQLiteStatement&) = delete;
127 SQLiteStatement(const SQLiteStatement&&) = delete;
128 ~SQLiteStatement();
129 SQLiteStatement& operator=(const SQLiteStatement&) = delete;
130
138 template <typename... Args> void bind(const Args&... args)
139 {
140 bindn<sizeof...(args)>(args...);
141 }
142
143 void bind_null_val(int idx);
144 void bind_val(int idx, int val);
145 void bind_val(int idx, unsigned val);
146 void bind_val(int idx, unsigned short val);
147 void bind_val(int idx, const Datetime& val);
148 void bind_val(int idx, const char* val); // Warning: SQLITE_STATIC is used
149 void bind_val(int idx,
150 const std::string& val); // Warning: SQLITE_STATIC is used
151 void
152 bind_val(int idx,
153 const std::vector<uint8_t>& val); // Warning: SQLITE_STATIC is used
154
156 void execute();
157
164 void execute(std::function<void()> on_row);
165
170 void execute_one(std::function<void()> on_row);
171
173 int column_int(int col) { return sqlite3_column_int(stm, col); }
174
176 sqlite3_int64 column_int64(int col)
177 {
178 return sqlite3_column_int64(stm, col);
179 }
180
182 double column_double(int col) { return sqlite3_column_double(stm, col); }
183
185 const char* column_string(int col)
186 {
187 return (const char*)sqlite3_column_text(stm, col);
188 }
189
191 std::vector<uint8_t> column_blob(int col)
192 {
193 int size = sqlite3_column_bytes(stm, col);
194 const uint8_t* val = (const uint8_t*)sqlite3_column_blob(stm, col);
195 return std::vector<uint8_t>(val, val + size);
196 }
197
200
202 bool column_isnull(int col)
203 {
204 return sqlite3_column_type(stm, col) == SQLITE_NULL;
205 }
206
207 void wrap_sqlite3_reset();
208 void wrap_sqlite3_reset_nothrow() noexcept;
213 [[noreturn]] void reset_and_throw(const std::string& errmsg);
214
215 operator sqlite3_stmt*() { return stm; }
216#if 0
218 int execute();
220 int exec_direct(const char* query);
222 int exec_direct(const char* query, int qlen);
223
225 int execute_and_close();
227 int exec_direct_and_close(const char* query);
229 int exec_direct_and_close(const char* query, int qlen);
230
235 int columns_count();
236 bool fetch();
237 bool fetch_expecting_one();
238 void close_cursor();
239 void close_cursor_if_needed();
241 size_t select_rowcount();
243 size_t rowcount();
244#endif
245
246private:
247 // Implementation of variadic bind: terminating condition
248 template <size_t total> void bindn() {}
249 // Implementation of variadic bind: recursive iteration over the parameter
250 // pack
251 template <size_t total, typename... Args, typename T>
252 void bindn(const T& first, const Args&... args)
253 {
254 bind_val(total - sizeof...(args), first);
255 bindn<total>(args...);
256 }
257};
258
259} // namespace sql
260} // namespace dballe
261#endif
Database connection.
Definition sqlite.h:36
void explain(const std::string &query, FILE *out) override
Format and print the EXPLAIN output for the query to the given file.
std::string get_setting(const std::string &key) override
Get a value from the settings table.
std::string pathname
Connection pathname.
Definition sqlite.h:39
int changes()
Count the number of rows modified by the last query that was run.
bool forked
Marker to catch attempts to reuse connections in forked processes.
Definition sqlite.h:45
sqlite3 * db
Database connection.
Definition sqlite.h:43
void drop_settings() override
Drop the settings table.
int get_last_insert_id()
Return LAST_INSERT_ID or LAST_INSER_ROWID or whatever is appropriate for the current database,...
bool has_table(const std::string &name) override
Check if the database contains a table.
void execute(const std::string &query) override
Execute a query without reading its results.
void set_setting(const std::string &key, const std::string &value) override
Set a value in the settings table.
std::unique_ptr< Transaction > transaction(bool readonly=false) override
Begin a transaction.
void exec(const std::string &query)
Wrap sqlite3_exec, without a callback.
void drop_table_if_exists(const char *name)
Delete a table in the database if it exists, otherwise do nothing.
int flags
Connection flags.
Definition sqlite.h:41
#define WREPORT_THROWF_ATTRS(a, b)
Common infrastructure for talking with SQL databases.
Date and time.
Definition types.h:164
Error in case of failed database operations.
Definition error.h:22
SQLite statement.
Definition sqlite.h:120
sqlite3_int64 column_int64(int col)
Read the int value of a column in the result set (0-based)
Definition sqlite.h:176
void reset_and_throw(const std::string &errmsg)
Get the current error message, reset the statement and throw error_sqlite.
void execute()
Run the query, ignoring all results.
const char * column_string(int col)
Read the string value of a column in the result set (0-based)
Definition sqlite.h:185
std::vector< uint8_t > column_blob(int col)
Read the string value of a column in the result set (0-based)
Definition sqlite.h:191
void execute(std::function< void()> on_row)
Run the query, calling on_row for every row in the result.
int column_int(int col)
Read the int value of a column in the result set (0-based)
Definition sqlite.h:173
double column_double(int col)
Read the double value of a column in the result set (0-based)
Definition sqlite.h:182
Datetime column_datetime(int col)
Read the string value of a column and parse it as a Datetime.
void bind(const Args &... args)
Bind all the arguments in a single invocation.
Definition sqlite.h:138
void execute_one(std::function< void()> on_row)
Run the query, raising an error if there is more than one row in the result.
bool column_isnull(int col)
Check if a column has a NULL value (0-based)
Definition sqlite.h:202