|
ferencd@0
|
1 #ifndef CPPDB_H
|
|
ferencd@0
|
2 #define CPPDB_H
|
|
ferencd@0
|
3
|
|
ferencd@0
|
4 #include <string>
|
|
ferencd@0
|
5 #include <common.h>
|
|
ferencd@0
|
6 #include <tuple>
|
|
ferencd@0
|
7 #include <functional>
|
|
ferencd@0
|
8 #include <type_traits>
|
|
ferencd@0
|
9 #include <algorithm>
|
|
ferencd@0
|
10
|
|
ferencd@0
|
11 #define _O(x) x
|
|
ferencd@0
|
12
|
|
ferencd@0
|
13 // helper macros
|
|
ferencd@0
|
14 #define CONCAT_IMPL( x, y ) x##y
|
|
ferencd@0
|
15 #define MACRO_CONCAT( x, y ) CONCAT_IMPL( x, y )
|
|
ferencd@0
|
16
|
|
ferencd@0
|
17 // basic value retrieval for various column types
|
|
ferencd@0
|
18 struct value_renderer
|
|
ferencd@0
|
19 {
|
|
ferencd@0
|
20 value_renderer() = default;
|
|
ferencd@0
|
21 virtual ~value_renderer() = default;
|
|
ferencd@0
|
22 virtual std::string render(const std::string& t) const { return t; }
|
|
ferencd@0
|
23
|
|
ferencd@0
|
24 virtual std::string value() const = 0;
|
|
ferencd@0
|
25 virtual std::string crypted(bool) = 0;
|
|
ferencd@0
|
26 virtual value_renderer& decrypted(bool) = 0;
|
|
ferencd@0
|
27
|
|
ferencd@0
|
28 };
|
|
ferencd@0
|
29
|
|
ferencd@0
|
30 /**
|
|
ferencd@0
|
31 * Class representing a column
|
|
ferencd@0
|
32 */
|
|
ferencd@0
|
33 class Column
|
|
ferencd@0
|
34 {
|
|
ferencd@0
|
35 public:
|
|
ferencd@0
|
36 virtual ~Column() = default;
|
|
ferencd@0
|
37 virtual std::string name() const = 0;
|
|
ferencd@0
|
38 virtual std::string realname() const = 0;
|
|
ferencd@0
|
39 virtual std::string type() const = 0;
|
|
ferencd@0
|
40 virtual const value_renderer* get_value_renderer() const = 0;
|
|
ferencd@0
|
41 virtual std::string extra_modifiers() const = 0;
|
|
ferencd@0
|
42 virtual std::string crypt_value(const std::string&) const = 0;
|
|
ferencd@0
|
43 virtual std::string decrypt_value(const std::string&) const = 0;
|
|
ferencd@0
|
44 virtual Column* clone() const = 0;
|
|
ferencd@0
|
45 };
|
|
ferencd@0
|
46
|
|
ferencd@0
|
47 class BasicColumn : public Column
|
|
ferencd@0
|
48 {
|
|
ferencd@0
|
49 public:
|
|
ferencd@0
|
50 virtual std::string name() const { return "" ;}
|
|
ferencd@0
|
51 virtual std::string type() const { return "" ;}
|
|
ferencd@0
|
52 virtual std::string extra_modifiers() const { return "";}
|
|
ferencd@0
|
53 };
|
|
ferencd@0
|
54
|
|
ferencd@0
|
55 class NotAColumn : public Column
|
|
ferencd@0
|
56 {
|
|
ferencd@0
|
57 public:
|
|
ferencd@0
|
58 virtual std::string name() const = 0;
|
|
ferencd@0
|
59 virtual std::string realname() const = 0;
|
|
ferencd@0
|
60 virtual std::string type() const { return ""; }
|
|
ferencd@0
|
61 virtual const value_renderer* get_value_renderer() const { return nullptr; }
|
|
ferencd@0
|
62 virtual std::string extra_modifiers() const { return ""; }
|
|
ferencd@0
|
63 virtual std::string crypt_value(const std::string&) const { return ""; }
|
|
ferencd@0
|
64 virtual std::string decrypt_value(const std::string&) const { return ""; }
|
|
ferencd@0
|
65 virtual Column* clone() const { return nullptr; }
|
|
ferencd@0
|
66 };
|
|
ferencd@0
|
67
|
|
ferencd@0
|
68 class DescAsColumn : public NotAColumn
|
|
ferencd@0
|
69 {
|
|
ferencd@0
|
70 public:
|
|
ferencd@0
|
71 typedef DescAsColumn type;
|
|
ferencd@0
|
72 virtual std::string name() const { return "DESC"; }
|
|
ferencd@0
|
73 virtual std::string realname() const { return "DESC"; }
|
|
ferencd@0
|
74 };
|
|
ferencd@0
|
75
|
|
ferencd@0
|
76 class AscAsColumn : public NotAColumn
|
|
ferencd@0
|
77 {
|
|
ferencd@0
|
78 public:
|
|
ferencd@0
|
79 typedef AscAsColumn type;
|
|
ferencd@0
|
80 virtual std::string name() const { return "ASC"; }
|
|
ferencd@0
|
81 virtual std::string realname() const { return "ASC"; }
|
|
ferencd@0
|
82 };
|
|
ferencd@0
|
83
|
|
ferencd@0
|
84 #define DESC ,DescAsColumn()
|
|
ferencd@0
|
85 #define ASC ,AscAsColumn()
|
|
ferencd@0
|
86
|
|
ferencd@0
|
87 class BasicTable
|
|
ferencd@0
|
88 {
|
|
ferencd@0
|
89 public:
|
|
ferencd@0
|
90 virtual std::string name() const = 0;
|
|
ferencd@0
|
91 virtual bool is_crypted() const = 0;
|
|
ferencd@0
|
92 virtual ~BasicTable() = default;
|
|
ferencd@0
|
93 };
|
|
ferencd@0
|
94
|
|
ferencd@0
|
95 struct Functor
|
|
ferencd@0
|
96 {
|
|
ferencd@0
|
97 Functor(std::string& rstr) : s(rstr) {}
|
|
ferencd@0
|
98 std::string& s;
|
|
ferencd@0
|
99
|
|
ferencd@0
|
100 template<typename T>
|
|
ferencd@0
|
101 void operator()(T& t)
|
|
ferencd@0
|
102 {
|
|
ferencd@0
|
103 std::string g = unafrog::utils::to_string(t);
|
|
ferencd@0
|
104 this->s = g;
|
|
ferencd@0
|
105 }
|
|
ferencd@0
|
106 };
|
|
ferencd@0
|
107
|
|
ferencd@0
|
108 struct GetNameFunctor
|
|
ferencd@0
|
109 {
|
|
ferencd@0
|
110 GetNameFunctor(std::string& rstr) : s(rstr) {}
|
|
ferencd@0
|
111 std::string& s;
|
|
ferencd@0
|
112
|
|
ferencd@0
|
113 template<typename T>
|
|
ferencd@0
|
114 void operator()(T& t)
|
|
ferencd@0
|
115 {
|
|
ferencd@0
|
116 std::string g = t.name();
|
|
ferencd@0
|
117 this->s = g;
|
|
ferencd@0
|
118 }
|
|
ferencd@0
|
119 };
|
|
ferencd@0
|
120
|
|
ferencd@0
|
121
|
|
ferencd@0
|
122 static const char* insert_into = "INSERT OR IGNORE INTO ";
|
|
ferencd@0
|
123
|
|
ferencd@0
|
124 // columnset stuff for insert operations
|
|
ferencd@0
|
125 class Columnset
|
|
ferencd@0
|
126 {
|
|
ferencd@0
|
127 size_t colcount;
|
|
ferencd@0
|
128 std::vector<std::string> colnames;
|
|
ferencd@0
|
129 std::vector<const Column*> cols;
|
|
ferencd@0
|
130 std::vector<const Column*> mcols;
|
|
ferencd@0
|
131
|
|
ferencd@0
|
132 std::vector<const value_renderer*> valrends;
|
|
ferencd@0
|
133 const BasicTable& t;
|
|
ferencd@0
|
134 mutable std::string values_s;
|
|
ferencd@0
|
135 mutable std::string s;
|
|
ferencd@0
|
136
|
|
ferencd@0
|
137 public:
|
|
ferencd@0
|
138 template<class ...Cs>
|
|
ferencd@0
|
139 Columnset(const BasicTable& bt, Cs&... inputs) : colcount(sizeof...(Cs)), cols{&inputs...}, t(bt), values_s(""),
|
|
ferencd@0
|
140 s(insert_into + t.name() + "(")
|
|
ferencd@0
|
141 {
|
|
ferencd@0
|
142 for (auto c : cols)
|
|
ferencd@0
|
143 {
|
|
ferencd@0
|
144 colnames.push_back(c->name());
|
|
ferencd@0
|
145 valrends.push_back(c->get_value_renderer());
|
|
ferencd@0
|
146 mcols.push_back(c->clone());
|
|
ferencd@0
|
147 }
|
|
ferencd@0
|
148 }
|
|
ferencd@0
|
149
|
|
ferencd@0
|
150 virtual ~Columnset()
|
|
ferencd@0
|
151 {
|
|
ferencd@0
|
152 for (auto c : mcols)
|
|
ferencd@0
|
153 {
|
|
ferencd@0
|
154 delete c;
|
|
ferencd@0
|
155 }
|
|
ferencd@0
|
156 for (auto c : valrends)
|
|
ferencd@0
|
157 {
|
|
ferencd@0
|
158 delete c;
|
|
ferencd@0
|
159 }
|
|
ferencd@0
|
160 }
|
|
ferencd@0
|
161
|
|
ferencd@0
|
162 template <class ...Vals>
|
|
ferencd@0
|
163 std::string insert(const char* c, Vals... v)
|
|
ferencd@0
|
164 {
|
|
ferencd@0
|
165 return std::string(c), + valset(v...);
|
|
ferencd@0
|
166 }
|
|
ferencd@0
|
167
|
|
ferencd@0
|
168 template <class ...Vals>
|
|
ferencd@0
|
169 std::string insert(Vals... v) const
|
|
ferencd@0
|
170 {
|
|
ferencd@0
|
171 auto r = valset(v...);
|
|
ferencd@0
|
172 for(size_t i=0; i<colcount; i++)
|
|
ferencd@0
|
173 {
|
|
ferencd@0
|
174 std::string cn = colnames.at(i);
|
|
ferencd@0
|
175 s += cn.substr(cn.find('.') + 1);
|
|
ferencd@0
|
176
|
|
ferencd@0
|
177 // the value from the template arguments, stored as a tuple.
|
|
ferencd@0
|
178 std::string returned;
|
|
ferencd@0
|
179 Functor a(returned);
|
|
ferencd@0
|
180 for_index(i, r, a);
|
|
ferencd@0
|
181 std::string crypted = mcols.at(i)->crypt_value(returned);
|
|
ferencd@0
|
182 values_s += valrends.at(i)->render(crypted);
|
|
ferencd@0
|
183 if(i < cols.size() - 1)
|
|
ferencd@0
|
184 {
|
|
ferencd@0
|
185 s+= ", ";
|
|
ferencd@0
|
186 values_s += ", ";
|
|
ferencd@0
|
187 }
|
|
ferencd@0
|
188 }
|
|
ferencd@0
|
189 s += ") VALUES (" + values_s + ")";
|
|
ferencd@0
|
190 return s;
|
|
ferencd@0
|
191 }
|
|
ferencd@0
|
192
|
|
ferencd@0
|
193 std::string prepare_insert() const
|
|
ferencd@0
|
194 {
|
|
ferencd@0
|
195 std::string s = std::string(insert_into) + t.name() + "(";
|
|
ferencd@0
|
196 std::string values_s = "";
|
|
ferencd@0
|
197
|
|
ferencd@0
|
198 for(size_t i=0; i<colcount; i++)
|
|
ferencd@0
|
199 {
|
|
ferencd@0
|
200 std::string cn = mcols[i]->name();
|
|
ferencd@0
|
201 s += cn.substr(cn.find('.') + 1);
|
|
ferencd@0
|
202 values_s += ":v" + std::to_string(i + 1);
|
|
ferencd@0
|
203
|
|
ferencd@0
|
204 if(i < cols.size() - 1)
|
|
ferencd@0
|
205 {
|
|
ferencd@0
|
206 s+= ", ";
|
|
ferencd@0
|
207 values_s += ", ";
|
|
ferencd@0
|
208 }
|
|
ferencd@0
|
209 }
|
|
ferencd@0
|
210 s += _O(") VALUES (") + values_s + ")";
|
|
ferencd@0
|
211 return s;
|
|
ferencd@0
|
212 }
|
|
ferencd@0
|
213
|
|
ferencd@0
|
214 };
|
|
ferencd@0
|
215
|
|
ferencd@0
|
216 /**
|
|
ferencd@0
|
217 * Class representing a Table
|
|
ferencd@0
|
218 */
|
|
ferencd@0
|
219 class Table : public BasicTable
|
|
ferencd@0
|
220 {
|
|
ferencd@0
|
221 mutable std::vector<std::string> foreign_keys;
|
|
ferencd@0
|
222 std::vector<std::string> inited_foreign_keys;
|
|
ferencd@0
|
223 std::vector<const Column*> columns;
|
|
ferencd@0
|
224 std::string resolve_foreign_key(const std::string& s) const;
|
|
ferencd@0
|
225
|
|
ferencd@0
|
226 protected:
|
|
ferencd@0
|
227 bool init_foreign_key(const std::string& s);
|
|
ferencd@0
|
228
|
|
ferencd@0
|
229 public:
|
|
ferencd@0
|
230 virtual std::string verify() const;
|
|
ferencd@0
|
231 virtual std::string create() const;
|
|
ferencd@0
|
232
|
|
ferencd@0
|
233 virtual std::string name() const = 0;
|
|
ferencd@0
|
234 virtual std::string realname() const = 0;
|
|
ferencd@0
|
235 virtual bool is_crypted() const = 0;
|
|
ferencd@0
|
236
|
|
ferencd@0
|
237 void addColumn(const Column* c) {columns.push_back(c);}
|
|
ferencd@0
|
238 };
|
|
ferencd@0
|
239
|
|
ferencd@0
|
240 class Condition
|
|
ferencd@0
|
241 {
|
|
ferencd@0
|
242 public:
|
|
ferencd@0
|
243 Condition(const std::string& s);
|
|
ferencd@0
|
244 std::string cond() const;
|
|
ferencd@0
|
245 private:
|
|
ferencd@0
|
246 std::string cstr;
|
|
ferencd@0
|
247 };
|
|
ferencd@0
|
248
|
|
ferencd@0
|
249 std::string operator && (const Condition& c1, const Condition& c2);
|
|
ferencd@0
|
250 std::string operator || (const Condition& c1, const Condition& c2);
|
|
ferencd@0
|
251 typedef std::string (*PT)(const Condition& c1, const Condition& c2);
|
|
ferencd@0
|
252
|
|
ferencd@0
|
253 #define AND &&
|
|
ferencd@0
|
254 #define OR ||
|
|
ferencd@0
|
255
|
|
ferencd@0
|
256 template<typename TF>
|
|
ferencd@0
|
257 std::string write_debug_output( TF const& f) {
|
|
ferencd@0
|
258 std::stringstream ss;
|
|
ferencd@0
|
259 ss << f.get_modifier();
|
|
ferencd@0
|
260 return ss.str();
|
|
ferencd@0
|
261 }
|
|
ferencd@0
|
262
|
|
ferencd@0
|
263 struct modifier_retriever {
|
|
ferencd@0
|
264 template<typename TF, typename ... TR>
|
|
ferencd@0
|
265 std::string write( TF const& f, TR const& ... rest ) {
|
|
ferencd@0
|
266 std::string full = write_debug_output( f );
|
|
ferencd@0
|
267 full += " ";
|
|
ferencd@0
|
268 full += write( rest... );
|
|
ferencd@0
|
269 return full;
|
|
ferencd@0
|
270 }
|
|
ferencd@0
|
271 template<typename TF>
|
|
ferencd@0
|
272 std::string write( TF const& f ) {
|
|
ferencd@0
|
273 return write_debug_output( f );
|
|
ferencd@0
|
274 }
|
|
ferencd@0
|
275 std::string write() {
|
|
ferencd@0
|
276 return "";
|
|
ferencd@0
|
277 }
|
|
ferencd@0
|
278 };
|
|
ferencd@0
|
279
|
|
ferencd@0
|
280 namespace cppdb
|
|
ferencd@0
|
281 {
|
|
ferencd@0
|
282 std::string crypt_db_name(const std::string& in);
|
|
ferencd@0
|
283 std::string crypt_db_value(const std::string& in, bool do_crypt);
|
|
ferencd@0
|
284 std::string decrypt_db_value(const std::string& in, bool do_decrypt);
|
|
ferencd@0
|
285 unsigned long crypt_number(unsigned long in, bool do_crypt);
|
|
ferencd@0
|
286 unsigned long decrypt_number(unsigned long in, bool do_crypt);
|
|
ferencd@0
|
287 }
|
|
ferencd@0
|
288
|
|
ferencd@0
|
289 #define TABLE_WRAPPER(Name,Crypt) namespace { \
|
|
ferencd@0
|
290 class Table##Name : public Table \
|
|
ferencd@0
|
291 { \
|
|
ferencd@0
|
292 mutable std::string crypted_name = ""; \
|
|
ferencd@0
|
293 public: \
|
|
ferencd@0
|
294 static std::string tablename; \
|
|
ferencd@0
|
295 Table##Name() {} \
|
|
ferencd@0
|
296 bool is_crypted() const {return Crypt;} \
|
|
ferencd@0
|
297 template<class ...Cs> \
|
|
ferencd@0
|
298 const Columnset operator() (Cs... cols) const \
|
|
ferencd@0
|
299 { return Columnset(*this, cols...);} \
|
|
ferencd@0
|
300 virtual std::string name() const \
|
|
ferencd@0
|
301 { \
|
|
ferencd@0
|
302 if(Crypt) \
|
|
ferencd@0
|
303 { \
|
|
ferencd@0
|
304 if(crypted_name.empty()) \
|
|
ferencd@0
|
305 crypted_name = cppdb::crypt_db_name(tablename); \
|
|
ferencd@0
|
306 return crypted_name; \
|
|
ferencd@0
|
307 } \
|
|
ferencd@0
|
308 else return tablename; \
|
|
ferencd@0
|
309 } \
|
|
ferencd@0
|
310 virtual std::string realname() const {return tablename; }
|
|
ferencd@0
|
311
|
|
ferencd@0
|
312 #define TABLE(Name) TABLE_WRAPPER(Name,0)
|
|
ferencd@0
|
313 #define CRYP_TABLE(Name) TABLE_WRAPPER(Name,1)
|
|
ferencd@0
|
314
|
|
ferencd@0
|
315 // Will create the actual "Name" object of type Table##Name
|
|
ferencd@0
|
316 #define ENDTABLE(Name) }; \
|
|
ferencd@0
|
317 std::string Table##Name::tablename = #Name; \
|
|
ferencd@0
|
318 const Table##Name& Name = Table##Name(); \
|
|
ferencd@0
|
319 bool MACRO_CONCAT(reg_tab_, Name) = cppdb_warehouse::instance().add_table(&Name); \
|
|
ferencd@0
|
320 }
|
|
ferencd@0
|
321
|
|
ferencd@0
|
322 #define DEF_OPERATOR(OP,sqlop,Type) \
|
|
ferencd@0
|
323 Condition operator OP (const Type::type& t) const \
|
|
ferencd@0
|
324 { return Condition( "(" + name() + #sqlop + unafrog::utils::to_string(t) + ")"); } \
|
|
ferencd@0
|
325 Condition operator OP (const Column& t) const \
|
|
ferencd@0
|
326 { return Condition( "(" + name() + #sqlop + t.name() + ")"); } \
|
|
ferencd@0
|
327
|
|
ferencd@0
|
328
|
|
ferencd@0
|
329 #define COLUMN_WRAPPER(Name, Type, Crypt, ...) \
|
|
ferencd@0
|
330 class Column##Name : public BasicColumn \
|
|
ferencd@0
|
331 { \
|
|
ferencd@0
|
332 Table& parent; \
|
|
ferencd@0
|
333 mutable std::string crypted_name = ""; \
|
|
ferencd@0
|
334 std::string extra = modifier_retriever().write(__VA_ARGS__); \
|
|
ferencd@0
|
335 public: \
|
|
ferencd@0
|
336 Column##Name (Table& p) : parent(p) {p.addColumn(this);} \
|
|
ferencd@0
|
337 virtual std::string name() const \
|
|
ferencd@0
|
338 { \
|
|
ferencd@0
|
339 if (Crypt || parent.is_crypted()) \
|
|
ferencd@0
|
340 { \
|
|
ferencd@0
|
341 if(crypted_name.empty()) \
|
|
ferencd@0
|
342 { \
|
|
ferencd@0
|
343 crypted_name = parent.name() + "." + cppdb::crypt_db_name(#Name); \
|
|
ferencd@0
|
344 } \
|
|
ferencd@0
|
345 return crypted_name; \
|
|
ferencd@0
|
346 } \
|
|
ferencd@0
|
347 else return parent.name() + "." + #Name; \
|
|
ferencd@0
|
348 } \
|
|
ferencd@0
|
349 virtual std::string realname() const { return #Name; } \
|
|
ferencd@0
|
350 DEF_OPERATOR(==, =, Type) \
|
|
ferencd@0
|
351 Condition operator == (const std::string& t) const \
|
|
ferencd@0
|
352 { return Condition( "(" + name() + " = '" + t + "')"); } \
|
|
ferencd@0
|
353 DEF_OPERATOR(!=, <>, Type) \
|
|
ferencd@0
|
354 DEF_OPERATOR(<=, <=, Type) \
|
|
ferencd@0
|
355 DEF_OPERATOR(>=, >=, Type) \
|
|
ferencd@0
|
356 DEF_OPERATOR(<, <, Type) \
|
|
ferencd@0
|
357 DEF_OPERATOR(>, >, Type) \
|
|
ferencd@0
|
358 std::string type() const { return Type().get_type(); } \
|
|
ferencd@0
|
359 std::string extra_modifiers() const { return extra; } \
|
|
ferencd@0
|
360 const value_renderer* get_value_renderer() const { return new Type(); } \
|
|
ferencd@0
|
361 std::string crypt_value(const std::string& value) const \
|
|
ferencd@0
|
362 { \
|
|
ferencd@0
|
363 return Type(value).crypted(Crypt || parent.is_crypted()); \
|
|
ferencd@0
|
364 } \
|
|
ferencd@0
|
365 std::string crypt_value(const Type::type& value) const \
|
|
ferencd@0
|
366 { \
|
|
ferencd@0
|
367 return Type(value).crypted(Crypt || parent.is_crypted()); \
|
|
ferencd@0
|
368 } \
|
|
ferencd@0
|
369 std::string decrypt_value(const std::string& value) const \
|
|
ferencd@0
|
370 { \
|
|
ferencd@0
|
371 return Type(value).decrypted(Crypt || parent.is_crypted()).value(); \
|
|
ferencd@0
|
372 } \
|
|
ferencd@0
|
373 Column* clone() const { Column* c = new Column##Name(parent); dynamic_cast<Column##Name*>(c)->crypted_name = crypted_name; dynamic_cast<Column##Name*>(c)->extra = extra; return c;}\
|
|
ferencd@0
|
374 }; \
|
|
ferencd@0
|
375 Column##Name Name = Column##Name(*this); \
|
|
ferencd@0
|
376 bool MACRO_CONCAT(reg_col_, Name) = cppdb_warehouse::instance().add_column(&Name)
|
|
ferencd@0
|
377
|
|
ferencd@0
|
378
|
|
ferencd@0
|
379 #define COLUMN(Name, Type, ...) COLUMN_WRAPPER(Name, Type, 0, __VA_ARGS__)
|
|
ferencd@0
|
380 #define CRYP_COLUMN(Name, Type, ...) COLUMN_WRAPPER(Name, Type, 1, __VA_ARGS__)
|
|
ferencd@0
|
381
|
|
ferencd@0
|
382 // Foreign Key stuff
|
|
ferencd@0
|
383 #define FOREIGN_KEY(X) bool MACRO_CONCAT(g, __COUNTER__ ) = init_foreign_key(std::string(#X))
|
|
ferencd@0
|
384
|
|
ferencd@0
|
385 // Order by
|
|
ferencd@0
|
386
|
|
ferencd@0
|
387 template<typename T, typename U>
|
|
ferencd@0
|
388 struct is_same : std::false_type { };
|
|
ferencd@0
|
389
|
|
ferencd@0
|
390 template<typename T>
|
|
ferencd@0
|
391 struct is_same<T, T> : std::true_type { };
|
|
ferencd@0
|
392
|
|
ferencd@0
|
393 template<typename T, typename U>
|
|
ferencd@0
|
394 constexpr bool eqTypes() { return is_same<T, U>::value; }
|
|
ferencd@0
|
395
|
|
ferencd@0
|
396 std::string orderby_helper(const Column& c);
|
|
ferencd@0
|
397
|
|
ferencd@0
|
398 template <class... args>
|
|
ferencd@0
|
399 std::string orderby_helper(args... a)
|
|
ferencd@0
|
400 {
|
|
ferencd@0
|
401
|
|
ferencd@0
|
402 std::size_t cnt = sizeof...(args);
|
|
ferencd@0
|
403 auto r = std::tuple<args...>(a...);
|
|
ferencd@0
|
404 std::vector<std::string> columns;
|
|
ferencd@0
|
405
|
|
ferencd@0
|
406 for(std::size_t i=0; i<cnt; i++)
|
|
ferencd@0
|
407 {
|
|
ferencd@0
|
408 std::string returned;
|
|
ferencd@0
|
409 GetNameFunctor a(returned);
|
|
ferencd@0
|
410 for_index(i, r, a);
|
|
ferencd@0
|
411 columns.push_back(returned);
|
|
ferencd@0
|
412 }
|
|
ferencd@0
|
413 std::string result = "";
|
|
ferencd@0
|
414 for(size_t i = 0; i<columns.size(); i++)
|
|
ferencd@0
|
415 {
|
|
ferencd@0
|
416 result += columns.at(i);
|
|
ferencd@0
|
417 if(i < columns.size() - 1)
|
|
ferencd@0
|
418 {
|
|
ferencd@0
|
419 if(columns.at(i + 1) != "ASC" && columns.at(i + 1) != "DESC")
|
|
ferencd@0
|
420 {
|
|
ferencd@0
|
421 result += ", ";
|
|
ferencd@0
|
422 }
|
|
ferencd@0
|
423 else
|
|
ferencd@0
|
424 {
|
|
ferencd@0
|
425 result += " ";
|
|
ferencd@0
|
426 }
|
|
ferencd@0
|
427 }
|
|
ferencd@0
|
428 }
|
|
ferencd@0
|
429 return result;
|
|
ferencd@0
|
430 }
|
|
ferencd@0
|
431
|
|
ferencd@0
|
432 template <class... all>
|
|
ferencd@0
|
433 std::string ORDER_BY(all... a)
|
|
ferencd@0
|
434 {
|
|
ferencd@0
|
435 std::string s = " ORDER BY ";
|
|
ferencd@0
|
436 std::string g = orderby_helper(a...);
|
|
ferencd@0
|
437 return s + g;
|
|
ferencd@0
|
438 }
|
|
ferencd@0
|
439
|
|
ferencd@0
|
440 // Where
|
|
ferencd@0
|
441
|
|
ferencd@0
|
442 std::string where_helper(const Condition& c);
|
|
ferencd@0
|
443
|
|
ferencd@0
|
444 template <class C = Condition, class... args>
|
|
ferencd@0
|
445 std::string where_helper(const Condition& c, args... a)
|
|
ferencd@0
|
446 {
|
|
ferencd@0
|
447 std::string s = c.cond();
|
|
ferencd@0
|
448 s += from(a...);
|
|
ferencd@0
|
449 return s;
|
|
ferencd@0
|
450 }
|
|
ferencd@0
|
451
|
|
ferencd@0
|
452 template <class... all>
|
|
ferencd@0
|
453 std::string WHERE(all... a)
|
|
ferencd@0
|
454 {
|
|
ferencd@0
|
455 std::string s = "WHERE ";
|
|
ferencd@0
|
456 std::string g = where_helper(a...);
|
|
ferencd@0
|
457 return s + g;
|
|
ferencd@0
|
458 }
|
|
ferencd@0
|
459
|
|
ferencd@0
|
460 // From
|
|
ferencd@0
|
461
|
|
ferencd@0
|
462 std::string from_helper(const Table& t);
|
|
ferencd@0
|
463
|
|
ferencd@0
|
464 template <class T = Table, class... args>
|
|
ferencd@0
|
465 std::string from_helper(const Table& t, args... a)
|
|
ferencd@0
|
466 {
|
|
ferencd@0
|
467 std::string s = t.name() + ", ";
|
|
ferencd@0
|
468 s += from_helper(a...);
|
|
ferencd@0
|
469 return s;
|
|
ferencd@0
|
470 }
|
|
ferencd@0
|
471
|
|
ferencd@0
|
472 template <class... all>
|
|
ferencd@0
|
473 std::string FROM(all... a)
|
|
ferencd@0
|
474 {
|
|
ferencd@0
|
475 std::string s = "FROM ";
|
|
ferencd@0
|
476 std::string g = from_helper(a...);
|
|
ferencd@0
|
477 return s + g + " ";
|
|
ferencd@0
|
478 }
|
|
ferencd@0
|
479
|
|
ferencd@0
|
480 // Select
|
|
ferencd@0
|
481
|
|
ferencd@0
|
482 std::string select_helper(const Column& c);
|
|
ferencd@0
|
483
|
|
ferencd@0
|
484 template <class C = Column, class... args>
|
|
ferencd@0
|
485 std::string select_helper(const Column& c, args... a)
|
|
ferencd@0
|
486 {
|
|
ferencd@0
|
487 std::string s = c.name() + ", ";
|
|
ferencd@0
|
488 s += select_helper(a...);
|
|
ferencd@0
|
489 return s;
|
|
ferencd@0
|
490 }
|
|
ferencd@0
|
491
|
|
ferencd@0
|
492
|
|
ferencd@0
|
493 template <class... all>
|
|
ferencd@0
|
494 std::string SELECT(all... a)
|
|
ferencd@0
|
495 {
|
|
ferencd@0
|
496 std::string s = "SELECT ";
|
|
ferencd@0
|
497 std::string g = select_helper(a...);
|
|
ferencd@0
|
498 return s + g + " ";
|
|
ferencd@0
|
499 }
|
|
ferencd@0
|
500
|
|
ferencd@0
|
501 // Delete
|
|
ferencd@0
|
502
|
|
ferencd@0
|
503 #define DELETE "DELETE "
|
|
ferencd@0
|
504
|
|
ferencd@0
|
505 // Update
|
|
ferencd@0
|
506
|
|
ferencd@0
|
507 std::string UPDATE(const Table& tab);
|
|
ferencd@0
|
508
|
|
ferencd@0
|
509 std::string set_helper(int total_size, const Column& c);
|
|
ferencd@0
|
510
|
|
ferencd@0
|
511 template <class C = Column, class... args>
|
|
ferencd@0
|
512 std::string set_helper(std::size_t total_size, const Column& c, args... a)
|
|
ferencd@0
|
513 {
|
|
ferencd@0
|
514 std::string s = c.realname() + "=:v";
|
|
ferencd@0
|
515 std::stringstream ss;
|
|
ferencd@0
|
516 ss << total_size - sizeof...(a);
|
|
ferencd@0
|
517 s += ss.str() + ", ";
|
|
ferencd@0
|
518 s += set_helper(total_size, a...);
|
|
ferencd@0
|
519 return s;
|
|
ferencd@0
|
520 }
|
|
ferencd@0
|
521
|
|
ferencd@0
|
522 template <class... all>
|
|
ferencd@0
|
523 std::string SET(all... a)
|
|
ferencd@0
|
524 {
|
|
ferencd@0
|
525 std::string s = " SET ";
|
|
ferencd@0
|
526 std::string g = set_helper(sizeof...(a), a...);
|
|
ferencd@0
|
527 return s + g ;
|
|
ferencd@0
|
528 }
|
|
ferencd@0
|
529
|
|
ferencd@0
|
530 // varchar support
|
|
ferencd@0
|
531 template<size_t SIZE> class varchar : public value_renderer
|
|
ferencd@0
|
532 {
|
|
ferencd@0
|
533 public:
|
|
ferencd@0
|
534 // this has to be "const char*" otherwise overloading upon const std::string& is not possible in Column classes
|
|
ferencd@0
|
535 typedef const char* type;
|
|
ferencd@0
|
536
|
|
ferencd@0
|
537 varchar() : s(SIZE) {}
|
|
ferencd@0
|
538 varchar(const std::string& v) : s(SIZE), mvalue(v) {}
|
|
ferencd@0
|
539 operator std::string () const
|
|
ferencd@0
|
540 {
|
|
ferencd@0
|
541 return _O("VARCHAR(") + std::to_string(s) + ")";
|
|
ferencd@0
|
542 }
|
|
ferencd@0
|
543
|
|
ferencd@0
|
544 std::string get_type() const
|
|
ferencd@0
|
545 {
|
|
ferencd@0
|
546 return operator std::string();
|
|
ferencd@0
|
547 }
|
|
ferencd@0
|
548
|
|
ferencd@0
|
549 virtual std::string render(const std::string& t) const {return "\"" + t + "\"" ; }
|
|
ferencd@0
|
550
|
|
ferencd@0
|
551 virtual std::string crypted(bool crypt) {return cppdb::crypt_db_value(mvalue, crypt); }
|
|
ferencd@0
|
552 virtual value_renderer& decrypted(bool crypt) { mvalue = cppdb::decrypt_db_value(mvalue, crypt); return *this;}
|
|
ferencd@0
|
553 std::string value() const {return mvalue; }
|
|
ferencd@0
|
554 private:
|
|
ferencd@0
|
555 size_t s;
|
|
ferencd@0
|
556 std::string mvalue = "";
|
|
ferencd@0
|
557 };
|
|
ferencd@0
|
558
|
|
ferencd@0
|
559 template <size_t SIZE>
|
|
ferencd@0
|
560 std::basic_ostream<char>& operator << (std::basic_ostream<char>& os, varchar<SIZE> vc)
|
|
ferencd@0
|
561 {
|
|
ferencd@0
|
562 os << vc.operator std::string();
|
|
ferencd@0
|
563 return os;
|
|
ferencd@0
|
564 }
|
|
ferencd@0
|
565
|
|
ferencd@0
|
566 #define VARCHAR(S) varchar<S>
|
|
ferencd@0
|
567
|
|
ferencd@0
|
568 // text support
|
|
ferencd@0
|
569 class text: public value_renderer
|
|
ferencd@0
|
570 {
|
|
ferencd@0
|
571 public:
|
|
ferencd@0
|
572 // this has to be "const char*" otherwise overloading upon const std::string& is not possible in Column classes
|
|
ferencd@0
|
573 typedef const char* type;
|
|
ferencd@0
|
574
|
|
ferencd@0
|
575 text() = default;
|
|
ferencd@0
|
576 text(const std::string& v) : mvalue(v) {}
|
|
ferencd@0
|
577 operator std::string () const
|
|
ferencd@0
|
578 {
|
|
ferencd@0
|
579 return _O("TEXT");
|
|
ferencd@0
|
580 }
|
|
ferencd@0
|
581
|
|
ferencd@0
|
582 std::string get_type() const
|
|
ferencd@0
|
583 {
|
|
ferencd@0
|
584 return operator std::string();
|
|
ferencd@0
|
585 }
|
|
ferencd@0
|
586
|
|
ferencd@0
|
587 virtual std::string render(const std::string& t) const {return "\"" + t + "\"" ; }
|
|
ferencd@0
|
588
|
|
ferencd@0
|
589 virtual std::string crypted(bool crypt) {return cppdb::crypt_db_value(mvalue, crypt); }
|
|
ferencd@0
|
590 virtual value_renderer& decrypted(bool crypt) { mvalue = cppdb::decrypt_db_value(mvalue, crypt); return *this;}
|
|
ferencd@0
|
591 std::string value() const {return mvalue; }
|
|
ferencd@0
|
592 private:
|
|
ferencd@0
|
593 std::string mvalue = "";
|
|
ferencd@0
|
594 };
|
|
ferencd@0
|
595 std::basic_ostream<char>& operator << (std::basic_ostream<char>& os, const text& tx);
|
|
ferencd@0
|
596
|
|
ferencd@0
|
597 #define TEXT text
|
|
ferencd@0
|
598
|
|
ferencd@0
|
599 // other types support
|
|
ferencd@0
|
600 template <class T> class simple_type : public value_renderer
|
|
ferencd@0
|
601 {
|
|
ferencd@0
|
602 public:
|
|
ferencd@0
|
603 typedef T type;
|
|
ferencd@0
|
604 simple_type() = default;
|
|
ferencd@0
|
605 simple_type(T t) : mt(t) {}
|
|
ferencd@0
|
606 private:
|
|
ferencd@0
|
607 T mt;
|
|
ferencd@0
|
608 };
|
|
ferencd@0
|
609
|
|
ferencd@0
|
610 template <> class simple_type<time_t> : public value_renderer
|
|
ferencd@0
|
611 {
|
|
ferencd@0
|
612 public:
|
|
ferencd@0
|
613 typedef int type;
|
|
ferencd@0
|
614 simple_type() = default;
|
|
ferencd@0
|
615 simple_type(time_t t) : mt(t) {}
|
|
ferencd@0
|
616 simple_type(const std::string& sv) : mt(stol(sv)) {}
|
|
ferencd@0
|
617 std::string get_type() const {return _O("TIMESTAMP"); }
|
|
ferencd@0
|
618 virtual std::string crypted(bool crypt) {return std::to_string(cppdb::crypt_number(mt, crypt));}
|
|
ferencd@0
|
619 virtual value_renderer& decrypted(bool crypt) { mt = cppdb::decrypt_number(mt, crypt); return *this; }
|
|
ferencd@0
|
620 std::string value() const {return std::to_string(mt); }
|
|
ferencd@0
|
621 private:
|
|
ferencd@0
|
622 time_t mt = 0;
|
|
ferencd@0
|
623 };
|
|
ferencd@0
|
624
|
|
ferencd@0
|
625 template <> class simple_type<int> : public value_renderer
|
|
ferencd@0
|
626 {
|
|
ferencd@0
|
627 public:
|
|
ferencd@0
|
628 typedef int type;
|
|
ferencd@0
|
629 simple_type() = default;
|
|
ferencd@0
|
630 simple_type(int t) : mt(t) {}
|
|
ferencd@0
|
631 simple_type(const std::string& sv) : mt(stoi(sv)) {}
|
|
ferencd@0
|
632 std::string get_type() const {return _O("INTEGER"); }
|
|
ferencd@0
|
633 virtual std::string crypted(bool crypt) {return std::to_string(cppdb::crypt_number(mt, crypt));}
|
|
ferencd@0
|
634 virtual value_renderer& decrypted(bool crypt) { mt = static_cast<int>(cppdb::decrypt_number(mt, crypt)); return *this; }
|
|
ferencd@0
|
635 std::string value() const {return std::to_string(mt); }
|
|
ferencd@0
|
636 private:
|
|
ferencd@0
|
637 int mt = 0;
|
|
ferencd@0
|
638 };
|
|
ferencd@0
|
639
|
|
ferencd@0
|
640 #define INTEGER simple_type<int>
|
|
ferencd@0
|
641 #define TIMESTAMP simple_type<time_t>
|
|
ferencd@0
|
642
|
|
ferencd@0
|
643 struct primary_key { const std::string modifier() {return _O("PRIMARY KEY"); } };
|
|
ferencd@0
|
644 struct not_null { const std::string modifier() {return _O("NOT NULL"); } };
|
|
ferencd@0
|
645
|
|
ferencd@0
|
646 template<class D>
|
|
ferencd@0
|
647 struct defaults
|
|
ferencd@0
|
648 {
|
|
ferencd@0
|
649 defaults(const D& d) : md(d) {}
|
|
ferencd@0
|
650 std::string get_modifier() const
|
|
ferencd@0
|
651 {
|
|
ferencd@0
|
652 std::string res = _O("DEFAULT ");
|
|
ferencd@0
|
653 std::stringstream ss; ss << md ; return res + ss.str();
|
|
ferencd@0
|
654 }
|
|
ferencd@0
|
655 private:
|
|
ferencd@0
|
656 D md;
|
|
ferencd@0
|
657 };
|
|
ferencd@0
|
658
|
|
ferencd@0
|
659 template <class T> class modifier_templ
|
|
ferencd@0
|
660 {
|
|
ferencd@0
|
661 public:
|
|
ferencd@0
|
662 modifier_templ(){}
|
|
ferencd@0
|
663 std::string get_modifier() const {return T().modifier();}
|
|
ferencd@0
|
664 };
|
|
ferencd@0
|
665
|
|
ferencd@0
|
666 static const modifier_templ<primary_key> pk;
|
|
ferencd@0
|
667 static const modifier_templ<not_null> nn;
|
|
ferencd@0
|
668
|
|
ferencd@0
|
669 #define PRIMARY_KEY pk
|
|
ferencd@0
|
670 #define NOT_NULL nn
|
|
ferencd@0
|
671 #define CURRENT_TIMESTAMP _O("CURRENT_TIMESTAMP")
|
|
ferencd@0
|
672 #define DEFAULT(X) defaults<decltype(X)>(X)
|
|
ferencd@0
|
673
|
|
ferencd@0
|
674 /* The actual warehouse keeping all the tables, columns and other elements */
|
|
ferencd@0
|
675 class cppdb_warehouse
|
|
ferencd@0
|
676 {
|
|
ferencd@0
|
677 public:
|
|
ferencd@0
|
678 static cppdb_warehouse& instance();
|
|
ferencd@0
|
679 bool add_column(const Column* c);
|
|
ferencd@0
|
680 bool add_table(const Table* t);
|
|
ferencd@0
|
681 const Table* table(const std::string& tabname);
|
|
ferencd@0
|
682 const Column* column(const std::string& colname);
|
|
ferencd@0
|
683 private:
|
|
ferencd@0
|
684 std::vector<const Column*> columns;
|
|
ferencd@0
|
685 std::vector<const Table*> tables;
|
|
ferencd@0
|
686 };
|
|
ferencd@0
|
687
|
|
ferencd@0
|
688 #endif // CPPDB
|