boat
C++23 geospatial library
Loading...
Searching...
No Matches
command.hpp
Go to the documentation of this file.
1// Andrew Naplavkov
2
3#ifndef BOAT_SQL_SQLITE_COMMAND_HPP
4#define BOAT_SQL_SQLITE_COMMAND_HPP
5
6#include <boat/db/command.hpp>
7#include <boat/sql/sqlite/detail/utility.hpp>
8#include <filesystem>
9
11
12class command : public db::command {
13 unique_ptr<sqlite3, sqlite3_close_v2> dbc_;
14 unique_ptr<void, spatialite_cleanup_ex> spatial_;
15
16public:
17 explicit command(char const* file)
18 {
19 constexpr int flags =
20 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
21 auto exists = std::filesystem::exists(file);
22 sqlite3* dbc;
23 check(sqlite3_open_v2(file, &dbc, flags, 0), dbc_);
24 dbc_.reset(dbc);
25 spatial_.reset(spatialite_alloc_connection());
26 spatialite_init_ex(dbc_.get(), spatial_.get(), 0);
27 if (!exists)
28 try {
29 exec("SELECT InitSpatialMetaData(1)");
30 }
31 catch (std::exception const&) {
32 }
33 }
34
35 db::rowset exec(db::query const& qry, std::stop_token tok = {}) override
36 {
37 auto stop =
38 std::stop_callback{tok, [&] { sqlite3_interrupt(dbc_.get()); }};
39 auto ret = db::rowset{};
40 auto const txt = qry.text(id_quote(), param_mark());
41 auto first = txt.data();
42 auto last = first + txt.size();
43 auto ps = qry.params();
44 auto it = ps.begin();
45 while (first != last) {
46 sqlite3_stmt* stmt{};
47 check(sqlite3_prepare_v2(
48 dbc_.get(), first, int(last - first), &stmt, &first),
49 dbc_);
50 if (!stmt)
51 continue;
52 ret = {};
53 auto _ = unique_ptr<sqlite3_stmt, sqlite3_finalize>{stmt};
54 int params = sqlite3_bind_parameter_count(stmt);
55 for (int i{}; i < params && it != ps.end(); ++i, ++it)
56 check(bind_value(stmt, i + 1, *it), dbc_);
57 int cols = sqlite3_column_count(stmt);
58 ret.columns.resize(cols);
59 for (int i{}; i < cols; ++i)
60 ret.columns[i] = sqlite3_column_name(stmt, i);
61 int ec = sqlite3_step(stmt);
62 for (; SQLITE_DONE != ec; ec = sqlite3_step(stmt)) {
63 check(ec, dbc_);
64 auto& row = ret.rows.emplace_back(cols);
65 for (int i{}; i < cols; ++i)
66 row[i] = column_value(stmt, i);
67 }
68 }
69 return ret;
70 }
71
72 void set_autocommit(bool on) override { exec(on ? "rollback;" : "begin;"); }
73 void commit() override { exec("commit;begin;"); }
74 char id_quote() override { return '"'; }
75 std::string param_mark() override { return "?"; }
76 std::string dbms() override { return "sqlite"; }
77};
78
79} // namespace boat::sql::sqlite
80
81#endif // BOAT_SQL_SQLITE_COMMAND_HPP
Definition query.hpp:20
std::string text(char id_quote, std::string_view param_mark) const
Definition query.hpp:47
std::generator< std::reference_wrapper< variant const > > params() const
Definition query.hpp:73
void set_autocommit(bool on) override
Definition command.hpp:72
command(char const *file)
Definition command.hpp:17
void commit() override
Definition command.hpp:73
std::string param_mark() override
"{}" in the result is replaced with the parameter number.
Definition command.hpp:75
std::string dbms() override
The result is lower-case.
Definition command.hpp:76
char id_quote() override
Definition command.hpp:74
db::rowset exec(db::query const &qry, std::stop_token tok={}) override
Definition command.hpp:35
Definition command.hpp:10
Definition command.hpp:12
Definition rowset.hpp:12