-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSqlite3.H
147 lines (121 loc) · 3.4 KB
/
Sqlite3.H
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#pragma once
#include <sqlite3.h>
#include <string>
#include <tuple>
#include <vector>
#include <exception>
#include <cstdint>
namespace SQL{
using std::string;
using std::vector;
using std::tuple;
typedef std::runtime_error SQLRTerror;
template <typename T>
static T get_single(sqlite3_stmt* ppsm, int iCol);
template <>
inline int get_single(sqlite3_stmt* ppsm, int iCol)
{
return sqlite3_column_int(ppsm, iCol);
}
template <>
inline double get_single(sqlite3_stmt* ppsm, int iCol)
{
return sqlite3_column_double(ppsm, iCol);
}
template <>
inline std::string get_single(sqlite3_stmt *ppsm, int iCol)
{
const char * foo = reinterpret_cast<const char*>(
sqlite3_column_text(ppsm,iCol));
return(foo?string(foo):"");
}
template <>
inline std::int64_t get_single(sqlite3_stmt *ppsm, int iCol)
{
return sqlite3_column_int64(ppsm, iCol);
}
class Con{
protected:
sqlite3 *db;
private:
const string dbfilename;
public:
Con(const string &dbfile):
dbfilename(dbfile)
{
int erg;
erg = sqlite3_open(dbfilename.c_str(),&db);
if(erg != SQLITE_OK){
throw(SQLRTerror(sqlite3_errmsg(db)));
}
}
~Con()
{
sqlite3_close(db);
}
private:
struct PPSM
{
sqlite3_stmt * me;
PPSM(sqlite3 *db , const string &query):
me(nullptr)
{
if (sqlite3_prepare_v2( db, query.c_str(), query.size(),
&me, nullptr)
!= SQLITE_OK){
throw(SQLRTerror(sqlite3_errmsg(db)));
}
}
void bindvals(vector<string>&& vals){
int pos=0;
for(auto& v : vals){
sqlite3_bind_text(me,++pos,v.c_str(),v.size(),SQLITE_TRANSIENT);
}
}
~PPSM(){
sqlite3_finalize(me);
}
};
public:
//> Within the initializer-list of a braced-init-list, the initializer-clauses, including
// any that result from pack expansions, are evaluated in the order in which they appear.
// That is, every value computation and side effect associated with a given initializer-clause
// is sequenced before every value computation and side effect associated with any
// initializer-clause that follows it in the comma-separated list of the initializer-list.
template<typename ...ARGS>
vector<tuple<ARGS...>> bindnquery(const string& query,
vector<string>&& bindvals={}){
PPSM ppsm(db, query);
ppsm.bindvals(std::forward<decltype(bindvals)>(bindvals));
vector<tuple<ARGS...> > answer {};
while (sqlite3_step(ppsm.me) == SQLITE_ROW){
int col = 0;
#pragma GCC diagnostic ignored "-Wsequence-point"
tuple<ARGS...> r { get_single<ARGS>(ppsm.me,(col++))... };
answer.push_back(r);
}
return answer;
}
//for update and such....
void query_nothing(const string& query, vector<string>&& bindvals={}){
PPSM ppsm(db,query);
ppsm.bindvals(std::forward<decltype(bindvals)>(bindvals));
auto result = sqlite3_step(ppsm.me);
if(result ==SQLITE_BUSY){
do {
sched_yield();
result = sqlite3_step(ppsm.me);;
} while (result == SQLITE_BUSY);
}
}
template<typename QType>
QType query_one(const string & query, vector<string>&& bindvals={}){
PPSM ppsm(db, query);
ppsm.bindvals(std::forward<decltype(bindvals)>(bindvals));
if(sqlite3_step(ppsm.me) != SQLITE_ROW){
throw(std::runtime_error("Query did not yield answer:"+query));
}
return get_single<QType>(ppsm.me,0);
}
};
}