8#include <botan/sqlite3.h>
9#include <botan/exceptn.h>
10#include <botan/mem_ops.h>
11#include <botan/internal/fmt.h>
20 const int open_flags = sqlite_open_flags.value_or(
21 SQLITE_OPEN_READWRITE |
23 SQLITE_OPEN_FULLMUTEX);
24 int rc = ::sqlite3_open_v2(std::string(db_filename).c_str(), &m_db, open_flags,
nullptr);
28 const std::string err_msg = ::sqlite3_errmsg(m_db);
29 ::sqlite3_close(m_db);
38 ::sqlite3_close(m_db);
44 return std::make_shared<Sqlite3_Statement>(m_db, base_sql);
52 return stmt->get_size_t(0);
54 throw SQL_DB_Error(
fmt(
"Querying size of table '{}' failed", table_name));
59 char* errmsg =
nullptr;
60 int rc = ::sqlite3_exec(m_db, std::string(table_schema).c_str(),
nullptr,
nullptr, &errmsg);
64 const std::string err_msg = errmsg;
65 ::sqlite3_free(errmsg);
66 ::sqlite3_close(m_db);
68 throw SQL_DB_Error(
"sqlite3_exec for table failed - " + err_msg);
76 const auto result = ::sqlite3_changes(m_db);
78 return static_cast<size_t>(result);
83 const int flag = sqlite3_threadsafe();
100Sqlite3_Database::Sqlite3_Statement::Sqlite3_Statement(sqlite3* db, std::string_view base_sql)
102 int rc = ::sqlite3_prepare_v2(db, base_sql.data(),
static_cast<int>(base_sql.size()), &m_stmt,
nullptr);
105 throw SQL_DB_Error(
fmt(
"sqlite3_prepare failed on '{}' with err {}", base_sql, rc), rc);
108void Sqlite3_Database::Sqlite3_Statement::bind(
int column, std::string_view val)
110 int rc = ::sqlite3_bind_text(m_stmt, column, val.data(),
static_cast<int>(val.size()), SQLITE_TRANSIENT);
112 throw SQL_DB_Error(
"sqlite3_bind_text failed", rc);
115void Sqlite3_Database::Sqlite3_Statement::bind(
int column,
size_t val)
117 if(val !=
static_cast<size_t>(
static_cast<int>(val)))
118 throw SQL_DB_Error(
"sqlite3 cannot store " + std::to_string(val) +
" without truncation");
119 int rc = ::sqlite3_bind_int(m_stmt, column,
static_cast<int>(val));
121 throw SQL_DB_Error(
"sqlite3_bind_int failed", rc);
124void Sqlite3_Database::Sqlite3_Statement::bind(
int column, std::chrono::system_clock::time_point time)
126 const uint64_t timeval = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count();
127 bind(column,
static_cast<size_t>(timeval));
130void Sqlite3_Database::Sqlite3_Statement::bind(
int column,
const std::vector<uint8_t>& val)
132 int rc = ::sqlite3_bind_blob(m_stmt, column, val.data(),
static_cast<int>(val.size()), SQLITE_TRANSIENT);
134 throw SQL_DB_Error(
"sqlite3_bind_text failed", rc);
137void Sqlite3_Database::Sqlite3_Statement::bind(
int column,
const uint8_t* p,
size_t len)
139 int rc = ::sqlite3_bind_blob(m_stmt, column, p,
static_cast<int>(len), SQLITE_TRANSIENT);
141 throw SQL_DB_Error(
"sqlite3_bind_text failed", rc);
144std::pair<const uint8_t*, size_t> Sqlite3_Database::Sqlite3_Statement::get_blob(
int column)
146 const auto column_type = ::sqlite3_column_type(m_stmt, column);
147 if(column_type == SQLITE_NULL)
153 "Return value is a blob");
155 const void* session_blob = ::sqlite3_column_blob(m_stmt, column);
156 const int session_blob_size = ::sqlite3_column_bytes(m_stmt, column);
158 BOTAN_ASSERT(session_blob_size >= 0,
"Blob size is non-negative");
160 return std::make_pair(
static_cast<const uint8_t*
>(session_blob),
161 static_cast<size_t>(session_blob_size));
164std::string Sqlite3_Database::Sqlite3_Statement::get_str(
int column)
166 BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_TEXT,
167 "Return value is text");
169 const unsigned char* str = ::sqlite3_column_text(m_stmt, column);
174size_t Sqlite3_Database::Sqlite3_Statement::get_size_t(
int column)
176 BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER,
177 "Return count is an integer");
179 const int sessions_int = ::sqlite3_column_int(m_stmt, column);
181 BOTAN_ASSERT(sessions_int >= 0,
"Expected size_t is non-negative");
183 return static_cast<size_t>(sessions_int);
186size_t Sqlite3_Database::Sqlite3_Statement::spin()
197bool Sqlite3_Database::Sqlite3_Statement::step()
199 return (::sqlite3_step(m_stmt) == SQLITE_ROW);
202Sqlite3_Database::Sqlite3_Statement::~Sqlite3_Statement()
204 ::sqlite3_finalize(m_stmt);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ASSERT(expr, assertion_made)
std::shared_ptr< Statement > new_statement(std::string_view sql) const override
size_t rows_changed_by_last_statement() override
bool is_threadsafe() const override
void create_table(std::string_view table_schema) override
Sqlite3_Database(std::string_view file, std::optional< int > sqlite_open_flags=std::nullopt)
size_t row_count(std::string_view table_name) override
std::string fmt(std::string_view format, const T &... args)
const char * cast_uint8_ptr_to_char(const uint8_t *b)