discord-bot/libs/sqlite_orm-1.8.2/dev/util.h

131 lines
4.3 KiB
C
Raw Normal View History

2024-02-25 14:05:45 -05:00
#pragma once
#include <sqlite3.h>
#include <string> // std::string
#include <utility> // std::move
#include "error_code.h"
namespace sqlite_orm {
/**
* Escape the provided character in the given string by doubling it.
* @param str A copy of the original string
* @param char2Escape The character to escape
*/
inline std::string sql_escape(std::string str, char char2Escape) {
for(size_t pos = 0; (pos = str.find(char2Escape, pos)) != str.npos; pos += 2) {
str.replace(pos, 1, 2, char2Escape);
}
return str;
}
/**
* Quote the given string value using single quotes,
* escape containing single quotes by doubling them.
*/
inline std::string quote_string_literal(std::string v) {
constexpr char quoteChar = '\'';
return quoteChar + sql_escape(std::move(v), quoteChar) + quoteChar;
}
/**
* Quote the given string value using single quotes,
* escape containing single quotes by doubling them.
*/
inline std::string quote_blob_literal(std::string v) {
constexpr char quoteChar = '\'';
return std::string{char('x'), quoteChar} + std::move(v) + quoteChar;
}
/**
* Quote the given identifier using double quotes,
* escape containing double quotes by doubling them.
*/
inline std::string quote_identifier(std::string identifier) {
constexpr char quoteChar = '"';
return quoteChar + sql_escape(std::move(identifier), quoteChar) + quoteChar;
}
namespace internal {
// Wrapper to reduce boiler-plate code
inline sqlite3_stmt* reset_stmt(sqlite3_stmt* stmt) {
sqlite3_reset(stmt);
return stmt;
}
// note: query is deliberately taken by value, such that it is thrown away early
inline sqlite3_stmt* prepare_stmt(sqlite3* db, std::string query) {
sqlite3_stmt* stmt;
if(sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
throw_translated_sqlite_error(db);
}
return stmt;
}
inline void perform_void_exec(sqlite3* db, const std::string& query) {
int rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr);
if(rc != SQLITE_OK) {
throw_translated_sqlite_error(db);
}
}
inline void perform_exec(sqlite3* db,
const char* query,
int (*callback)(void* data, int argc, char** argv, char**),
void* user_data) {
int rc = sqlite3_exec(db, query, callback, user_data, nullptr);
if(rc != SQLITE_OK) {
throw_translated_sqlite_error(db);
}
}
inline void perform_exec(sqlite3* db,
const std::string& query,
int (*callback)(void* data, int argc, char** argv, char**),
void* user_data) {
return perform_exec(db, query.c_str(), callback, user_data);
}
template<int expected = SQLITE_DONE>
void perform_step(sqlite3_stmt* stmt) {
int rc = sqlite3_step(stmt);
if(rc != expected) {
throw_translated_sqlite_error(stmt);
}
}
template<class L>
void perform_step(sqlite3_stmt* stmt, L&& lambda) {
switch(int rc = sqlite3_step(stmt)) {
case SQLITE_ROW: {
lambda(stmt);
} break;
case SQLITE_DONE:
break;
default: {
throw_translated_sqlite_error(stmt);
}
}
}
template<class L>
void perform_steps(sqlite3_stmt* stmt, L&& lambda) {
int rc;
do {
switch(rc = sqlite3_step(stmt)) {
case SQLITE_ROW: {
lambda(stmt);
} break;
case SQLITE_DONE:
break;
default: {
throw_translated_sqlite_error(stmt);
}
}
} while(rc != SQLITE_DONE);
}
}
}