1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#pragma once
#include <utils/optional_bool.hpp>
#include <database/statement.hpp>
#include <database/column.hpp>
#include <logger/logger.hpp>
#include <vector>
#include <string>
#include <sqlite3.h>
struct Query
{
std::string body;
std::vector<std::string> params;
Query(std::string str):
body(std::move(str))
{}
Statement prepare(sqlite3* db)
{
sqlite3_stmt* stmt;
log_debug(this->body);
auto res = sqlite3_prepare(db, this->body.data(), static_cast<int>(this->body.size()) + 1,
&stmt, nullptr);
if (res != SQLITE_OK)
{
log_error("Error preparing statement: ", sqlite3_errmsg(db));
return nullptr;
}
Statement statement(stmt);
int i = 1;
for (const std::string& param: this->params)
{
if (sqlite3_bind_text(statement.get(), i, param.data(), static_cast<int>(param.size()), SQLITE_TRANSIENT) != SQLITE_OK)
log_debug("Failed to bind ", param, " to param ", i);
else
log_debug("Bound ", param, " to ", i);
i++;
}
return statement;
}
void execute(sqlite3* db)
{
auto statement = this->prepare(db);
while (sqlite3_step(statement.get()) != SQLITE_DONE)
;
}
};
template <typename ColumnType>
void add_param(Query& query, const ColumnType& column)
{
actual_add_param(query, column.value);
}
template <>
void add_param<Id>(Query& query, const Id& column);
template <typename T>
void actual_add_param(Query& query, const T& val)
{
query.params.push_back(std::to_string(val));
}
void actual_add_param(Query& query, const std::string& val);
void actual_add_param(Query& query, const OptionalBool& val);
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, Query&>::type
operator<<(Query& query, const T&)
{
query.body += T::name;
return query;
}
Query& operator<<(Query& query, const char* str);
Query& operator<<(Query& query, const std::string& str);
template <typename Integer>
typename std::enable_if<std::is_integral<Integer>::value, Query&>::type
operator<<(Query& query, const Integer& i)
{
query.body += "?";
actual_add_param(query, i);
return query;
}
|