2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file sql_connection.h
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of SQL connection
22 #ifndef CKM_SQL_CONNECTION_H
23 #define CKM_SQL_CONNECTION_H
25 #include <dpl/noncopyable.h>
26 #include <dpl/exception.h>
27 #include <dpl/availability.h>
29 #include <boost/optional.hpp>
30 #include <dpl/string.h>
31 #include <dpl/log/log.h>
32 #include <sqlcipher.h>
34 #include <dpl/assert.h>
41 * SQL connection class
47 * SQL Exception classes
52 DECLARE_EXCEPTION_TYPE(CKM::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 DECLARE_EXCEPTION_TYPE(Base, InvalidArguments)
60 typedef int ColumnIndex;
61 typedef int ArgumentIndex;
64 * SQL processed data command
70 SqlConnection *m_masterConnection;
71 sqlcipher3_stmt *m_stmt;
73 void CheckBindResult(int result);
74 void CheckColumnIndex(SqlConnection::ColumnIndex column);
76 DataCommand(SqlConnection *connection, const char *buffer);
78 friend class SqlConnection;
81 virtual ~DataCommand();
84 * Bind null to the prepared statement argument
86 * @param position Index of argument to bind value to
88 void BindNull(ArgumentIndex position);
91 * Bind int to the prepared statement argument
93 * @param position Index of argument to bind value to
94 * @param value Value to bind
96 void BindInteger(ArgumentIndex position, int value);
99 * Bind int8_t to the prepared statement argument
101 * @param position Index of argument to bind value to
102 * @param value Value to bind
104 void BindInt8(ArgumentIndex position, int8_t value);
107 * Bind int16 to the prepared statement argument
109 * @param position Index of argument to bind value to
110 * @param value Value to bind
112 void BindInt16(ArgumentIndex position, int16_t value);
115 * Bind int32 to the prepared statement argument
117 * @param position Index of argument to bind value to
118 * @param value Value to bind
120 void BindInt32(ArgumentIndex position, int32_t value);
123 * Bind int64 to the prepared statement argument
125 * @param position Index of argument to bind value to
126 * @param value Value to bind
128 void BindInt64(ArgumentIndex position, int64_t value);
131 * Bind float to the prepared statement argument
133 * @param position Index of argument to bind value to
134 * @param value Value to bind
136 void BindFloat(ArgumentIndex position, float value);
139 * Bind double to the prepared statement argument
141 * @param position Index of argument to bind value to
142 * @param value Value to bind
144 void BindDouble(ArgumentIndex position, double value);
147 * Bind string to the prepared statement argument
149 * @param position Index of argument to bind value to
150 * @param value Value to bind
152 void BindString(ArgumentIndex position, const char *value);
155 * Bind string to the prepared statement argument
157 * @param position Index of argument to bind value to
158 * @param value Value to bind
160 void BindString(ArgumentIndex position, const String& value);
163 * Bind optional int to the prepared statement argument.
164 * If optional is not set null will be bound
166 * @param position Index of argument to bind value to
167 * @param value Value to bind
169 void BindInteger(ArgumentIndex position, const boost::optional<int> &value);
172 * Bind optional int8 to the prepared statement argument.
173 * If optional is not set null will be bound
175 * @param position Index of argument to bind value to
176 * @param value Value to bind
178 void BindInt8(ArgumentIndex position, const boost::optional<int8_t> &value);
181 * Bind optional int16 to the prepared statement argument.
182 * If optional is not set null will be bound
184 * @param position Index of argument to bind value to
185 * @param value Value to bind
187 void BindInt16(ArgumentIndex position, const boost::optional<int16_t> &value);
190 * Bind optional int32 to the prepared statement argument.
191 * If optional is not set null will be bound
193 * @param position Index of argument to bind value to
194 * @param value Value to bind
196 void BindInt32(ArgumentIndex position, const boost::optional<int32_t> &value);
199 * Bind optional int64 to the prepared statement argument.
200 * If optional is not set null will be bound
202 * @param position Index of argument to bind value to
203 * @param value Value to bind
205 void BindInt64(ArgumentIndex position, const boost::optional<int64_t> &value);
208 * Bind optional float to the prepared statement argument.
209 * If optional is not set null will be bound
211 * @param position Index of argument to bind value to
212 * @param value Value to bind
214 void BindFloat(ArgumentIndex position, const boost::optional<float> &value);
217 * Bind optional double to the prepared statement argument.
218 * If optional is not set null will be bound
220 * @param position Index of argument to bind value to
221 * @param value Value to bind
223 void BindDouble(ArgumentIndex position, const boost::optional<double> &value);
226 * Bind optional string to the prepared statement argument.
227 * If optional is not set null will be bound
229 * @param position Index of argument to bind value to
230 * @param value Value to bind
232 void BindString(ArgumentIndex position, const boost::optional<String> &value);
235 * Execute the prepared statement and/or move
236 * to the next row of the result
238 * @return True when there was a row returned
243 * Reset prepared statement's arguments
244 * All parameters will become null
249 * Checks whether column value is null
251 * @throw Exception::InvalidColumn
253 bool IsColumnNull(ColumnIndex column);
256 * Get integer value from column in current row.
258 * @throw Exception::InvalidColumn
260 int GetColumnInteger(ColumnIndex column);
263 * Get int8 value from column in current row.
265 * @throw Exception::InvalidColumn
267 int8_t GetColumnInt8(ColumnIndex column);
270 * Get int16 value from column in current row.
272 * @throw Exception::InvalidColumn
274 int16_t GetColumnInt16(ColumnIndex column);
276 * Get int32 value from column in current row.
278 * @throw Exception::InvalidColumn
280 int32_t GetColumnInt32(ColumnIndex column);
283 * Get int64 value from column in current row.
285 * @throw Exception::InvalidColumn
287 int64_t GetColumnInt64(ColumnIndex column);
290 * Get float value from column in current row.
292 * @throw Exception::InvalidColumn
294 float GetColumnFloat(ColumnIndex column);
297 * Get double value from column in current row.
299 * @throw Exception::InvalidColumn
301 double GetColumnDouble(ColumnIndex column);
304 * Get string value from column in current row.
306 * @throw Exception::InvalidColumn
308 std::string GetColumnString(ColumnIndex column);
311 * Get optional integer value from column in current row.
313 * @throw Exception::InvalidColumn
315 boost::optional<int> GetColumnOptionalInteger(ColumnIndex column);
318 * Get optional int8 value from column in current row.
320 * @throw Exception::InvalidColumn
322 boost::optional<int8_t> GetColumnOptionalInt8(ColumnIndex column);
325 * Get optional int16value from column in current row.
327 * @throw Exception::InvalidColumn
329 boost::optional<int16_t> GetColumnOptionalInt16(ColumnIndex column);
332 * Get optional int32 value from column in current row.
334 * @throw Exception::InvalidColumn
336 boost::optional<int32_t> GetColumnOptionalInt32(ColumnIndex column);
339 * Get optional int64 value from column in current row.
341 * @throw Exception::InvalidColumn
343 boost::optional<int64_t> GetColumnOptionalInt64(ColumnIndex column);
346 * Get optional float value from column in current row.
348 * @throw Exception::InvalidColumn
350 boost::optional<float> GetColumnOptionalFloat(ColumnIndex column);
353 * Get optional double value from column in current row.
355 * @throw Exception::InvalidColumn
357 boost::optional<double> GetColumnOptionalDouble(ColumnIndex column);
360 * Get optional string value from column in current row.
362 * @throw Exception::InvalidColumn
364 boost::optional<String> GetColumnOptionalString(ColumnIndex column);
367 // Move on copy semantics
368 typedef std::auto_ptr<DataCommand> DataCommandAutoPtr;
376 RO = SQLCIPHER_OPEN_NOMUTEX | SQLCIPHER_OPEN_READONLY,
377 RW = SQLCIPHER_OPEN_NOMUTEX | SQLCIPHER_OPEN_READWRITE,
378 CRW = RW | SQLCIPHER_OPEN_CREATE
383 typedef sqlcipher3_int64 RowID;
386 * Synchronization object used to synchronize SQL connection
387 * to the same database across different threads and processes
389 class SynchronizationObject
392 virtual ~SynchronizationObject() {}
395 * Synchronizes SQL connection for multiple clients.
397 virtual void Synchronize() = 0;
400 * Notify all waiting clients that the connection is no longer locked.
402 virtual void NotifyAll() = 0;
406 sqlcipher3 *m_connection;
410 // Stored data procedures
411 int m_dataCommandsCount;
413 // Synchronization object
414 std::unique_ptr<SynchronizationObject> m_synchronizationObject;
418 virtual void Connect(const std::string &address,
419 Flag::Option = Flag::RO);
420 virtual void Disconnect();
422 void TurnOnForeignKeys();
424 static SynchronizationObject *AllocDefaultSynchronizationObject();
428 * Open SQL connection
430 * Synchronization is archieved by using provided asynchronization object.
431 * If synchronizationObject is set to NULL, so synchronization is performed.
432 * Ownership of the synchronization object is transfered to sql connection
435 * @param address Database file name
436 * @param flags Open flags
437 * @param synchronizationObject A synchronization object to use.
439 explicit SqlConnection(const std::string &address = std::string(),
440 Flag::Option options = Flag::RO,
441 SynchronizationObject *synchronizationObject =
442 AllocDefaultSynchronizationObject());
447 virtual ~SqlConnection();
450 * Added extension for encryption functionality:
452 * SetKey gives sqlcipher key, which will be used to encrypt the database
453 * This function will only fail because of invalid arguments. To check if
454 * database can be opened with provided key, it is necessary to perform
455 * some operation on the database (i.e. read from it) and confirm if it
457 * Password must have length >= 1.
459 * @param rawPass password given in raw binary format
461 void SetKey(const std::vector<unsigned char> &rawPass);
464 * ResetKey is used for changing key used for database encryption.
465 * If key was already set by using SetKey, this function will only change it.
466 * If no key was yet set, this function first will set key with rawPassOld and
467 * then change it to rawPassNew.
468 * Same rules for failing apply as for SetKey.
469 * Both password must have length >=1.
471 * @param rawPassOld current password for encryption in raw binary format
472 * @param rawPassNew new password for encryption in raw binary format
475 void ResetKey(const std::vector<unsigned char> &rawPassOld,
476 const std::vector<unsigned char> &rawPassNew);
479 * Execute SQL command without result
484 void ExecCommand(const char *format, ...) CKM_DEPRECATED_WITH_MESSAGE(
485 "To prevent sql injection do not use this \
486 method for direct sql execution");
489 * Execute BEGIN; command to start new transaction
492 void BeginTransaction();
495 * Execute ROLLBACK; command to discard changes made
498 void RollbackTransaction();
501 * Execute COMMIT; command to commit changes in database
504 void CommitTransaction();
507 * Prepare stored procedure
509 * @param format SQL statement
510 * @return Data command representing stored procedure
512 DataCommandAutoPtr PrepareDataCommand(const char *format, ...);
515 * Check whether given table exists
517 * @param tableName Name of the table to check
518 * @return True if given table name exists
520 bool CheckTableExist(const char *tableName);
523 * Get last insert operation new row id
527 RowID GetLastInsertRowID() const;
532 #endif // CKM_SQL_CONNECTION_H