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 &params) = 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 &params);
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_