15#include <unordered_set>
17#include <unordered_map>
22#define SQLITE_CONTAINERS_BUSY_RETRY_DELAY_MS 50
51 while ((err = sqlite3_step(stmt)) == SQLITE_ROW);
72 inline void execute(sqlite3 *sqlite_db, sqlite3_stmt *stmt) {
73 if (!sqlite_db || !stmt)
throw sqlite_exception(
"Invalid database or statement pointer.");
76 while ((err = sqlite3_step(stmt)) == SQLITE_ROW);
84 throw sqlite_exception(
"Disk full or IO error: " + std::string(sqlite3_errmsg(sqlite_db)) +
". Error code: " + std::to_string(err), err);
86 throw sqlite_exception(
"Failed to insert data into database: " + std::string(sqlite3_errmsg(sqlite_db)) +
". Error code: " + std::to_string(err), err);
88 throw sqlite_exception(
"SQLite error: " + std::string(sqlite3_errmsg(sqlite_db)) +
". Error code: " + std::to_string(err), err);
97 inline void execute(sqlite3 *sqlite_db,
const char *query) {
99 if (!query || std::strlen(query) == 0)
throw sqlite_exception(
"Empty SQL request.");
102 err = sqlite3_exec(sqlite_db, query,
nullptr,
nullptr,
nullptr);
103 if (err == SQLITE_BUSY) {
106 if (err != SQLITE_OK) {
107 std::string err_msg =
"SQLite error during prepare: ";
108 err_msg += sqlite3_errmsg(sqlite_db);
109 err_msg +=
". Error code: ";
110 err_msg += std::to_string(err);
113 }
while (err == SQLITE_BUSY);
120 inline void execute(sqlite3 *sqlite_db,
const std::string &query) {
121 execute(sqlite_db, query.c_str());
131 typename std::enable_if<std::is_integral<T>::value>::type* = 0) {
137 typename std::enable_if<std::is_floating_point<T>::value>::type* = 0) {
143 typename std::enable_if<std::is_same<T, std::string>::value>::type* = 0) {
149 typename std::enable_if<
150 !std::is_integral<T>::value &&
151 !std::is_floating_point<T>::value &&
152 std::is_trivially_copyable<T>::value>::type* = 0) {
157 inline typename std::enable_if<
158 std::is_trivially_copyable<
159 typename T::value_type>::value &&
160 std::is_same<T, std::vector<typename T::value_type>>::value,
167 inline typename std::enable_if<
168 std::is_trivially_copyable<
169 typename T::value_type>::value &&
170 std::is_same<T, std::deque<typename T::value_type>>::value,
183 template<
template <
class...>
class ContainerT,
class T>
184 inline void add_value(ContainerT<T> &container, T &value,
185 typename std::enable_if<
186 std::is_same<ContainerT<T>, std::set<T>>::value ||
187 std::is_same<ContainerT<T>, std::unordered_set<T>>::value>::type* = 0) {
188 container.insert(std::move(value));
197 template<
template <
class...>
class ContainerT,
class T>
198 inline void add_value(ContainerT<T> &container,
const T &value,
const size_t& value_count = 0,
199 typename std::enable_if<
200 std::is_same<ContainerT<T>, std::multiset<T>>::value ||
201 std::is_same<ContainerT<T>, std::unordered_multiset<T>>::value>::type* = 0) {
202 for (
size_t i = 0; i < value_count; ++i) {
203 container.insert(value);
212 template<
template <
class...>
class ContainerT,
class T>
213 inline void add_value(ContainerT<T> &container, T &value,
214 typename std::enable_if<
215 std::is_same<ContainerT<T>, std::list<T>>::value ||
216 std::is_same<ContainerT<T>, std::vector<T>>::value ||
217 std::is_same<ContainerT<T>, std::deque<T>>::value>::type* = 0) {
218 container.emplace(container.end(), std::move(value));
227 template<
template <
class...>
class ContainerT,
class T>
228 inline void add_value(ContainerT<T> &container,
const T &value,
const size_t& value_count,
229 typename std::enable_if<
230 std::is_same<ContainerT<T>, std::list<T>>::value ||
231 std::is_same<ContainerT<T>, std::vector<T>>::value ||
232 std::is_same<ContainerT<T>, std::deque<T>>::value>::type* = 0) {
233 for (
size_t i = 0; i < value_count; ++i) {
234 container.emplace(container.end(), value);
244 template<
template <
class...>
class ContainerT,
class T>
245 inline void add_value(ContainerT<T> &container,
const T &value,
const size_t& value_count,
246 typename std::enable_if<
247 std::is_same<ContainerT<T>, std::set<T>>::value ||
248 std::is_same<ContainerT<T>, std::multiset<T>>::value ||
249 std::is_same<ContainerT<T>, std::unordered_set<T>>::value ||
250 std::is_same<ContainerT<T>, std::unordered_multiset<T>>::value>::type* = 0) {
251 for (
size_t i = 0; i < value_count; ++i) {
252 container.emplace(value);
264 template <
template <
class...>
class ContainerT,
typename KeyT,
typename ValueT>
265 inline void add_value(ContainerT<KeyT, ValueT> &container, KeyT& key, ValueT& value,
const size_t& value_count,
266 typename std::enable_if<
267 std::is_same<ContainerT<KeyT, ValueT>, std::multimap<KeyT, ValueT>>::value ||
268 std::is_same<ContainerT<KeyT, ValueT>, std::unordered_multimap<KeyT, ValueT>>::value>::type* = 0) {
269 for (
size_t i = 0; i < value_count; ++i) {
270 container.emplace(key, value);
283 template <
template <
class...>
class ContainerT,
typename KeyT,
typename ValueT>
284 inline std::list<ValueT>
get_values(ContainerT<KeyT, ValueT> &container,
const KeyT& key,
285 typename std::enable_if<
286 std::is_same<ContainerT<KeyT, ValueT>, std::map<KeyT, ValueT>>::value ||
287 std::is_same<ContainerT<KeyT, ValueT>, std::unordered_map<KeyT, ValueT>>::value>::type* = 0) {
288 std::list<ValueT> values;
289 auto it = container.find(key);
290 if (it == container.end())
return values;
291 values.push_back(it->second);
303 template<
template <
class...>
class ContainerT,
template <
class...>
class ValueContainerT,
typename KeyT,
typename ValueT>
304 inline std::list<ValueT>
get_values(ContainerT<KeyT, ValueContainerT<ValueT>> &container,
const KeyT& key,
305 typename std::enable_if<
306 std::is_same<ContainerT<KeyT, ValueT>, std::map<KeyT, ValueContainerT<ValueT>>>::value ||
307 std::is_same<ContainerT<KeyT, ValueT>, std::unordered_map<KeyT, ValueContainerT<ValueT>>>::value>::type* = 0) {
308 auto it = container.find(key);
309 std::list<ValueT> values;
310 for (
const auto& item : it->second) {
311 values.push_back(item);
323 template <
template <
class...>
class ContainerT,
typename KeyT,
typename ValueT>
324 inline std::list<ValueT>
get_values(ContainerT<KeyT, ValueT> &container,
const KeyT& key,
325 typename std::enable_if<
326 std::is_same<ContainerT<KeyT, ValueT>, std::multimap<KeyT, ValueT>>::value ||
327 std::is_same<ContainerT<KeyT, ValueT>, std::unordered_multimap<KeyT, ValueT>>::value>::type* = 0) {
328 auto range = container.equal_range(key);
329 std::list<ValueT> values;
330 for (
auto it = range.first; it != range.second; ++it) {
331 values.push_back(it->second);
338 template <
typename T>
340 return std::memcmp(&a, &b,
sizeof(T)) == 0;
#define SQLITE_CONTAINERS_BUSY_RETRY_DELAY_MS
Exception class for SQLite errors.
int error_code() const noexcept
sqlite_exception(const std::string &message, const int &error_code=-1)
Constructs a new sqlite_exception with the given message. param message The error message....
void execute(sqlite3_stmt *stmt)
Executes a SQLite statement.
std::enable_if< std::is_trivially_copyable< typenameT::value_type >::value &&std::is_same< T, std::vector< typenameT::value_type > >::value, std::string >::type get_sqlite_type()
bool byte_compare(const T &a, const T &b)
std::list< ValueT > get_values(ContainerT< KeyT, ValueT > &container, const KeyT &key, typename std::enable_if< std::is_same< ContainerT< KeyT, ValueT >, std::map< KeyT, ValueT > >::value||std::is_same< ContainerT< KeyT, ValueT >, std::unordered_map< KeyT, ValueT > >::value >::type *=0)
Retrieves values from a container (map or unordered_map) based on the key.
void add_value(ContainerT< T > &container, T &value, typename std::enable_if< std::is_same< ContainerT< T >, std::set< T > >::value||std::is_same< ContainerT< T >, std::unordered_set< T > >::value >::type *=0)
Adds a value to a container (set or unordered_set).