Mercurial > code
comparison C++/modules/Driver/Driver.h @ 334:0b576ee64d45
* Create brand new hierarchy
* Rename DynLib to Dynlib
* Remove some warnings
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 08 Mar 2015 14:26:33 +0100 |
parents | C++/Driver.h@1aceace80f61 |
children |
comparison
equal
deleted
inserted
replaced
333:412ca7a5e1ea | 334:0b576ee64d45 |
---|---|
1 /* | |
2 * Driver.h -- generic SQL driver access | |
3 * | |
4 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #ifndef _DRIVER_H_ | |
20 #define _DRIVER_H_ | |
21 | |
22 #include <ctime> | |
23 #include <memory> | |
24 #include <string> | |
25 #include <unordered_map> | |
26 #include <type_traits> | |
27 | |
28 /** | |
29 * @enum DriverColumn | |
30 * @brief The column type request | |
31 * | |
32 * Used for the drivers. | |
33 */ | |
34 enum class DriverColumn { | |
35 Invalid, //! not found | |
36 Boolean, //! bool or 0 / 1 | |
37 Date, //! date see Common/Date.h | |
38 Double, //! double | |
39 Integer, //! 32 or 64 bit int | |
40 String, //! varchar to std::string | |
41 }; | |
42 | |
43 template <typename T> | |
44 struct DriverTypeInfo : std::false_type { }; | |
45 | |
46 /** | |
47 * @class Query | |
48 * @brief Class for querying the database | |
49 * | |
50 * That class is returned when a SQL query succeed. It can retrieve the | |
51 * number of rows, columns and retrieve the results independantly from the | |
52 * driver. | |
53 * | |
54 * @see Driver::query | |
55 */ | |
56 class DriverQuery { | |
57 public: | |
58 friend struct DriverTypeInfo<bool>; | |
59 friend struct DriverTypeInfo<time_t>; | |
60 friend struct DriverTypeInfo<double>; | |
61 friend struct DriverTypeInfo<int>; | |
62 friend struct DriverTypeInfo<std::string>; | |
63 | |
64 class Impl { | |
65 public: | |
66 /** | |
67 * Get a bool. | |
68 * | |
69 * @param row the row number | |
70 * @param column the column | |
71 * @return the value | |
72 */ | |
73 virtual bool getBoolean(int row, const std::string &column) = 0; | |
74 | |
75 /** | |
76 * Get a Date. | |
77 * | |
78 * @param row the row number | |
79 * @param column the column | |
80 * @return the value | |
81 */ | |
82 virtual time_t getDate(int row, const std::string &column) = 0; | |
83 | |
84 /** | |
85 * Get a double. | |
86 * | |
87 * @param row the row number | |
88 * @param column the column | |
89 * @return the value | |
90 */ | |
91 virtual double getDouble(int row, const std::string &column) = 0; | |
92 | |
93 /** | |
94 * Get a integer. | |
95 * | |
96 * @param row the row number | |
97 * @param column the column | |
98 * @return the value | |
99 */ | |
100 virtual int getInt(int row, const std::string &column) = 0; | |
101 | |
102 /** | |
103 * Get a string. | |
104 * | |
105 * @param row the row number | |
106 * @param column the column | |
107 * @return the value | |
108 */ | |
109 virtual std::string getString(int row, const std::string &column) = 0; | |
110 | |
111 /** | |
112 * Returns the type of a named column. | |
113 * | |
114 * @param column the column name | |
115 * @return the type | |
116 */ | |
117 virtual DriverColumn type(const std::string &column) const = 0; | |
118 | |
119 /** | |
120 * Tells how many rows has been fetched. | |
121 * | |
122 * @return the number of rows | |
123 */ | |
124 virtual int countRows() = 0; | |
125 | |
126 /** | |
127 * Tells how many number of columns are present for each | |
128 * row. | |
129 * | |
130 * @return the number of columns | |
131 */ | |
132 virtual int countColumns() = 0; | |
133 | |
134 /** | |
135 * Tells if the column is null or not. | |
136 * | |
137 * @param row the row number | |
138 * @param column the column | |
139 * @return an true if null | |
140 */ | |
141 virtual bool isNull(int row, const std::string &column) = 0; | |
142 | |
143 /** | |
144 * Dump all rows and columns. | |
145 */ | |
146 virtual void dump() = 0; | |
147 }; | |
148 | |
149 using Ptr = std::shared_ptr<Impl>; | |
150 | |
151 private: | |
152 /** | |
153 * Check if the request is valid and throws an exception | |
154 * on error. | |
155 * | |
156 * @param row the row number | |
157 * @param column the column name | |
158 * @param type | |
159 * @throw Error on error | |
160 */ | |
161 void assertRequest(int row, const std::string &column, DriverColumn type); | |
162 | |
163 protected: | |
164 Ptr m_impl; | |
165 | |
166 public: | |
167 DriverQuery(Ptr impl); | |
168 | |
169 /** | |
170 * Default destructor. | |
171 */ | |
172 virtual ~DriverQuery(); | |
173 | |
174 /** | |
175 * Get a variable from a row and column. | |
176 * | |
177 * Specialization available: | |
178 * - bool | |
179 * - Date | |
180 * - double | |
181 * - int | |
182 * - std::string | |
183 * | |
184 * @param row the row number (starts from 0) | |
185 * @param column the the column name | |
186 * @return the value | |
187 * @throw Query::Error on error | |
188 */ | |
189 template <class T> | |
190 T get(int row, const std::string &column) | |
191 { | |
192 static_assert(DriverTypeInfo<T>::value, "unsupported type"); | |
193 | |
194 assertRequest(row, column, DriverTypeInfo<T>::type); | |
195 | |
196 return DriverTypeInfo<T>::get(*this, row, column); | |
197 } | |
198 | |
199 /** | |
200 * Returns the type of a named column. | |
201 * | |
202 * @param column the column name | |
203 * @return the type | |
204 */ | |
205 DriverColumn type(const std::string &column) const; | |
206 | |
207 /** | |
208 * Tells how many rows has been fetched. | |
209 * | |
210 * @return the number of rows | |
211 */ | |
212 int countRows(); | |
213 | |
214 /** | |
215 * Tells how many number of columns are present for each | |
216 * row. | |
217 * | |
218 * @return the number of columns | |
219 */ | |
220 int countColumns(); | |
221 | |
222 /** | |
223 * Tells if the column is null or not. | |
224 * | |
225 * @param row the row number | |
226 * @param column the column | |
227 * @return an true if null | |
228 */ | |
229 bool isNull(int row, const std::string &column); | |
230 | |
231 /** | |
232 * Dump all rows and columns. | |
233 */ | |
234 void dump(); | |
235 }; | |
236 | |
237 /** | |
238 * @class Request | |
239 * @brief A secure helper for creating requests | |
240 * | |
241 * This helps creating class with SQL injection security and such. | |
242 */ | |
243 class DriverRequest { | |
244 public: | |
245 friend struct DriverTypeInfo<bool>; | |
246 friend struct DriverTypeInfo<time_t>; | |
247 friend struct DriverTypeInfo<double>; | |
248 friend struct DriverTypeInfo<int>; | |
249 friend struct DriverTypeInfo<std::string>; | |
250 | |
251 class Impl { | |
252 public: | |
253 /** | |
254 * Bind a boolean. | |
255 * | |
256 * @param value the boolean | |
257 * @return the string to use | |
258 */ | |
259 virtual std::string bindBoolean(bool value) = 0; | |
260 | |
261 /** | |
262 * Bind a date. | |
263 * | |
264 * @param value the date | |
265 * @return the string to use | |
266 */ | |
267 virtual std::string bindDate(time_t value) = 0; | |
268 | |
269 /** | |
270 * Bind a double. | |
271 * | |
272 * @param value the double | |
273 * @return the string to use | |
274 */ | |
275 virtual std::string bindDouble(double value) = 0; | |
276 | |
277 /** | |
278 * Bind an integer. | |
279 * | |
280 * @param value the integer | |
281 * @return the string to use | |
282 */ | |
283 virtual std::string bindInteger(int value) = 0; | |
284 | |
285 /** | |
286 * Bind a string. | |
287 * | |
288 * @param value the string | |
289 * @return the string to use | |
290 */ | |
291 virtual std::string bindString(std::string value) = 0; | |
292 }; | |
293 | |
294 using Ptr = std::shared_ptr<Impl>; | |
295 | |
296 private: | |
297 size_t m_pos; | |
298 int m_params; | |
299 std::string m_command; | |
300 Ptr m_impl; | |
301 | |
302 void assertCorrect(); | |
303 | |
304 void setValue(const std::string &value); | |
305 | |
306 public: | |
307 DriverRequest(Ptr impl, const std::string &command); | |
308 | |
309 /** | |
310 * Default destructor. | |
311 */ | |
312 virtual ~DriverRequest(); | |
313 | |
314 /** | |
315 * Bind a value. | |
316 * | |
317 * @param value the value | |
318 */ | |
319 template <typename T> | |
320 void bind(T value) | |
321 { | |
322 static_assert(DriverTypeInfo<T>::value, "unsupported type"); | |
323 | |
324 setValue(DriverTypeInfo<T>::bind(value)); | |
325 } | |
326 | |
327 /** | |
328 * Convert the request to string. | |
329 * | |
330 * @return the request as a string | |
331 */ | |
332 operator std::string(); | |
333 }; | |
334 | |
335 /** | |
336 * @class Driver | |
337 * @brief A generic SQL driver | |
338 * | |
339 * This class is used to connect to a database and execute SQL queries. It | |
340 * does not include any DBMS code and just call virtual functions for | |
341 * a simpler integration of new DBMS drivers. | |
342 */ | |
343 class Driver { | |
344 public: | |
345 class Impl; | |
346 | |
347 using Params = std::unordered_map<std::string, std::string>; | |
348 using Ptr = std::shared_ptr<Impl>; | |
349 | |
350 class Impl { | |
351 public: | |
352 /** | |
353 * Create a synchronous connection, it waits and block until | |
354 * the connection is made up to a specified timeout max. | |
355 * | |
356 * @param params a list of parameters. | |
357 */ | |
358 virtual void connect(const Params ¶ms) = 0; | |
359 | |
360 /** | |
361 * Prepare a request with the specified SQL command. | |
362 * | |
363 * @param command the SQL command to parse and bind | |
364 * @return a request to use with query | |
365 * @see query | |
366 */ | |
367 virtual DriverRequest prepare(const std::string &command) = 0; | |
368 | |
369 /** | |
370 * Execute a query. | |
371 * | |
372 * @param query the SQL command | |
373 * @return a result | |
374 * @throw Query::Error on failure | |
375 */ | |
376 virtual DriverQuery query(const std::string &command) = 0; | |
377 | |
378 /** | |
379 * Get the driver connection description. | |
380 * | |
381 * @return the description | |
382 */ | |
383 virtual std::string description() const = 0; | |
384 | |
385 /** | |
386 * Get the driver version as a string. | |
387 * | |
388 * @return the version | |
389 */ | |
390 virtual std::string version() const = 0; | |
391 }; | |
392 | |
393 protected: | |
394 Ptr m_impl; | |
395 | |
396 public: | |
397 Driver() = default; | |
398 | |
399 /** | |
400 * Virtual destructor. | |
401 */ | |
402 virtual ~Driver() = default; | |
403 | |
404 /** | |
405 * Wrapper for std::string variant. | |
406 * | |
407 * @param request the request to use | |
408 * @return a result | |
409 * @throw Query::Error on failure | |
410 */ | |
411 DriverQuery query(DriverRequest request); | |
412 | |
413 /** | |
414 * Create a synchronous connection, it waits and block until | |
415 * the connection is made up to a specified timeout max. | |
416 * | |
417 * @param params a list of parameters. | |
418 */ | |
419 void connect(const Params ¶ms); | |
420 | |
421 /** | |
422 * Prepare a request with the specified SQL command. | |
423 * | |
424 * @param command the SQL command to parse and bind | |
425 * @return a request to use with query | |
426 * @see query | |
427 */ | |
428 DriverRequest prepare(const std::string &command); | |
429 | |
430 /** | |
431 * Execute a query. | |
432 * | |
433 * @param query the SQL command | |
434 * @return a result | |
435 * @throw Query::Error on failure | |
436 */ | |
437 DriverQuery query(const std::string &command); | |
438 | |
439 /** | |
440 * Get the driver connection description. | |
441 * | |
442 * @return the description | |
443 */ | |
444 std::string description() const; | |
445 | |
446 /** | |
447 * Get the driver version as a string. | |
448 * | |
449 * @return the version | |
450 */ | |
451 std::string version() const; | |
452 }; | |
453 | |
454 template <> | |
455 struct DriverTypeInfo<bool> : std::true_type { | |
456 static const DriverColumn type = DriverColumn::Boolean; | |
457 | |
458 static bool get(DriverQuery &query, int row, const std::string &column) | |
459 { | |
460 return query.m_impl->getBoolean(row, column); | |
461 } | |
462 | |
463 static void bind(DriverRequest &request, bool value) | |
464 { | |
465 request.m_impl->bindBoolean(value); | |
466 } | |
467 }; | |
468 | |
469 template <> | |
470 struct DriverTypeInfo<time_t> : std::true_type { | |
471 static const DriverColumn type = DriverColumn::Date; | |
472 | |
473 static time_t get(DriverQuery &query, int row, const std::string &column) | |
474 { | |
475 return query.m_impl->getDate(row, column); | |
476 } | |
477 | |
478 static void bind(DriverRequest &request, time_t value) | |
479 { | |
480 request.m_impl->bindDate(value); | |
481 } | |
482 }; | |
483 | |
484 template <> | |
485 struct DriverTypeInfo<double> : std::true_type { | |
486 static const DriverColumn type = DriverColumn::Double; | |
487 | |
488 static double get(DriverQuery &query, int row, const std::string &column) | |
489 { | |
490 return query.m_impl->getDouble(row, column); | |
491 } | |
492 | |
493 static void bind(DriverRequest &request, double value) | |
494 { | |
495 request.m_impl->bindDouble(value); | |
496 } | |
497 }; | |
498 | |
499 template <> | |
500 struct DriverTypeInfo<int> : std::true_type { | |
501 static const DriverColumn type = DriverColumn::Integer; | |
502 | |
503 static int get(DriverQuery &query, int row, const std::string &column) | |
504 { | |
505 return query.m_impl->getInt(row, column); | |
506 } | |
507 | |
508 static void bind(DriverRequest &request, int value) | |
509 { | |
510 request.m_impl->bindInteger(value); | |
511 } | |
512 }; | |
513 | |
514 template <> | |
515 struct DriverTypeInfo<std::string> : std::true_type { | |
516 static const DriverColumn type = DriverColumn::String; | |
517 | |
518 static std::string get(DriverQuery &query, int row, const std::string &column) | |
519 { | |
520 return query.m_impl->getString(row, column); | |
521 } | |
522 | |
523 static void bind(DriverRequest &request, const std::string &value) | |
524 { | |
525 request.m_impl->bindString(value); | |
526 } | |
527 }; | |
528 | |
529 #endif // !_DRIVER_H_ |