SlHelpers
Loading...
Searching...
No Matches
SQLConn.h
1// SPDX-License-Identifier: GPL-2.0-only
2
3#pragma once
4
5#include <filesystem>
6#include <optional>
7#include <string>
8#include <variant>
9#include <vector>
10
11#include "../helpers/Enum.h"
12#include "../helpers/LastError.h"
13#include "SQLiteSmart.h"
14
15namespace SlSqlite {
16
20enum class OpenFlags : unsigned {
21 NONE = 0,
22 CREATE = 1 << 0,
23 NO_FOREIGN_KEY = 1 << 1,
24 ERROR_ON_UNIQUE_CONSTRAINT = 1 << 2,
25 READ_ONLY = 1 << 3,
26};
27
28} // namespace
29
30ENABLE_BITMASK_OPERATORS(SlSqlite::OpenFlags);
31
32namespace SlSqlite {
33
37enum struct TransactionType {
38 DEFERRED,
39 IMMEDIATE,
40 EXCLUSIVE,
41};
42
43class Select;
44class SQLConn;
45
49class AutoTransaction {
50public:
51 AutoTransaction() = delete;
53 AutoTransaction(const SQLConn &conn,
54 TransactionType type = TransactionType::DEFERRED);
55 ~AutoTransaction() { end(); }
56
57 AutoTransaction(const AutoTransaction &) = delete;
58 AutoTransaction &operator=(const AutoTransaction &) = delete;
59
61 AutoTransaction(AutoTransaction &&other) noexcept : m_conn(other.m_conn) {
62 other.m_conn = nullptr;
63 }
64
65 AutoTransaction &operator=(AutoTransaction &&other) noexcept {
66 if (this != &other) {
67 end();
68 m_conn = other.m_conn;
69 other.m_conn = nullptr;
70 }
71
72 return *this;
73 }
74
76 void end();
77
79 bool operator!() const { return !m_conn; }
81 operator bool() const { return m_conn; }
82private:
83 const SQLConn *m_conn;
84};
85
89class SQLConn {
90 friend class Select;
91public:
92 virtual ~SQLConn() = default;
93
95 SQLConn(SQLConn &&) = default;
97 SQLConn &operator=(SQLConn &&) = default;
98
105 bool open(const std::filesystem::path &dbFile, OpenFlags flags = OpenFlags::NONE)
106 {
107 return openDB(dbFile, flags) && createDB() && prepDB();
108 }
109
116 bool openDB(const std::filesystem::path &dbFile,
117 OpenFlags flags = OpenFlags::NONE) noexcept;
118
125 virtual bool createDB() { return true; }
126
133 virtual bool prepDB() { return true; }
134
140 bool exec(const std::string &sql) const noexcept { return exec(sql, "exec failed"); }
141
148 bool attach(const std::filesystem::path &dbFile,
149 std::string_view dbName) const noexcept;
150
156 bool begin(TransactionType type = TransactionType::DEFERRED) const noexcept;
157
162 bool end() const noexcept { return exec("END;", "db END failed"); }
163
169 AutoTransaction beginAuto(TransactionType type = TransactionType::DEFERRED) const noexcept {
170 return AutoTransaction(*this, type);
171 }
172
174 std::string lastError() const { return m_lastError.lastError(); }
176 int lastErrorCode() const { return m_lastError.get<0>(); }
178 int lastErrorCodeExt() const { return m_lastError.get<1>(); }
179
180protected:
181 SQLConn() : m_flags(OpenFlags::NONE) {}
182
184 using BindVal = std::variant<std::monostate, int, unsigned, std::string, std::string_view>;
186 using Binding = std::vector<std::pair<std::string, BindVal>>;
188 using Column = std::variant<std::monostate, int, std::string>;
190 using Row = std::vector<Column>;
192 using SelectResult = std::vector<Row>;
193
195 enum TableFlags : unsigned {
196 TABLE_TEMPORARY = 1u << 0,
197 };
198
200 struct TableEntry {
202 std::string name;
204 std::vector<std::string> columns;
206 unsigned flags = 0u;
207 };
208
210 using Tables = std::vector<TableEntry>;
212 using Indices = std::vector<std::pair<std::string, std::string>>;
216 using Views = Indices;
218 using Statements = std::vector<std::pair<std::reference_wrapper<SQLStmtHolder>, std::string>>;
219
221 bool createTables(const Tables &tables) const noexcept;
223 bool createIndices(const Indices &indices) const noexcept;
225 bool createTriggers(const Triggers &triggers) const noexcept;
227 bool createViews(const Views &views) const noexcept;
228
230 bool prepareStatement(std::string_view sql, SQLStmtHolder &stmt) const noexcept;
232 bool prepareStatements(const Statements &stmts) const noexcept;
233
235 bool bind(const SQLStmtHolder &ins, const std::string &key,
236 const BindVal &val, bool transient = false) const noexcept;
238 bool bind(const SQLStmtHolder &ins, const Binding &binding,
239 bool transient = false) const noexcept;
241 bool step(const SQLStmtHolder &ins, uint64_t *affected = nullptr,
242 bool *uniqueError = nullptr) const noexcept;
244 bool insert(const SQLStmtHolder &ins, const Binding &binding = {},
245 uint64_t *affected = nullptr) const noexcept;
246
248 std::optional<SQLConn::SelectResult>
249 select(const SQLStmtHolder &sel, const Binding &binding) const noexcept;
250
252 static BindVal valueOrNull(bool cond, BindVal val) {
253 return cond ? std::move(val) : std::monostate();
254 }
255
258
260 LastError &setError(int ret, std::string_view error, bool errmsg = false) const;
261
263 SQLHolder sqlHolder;
265 OpenFlags m_flags;
268private:
269 bool exec(const std::string &SQL, std::string_view errorMsg,
270 bool includeSQL = false) const noexcept;
271
272 static constexpr bool isUniqueConstraint(int sqlExtError) noexcept;
273 static int busyHandler(void *, int count);
274 void dumpBinding(const Binding &binding) const noexcept;
275};
276
277inline AutoTransaction::AutoTransaction(const SQLConn &conn, TransactionType type)
278 : m_conn(conn.begin(type) ? &conn : nullptr)
279{
280}
281
283{
284 if (m_conn) {
285 m_conn->end();
286 m_conn = nullptr;
287 }
288}
289
290}
Stores a string (usually an error string) to be retrieved later.
Definition LastError.h:87
Begin a transaction in the constructor and end in the destructor.
Definition SQLConn.h:49
void end()
End the transaction manually.
Definition SQLConn.h:282
AutoTransaction & operator=(AutoTransaction &&other) noexcept
Move assignment.
Definition SQLConn.h:65
bool operator!() const
Test whether AutoTransaction is valid.
Definition SQLConn.h:79
AutoTransaction(AutoTransaction &&other) noexcept
Move constructor.
Definition SQLConn.h:61
SQLite3 connection (the core class).
Definition SQLConn.h:89
bool prepareStatement(std::string_view sql, SQLStmtHolder &stmt) const noexcept
Prepate one sql string into stmt.
std::variant< std::monostate, int, unsigned, std::string, std::string_view > BindVal
Bind value (SQL's null, number, string).
Definition SQLConn.h:184
std::variant< std::monostate, int, std::string > Column
One column returned by SELECT.
Definition SQLConn.h:188
SQLHolder sqlHolder
The DB connection.
Definition SQLConn.h:263
virtual bool createDB()
Creates tables, views, triggers and such.
Definition SQLConn.h:125
bool insert(const SQLStmtHolder &ins, const Binding &binding={}, uint64_t *affected=nullptr) const noexcept
Bind, step, and reset the statement ins, using the passed binding.
LastError & setError(int ret, std::string_view error, bool errmsg=false) const
Set last error to ret and error.
bool step(const SQLStmtHolder &ins, uint64_t *affected=nullptr, bool *uniqueError=nullptr) const noexcept
Do one step of the statement ins.
bool createIndices(const Indices &indices) const noexcept
Create indices in the DB as specified in indices.
std::vector< Column > Row
One row returned by SELECT (ie. list of Columns).
Definition SQLConn.h:190
bool createTables(const Tables &tables) const noexcept
Create tables in the DB as specified in tables.
AutoTransaction beginAuto(TransactionType type=TransactionType::DEFERRED) const noexcept
Begin a transaction which is automatically ended when the returned object dies.
Definition SQLConn.h:169
bool attach(const std::filesystem::path &dbFile, std::string_view dbName) const noexcept
Attach another database using ATTACH.
int lastErrorCode() const
Return the last error number.
Definition SQLConn.h:176
SQLConn & operator=(SQLConn &&)=default
Move assignment.
SQLConn(SQLConn &&)=default
Move constructor.
OpenFlags m_flags
OpenFlags.
Definition SQLConn.h:265
bool openDB(const std::filesystem::path &dbFile, OpenFlags flags=OpenFlags::NONE) noexcept
Just open a database file.
bool open(const std::filesystem::path &dbFile, OpenFlags flags=OpenFlags::NONE)
Open a database connection (openDB() + createDB() + prepDB()).
Definition SQLConn.h:105
std::optional< SQLConn::SelectResult > select(const SQLStmtHolder &sel, const Binding &binding) const noexcept
Perform one SELECT (sel), using the passed binding.
int lastErrorCodeExt() const
Return the last extended error number.
Definition SQLConn.h:178
bool createViews(const Views &views) const noexcept
Create views in the DB as specified in views.
bool begin(TransactionType type=TransactionType::DEFERRED) const noexcept
Begin a transaction.
virtual bool prepDB()
Prepares statements.
Definition SQLConn.h:133
std::vector< Row > SelectResult
Complete SELECT result.
Definition SQLConn.h:192
std::vector< std::pair< std::string, std::string > > Indices
Indices to be created by createIndices().
Definition SQLConn.h:212
bool exec(const std::string &sql) const noexcept
Execute sql.
Definition SQLConn.h:140
SlHelpers::LastErrorStream< int, int > LastError
Store a string + 2 ints.
Definition SQLConn.h:257
bool bind(const SQLStmtHolder &ins, const std::string &key, const BindVal &val, bool transient=false) const noexcept
Bind one value val into key of the statement ins.
std::string lastError() const
Return the last error string if some.
Definition SQLConn.h:174
std::vector< TableEntry > Tables
Tables to be created by createTables().
Definition SQLConn.h:210
bool createTriggers(const Triggers &triggers) const noexcept
Create triggers in the DB as specified in triggers.
bool prepareStatements(const Statements &stmts) const noexcept
Prepate all statements as specified in stmts.
static BindVal valueOrNull(bool cond, BindVal val)
A helper to build a null BindVal if cond does not hold, val otherwise.
Definition SQLConn.h:252
Indices Triggers
Triggers to be created by createTriggers().
Definition SQLConn.h:214
Indices Views
Views to be created by createViews().
Definition SQLConn.h:216
TableFlags
Flags for TableEntry::flags.
Definition SQLConn.h:195
std::vector< std::pair< std::string, BindVal > > Binding
Bind name -> bind value.
Definition SQLConn.h:186
bool end() const noexcept
End a transaction.
Definition SQLConn.h:162
std::vector< std::pair< std::reference_wrapper< SQLStmtHolder >, std::string > > Statements
Statements to be prepared by prepareStatements().
Definition SQLConn.h:218
LastError m_lastError
The last error + error code + extended error code.
Definition SQLConn.h:267
A table to be created by createTables().
Definition SQLConn.h:200
unsigned flags
See TableFlags.
Definition SQLConn.h:206
std::string name
Name of the table.
Definition SQLConn.h:202
std::vector< std::string > columns
List of columns.
Definition SQLConn.h:204