22 init(sqlite_db, query);
29 SqliteStmt(sqlite3 *sqlite_db,
const std::string &query) {
30 init(sqlite_db, query);
44 void init(sqlite3 *sqlite_db,
const char *query) {
47 err = sqlite3_prepare_v2(sqlite_db, query, -1, &
m_stmt,
nullptr);
48 if (err == SQLITE_BUSY) {
51 if (err != SQLITE_OK) {
52 std::string err_msg =
"Failed to prepare SQL statement: ";
53 err_msg += std::string(query);
54 err_msg +=
". Error code: ";
55 err_msg += std::to_string(err);
58 }
while (err == SQLITE_BUSY);
65 void init(sqlite3 *sqlite_db,
const std::string &query) {
66 init(sqlite_db, query.c_str());
78 const int err = sqlite3_reset(
m_stmt);
79 if (err == SQLITE_OK)
return;
80 throw sqlite_exception(
"Failed to reset SQL statement. Error code: " + std::to_string(err), err);
86 const int err = sqlite3_clear_bindings(
m_stmt);
87 if (err == SQLITE_OK)
return;
88 throw sqlite_exception(
"Failed to clear bindings on SQL statement. Error code: " + std::to_string(err), err);
107 return sqlite3_step(
m_stmt);
115 typename std::enable_if<std::is_integral<T>::value>::type* = 0) {
116 return static_cast<T
>(sqlite3_column_int64(
m_stmt, index));
121 typename std::enable_if<std::is_floating_point<T>::value>::type* = 0) {
122 return static_cast<T
>(sqlite3_column_double(
m_stmt, index));
127 typename std::enable_if<std::is_same<T, std::string>::value>::type* = 0) {
128 const unsigned char *text = sqlite3_column_text(
m_stmt, index);
130 return std::string(
reinterpret_cast<const char*
>(text));
132 return std::string();
137 typename std::enable_if<std::is_same<T, std::vector<char>>::value>::type* = 0) {
138 const void* blob = sqlite3_column_blob(
m_stmt, index);
139 const int blob_size = sqlite3_column_bytes(
m_stmt, index);
140 return std::vector<char>(
static_cast<const char*
>(blob),
static_cast<const char*
>(blob) + blob_size);
145 typename std::enable_if<std::is_same<T, std::vector<uint8_t>>::value>::type* = 0) {
146 const void* blob = sqlite3_column_blob(
m_stmt, index);
147 const int blob_size = sqlite3_column_bytes(
m_stmt, index);
148 return std::vector<uint8_t>(
static_cast<const uint8_t*
>(blob),
static_cast<const uint8_t*
>(blob) + blob_size);
153 typename std::enable_if<
154 !std::is_integral<T>::value &&
155 !std::is_floating_point<T>::value &&
156 !std::is_same<T, std::string>::value &&
157 !std::is_same<T, std::vector<char>>::value &&
158 !std::is_same<T, std::vector<uint8_t>>::value &&
159 std::is_trivially_copyable<T>::value
162 const void* blob = sqlite3_column_blob(
m_stmt, index);
163 const int blob_size = sqlite3_column_bytes(
m_stmt, index);
164 if (blob_size ==
sizeof(T)) {
165 std::memcpy(&value, blob,
sizeof(T));
178 typename std::enable_if<std::is_integral<T>::value>::type* = 0) {
179 return (sqlite3_bind_int64(
m_stmt, index,
static_cast<int64_t
>(value)) == SQLITE_OK);
184 typename std::enable_if<std::is_floating_point<T>::value>::type* = 0) {
185 return (sqlite3_bind_double(
m_stmt, index,
static_cast<double>(value)) == SQLITE_OK);
190 typename std::enable_if<std::is_same<T, std::string>::value>::type* = 0) {
191 return (sqlite3_bind_text(
m_stmt, index, value.c_str(), -1, SQLITE_STATIC) == SQLITE_OK);
196 typename std::enable_if<std::is_same<T, std::vector<char>>::value>::type* = 0) {
197 return (sqlite3_bind_blob(
m_stmt, index, value.data(), value.size(), SQLITE_STATIC) == SQLITE_OK);
202 typename std::enable_if<std::is_same<T, std::vector<uint8_t>>::value>::type* = 0) {
203 return (sqlite3_bind_blob(
m_stmt, index, value.data(), value.size(), SQLITE_STATIC) == SQLITE_OK);
208 typename std::enable_if<
209 !std::is_integral<T>::value &&
210 !std::is_floating_point<T>::value &&
211 !std::is_same<T, std::string>::value &&
212 !std::is_same<T, std::vector<char>>::value &&
213 !std::is_same<T, std::vector<uint8_t>>::value &&
214 std::is_trivially_copyable<T>::value
216 return (sqlite3_bind_blob(
m_stmt, index, &value,
sizeof(T), SQLITE_STATIC) == SQLITE_OK);
Utility functions for working with SQLite in sqlite_containers.
#define SQLITE_CONTAINERS_BUSY_RETRY_DELAY_MS
Class for managing SQLite prepared statements.
SqliteStmt(sqlite3 *sqlite_db, const char *query)
Constructs a SqliteStmt and prepares the statement.
T extract_column(const int &index, typename std::enable_if< !std::is_integral< T >::value &&!std::is_floating_point< T >::value &&!std::is_same< T, std::string >::value &&!std::is_same< T, std::vector< char > >::value &&!std::is_same< T, std::vector< uint8_t > >::value &&std::is_trivially_copyable< T >::value >::type *=0)
void clear_bindings()
Clears all bindings on the prepared statement.
SqliteStmt()=default
Default constructor.
bool bind_value(const int &index, const T &value, typename std::enable_if< std::is_same< T, std::vector< uint8_t > >::value >::type *=0)
sqlite3_stmt * m_stmt
Pointer to the prepared SQLite statement.
void execute(sqlite3 *sqlite_db)
Executes the prepared statement.
T extract_column(const int &index, typename std::enable_if< std::is_floating_point< T >::value >::type *=0)
sqlite3_stmt * get_stmt() noexcept
Gets the prepared SQLite statement.
T extract_column(const int &index, typename std::enable_if< std::is_integral< T >::value >::type *=0)
Extracts a value from a SQLite statement column.
void init(sqlite3 *sqlite_db, const std::string &query)
Initializes the statement.
void reset()
Resets the prepared statement.
bool bind_value(const int &index, const T &value, typename std::enable_if< std::is_floating_point< T >::value >::type *=0)
SqliteStmt(sqlite3 *sqlite_db, const std::string &query)
Constructs a SqliteStmt and prepares the statement.
void init(sqlite3 *sqlite_db, const char *query)
Initializes the statement.
bool bind_value(const int &index, const T &value, typename std::enable_if< std::is_same< T, std::string >::value >::type *=0)
T extract_column(const int &index, typename std::enable_if< std::is_same< T, std::string >::value >::type *=0)
bool bind_value(const int &index, const T &value, typename std::enable_if< !std::is_integral< T >::value &&!std::is_floating_point< T >::value &&!std::is_same< T, std::string >::value &&!std::is_same< T, std::vector< char > >::value &&!std::is_same< T, std::vector< uint8_t > >::value &&std::is_trivially_copyable< T >::value >::type *=0)
bool bind_value(const int &index, const T &value, typename std::enable_if< std::is_integral< T >::value >::type *=0)
Binds a value to a SQLite statement.
T extract_column(const int &index, typename std::enable_if< std::is_same< T, std::vector< char > >::value >::type *=0)
void execute()
Executes the prepared statement.
bool bind_value(const int &index, const T &value, typename std::enable_if< std::is_same< T, std::vector< char > >::value >::type *=0)
T extract_column(const int &index, typename std::enable_if< std::is_same< T, std::vector< uint8_t > >::value >::type *=0)
Exception class for SQLite errors.
void execute(sqlite3_stmt *stmt)
Executes a SQLite statement.