7110ba886a6caa6ca47ebc51eeca53da6369ad53
[framework/web/wrt-commons.git] / modules / db / include / dpl / db / sql_connection.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        sql_connection.h
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of SQL connection
21  */
22 #ifndef DPL_SQL_CONNECTION_H
23 #define DPL_SQL_CONNECTION_H
24
25 #include <dpl/noncopyable.h>
26 #include <dpl/exception.h>
27 #include <dpl/optional.h>
28 #include <dpl/scoped_ptr.h>
29 #include <dpl/string.h>
30 #include <dpl/log/log.h>
31 #include <sqlite3.h>
32 #include <string>
33 #include <dpl/assert.h>
34 #include <memory>
35 #include <stdint.h>
36
37 namespace DPL
38 {
39 namespace DB
40 {
41
42 /**
43  * SQL connection class
44  */
45 class SqlConnection
46 {
47 public:
48     /**
49      * SQL Exception classes
50      */
51     class Exception
52     {
53     public:
54         DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
55         DECLARE_EXCEPTION_TYPE(Base, SyntaxError)
56         DECLARE_EXCEPTION_TYPE(Base, ConnectionBroken)
57         DECLARE_EXCEPTION_TYPE(Base, InternalError)
58         DECLARE_EXCEPTION_TYPE(Base, InvalidColumn)
59     };
60
61     typedef int ColumnIndex;
62     typedef int ArgumentIndex;
63
64     /*
65      * SQL processed data command
66      */
67     class DataCommand
68         : private Noncopyable
69     {
70     private:
71         SqlConnection *m_masterConnection;
72         sqlite3_stmt *m_stmt;
73
74         void CheckBindResult(int result);
75         void CheckColumnIndex(SqlConnection::ColumnIndex column);
76
77         DataCommand(SqlConnection *connection, const char *buffer);
78
79         friend class SqlConnection;
80
81     public:
82         virtual ~DataCommand();
83
84         /**
85          * Bind null to the prepared statement argument
86          *
87          * @param position Index of argument to bind value to
88          */
89         void BindNull(ArgumentIndex position);
90
91         /**
92          * Bind int to the prepared statement argument
93          *
94          * @param position Index of argument to bind value to
95          * @param value Value to bind
96          */
97         void BindInteger(ArgumentIndex position, int value);
98
99         /**
100          * Bind int8_t to the prepared statement argument
101          *
102          * @param position Index of argument to bind value to
103          * @param value Value to bind
104          */
105         void BindInt8(ArgumentIndex position, int8_t value);
106
107         /**
108          * Bind int16 to the prepared statement argument
109          *
110          * @param position Index of argument to bind value to
111          * @param value Value to bind
112          */
113         void BindInt16(ArgumentIndex position, int16_t value);
114
115         /**
116          * Bind int32 to the prepared statement argument
117          *
118          * @param position Index of argument to bind value to
119          * @param value Value to bind
120          */
121         void BindInt32(ArgumentIndex position, int32_t value);
122
123         /**
124          * Bind int64 to the prepared statement argument
125          *
126          * @param position Index of argument to bind value to
127          * @param value Value to bind
128          */
129         void BindInt64(ArgumentIndex position, int64_t value);
130
131         /**
132          * Bind float to the prepared statement argument
133          *
134          * @param position Index of argument to bind value to
135          * @param value Value to bind
136          */
137         void BindFloat(ArgumentIndex position, float value);
138
139         /**
140          * Bind double to the prepared statement argument
141          *
142          * @param position Index of argument to bind value to
143          * @param value Value to bind
144          */
145         void BindDouble(ArgumentIndex position, double value);
146
147         /**
148          * Bind string to the prepared statement argument
149          *
150          * @param position Index of argument to bind value to
151          * @param value Value to bind
152          */
153         void BindString(ArgumentIndex position, const char *value);
154
155         /**
156          * Bind string to the prepared statement argument
157          *
158          * @param position Index of argument to bind value to
159          * @param value Value to bind
160          */
161         void BindString(ArgumentIndex position, const String& value);
162
163         /**
164          * Bind optional int to the prepared statement argument.
165          * If optional is not set null will be bound
166          *
167          * @param position Index of argument to bind value to
168          * @param value Value to bind
169          */
170         void BindInteger(ArgumentIndex position, const Optional<int> &value);
171
172         /**
173          * Bind optional int8 to the prepared statement argument.
174          * If optional is not set null will be bound
175          *
176          * @param position Index of argument to bind value to
177          * @param value Value to bind
178          */
179         void BindInt8(ArgumentIndex position, const Optional<int8_t> &value);
180
181         /**
182          * Bind optional int16 to the prepared statement argument.
183          * If optional is not set null will be bound
184          *
185          * @param position Index of argument to bind value to
186          * @param value Value to bind
187          */
188         void BindInt16(ArgumentIndex position, const Optional<int16_t> &value);
189
190         /**
191          * Bind optional int32 to the prepared statement argument.
192          * If optional is not set null will be bound
193          *
194          * @param position Index of argument to bind value to
195          * @param value Value to bind
196          */
197         void BindInt32(ArgumentIndex position, const Optional<int32_t> &value);
198
199         /**
200          * Bind optional int64 to the prepared statement argument.
201          * If optional is not set null will be bound
202          *
203          * @param position Index of argument to bind value to
204          * @param value Value to bind
205          */
206         void BindInt64(ArgumentIndex position, const Optional<int64_t> &value);
207
208         /**
209          * Bind optional float to the prepared statement argument.
210          * If optional is not set null will be bound
211          *
212          * @param position Index of argument to bind value to
213          * @param value Value to bind
214          */
215         void BindFloat(ArgumentIndex position, const Optional<float> &value);
216
217         /**
218          * Bind optional double to the prepared statement argument.
219          * If optional is not set null will be bound
220          *
221          * @param position Index of argument to bind value to
222          * @param value Value to bind
223          */
224         void BindDouble(ArgumentIndex position, const Optional<double> &value);
225
226         /**
227          * Bind optional string to the prepared statement argument.
228          * If optional is not set null will be bound
229          *
230          * @param position Index of argument to bind value to
231          * @param value Value to bind
232          */
233         void BindString(ArgumentIndex position, const Optional<String> &value);
234
235         /**
236          * Execute the prepared statement and/or move
237          * to the next row of the result
238          *
239          * @return True when there was a row returned
240          */
241         bool Step();
242
243         /**
244          * Reset prepared statement's arguments
245          * All parameters will become null
246          */
247         void Reset();
248
249         /**
250          * Checks whether column value is null
251          *
252          * @throw Exception::InvalidColumn
253          */
254         bool IsColumnNull(ColumnIndex column);
255
256         /**
257          * Get integer value from column in current row.
258          *
259          * @throw Exception::InvalidColumn
260          */
261         int GetColumnInteger(ColumnIndex column);
262
263         /**
264          * Get int8 value from column in current row.
265          *
266          * @throw Exception::InvalidColumn
267          */
268         int8_t GetColumnInt8(ColumnIndex column);
269
270         /**
271          * Get int16 value from column in current row.
272          *
273          * @throw Exception::InvalidColumn
274          */
275         int16_t GetColumnInt16(ColumnIndex column);
276         /**
277          * Get int32 value from column in current row.
278          *
279          * @throw Exception::InvalidColumn
280          */
281         int32_t GetColumnInt32(ColumnIndex column);
282
283         /**
284          * Get int64 value from column in current row.
285          *
286          * @throw Exception::InvalidColumn
287          */
288         int64_t GetColumnInt64(ColumnIndex column);
289
290         /**
291          * Get float value from column in current row.
292          *
293          * @throw Exception::InvalidColumn
294          */
295         float GetColumnFloat(ColumnIndex column);
296
297         /**
298          * Get double value from column in current row.
299          *
300          * @throw Exception::InvalidColumn
301          */
302         double GetColumnDouble(ColumnIndex column);
303
304         /**
305          * Get string value from column in current row.
306          *
307          * @throw Exception::InvalidColumn
308          */
309         std::string GetColumnString(ColumnIndex column);
310
311         /**
312          * Get optional integer value from column in current row.
313          *
314          * @throw Exception::InvalidColumn
315          */
316         Optional<int> GetColumnOptionalInteger(ColumnIndex column);
317
318         /**
319          * Get optional int8 value from column in current row.
320          *
321          * @throw Exception::InvalidColumn
322          */
323         Optional<int8_t> GetColumnOptionalInt8(ColumnIndex column);
324
325         /**
326          * Get optional int16value from column in current row.
327          *
328          * @throw Exception::InvalidColumn
329          */
330         Optional<int16_t> GetColumnOptionalInt16(ColumnIndex column);
331
332         /**
333          * Get optional int32 value from column in current row.
334          *
335          * @throw Exception::InvalidColumn
336          */
337         Optional<int32_t> GetColumnOptionalInt32(ColumnIndex column);
338
339         /**
340          * Get optional int64 value from column in current row.
341          *
342          * @throw Exception::InvalidColumn
343          */
344         Optional<int64_t> GetColumnOptionalInt64(ColumnIndex column);
345
346         /**
347          * Get optional float value from column in current row.
348          *
349          * @throw Exception::InvalidColumn
350          */
351         Optional<float> GetColumnOptionalFloat(ColumnIndex column);
352
353         /**
354          * Get optional double value from column in current row.
355          *
356          * @throw Exception::InvalidColumn
357          */
358         Optional<double> GetColumnOptionalDouble(ColumnIndex column);
359
360         /**
361          * Get optional string value from column in current row.
362          *
363          * @throw Exception::InvalidColumn
364          */
365         Optional<String> GetColumnOptionalString(ColumnIndex column);
366     };
367
368     // Move on copy semantics
369     typedef std::auto_ptr<DataCommand> DataCommandAutoPtr;
370
371     // Open flags
372     class Flag
373     {
374     public:
375         enum Type
376         {
377             None      = 1<<0,
378             UseLucene = 1<<1
379         };
380
381         enum Option
382         {
383             RO = SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READONLY,
384             RW =
385             SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
386         };
387     };
388
389     // RowID
390     typedef sqlite3_int64 RowID;
391
392     /**
393      * Synchronization object used to synchronize SQL connection
394      * to the same database across different threads and processes
395      */
396     class SynchronizationObject
397     {
398     public:
399         virtual ~SynchronizationObject() {}
400
401         /**
402          * Synchronizes SQL connection for multiple clients.
403          */
404         virtual void Synchronize() = 0;
405
406         /**
407          * Notify all waiting clients that the connection is no longer locked.
408          */
409         virtual void NotifyAll() = 0;
410     };
411
412 protected:
413     sqlite3 *m_connection;
414
415     // Options
416     bool m_usingLucene;
417
418     // Stored data procedures
419     int m_dataCommandsCount;
420
421     // Synchronization object
422     ScopedPtr<SynchronizationObject> m_synchronizationObject;
423
424     virtual void Connect(const std::string &address,
425                          Flag::Type = Flag::None, Flag::Option = Flag::RO);
426     virtual void Disconnect();
427
428     void TurnOnForeignKeys();
429
430     static SynchronizationObject *AllocDefaultSynchronizationObject();
431
432 public:
433     /**
434      * Open SQL connection
435      *
436      * Synchronization is archieved by using provided asynchronization object.
437      * If synchronizationObject is set to NULL, so synchronization is performed.
438      * Ownership of the synchronization object is transfered to sql connection
439      * object.
440      *
441      * @param address Database file name
442      * @param flags Open flags
443      * @param synchronizationObject A synchronization object to use.
444      */
445     explicit SqlConnection(const std::string &address = std::string(),
446                            Flag::Type flags = Flag::None,
447                            Flag::Option options = Flag::RO,
448                            SynchronizationObject *synchronizationObject =
449                                AllocDefaultSynchronizationObject());
450
451     /**
452      * Destructor
453      */
454     virtual ~SqlConnection();
455
456     /**
457      * Execute SQL command without result
458      *
459      * @param format
460      * @param ...
461      */
462     void ExecCommand(const char *format, ...);
463
464     /**
465      * Prepare stored procedure
466      *
467      * @param format SQL statement
468      * @return Data command representing stored procedure
469      */
470     DataCommandAutoPtr PrepareDataCommand(const char *format, ...);
471
472     /**
473      * Check whether given table exists
474      *
475      * @param tableName Name of the table to check
476      * @return True if given table name exists
477      */
478     bool CheckTableExist(const char *tableName);
479
480     /**
481      * Get last insert operation new row id
482      *
483      * @return Row ID
484      */
485     RowID GetLastInsertRowID() const;
486 };
487
488 } // namespace DB
489 } // namespace DPL
490
491 #endif // DPL_SQL_CONNECTION_H