OpenSWMM Engine  6.0.0-alpha.1
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.1)
Loading...
Searching...
No Matches
GpkgUtils.hpp
Go to the documentation of this file.
1
11#ifndef OPENSWMM_GPKG_UTILS_HPP
12#define OPENSWMM_GPKG_UTILS_HPP
13
14#include <sqlite3.h>
15#include <string>
16#include <stdexcept>
17#include <memory>
18#include <vector>
19
20namespace openswmm::gpkg {
21
22// ============================================================================
23// Exception
24// ============================================================================
25
26class GpkgError : public std::runtime_error {
27public:
28 explicit GpkgError(const std::string& msg) : std::runtime_error(msg) {}
29 GpkgError(const std::string& msg, int rc)
30 : std::runtime_error(msg + " (sqlite rc=" + std::to_string(rc) + ")") {}
31};
32
33// ============================================================================
34// RAII: Database handle
35// ============================================================================
36
37struct DbDeleter {
38 void operator()(sqlite3* db) const noexcept {
39 if (db) sqlite3_close_v2(db);
40 }
41};
42using DbPtr = std::unique_ptr<sqlite3, DbDeleter>;
43
44inline DbPtr open_database(const std::string& path, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) {
45 sqlite3* raw = nullptr;
46 int rc = sqlite3_open_v2(path.c_str(), &raw, flags, nullptr);
47 DbPtr db(raw);
48 if (rc != SQLITE_OK) {
49 std::string msg = raw ? sqlite3_errmsg(raw) : "unknown error";
50 throw GpkgError("Failed to open database '" + path + "': " + msg, rc);
51 }
52 return db;
53}
54
55// ============================================================================
56// RAII: Prepared statement
57// ============================================================================
58
60 void operator()(sqlite3_stmt* stmt) const noexcept {
61 if (stmt) sqlite3_finalize(stmt);
62 }
63};
64using StmtPtr = std::unique_ptr<sqlite3_stmt, StmtDeleter>;
65
66inline StmtPtr prepare(sqlite3* db, const std::string& sql) {
67 sqlite3_stmt* raw = nullptr;
68 int rc = sqlite3_prepare_v2(db, sql.c_str(), static_cast<int>(sql.size()), &raw, nullptr);
69 StmtPtr stmt(raw);
70 if (rc != SQLITE_OK) {
71 throw GpkgError("Failed to prepare: " + sql + " — " + sqlite3_errmsg(db), rc);
72 }
73 return stmt;
74}
75
76// ============================================================================
77// Helpers
78// ============================================================================
79
80inline void exec(sqlite3* db, const std::string& sql) {
81 char* errmsg = nullptr;
82 int rc = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errmsg);
83 if (rc != SQLITE_OK) {
84 std::string msg = errmsg ? errmsg : "unknown error";
85 sqlite3_free(errmsg);
86 throw GpkgError("exec failed: " + msg + " — SQL: " + sql, rc);
87 }
88}
89
90inline void bind_text(sqlite3_stmt* stmt, int col, const std::string& val) {
91 sqlite3_bind_text(stmt, col, val.c_str(), static_cast<int>(val.size()), SQLITE_TRANSIENT);
92}
93
94inline void bind_double(sqlite3_stmt* stmt, int col, double val) {
95 sqlite3_bind_double(stmt, col, val);
96}
97
98inline void bind_int(sqlite3_stmt* stmt, int col, int val) {
99 sqlite3_bind_int(stmt, col, val);
100}
101
102inline void bind_null(sqlite3_stmt* stmt, int col) {
103 sqlite3_bind_null(stmt, col);
104}
105
106inline void bind_blob(sqlite3_stmt* stmt, int col, const void* data, int size) {
107 sqlite3_bind_blob(stmt, col, data, size, SQLITE_TRANSIENT);
108}
109
110inline std::string column_text(sqlite3_stmt* stmt, int col) {
111 const unsigned char* txt = sqlite3_column_text(stmt, col);
112 return txt ? std::string(reinterpret_cast<const char*>(txt)) : std::string{};
113}
114
115inline double column_double(sqlite3_stmt* stmt, int col) {
116 return sqlite3_column_double(stmt, col);
117}
118
119inline int column_int(sqlite3_stmt* stmt, int col) {
120 return sqlite3_column_int(stmt, col);
121}
122
123inline bool column_is_null(sqlite3_stmt* stmt, int col) {
124 return sqlite3_column_type(stmt, col) == SQLITE_NULL;
125}
126
127inline std::vector<uint8_t> column_blob(sqlite3_stmt* stmt, int col) {
128 int size = sqlite3_column_bytes(stmt, col);
129 const uint8_t* data = static_cast<const uint8_t*>(sqlite3_column_blob(stmt, col));
130 if (!data || size <= 0) return {};
131 return {data, data + size};
132}
133
134// RAII transaction guard
136public:
137 explicit Transaction(sqlite3* db) : db_(db) {
138 exec(db_, "BEGIN IMMEDIATE");
139 }
140 void commit() {
141 if (!committed_) {
142 exec(db_, "COMMIT");
143 committed_ = true;
144 }
145 }
147 if (!committed_) {
148 sqlite3_exec(db_, "ROLLBACK", nullptr, nullptr, nullptr);
149 }
150 }
151 Transaction(const Transaction&) = delete;
153private:
154 sqlite3* db_;
155 bool committed_ = false;
156};
157
158} // namespace openswmm::gpkg
159
160#endif // OPENSWMM_GPKG_UTILS_HPP
int size
Definition XSectBatch.cpp:567
const double * data
Definition XSectBatch.cpp:567
Definition GpkgUtils.hpp:26
GpkgError(const std::string &msg, int rc)
Definition GpkgUtils.hpp:29
GpkgError(const std::string &msg)
Definition GpkgUtils.hpp:28
Definition GpkgUtils.hpp:135
Transaction(sqlite3 *db)
Definition GpkgUtils.hpp:137
void commit()
Definition GpkgUtils.hpp:140
~Transaction()
Definition GpkgUtils.hpp:146
Transaction & operator=(const Transaction &)=delete
Transaction(const Transaction &)=delete
Definition GeoPackageInputPlugin.cpp:15
std::unique_ptr< sqlite3_stmt, StmtDeleter > StmtPtr
Definition GpkgUtils.hpp:64
void exec(sqlite3 *db, const std::string &sql)
Definition GpkgUtils.hpp:80
void bind_blob(sqlite3_stmt *stmt, int col, const void *data, int size)
Definition GpkgUtils.hpp:106
DbPtr open_database(const std::string &path, int flags=SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE)
Definition GpkgUtils.hpp:44
void bind_int(sqlite3_stmt *stmt, int col, int val)
Definition GpkgUtils.hpp:98
void bind_double(sqlite3_stmt *stmt, int col, double val)
Definition GpkgUtils.hpp:94
StmtPtr prepare(sqlite3 *db, const std::string &sql)
Definition GpkgUtils.hpp:66
void bind_null(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:102
std::string column_text(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:110
int column_int(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:119
bool column_is_null(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:123
std::unique_ptr< sqlite3, DbDeleter > DbPtr
Definition GpkgUtils.hpp:42
void bind_text(sqlite3_stmt *stmt, int col, const std::string &val)
Definition GpkgUtils.hpp:90
double column_double(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:115
std::vector< uint8_t > column_blob(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:127
Definition GpkgUtils.hpp:37
void operator()(sqlite3 *db) const noexcept
Definition GpkgUtils.hpp:38
Definition GpkgUtils.hpp:59
void operator()(sqlite3_stmt *stmt) const noexcept
Definition GpkgUtils.hpp:60