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>
38 #include <safe-buffer.h>
43 * SQL connection class
49 * SQL Exception classes
54 DECLARE_EXCEPTION_TYPE(CKM::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 DECLARE_EXCEPTION_TYPE(Base, InvalidArguments)
62 typedef int ColumnIndex;
63 typedef int ArgumentIndex;
66 * SQL processed data command
72 SqlConnection *m_masterConnection;
73 sqlcipher3_stmt *m_stmt;
75 void CheckBindResult(int result);
76 void CheckColumnIndex(SqlConnection::ColumnIndex column);
78 DataCommand(SqlConnection *connection, const char *buffer);
80 friend class SqlConnection;
83 virtual ~DataCommand();
86 * Bind null to the prepared statement argument
88 * @param position Index of argument to bind value to
90 void BindNull(ArgumentIndex position);
93 * Bind int to the prepared statement argument
95 * @param position Index of argument to bind value to
96 * @param value Value to bind
98 void BindInteger(ArgumentIndex position, int value);
101 * Bind int8_t to the prepared statement argument
103 * @param position Index of argument to bind value to
104 * @param value Value to bind
106 void BindInt8(ArgumentIndex position, int8_t value);
109 * Bind int16 to the prepared statement argument
111 * @param position Index of argument to bind value to
112 * @param value Value to bind
114 void BindInt16(ArgumentIndex position, int16_t value);
117 * Bind int32 to the prepared statement argument
119 * @param position Index of argument to bind value to
120 * @param value Value to bind
122 void BindInt32(ArgumentIndex position, int32_t value);
125 * Bind int64 to the prepared statement argument
127 * @param position Index of argument to bind value to
128 * @param value Value to bind
130 void BindInt64(ArgumentIndex position, int64_t value);
133 * Bind float to the prepared statement argument
135 * @param position Index of argument to bind value to
136 * @param value Value to bind
138 void BindFloat(ArgumentIndex position, float value);
141 * Bind double to the prepared statement argument
143 * @param position Index of argument to bind value to
144 * @param value Value to bind
146 void BindDouble(ArgumentIndex position, double value);
149 * Bind string to the prepared statement argument
151 * @param position Index of argument to bind value to
152 * @param value Value to bind
154 void BindString(ArgumentIndex position, const char *value);
157 * Bind string to the prepared statement argument
159 * @param position Index of argument to bind value to
160 * @param value Value to bind
162 void BindString(ArgumentIndex position, const String& value);
165 * Bind string to the prepared statement argument
167 * @param position Index of argument to bind value to
168 * @param value Value to bind
170 void BindBlob(ArgumentIndex position, const SafeBuffer &value);
173 * Bind optional int to the prepared statement argument.
174 * If optional is not set null will be bound
176 * @param position Index of argument to bind value to
177 * @param value Value to bind
179 void BindInteger(ArgumentIndex position, const boost::optional<int> &value);
182 * Bind optional int8 to the prepared statement argument.
183 * If optional is not set null will be bound
185 * @param position Index of argument to bind value to
186 * @param value Value to bind
188 void BindInt8(ArgumentIndex position, const boost::optional<int8_t> &value);
191 * Bind optional int16 to the prepared statement argument.
192 * If optional is not set null will be bound
194 * @param position Index of argument to bind value to
195 * @param value Value to bind
197 void BindInt16(ArgumentIndex position, const boost::optional<int16_t> &value);
200 * Bind optional int32 to the prepared statement argument.
201 * If optional is not set null will be bound
203 * @param position Index of argument to bind value to
204 * @param value Value to bind
206 void BindInt32(ArgumentIndex position, const boost::optional<int32_t> &value);
209 * Bind optional int64 to the prepared statement argument.
210 * If optional is not set null will be bound
212 * @param position Index of argument to bind value to
213 * @param value Value to bind
215 void BindInt64(ArgumentIndex position, const boost::optional<int64_t> &value);
218 * Bind optional float to the prepared statement argument.
219 * If optional is not set null will be bound
221 * @param position Index of argument to bind value to
222 * @param value Value to bind
224 void BindFloat(ArgumentIndex position, const boost::optional<float> &value);
227 * Bind optional double to the prepared statement argument.
228 * If optional is not set null will be bound
230 * @param position Index of argument to bind value to
231 * @param value Value to bind
233 void BindDouble(ArgumentIndex position, const boost::optional<double> &value);
236 * Bind optional string to the prepared statement argument.
237 * If optional is not set null will be bound
239 * @param position Index of argument to bind value to
240 * @param value Value to bind
242 void BindString(ArgumentIndex position, const boost::optional<String> &value);
245 * Bind optional string to the prepared statement argument.
246 * If optional is not set null will be bound
248 * @param position Index of argument to bind value to
249 * @param value Value to bind
251 void BindBlob(ArgumentIndex position,
252 const boost::optional<SafeBuffer> &value);
255 * Execute the prepared statement and/or move
256 * to the next row of the result
258 * @return True when there was a row returned
263 * Reset prepared statement's arguments
264 * All parameters will become null
269 * Checks whether column value is null
271 * @throw Exception::InvalidColumn
273 bool IsColumnNull(ColumnIndex column);
276 * Get integer value from column in current row.
278 * @throw Exception::InvalidColumn
280 int GetColumnInteger(ColumnIndex column);
283 * Get int8 value from column in current row.
285 * @throw Exception::InvalidColumn
287 int8_t GetColumnInt8(ColumnIndex column);
290 * Get int16 value from column in current row.
292 * @throw Exception::InvalidColumn
294 int16_t GetColumnInt16(ColumnIndex column);
296 * Get int32 value from column in current row.
298 * @throw Exception::InvalidColumn
300 int32_t GetColumnInt32(ColumnIndex column);
303 * Get int64 value from column in current row.
305 * @throw Exception::InvalidColumn
307 int64_t GetColumnInt64(ColumnIndex column);
310 * Get float value from column in current row.
312 * @throw Exception::InvalidColumn
314 float GetColumnFloat(ColumnIndex column);
317 * Get double value from column in current row.
319 * @throw Exception::InvalidColumn
321 double GetColumnDouble(ColumnIndex column);
324 * Get string value from column in current row.
326 * @throw Exception::InvalidColumn
328 std::string GetColumnString(ColumnIndex column);
331 * Get string value from column in current row.
333 * @throw Exception::InvalidColumn
335 SafeBuffer GetColumnBlob(ColumnIndex column);
338 * Get optional integer value from column in current row.
340 * @throw Exception::InvalidColumn
342 boost::optional<int> GetColumnOptionalInteger(ColumnIndex column);
345 * Get optional int8 value from column in current row.
347 * @throw Exception::InvalidColumn
349 boost::optional<int8_t> GetColumnOptionalInt8(ColumnIndex column);
352 * Get optional int16value from column in current row.
354 * @throw Exception::InvalidColumn
356 boost::optional<int16_t> GetColumnOptionalInt16(ColumnIndex column);
359 * Get optional int32 value from column in current row.
361 * @throw Exception::InvalidColumn
363 boost::optional<int32_t> GetColumnOptionalInt32(ColumnIndex column);
366 * Get optional int64 value from column in current row.
368 * @throw Exception::InvalidColumn
370 boost::optional<int64_t> GetColumnOptionalInt64(ColumnIndex column);
373 * Get optional float value from column in current row.
375 * @throw Exception::InvalidColumn
377 boost::optional<float> GetColumnOptionalFloat(ColumnIndex column);
380 * Get optional double value from column in current row.
382 * @throw Exception::InvalidColumn
384 boost::optional<double> GetColumnOptionalDouble(ColumnIndex column);
387 * Get optional string value from column in current row.
389 * @throw Exception::InvalidColumn
391 boost::optional<String> GetColumnOptionalString(ColumnIndex column);
394 * Get string value from column in current row.
396 * @throw Exception::InvalidColumn
398 boost::optional<SafeBuffer> GetColumnOptionalBlob(ColumnIndex column);
401 // Move on copy constructor. No copy semantics
402 typedef std::unique_ptr<DataCommand> DataCommandUniquePtr;
410 RO = SQLCIPHER_OPEN_NOMUTEX | SQLCIPHER_OPEN_READONLY,
411 RW = SQLCIPHER_OPEN_NOMUTEX | SQLCIPHER_OPEN_READWRITE,
412 CRW = RW | SQLCIPHER_OPEN_CREATE
417 typedef sqlcipher3_int64 RowID;
420 * Synchronization object used to synchronize SQL connection
421 * to the same database across different threads and processes
423 class SynchronizationObject
426 virtual ~SynchronizationObject() {}
429 * Synchronizes SQL connection for multiple clients.
431 virtual void Synchronize() = 0;
434 * Notify all waiting clients that the connection is no longer locked.
436 virtual void NotifyAll() = 0;
440 sqlcipher3 *m_connection;
444 // Stored data procedures
445 int m_dataCommandsCount;
447 // Synchronization object
448 std::unique_ptr<SynchronizationObject> m_synchronizationObject;
452 virtual void Connect(const std::string &address,
453 Flag::Option = Flag::RO);
454 virtual void Disconnect();
456 void TurnOnForeignKeys();
458 static SynchronizationObject *AllocDefaultSynchronizationObject();
462 * Open SQL connection
464 * Synchronization is archieved by using provided asynchronization object.
465 * If synchronizationObject is set to NULL, so synchronization is performed.
466 * Ownership of the synchronization object is transfered to sql connection
469 * @param address Database file name
470 * @param flags Open flags
471 * @param synchronizationObject A synchronization object to use.
473 explicit SqlConnection(const std::string &address = std::string(),
474 Flag::Option options = Flag::RO,
475 SynchronizationObject *synchronizationObject =
476 AllocDefaultSynchronizationObject());
481 virtual ~SqlConnection();
484 * Added extension for encryption functionality:
486 * SetKey gives sqlcipher key, which will be used to encrypt the database
487 * This function will only fail because of invalid arguments. To check if
488 * database can be opened with provided key, it is necessary to perform
489 * some operation on the database (i.e. read from it) and confirm if it
491 * Password must have length >= 1.
493 * @param rawPass password given in raw binary format
495 void SetKey(const SafeBuffer &rawPass);
498 * ResetKey is used for changing key used for database encryption.
499 * If key was already set by using SetKey, this function will only change it.
500 * If no key was yet set, this function first will set key with rawPassOld and
501 * then change it to rawPassNew.
502 * Same rules for failing apply as for SetKey.
503 * Both password must have length >=1.
505 * @param rawPassOld current password for encryption in raw binary format
506 * @param rawPassNew new password for encryption in raw binary format
509 void ResetKey(const SafeBuffer &rawPassOld,
510 const SafeBuffer &rawPassNew);
513 * Execute SQL command without result
518 void ExecCommand(const char *format, ...) CKM_DEPRECATED_WITH_MESSAGE(
519 "To prevent sql injection do not use this \
520 method for direct sql execution");
523 * Execute BEGIN; command to start new transaction
526 void BeginTransaction();
529 * Execute ROLLBACK; command to discard changes made
532 void RollbackTransaction();
535 * Execute COMMIT; command to commit changes in database
538 void CommitTransaction();
541 * Prepare stored procedure
543 * @param format SQL statement
544 * @return Data command representing stored procedure
546 DataCommandUniquePtr PrepareDataCommand(const char *format, ...);
549 * Check whether given table exists
551 * @param tableName Name of the table to check
552 * @return True if given table name exists
554 bool CheckTableExist(const char *tableName);
557 * Get last insert operation new row id
561 RowID GetLastInsertRowID() const;
566 #endif // CKM_SQL_CONNECTION_H