27#ifndef OPENSWMM_GPKG_UTILS_HPP
28#define OPENSWMM_GPKG_UTILS_HPP
54 explicit GpkgError(
const std::string& msg) : std::runtime_error(msg) {}
62 : std::runtime_error(msg +
" (sqlite rc=" + std::to_string(rc) +
")") {}
87using DbPtr = std::unique_ptr<sqlite3, DbDeleter>;
104 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) {
105 sqlite3* raw =
nullptr;
106 int rc = sqlite3_open_v2(path.c_str(), &raw, flags,
nullptr);
108 if (rc != SQLITE_OK) {
109 std::string msg = raw ? sqlite3_errmsg(raw) :
"unknown error";
110 throw GpkgError(
"Failed to open database '" + path +
"': " + msg, rc);
118 if (sqlite3_exec(db.get(),
"PRAGMA foreign_keys=ON",
nullptr,
nullptr, &err) != SQLITE_OK) {
119 std::string msg = err ? err :
"unknown error";
121 throw GpkgError(
"Failed to enable foreign_keys pragma on '" + path +
"': " + msg, rc);
131 sqlite3_busy_timeout(db.get(), 5000);
153 sqlite3_finalize(stmt);
156using StmtPtr = std::unique_ptr<sqlite3_stmt, StmtDeleter>;
172 sqlite3_stmt* raw =
nullptr;
173 int rc = sqlite3_prepare_v2(db, sql.c_str(),
static_cast<int>(sql.size()), &raw,
nullptr);
175 if (rc != SQLITE_OK) {
176 throw GpkgError(
"Failed to prepare: " + sql +
" — " + sqlite3_errmsg(db), rc);
198inline void exec(sqlite3* db,
const std::string& sql) {
199 char* errmsg =
nullptr;
200 int rc = sqlite3_exec(db, sql.c_str(),
nullptr,
nullptr, &errmsg);
201 if (rc != SQLITE_OK) {
202 std::string msg = errmsg ? errmsg :
"unknown error";
203 sqlite3_free(errmsg);
204 throw GpkgError(
"exec failed: " + msg +
" — SQL: " + sql, rc);
220inline void bind_text(sqlite3_stmt* stmt,
int col,
const std::string& val) {
221 sqlite3_bind_text(stmt, col, val.c_str(),
static_cast<int>(val.size()), SQLITE_TRANSIENT);
234 sqlite3_bind_double(stmt, col, val);
246inline void bind_int(sqlite3_stmt* stmt,
int col,
int val) {
247 sqlite3_bind_int(stmt, col, val);
259 sqlite3_bind_null(stmt, col);
276inline void bind_blob(sqlite3_stmt* stmt,
int col,
const void* data,
int size) {
277 sqlite3_bind_blob(stmt, col, data, size, SQLITE_TRANSIENT);
293 const unsigned char* txt = sqlite3_column_text(stmt, col);
294 return txt ? std::string(
reinterpret_cast<const char*
>(txt)) : std::string{};
307 return sqlite3_column_double(stmt, col);
319 return sqlite3_column_int(stmt, col);
331 return sqlite3_column_type(stmt, col) == SQLITE_NULL;
346inline std::vector<uint8_t>
column_blob(sqlite3_stmt* stmt,
int col) {
347 int size = sqlite3_column_bytes(stmt, col);
348 const uint8_t* data =
static_cast<const uint8_t*
>(sqlite3_column_blob(stmt, col));
349 if (!data || size <= 0)
351 return {data, data + size};
419 for (
int attempt = 0; attempt < 3; ++attempt) {
422 for (sqlite3_stmt* s = sqlite3_next_stmt(db_,
nullptr); s !=
nullptr;
423 s = sqlite3_next_stmt(db_, s)) {
426 sqlite3_exec(db_,
"ROLLBACK",
nullptr,
nullptr,
nullptr);
430 if (sqlite3_get_autocommit(db_) != 0)
453 bool finished_ =
false;
Runtime-error carrier for owned GeoPackage/SQLite diagnostic text.
Definition GpkgUtils.hpp:45
GpkgError(const std::string &msg, int rc)
Own a failure message with a formatted SQLite result code.
Definition GpkgUtils.hpp:61
GpkgError(const std::string &msg)
Own a supplied GeoPackage failure message.
Definition GpkgUtils.hpp:54
Transaction(sqlite3 *db)
Borrow a connection and begin an immediate write transaction.
Definition GpkgUtils.hpp:395
void commit()
Commit an unfinished transaction and mark the guard finished.
Definition GpkgUtils.hpp:402
~Transaction()
Attempt best-effort rollback unless already committed/rolled back.
Definition GpkgUtils.hpp:441
void rollback()
Best-effort reset all live statements and roll back an unfinished transaction.
Definition GpkgUtils.hpp:416
Transaction & operator=(const Transaction &)=delete
Disallow copy replacement of a transaction guard.
Transaction(const Transaction &)=delete
Disallow copying one transaction cleanup responsibility.
Definition ExternalContentReader.cpp:50
std::unique_ptr< sqlite3_stmt, StmtDeleter > StmtPtr
Definition GpkgUtils.hpp:156
void exec(sqlite3 *db, const std::string &sql)
Execute SQL text and discard all returned rows.
Definition GpkgUtils.hpp:198
void bind_blob(sqlite3_stmt *stmt, int col, const void *data, int size)
Bind copied binary bytes, discarding SQLite status.
Definition GpkgUtils.hpp:276
DbPtr open_database(const std::string &path, int flags=SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE)
Open an owned connection and configure GeoPackage connection defaults.
Definition GpkgUtils.hpp:103
void bind_int(sqlite3_stmt *stmt, int col, int val)
Bind an int SQL parameter, discarding SQLite status.
Definition GpkgUtils.hpp:246
void bind_double(sqlite3_stmt *stmt, int col, double val)
Bind a floating SQL parameter, discarding SQLite status.
Definition GpkgUtils.hpp:233
StmtPtr prepare(sqlite3 *db, const std::string &sql)
Prepare the first SQL statement without stepping it.
Definition GpkgUtils.hpp:171
std::unique_ptr< sqlite3, DbDeleter > DbPtr
Definition GpkgUtils.hpp:87
void bind_null(sqlite3_stmt *stmt, int col)
Bind SQL NULL, discarding SQLite status.
Definition GpkgUtils.hpp:258
std::string column_text(sqlite3_stmt *stmt, int col)
Copy current-row text using NUL-terminated SQLite conversion.
Definition GpkgUtils.hpp:292
int column_int(sqlite3_stmt *stmt, int col)
Read current-row SQLite numeric conversion as int.
Definition GpkgUtils.hpp:318
bool column_is_null(sqlite3_stmt *stmt, int col)
Test the current-row SQLite column type for NULL.
Definition GpkgUtils.hpp:330
void bind_text(sqlite3_stmt *stmt, int col, const std::string &val)
Bind a copied SQL text parameter, discarding SQLite status.
Definition GpkgUtils.hpp:220
double column_double(sqlite3_stmt *stmt, int col)
Read current-row SQLite numeric conversion as double.
Definition GpkgUtils.hpp:306
std::vector< uint8_t > column_blob(sqlite3_stmt *stmt, int col)
Copy current-row blob bytes into owned storage.
Definition GpkgUtils.hpp:346
Unique-pointer deleter using SQLite deferred close semantics.
Definition GpkgUtils.hpp:72
void operator()(sqlite3 *db) const noexcept
Best-effort close a uniquely owned SQLite connection.
Definition GpkgUtils.hpp:82
Unique-pointer deleter that finalizes prepared statements.
Definition GpkgUtils.hpp:143
void operator()(sqlite3_stmt *stmt) const noexcept
Finalize a uniquely owned SQLite statement.
Definition GpkgUtils.hpp:151