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