27#ifndef OPENSWMM_GPKG_UTILS_HPP
28#define OPENSWMM_GPKG_UTILS_HPP
44 explicit GpkgError(
const std::string& msg) : std::runtime_error(msg) {}
46 : std::runtime_error(msg +
" (sqlite rc=" + std::to_string(rc) +
")") {}
55 if (db) sqlite3_close_v2(db);
58using DbPtr = std::unique_ptr<sqlite3, DbDeleter>;
60inline DbPtr open_database(
const std::string& path,
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) {
61 sqlite3* raw =
nullptr;
62 int rc = sqlite3_open_v2(path.c_str(), &raw, flags,
nullptr);
64 if (rc != SQLITE_OK) {
65 std::string msg = raw ? sqlite3_errmsg(raw) :
"unknown error";
66 throw GpkgError(
"Failed to open database '" + path +
"': " + msg, rc);
74 if (sqlite3_exec(db.get(),
"PRAGMA foreign_keys=ON",
nullptr,
nullptr,
76 std::string msg = err ? err :
"unknown error";
78 throw GpkgError(
"Failed to enable foreign_keys pragma on '" + path
89 sqlite3_busy_timeout(db.get(), 5000);
100 if (stmt) sqlite3_finalize(stmt);
103using StmtPtr = std::unique_ptr<sqlite3_stmt, StmtDeleter>;
106 sqlite3_stmt* raw =
nullptr;
107 int rc = sqlite3_prepare_v2(db, sql.c_str(),
static_cast<int>(sql.size()), &raw,
nullptr);
109 if (rc != SQLITE_OK) {
110 throw GpkgError(
"Failed to prepare: " + sql +
" — " + sqlite3_errmsg(db), rc);
119inline void exec(sqlite3* db,
const std::string& sql) {
120 char* errmsg =
nullptr;
121 int rc = sqlite3_exec(db, sql.c_str(),
nullptr,
nullptr, &errmsg);
122 if (rc != SQLITE_OK) {
123 std::string msg = errmsg ? errmsg :
"unknown error";
124 sqlite3_free(errmsg);
125 throw GpkgError(
"exec failed: " + msg +
" — SQL: " + sql, rc);
129inline void bind_text(sqlite3_stmt* stmt,
int col,
const std::string& val) {
130 sqlite3_bind_text(stmt, col, val.c_str(),
static_cast<int>(val.size()), SQLITE_TRANSIENT);
134 sqlite3_bind_double(stmt, col, val);
137inline void bind_int(sqlite3_stmt* stmt,
int col,
int val) {
138 sqlite3_bind_int(stmt, col, val);
142 sqlite3_bind_null(stmt, col);
145inline void bind_blob(sqlite3_stmt* stmt,
int col,
const void* data,
int size) {
146 sqlite3_bind_blob(stmt, col, data, size, SQLITE_TRANSIENT);
150 const unsigned char* txt = sqlite3_column_text(stmt, col);
151 return txt ? std::string(
reinterpret_cast<const char*
>(txt)) : std::string{};
155 return sqlite3_column_double(stmt, col);
159 return sqlite3_column_int(stmt, col);
163 return sqlite3_column_type(stmt, col) == SQLITE_NULL;
166inline std::vector<uint8_t>
column_blob(sqlite3_stmt* stmt,
int col) {
167 int size = sqlite3_column_bytes(stmt, col);
168 const uint8_t* data =
static_cast<const uint8_t*
>(sqlite3_column_blob(stmt, col));
169 if (!data || size <= 0)
return {};
170 return {data, data + size};
198 exec(db_,
"BEGIN IMMEDIATE");
207 if (finished_)
return;
208 for (
int attempt = 0; attempt < 3; ++attempt) {
211 for (sqlite3_stmt* s = sqlite3_next_stmt(db_,
nullptr); s !=
nullptr;
212 s = sqlite3_next_stmt(db_, s)) {
215 sqlite3_exec(db_,
"ROLLBACK",
nullptr,
nullptr,
nullptr);
219 if (sqlite3_get_autocommit(db_) != 0)
break;
230 bool finished_ =
false;
Definition GpkgUtils.hpp:42
GpkgError(const std::string &msg, int rc)
Definition GpkgUtils.hpp:45
GpkgError(const std::string &msg)
Definition GpkgUtils.hpp:44
Transaction(sqlite3 *db)
Definition GpkgUtils.hpp:197
void commit()
Definition GpkgUtils.hpp:200
~Transaction()
Definition GpkgUtils.hpp:223
void rollback()
Definition GpkgUtils.hpp:206
Transaction & operator=(const Transaction &)=delete
Transaction(const Transaction &)=delete
Definition ExternalContentReader.cpp:49
std::unique_ptr< sqlite3_stmt, StmtDeleter > StmtPtr
Definition GpkgUtils.hpp:103
void exec(sqlite3 *db, const std::string &sql)
Definition GpkgUtils.hpp:119
void bind_blob(sqlite3_stmt *stmt, int col, const void *data, int size)
Definition GpkgUtils.hpp:145
DbPtr open_database(const std::string &path, int flags=SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE)
Definition GpkgUtils.hpp:60
void bind_int(sqlite3_stmt *stmt, int col, int val)
Definition GpkgUtils.hpp:137
void bind_double(sqlite3_stmt *stmt, int col, double val)
Definition GpkgUtils.hpp:133
StmtPtr prepare(sqlite3 *db, const std::string &sql)
Definition GpkgUtils.hpp:105
std::unique_ptr< sqlite3, DbDeleter > DbPtr
Definition GpkgUtils.hpp:58
void bind_null(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:141
std::string column_text(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:149
int column_int(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:158
bool column_is_null(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:162
void bind_text(sqlite3_stmt *stmt, int col, const std::string &val)
Definition GpkgUtils.hpp:129
double column_double(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:154
std::vector< uint8_t > column_blob(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:166
Definition GpkgUtils.hpp:53
void operator()(sqlite3 *db) const noexcept
Definition GpkgUtils.hpp:54
Definition GpkgUtils.hpp:98
void operator()(sqlite3_stmt *stmt) const noexcept
Definition GpkgUtils.hpp:99