11#ifndef OPENSWMM_GPKG_UTILS_HPP
12#define OPENSWMM_GPKG_UTILS_HPP
28 explicit GpkgError(
const std::string& msg) : std::runtime_error(msg) {}
30 : std::runtime_error(msg +
" (sqlite rc=" + std::to_string(rc) +
")") {}
39 if (db) sqlite3_close_v2(db);
42using DbPtr = std::unique_ptr<sqlite3, DbDeleter>;
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);
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);
58 if (sqlite3_exec(db.get(),
"PRAGMA foreign_keys=ON",
nullptr,
nullptr,
60 std::string msg = err ? err :
"unknown error";
62 throw GpkgError(
"Failed to enable foreign_keys pragma on '" + path
73 sqlite3_busy_timeout(db.get(), 5000);
84 if (stmt) sqlite3_finalize(stmt);
87using StmtPtr = std::unique_ptr<sqlite3_stmt, StmtDeleter>;
90 sqlite3_stmt* raw =
nullptr;
91 int rc = sqlite3_prepare_v2(db, sql.c_str(),
static_cast<int>(sql.size()), &raw,
nullptr);
93 if (rc != SQLITE_OK) {
94 throw GpkgError(
"Failed to prepare: " + sql +
" — " + sqlite3_errmsg(db), rc);
103inline void exec(sqlite3* db,
const std::string& sql) {
104 char* errmsg =
nullptr;
105 int rc = sqlite3_exec(db, sql.c_str(),
nullptr,
nullptr, &errmsg);
106 if (rc != SQLITE_OK) {
107 std::string msg = errmsg ? errmsg :
"unknown error";
108 sqlite3_free(errmsg);
109 throw GpkgError(
"exec failed: " + msg +
" — SQL: " + sql, rc);
113inline void bind_text(sqlite3_stmt* stmt,
int col,
const std::string& val) {
114 sqlite3_bind_text(stmt, col, val.c_str(),
static_cast<int>(val.size()), SQLITE_TRANSIENT);
118 sqlite3_bind_double(stmt, col, val);
121inline void bind_int(sqlite3_stmt* stmt,
int col,
int val) {
122 sqlite3_bind_int(stmt, col, val);
126 sqlite3_bind_null(stmt, col);
129inline void bind_blob(sqlite3_stmt* stmt,
int col,
const void* data,
int size) {
130 sqlite3_bind_blob(stmt, col, data, size, SQLITE_TRANSIENT);
134 const unsigned char* txt = sqlite3_column_text(stmt, col);
135 return txt ? std::string(
reinterpret_cast<const char*
>(txt)) : std::string{};
139 return sqlite3_column_double(stmt, col);
143 return sqlite3_column_int(stmt, col);
147 return sqlite3_column_type(stmt, col) == SQLITE_NULL;
150inline std::vector<uint8_t>
column_blob(sqlite3_stmt* stmt,
int col) {
151 int size = sqlite3_column_bytes(stmt, col);
152 const uint8_t* data =
static_cast<const uint8_t*
>(sqlite3_column_blob(stmt, col));
153 if (!data || size <= 0)
return {};
154 return {data, data + size};
182 exec(db_,
"BEGIN IMMEDIATE");
191 if (finished_)
return;
192 for (
int attempt = 0; attempt < 3; ++attempt) {
195 for (sqlite3_stmt* s = sqlite3_next_stmt(db_,
nullptr); s !=
nullptr;
196 s = sqlite3_next_stmt(db_, s)) {
199 sqlite3_exec(db_,
"ROLLBACK",
nullptr,
nullptr,
nullptr);
203 if (sqlite3_get_autocommit(db_) != 0)
break;
214 bool finished_ =
false;
Definition GpkgUtils.hpp:26
GpkgError(const std::string &msg, int rc)
Definition GpkgUtils.hpp:29
GpkgError(const std::string &msg)
Definition GpkgUtils.hpp:28
Transaction(sqlite3 *db)
Definition GpkgUtils.hpp:181
void commit()
Definition GpkgUtils.hpp:184
~Transaction()
Definition GpkgUtils.hpp:207
void rollback()
Definition GpkgUtils.hpp:190
Transaction & operator=(const Transaction &)=delete
Transaction(const Transaction &)=delete
Definition ExternalContentReader.cpp:33
std::unique_ptr< sqlite3_stmt, StmtDeleter > StmtPtr
Definition GpkgUtils.hpp:87
void exec(sqlite3 *db, const std::string &sql)
Definition GpkgUtils.hpp:103
void bind_blob(sqlite3_stmt *stmt, int col, const void *data, int size)
Definition GpkgUtils.hpp:129
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:121
void bind_double(sqlite3_stmt *stmt, int col, double val)
Definition GpkgUtils.hpp:117
StmtPtr prepare(sqlite3 *db, const std::string &sql)
Definition GpkgUtils.hpp:89
std::unique_ptr< sqlite3, DbDeleter > DbPtr
Definition GpkgUtils.hpp:42
void bind_null(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:125
std::string column_text(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:133
int column_int(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:142
bool column_is_null(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:146
void bind_text(sqlite3_stmt *stmt, int col, const std::string &val)
Definition GpkgUtils.hpp:113
double column_double(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:138
std::vector< uint8_t > column_blob(sqlite3_stmt *stmt, int col)
Definition GpkgUtils.hpp:150
Definition GpkgUtils.hpp:37
void operator()(sqlite3 *db) const noexcept
Definition GpkgUtils.hpp:38
Definition GpkgUtils.hpp:82
void operator()(sqlite3_stmt *stmt) const noexcept
Definition GpkgUtils.hpp:83