Switch to sqlcipher library
[platform/core/security/key-manager.git] / src / manager / dpl / db / src / sql_connection.cpp
index 9935499..3aa5b72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
 #include <stddef.h>
 #include <dpl/db/sql_connection.h>
 #include <dpl/db/naive_synchronization_object.h>
-#include <dpl/noncopyable.h>
-#include <dpl/assert.h>
 #include <dpl/scoped_ptr.h>
-#include <db-util.h>
 #include <unistd.h>
+#include <cassert>
 #include <cstdio>
 #include <cstdarg>
 #include <memory>
+#include <noncopyable.h>
 
-namespace CKM {
-namespace DB {
-namespace // anonymous
-{
-class ScopedNotifyAll :
-    public Noncopyable
-{
-  private:
-    SqlConnection::SynchronizationObject *m_synchronizationObject;
-
-  public:
-    explicit ScopedNotifyAll(
-        SqlConnection::SynchronizationObject *synchronizationObject) :
-        m_synchronizationObject(synchronizationObject)
-    {}
 
-    ~ScopedNotifyAll()
-    {
-        if (!m_synchronizationObject) {
-            return;
-        }
+namespace {
+const int MAX_RETRY = 10;
+}
 
-        LogPedantic("Notifying after successful synchronize");
-        m_synchronizationObject->NotifyAll();
-    }
+namespace CKM {
+namespace DB {
+namespace { // anonymous
+class ScopedNotifyAll {
+private:
+       SqlConnection::SynchronizationObject *m_synchronizationObject;
+
+public:
+       NONCOPYABLE(ScopedNotifyAll)
+
+       explicit ScopedNotifyAll(
+               SqlConnection::SynchronizationObject *synchronizationObject) :
+               m_synchronizationObject(synchronizationObject)
+       {
+       }
+
+       ~ScopedNotifyAll()
+       {
+               if (!m_synchronizationObject)
+                       return;
+
+               LogPedantic("Notifying after successful synchronize");
+               m_synchronizationObject->NotifyAll();
+       }
 };
 } // namespace anonymous
 
 SqlConnection::DataCommand::DataCommand(SqlConnection *connection,
-                                        const char *buffer) :
-    m_masterConnection(connection),
-    m_stmt(NULL)
+                                                                               const char *buffer) :
+       m_masterConnection(connection),
+       m_stmt(NULL)
 {
-    Assert(connection != NULL);
+       assert(connection != NULL);
 
-    // Notify all after potentially synchronized database connection access
-    ScopedNotifyAll notifyAll(connection->m_synchronizationObject.get());
+       // Notify all after potentially synchronized database connection access
+       ScopedNotifyAll notifyAll(connection->m_synchronizationObject.get());
 
-    for (;;) {
-        int ret = sqlcipher3_prepare_v2(connection->m_connection,
-                                     buffer, strlen(buffer),
-                                     &m_stmt, NULL);
+       for (int i = 0; i < MAX_RETRY; i++) {
+               int ret = sqlite3_prepare_v2(connection->m_connection,
+                                                                               buffer, strlen(buffer),
+                                                                               &m_stmt, NULL);
 
-        if (ret == SQLCIPHER_OK) {
-            LogPedantic("Data command prepared successfuly");
-            break;
-        } else if (ret == SQLCIPHER_BUSY) {
-            LogPedantic("Collision occurred while preparing SQL command");
+               if (ret == SQLITE_OK) {
+                       LogPedantic("Prepared data command: " << buffer);
 
-            // Synchronize if synchronization object is available
-            if (connection->m_synchronizationObject) {
-                LogPedantic("Performing synchronization");
-                connection->m_synchronizationObject->Synchronize();
-                continue;
-            }
+                       // Increment stored data command count
+                       ++m_masterConnection->m_dataCommandsCount;
+                       return;
+               } else if (ret == SQLITE_BUSY) {
+                       LogPedantic("Collision occurred while preparing SQL command");
 
-            // No synchronization object defined. Fail.
-        }
+                       // Synchronize if synchronization object is available
+                       if (connection->m_synchronizationObject) {
+                               LogPedantic("Performing synchronization");
+                               connection->m_synchronizationObject->Synchronize();
+                               continue;
+                       }
 
-        // Fatal error
-        const char *error = sqlcipher3_errmsg(m_masterConnection->m_connection);
+                       // No synchronization object defined. Fail.
+               }
 
-        LogPedantic("SQL prepare data command failed");
-        LogPedantic("    Statement: " << buffer);
-        LogPedantic("    Error: " << error);
+               // Fatal error
+               const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
 
-        ThrowMsg(Exception::SyntaxError, error);
-    }
+               LogError("SQL prepare data command failed");
+               LogError("    Statement: " << buffer);
+               LogError("    Error: " << error);
 
-    LogPedantic("Prepared data command: " << buffer);
+               ThrowMsg(Exception::SyntaxError, error);
+       }
 
-    // Increment stored data command count
-    ++m_masterConnection->m_dataCommandsCount;
+       LogError("sqlite in the state of possible infinite loop");
+       ThrowMsg(Exception::InternalError, "sqlite permanently busy");
 }
 
 SqlConnection::DataCommand::~DataCommand()
 {
-    LogPedantic("SQL data command finalizing");
+       LogPedantic("SQL data command finalizing");
 
-    if (sqlcipher3_finalize(m_stmt) != SQLCIPHER_OK) {
-        LogPedantic("Failed to finalize data command");
-    }
+       if (sqlite3_finalize(m_stmt) != SQLITE_OK)
+               LogError("Failed to finalize data command");
 
-    // Decrement stored data command count
-    --m_masterConnection->m_dataCommandsCount;
+       // Decrement stored data command count
+       --m_masterConnection->m_dataCommandsCount;
 }
 
 void SqlConnection::DataCommand::CheckBindResult(int result)
 {
-    if (result != SQLCIPHER_OK) {
-        const char *error = sqlcipher3_errmsg(
-                m_masterConnection->m_connection);
+       if (result != SQLITE_OK) {
+               const char *error = sqlite3_errmsg(
+                                                               m_masterConnection->m_connection);
 
-        LogPedantic("Failed to bind SQL statement parameter");
-        LogPedantic("    Error: " << error);
+               LogError("Failed to bind SQL statement parameter");
+               LogError("    Error: " << error);
 
-        ThrowMsg(Exception::SyntaxError, error);
-    }
+               ThrowMsg(Exception::SyntaxError, error);
+       }
 }
 
+//LCOV_EXCL_START
 void SqlConnection::DataCommand::BindNull(
-    SqlConnection::ArgumentIndex position)
+       SqlConnection::ArgumentIndex position)
 {
-    CheckBindResult(sqlcipher3_bind_null(m_stmt, position));
-    LogPedantic("SQL data command bind null: ["
-                << position << "]");
+       CheckBindResult(sqlite3_bind_null(m_stmt, position));
+       LogPedantic("SQL data command bind null: ["
+                               << position << "]");
 }
+//LCOV_EXCL_STOP
 
 void SqlConnection::DataCommand::BindInteger(
-    SqlConnection::ArgumentIndex position,
-    int value)
+       SqlConnection::ArgumentIndex position,
+       int value)
 {
-    CheckBindResult(sqlcipher3_bind_int(m_stmt, position, value));
-    LogPedantic("SQL data command bind integer: ["
-                << position << "] -> " << value);
+       CheckBindResult(sqlite3_bind_int(m_stmt, position, value));
+       LogPedantic("SQL data command bind integer: ["
+                               << position << "] -> " << value);
 }
 
+//LCOV_EXCL_START
 void SqlConnection::DataCommand::BindInt8(
-    SqlConnection::ArgumentIndex position,
-    int8_t value)
+       SqlConnection::ArgumentIndex position,
+       int8_t value)
 {
-    CheckBindResult(sqlcipher3_bind_int(m_stmt, position,
-                                     static_cast<int>(value)));
-    LogPedantic("SQL data command bind int8: ["
-                << position << "] -> " << value);
+       CheckBindResult(sqlite3_bind_int(m_stmt, position,
+                                                                               static_cast<int>(value)));
+       LogPedantic("SQL data command bind int8: ["
+                               << position << "] -> " << value);
 }
 
 void SqlConnection::DataCommand::BindInt16(
-    SqlConnection::ArgumentIndex position,
-    int16_t value)
+       SqlConnection::ArgumentIndex position,
+       int16_t value)
 {
-    CheckBindResult(sqlcipher3_bind_int(m_stmt, position,
-                                     static_cast<int>(value)));
-    LogPedantic("SQL data command bind int16: ["
-                << position << "] -> " << value);
+       CheckBindResult(sqlite3_bind_int(m_stmt, position,
+                                                                               static_cast<int>(value)));
+       LogPedantic("SQL data command bind int16: ["
+                               << position << "] -> " << value);
 }
 
 void SqlConnection::DataCommand::BindInt32(
-    SqlConnection::ArgumentIndex position,
-    int32_t value)
+       SqlConnection::ArgumentIndex position,
+       int32_t value)
 {
-    CheckBindResult(sqlcipher3_bind_int(m_stmt, position,
-                                     static_cast<int>(value)));
-    LogPedantic("SQL data command bind int32: ["
-                << position << "] -> " << value);
+       CheckBindResult(sqlite3_bind_int(m_stmt, position,
+                                                                               static_cast<int>(value)));
+       LogPedantic("SQL data command bind int32: ["
+                               << position << "] -> " << value);
 }
 
 void SqlConnection::DataCommand::BindInt64(
-    SqlConnection::ArgumentIndex position,
-    int64_t value)
+       SqlConnection::ArgumentIndex position,
+       int64_t value)
 {
-    CheckBindResult(sqlcipher3_bind_int64(m_stmt, position,
-                                       static_cast<sqlcipher3_int64>(value)));
-    LogPedantic("SQL data command bind int64: ["
-                << position << "] -> " << value);
+       CheckBindResult(sqlite3_bind_int64(m_stmt, position,
+                                                                                 static_cast<sqlite3_int64>(value)));
+       LogPedantic("SQL data command bind int64: ["
+                               << position << "] -> " << value);
 }
 
 void SqlConnection::DataCommand::BindFloat(
-    SqlConnection::ArgumentIndex position,
-    float value)
+       SqlConnection::ArgumentIndex position,
+       float value)
 {
-    CheckBindResult(sqlcipher3_bind_double(m_stmt, position,
-                                        static_cast<double>(value)));
-    LogPedantic("SQL data command bind float: ["
-                << position << "] -> " << value);
+       CheckBindResult(sqlite3_bind_double(m_stmt, position,
+                                                                                  static_cast<double>(value)));
+       LogPedantic("SQL data command bind float: ["
+                               << position << "] -> " << value);
 }
 
 void SqlConnection::DataCommand::BindDouble(
-    SqlConnection::ArgumentIndex position,
-    double value)
+       SqlConnection::ArgumentIndex position,
+       double value)
 {
-    CheckBindResult(sqlcipher3_bind_double(m_stmt, position, value));
-    LogPedantic("SQL data command bind double: ["
-                << position << "] -> " << value);
+       CheckBindResult(sqlite3_bind_double(m_stmt, position, value));
+       LogPedantic("SQL data command bind double: ["
+                               << position << "] -> " << value);
 }
+//LCOV_EXCL_STOP
 
 void SqlConnection::DataCommand::BindString(
-    SqlConnection::ArgumentIndex position,
-    const char *value)
+       SqlConnection::ArgumentIndex position,
+       const char *value)
 {
-    if (!value) {
-        BindNull(position);
-        return;
-    }
-
-    // Assume that text may disappear
-    CheckBindResult(sqlcipher3_bind_text(m_stmt, position,
-                                      value, strlen(value),
-                                      SQLCIPHER_TRANSIENT));
-
-    LogPedantic("SQL data command bind string: ["
-                << position << "] -> " << value);
+       if (!value) {
+               BindNull(position);
+               return;
+       }
+
+       // Assume that text may disappear
+       CheckBindResult(sqlite3_bind_text(m_stmt, position,
+                                                                                value, strlen(value),
+                                                                                SQLITE_TRANSIENT));
+
+       LogPedantic("SQL data command bind string: ["
+                               << position << "] -> " << value);
 }
 
 void SqlConnection::DataCommand::BindBlob(
-    SqlConnection::ArgumentIndex position,
-    const std::vector<unsigned char> &raw)
-{
-    if (raw.size() == 0) {
-        BindNull(position);
-        return;
-    }
-
-    // Assume that blob may dissappear
-    CheckBindResult(sqlcipher3_bind_blob(m_stmt, position,
-                                      raw.data(), raw.size(),
-                                      SQLCIPHER_TRANSIENT));
-    LogPedantic("SQL data command bind blob of size "
-                << raw.size());
-}
-
-void SqlConnection::DataCommand::BindString(
-    SqlConnection::ArgumentIndex position,
-    const String &value)
+       SqlConnection::ArgumentIndex position,
+       const RawBuffer &raw)
 {
-    BindString(position, ToUTF8String(value).c_str());
+       if (raw.size() == 0) {
+               BindNull(position);
+               return;
+       }
+
+       // Assume that blob may dissappear
+       CheckBindResult(sqlite3_bind_blob(m_stmt, position,
+                                                                                raw.data(), raw.size(),
+                                                                                SQLITE_TRANSIENT));
+       LogPedantic("SQL data command bind blob of size: ["
+                               << position << "] -> " << raw.size());
 }
 
+//LCOV_EXCL_START
 void SqlConnection::DataCommand::BindInteger(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<int> &value)
+       SqlConnection::ArgumentIndex position,
+       const boost::optional<int> &value)
 {
-    if (!value) {
-        BindNull(position);
-    } else {
-        BindInteger(position, *value);
-    }
+       if (!value)
+               BindNull(position);
+       else
+               BindInteger(position, *value);
 }
 
 void SqlConnection::DataCommand::BindInt8(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<int8_t> &value)
+       SqlConnection::ArgumentIndex position,
+       const boost::optional<int8_t> &value)
 {
-    if (!value) {
-        BindNull(position);
-    } else {
-        BindInt8(position, *value);
-    }
+       if (!value)
+               BindNull(position);
+       else
+               BindInt8(position, *value);
 }
 
 void SqlConnection::DataCommand::BindInt16(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<int16_t> &value)
+       SqlConnection::ArgumentIndex position,
+       const boost::optional<int16_t> &value)
 {
-    if (!value) {
-        BindNull(position);
-    } else {
-        BindInt16(position, *value);
-    }
+       if (!value)
+               BindNull(position);
+       else
+               BindInt16(position, *value);
 }
 
 void SqlConnection::DataCommand::BindInt32(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<int32_t> &value)
+       SqlConnection::ArgumentIndex position,
+       const boost::optional<int32_t> &value)
 {
-    if (!value) {
-        BindNull(position);
-    } else {
-        BindInt32(position, *value);
-    }
+       if (!value)
+               BindNull(position);
+       else
+               BindInt32(position, *value);
 }
 
 void SqlConnection::DataCommand::BindInt64(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<int64_t> &value)
+       SqlConnection::ArgumentIndex position,
+       const boost::optional<int64_t> &value)
 {
-    if (!value) {
-        BindNull(position);
-    } else {
-        BindInt64(position, *value);
-    }
+       if (!value)
+               BindNull(position);
+       else
+               BindInt64(position, *value);
 }
 
 void SqlConnection::DataCommand::BindFloat(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<float> &value)
+       SqlConnection::ArgumentIndex position,
+       const boost::optional<float> &value)
 {
-    if (!value) {
-        BindNull(position);
-    } else {
-        BindFloat(position, *value);
-    }
+       if (!value)
+               BindNull(position);
+       else
+               BindFloat(position, *value);
 }
 
 void SqlConnection::DataCommand::BindDouble(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<double> &value)
+       SqlConnection::ArgumentIndex position,
+       const boost::optional<double> &value)
 {
-    if (!value) {
-        BindNull(position);
-    } else {
-        BindDouble(position, *value);
-    }
-}
-
-void SqlConnection::DataCommand::BindString(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<String> &value)
-{
-    if (!!value) {
-        BindString(position, ToUTF8String(*value).c_str());
-    } else {
-        BindNull(position);
-    }
+       if (!value)
+               BindNull(position);
+       else
+               BindDouble(position, *value);
 }
 
 void SqlConnection::DataCommand::BindBlob(
-    SqlConnection::ArgumentIndex position,
-    const boost::optional<std::vector<unsigned char>> &value)
+       SqlConnection::ArgumentIndex position,
+       const boost::optional<RawBuffer> &value)
 {
-    if (!!value) {
-        BindBlob(position, *value);
-    } else {
-        BindNull(position);
-    }
+       if (!!value)
+               BindBlob(position, *value);
+       else
+               BindNull(position);
 }
+//LCOV_EXCL_STOP
 
 bool SqlConnection::DataCommand::Step()
 {
-    // Notify all after potentially synchronized database connection access
-    ScopedNotifyAll notifyAll(
-        m_masterConnection->m_synchronizationObject.get());
+       // Notify all after potentially synchronized database connection access
+       ScopedNotifyAll notifyAll(
+               m_masterConnection->m_synchronizationObject.get());
 
-    for (;;) {
-        int ret = sqlcipher3_step(m_stmt);
+       for (int i = 0; i < MAX_RETRY; i++) {
+               int ret = sqlite3_step(m_stmt);
 
-        if (ret == SQLCIPHER_ROW) {
-            LogPedantic("SQL data command step ROW");
-            return true;
-        } else if (ret == SQLCIPHER_DONE) {
-            LogPedantic("SQL data command step DONE");
-            return false;
-        } else if (ret == SQLCIPHER_BUSY) {
-            LogPedantic("Collision occurred while executing SQL command");
+               if (ret == SQLITE_ROW) {
+                       LogPedantic("SQL data command step ROW");
+                       return true;
+               } else if (ret == SQLITE_DONE) {
+                       LogPedantic("SQL data command step DONE");
+                       return false;
+               } else if (ret == SQLITE_BUSY) {
+                       LogPedantic("Collision occurred while executing SQL command");
 
-            // Synchronize if synchronization object is available
-            if (m_masterConnection->m_synchronizationObject) {
-                LogPedantic("Performing synchronization");
+                       // Synchronize if synchronization object is available
+                       if (m_masterConnection->m_synchronizationObject) {
+                               LogPedantic("Performing synchronization");
 
-                m_masterConnection->
-                    m_synchronizationObject->Synchronize();
+                               m_masterConnection->
+                               m_synchronizationObject->Synchronize();
 
-                continue;
-            }
+                               continue;
+                       }
 
-            // No synchronization object defined. Fail.
-        }
+                       // No synchronization object defined. Fail.
+               }
 
-        // Fatal error
-        const char *error = sqlcipher3_errmsg(m_masterConnection->m_connection);
+               // Fatal error
+               const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
 
-        LogPedantic("SQL step data command failed");
-        LogPedantic("    Error: " << error);
+               LogError("SQL step data command failed");
+               LogError("    Error: " << error);
 
-        ThrowMsg(Exception::InternalError, error);
-    }
+               ThrowMsg(Exception::InternalError, error);
+       }
+
+       LogError("sqlite in the state of possible infinite loop");
+       ThrowMsg(Exception::InternalError, "sqlite permanently busy");
 }
 
 void SqlConnection::DataCommand::Reset()
 {
-    /*
-     * According to:
-     * http://www.sqllite.org/c3ref/stmt.html
-     *
-     * if last sqlcipher3_step command on this stmt returned an error,
-     * then sqlcipher3_reset will return that error, althought it is not an error.
-     * So sqlcipher3_reset allways succedes.
-     */
-    sqlcipher3_reset(m_stmt);
-
-    LogPedantic("SQL data command reset");
+       /*
+        * According to:
+        * http://www.sqllite.org/c3ref/stmt.html
+        *
+        * if last sqlite3_step command on this stmt returned an error,
+        * then sqlite3_reset will return that error, althought it is not an error.
+        * So sqlite3_reset allways succedes.
+        */
+       sqlite3_reset(m_stmt);
+
+       LogPedantic("SQL data command reset");
 }
 
 void SqlConnection::DataCommand::CheckColumnIndex(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    if (column < 0 || column >= sqlcipher3_column_count(m_stmt)) {
-        ThrowMsg(Exception::InvalidColumn, "Column index is out of bounds");
-    }
+       if (column < 0 || column >= sqlite3_column_count(m_stmt))
+               ThrowMsg(Exception::InvalidColumn, "Column index is out of bounds");
 }
 
+//LCOV_EXCL_START
 bool SqlConnection::DataCommand::IsColumnNull(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column type: [" << column << "]");
-    CheckColumnIndex(column);
-    return sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL;
+       LogPedantic("SQL data command get column type: [" << column << "]");
+       CheckColumnIndex(column);
+       return sqlite3_column_type(m_stmt, column) == SQLITE_NULL;
 }
+//LCOV_EXCL_STOP
 
 int SqlConnection::DataCommand::GetColumnInteger(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column integer: [" << column << "]");
-    CheckColumnIndex(column);
-    int value = sqlcipher3_column_int(m_stmt, column);
-    LogPedantic("    Value: " << value);
-    return value;
+       LogPedantic("SQL data command get column integer: [" << column << "]");
+       CheckColumnIndex(column);
+       int value = sqlite3_column_int(m_stmt, column);
+       LogPedantic("    Value: " << value);
+       return value;
 }
 
+//LCOV_EXCL_START
 int8_t SqlConnection::DataCommand::GetColumnInt8(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column int8: [" << column << "]");
-    CheckColumnIndex(column);
-    int8_t value = static_cast<int8_t>(sqlcipher3_column_int(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return value;
+       LogPedantic("SQL data command get column int8: [" << column << "]");
+       CheckColumnIndex(column);
+       int8_t value = static_cast<int8_t>(sqlite3_column_int(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return value;
 }
 
 int16_t SqlConnection::DataCommand::GetColumnInt16(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column int16: [" << column << "]");
-    CheckColumnIndex(column);
-    int16_t value = static_cast<int16_t>(sqlcipher3_column_int(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return value;
+       LogPedantic("SQL data command get column int16: [" << column << "]");
+       CheckColumnIndex(column);
+       int16_t value = static_cast<int16_t>(sqlite3_column_int(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return value;
 }
 
 int32_t SqlConnection::DataCommand::GetColumnInt32(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column int32: [" << column << "]");
-    CheckColumnIndex(column);
-    int32_t value = static_cast<int32_t>(sqlcipher3_column_int(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return value;
+       LogPedantic("SQL data command get column int32: [" << column << "]");
+       CheckColumnIndex(column);
+       int32_t value = static_cast<int32_t>(sqlite3_column_int(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return value;
 }
 
 int64_t SqlConnection::DataCommand::GetColumnInt64(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column int64: [" << column << "]");
-    CheckColumnIndex(column);
-    int64_t value = static_cast<int64_t>(sqlcipher3_column_int64(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return value;
+       LogPedantic("SQL data command get column int64: [" << column << "]");
+       CheckColumnIndex(column);
+       int64_t value = static_cast<int64_t>(sqlite3_column_int64(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return value;
 }
 
 float SqlConnection::DataCommand::GetColumnFloat(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column float: [" << column << "]");
-    CheckColumnIndex(column);
-    float value = static_cast<float>(sqlcipher3_column_double(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return value;
+       LogPedantic("SQL data command get column float: [" << column << "]");
+       CheckColumnIndex(column);
+       float value = static_cast<float>(sqlite3_column_double(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return value;
 }
 
 double SqlConnection::DataCommand::GetColumnDouble(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column double: [" << column << "]");
-    CheckColumnIndex(column);
-    double value = sqlcipher3_column_double(m_stmt, column);
-    LogPedantic("    Value: " << value);
-    return value;
+       LogPedantic("SQL data command get column double: [" << column << "]");
+       CheckColumnIndex(column);
+       double value = sqlite3_column_double(m_stmt, column);
+       LogPedantic("    Value: " << value);
+       return value;
 }
+//LCOV_EXCL_STOP
 
 std::string SqlConnection::DataCommand::GetColumnString(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column string: [" << column << "]");
-    CheckColumnIndex(column);
+       LogPedantic("SQL data command get column string: [" << column << "]");
+       CheckColumnIndex(column);
 
-    const char *value = reinterpret_cast<const char *>(
-            sqlcipher3_column_text(m_stmt, column));
+       const char *value = reinterpret_cast<const char *>(
+                                                       sqlite3_column_text(m_stmt, column));
 
-    LogPedantic("Value: " << (value ? value : "NULL"));
+       LogPedantic("Value: " << (value ? value : "NULL"));
 
-    if (value == NULL) {
-        return std::string();
-    }
+       if (value == NULL)
+               return std::string();
 
-    return std::string(value);
+       return std::string(value);
 }
 
-std::vector<unsigned char> SqlConnection::DataCommand::GetColumnBlob(
-    SqlConnection::ColumnIndex column)
+RawBuffer SqlConnection::DataCommand::GetColumnBlob(
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column blog: [" << column << "]");
-    CheckColumnIndex(column);
+       LogPedantic("SQL data command get column blog: [" << column << "]");
+       CheckColumnIndex(column);
 
-    const unsigned char *value = reinterpret_cast<const unsigned char*>(
-            sqlcipher3_column_blob(m_stmt, column));
+       const unsigned char *value = reinterpret_cast<const unsigned char *>(
+                                                                        sqlite3_column_blob(m_stmt, column));
 
-    if (value == NULL) {
-        return std::vector<unsigned char>();
-    }
+       if (value == NULL)
+               return RawBuffer();
 
-    int length = sqlcipher3_column_bytes(m_stmt, column);
-    LogPedantic("Got blob of length: " << length);
+       int length = sqlite3_column_bytes(m_stmt, column);
+       LogPedantic("Got blob of length: " << length);
 
-    return std::vector<unsigned char>(value, value + length);
+       return RawBuffer(value, value + length);
 }
 
+//LCOV_EXCL_START
 boost::optional<int> SqlConnection::DataCommand::GetColumnOptionalInteger(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column optional integer: ["
-                << column << "]");
-    CheckColumnIndex(column);
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<int>();
-    }
-    int value = sqlcipher3_column_int(m_stmt, column);
-    LogPedantic("    Value: " << value);
-    return boost::optional<int>(value);
+       LogPedantic("SQL data command get column optional integer: ["
+                               << column << "]");
+       CheckColumnIndex(column);
+
+       if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
+               return boost::optional<int>();
+
+       int value = sqlite3_column_int(m_stmt, column);
+       LogPedantic("    Value: " << value);
+       return boost::optional<int>(value);
 }
 
 boost::optional<int8_t> SqlConnection::DataCommand::GetColumnOptionalInt8(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column optional int8: ["
-                << column << "]");
-    CheckColumnIndex(column);
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<int8_t>();
-    }
-    int8_t value = static_cast<int8_t>(sqlcipher3_column_int(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return boost::optional<int8_t>(value);
+       LogPedantic("SQL data command get column optional int8: ["
+                               << column << "]");
+       CheckColumnIndex(column);
+
+       if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
+               return boost::optional<int8_t>();
+
+       int8_t value = static_cast<int8_t>(sqlite3_column_int(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return boost::optional<int8_t>(value);
 }
 
 boost::optional<int16_t> SqlConnection::DataCommand::GetColumnOptionalInt16(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column optional int16: ["
-                << column << "]");
-    CheckColumnIndex(column);
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<int16_t>();
-    }
-    int16_t value = static_cast<int16_t>(sqlcipher3_column_int(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return boost::optional<int16_t>(value);
+       LogPedantic("SQL data command get column optional int16: ["
+                               << column << "]");
+       CheckColumnIndex(column);
+
+       if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
+               return boost::optional<int16_t>();
+
+       int16_t value = static_cast<int16_t>(sqlite3_column_int(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return boost::optional<int16_t>(value);
 }
 
 boost::optional<int32_t> SqlConnection::DataCommand::GetColumnOptionalInt32(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column optional int32: ["
-                << column << "]");
-    CheckColumnIndex(column);
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<int32_t>();
-    }
-    int32_t value = static_cast<int32_t>(sqlcipher3_column_int(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return boost::optional<int32_t>(value);
+       LogPedantic("SQL data command get column optional int32: ["
+                               << column << "]");
+       CheckColumnIndex(column);
+
+       if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
+               return boost::optional<int32_t>();
+
+       int32_t value = static_cast<int32_t>(sqlite3_column_int(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return boost::optional<int32_t>(value);
 }
 
 boost::optional<int64_t> SqlConnection::DataCommand::GetColumnOptionalInt64(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column optional int64: ["
-                << column << "]");
-    CheckColumnIndex(column);
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<int64_t>();
-    }
-    int64_t value = static_cast<int64_t>(sqlcipher3_column_int64(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return boost::optional<int64_t>(value);
+       LogPedantic("SQL data command get column optional int64: ["
+                               << column << "]");
+       CheckColumnIndex(column);
+
+       if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
+               return boost::optional<int64_t>();
+
+       int64_t value = static_cast<int64_t>(sqlite3_column_int64(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return boost::optional<int64_t>(value);
 }
 
 boost::optional<float> SqlConnection::DataCommand::GetColumnOptionalFloat(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column optional float: ["
-                << column << "]");
-    CheckColumnIndex(column);
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<float>();
-    }
-    float value = static_cast<float>(sqlcipher3_column_double(m_stmt, column));
-    LogPedantic("    Value: " << value);
-    return boost::optional<float>(value);
+       LogPedantic("SQL data command get column optional float: ["
+                               << column << "]");
+       CheckColumnIndex(column);
+
+       if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
+               return boost::optional<float>();
+
+       float value = static_cast<float>(sqlite3_column_double(m_stmt, column));
+       LogPedantic("    Value: " << value);
+       return boost::optional<float>(value);
 }
 
 boost::optional<double> SqlConnection::DataCommand::GetColumnOptionalDouble(
-    SqlConnection::ColumnIndex column)
+       SqlConnection::ColumnIndex column)
 {
-    LogPedantic("SQL data command get column optional double: ["
-                << column << "]");
-    CheckColumnIndex(column);
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<double>();
-    }
-    double value = sqlcipher3_column_double(m_stmt, column);
-    LogPedantic("    Value: " << value);
-    return boost::optional<double>(value);
+       LogPedantic("SQL data command get column optional double: ["
+                               << column << "]");
+       CheckColumnIndex(column);
+
+       if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
+               return boost::optional<double>();
+
+       double value = sqlite3_column_double(m_stmt, column);
+       LogPedantic("    Value: " << value);
+       return boost::optional<double>(value);
+}
+
+boost::optional<RawBuffer> SqlConnection::DataCommand::GetColumnOptionalBlob(
+       SqlConnection::ColumnIndex column)
+{
+       LogPedantic("SQL data command get column blog: [" << column << "]");
+       CheckColumnIndex(column);
+
+       if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
+               return boost::optional<RawBuffer>();
+
+       const unsigned char *value = reinterpret_cast<const unsigned char *>(
+                                                                        sqlite3_column_blob(m_stmt, column));
+
+       int length = sqlite3_column_bytes(m_stmt, column);
+       LogPedantic("Got blob of length: " << length);
+
+       RawBuffer temp(value, value + length);
+       return boost::optional<RawBuffer>(temp);
+}
+//LCOV_EXCL_STOP
+
+void SqlConnection::Connect(const std::string &address,
+                                                       Flag::Option flag)
+{
+       if (m_connection != NULL) {
+               LogPedantic("Already connected.");
+               return;
+       }
+
+       LogPedantic("Connecting to DB: " << address << "...");
+
+       // Connect to database
+       int result;
+       result = sqlite3_open_v2(
+                                address.c_str(),
+                                &m_connection,
+                                flag,
+                                NULL);
+
+       if (result == SQLITE_OK) {
+               LogPedantic("Connected to DB");
+       } else {
+               LogError("Failed to connect to DB!");
+               ThrowMsg(Exception::ConnectionBroken, address);
+       }
+
+       // Enable foreign keys
+       TurnOnForeignKeys();
 }
 
-boost::optional<String> SqlConnection::DataCommand::GetColumnOptionalString(
-    SqlConnection::ColumnIndex column)
+const std::string SQLITE_RAW_PREFIX = "x'";
+const std::string SQLITE_RAW_SUFIX = "'";
+const std::size_t SQLITE_RAW_DATA_SIZE = 32;
+
+RawBuffer rawToHexString(const RawBuffer &raw)
 {
-    LogPedantic("SQL data command get column optional string: ["
-                << column << "]");
-    CheckColumnIndex(column);
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<String>();
-    }
-    const char *value = reinterpret_cast<const char *>(
-            sqlcipher3_column_text(m_stmt, column));
-    LogPedantic("Value: " << value);
-    String s = FromUTF8String(value);
-    return boost::optional<String>(s);
+       return hexDump<RawBuffer, true>(raw);
 }
 
-boost::optional<std::vector<unsigned char>> SqlConnection::DataCommand::GetColumnOptionalBlob(
-    SqlConnection::ColumnIndex column)
+RawBuffer createHexPass(const RawBuffer &rawPass)
 {
-    LogPedantic("SQL data command get column blog: [" << column << "]");
-    CheckColumnIndex(column);
+       // We are required to pass 64byte long hex password made out of 32byte raw
+       // binary data
+       RawBuffer output;
+       std::copy(SQLITE_RAW_PREFIX.begin(), SQLITE_RAW_PREFIX.end(),
+                         std::back_inserter(output));
 
-    if (sqlcipher3_column_type(m_stmt, column) == SQLCIPHER_NULL) {
-        return boost::optional<std::vector<unsigned char>>();
-    }
-    const unsigned char *value = reinterpret_cast<const unsigned char*>(
-            sqlcipher3_column_blob(m_stmt, column));
+       RawBuffer password = rawToHexString(rawPass);
 
-    int length = sqlcipher3_column_bytes(m_stmt, column);
-    LogPedantic("Got blob of length: " << length);
+       std::copy(password.begin(), password.end(),
+                         std::back_inserter(output));
 
-    std::vector<unsigned char> temp(value, value + length);
-    return boost::optional<std::vector<unsigned char>>(temp);
+       std::copy(SQLITE_RAW_SUFIX.begin(), SQLITE_RAW_SUFIX.end(),
+                         std::back_inserter(output));
+
+       return output;
 }
 
-void SqlConnection::Connect(const std::string &address,
-                            Flag::Option flag)
-{
-    if (m_connection != NULL) {
-        LogPedantic("Already connected.");
-        return;
-    }
-    LogPedantic("Connecting to DB: " << address << "...");
-
-    // Connect to database
-    int result;
-    result = sqlcipher3_open_v2(
-            address.c_str(),
-            &m_connection,
-            flag,
-            NULL);
-
-    if (result == SQLCIPHER_OK) {
-        LogPedantic("Connected to DB");
-    } else {
-        LogPedantic("Failed to connect to DB!");
-        ThrowMsg(Exception::ConnectionBroken, address);
-    }
-
-    // Enable foreign keys
-    TurnOnForeignKeys();
-}
-
-static std::string rawToHexString(const std::vector<unsigned char> &raw) {
-    std::string str(raw.size() * 2, '0');
-    for (std::size_t i = 0; i < raw.size(); i++)
-        sprintf(&str[i*2], "%02X", raw[i]);
-    return str;
-}
-
-void SqlConnection::SetKey(const std::vector<unsigned char> &rawPass){
-    if (m_connection == NULL) {
-        LogPedantic("Cannot set key. No connection to DB!");
-        return;
-    }
-    std::string pass = "x'" + rawToHexString(rawPass) + "'";
-    int result = sqlcipher3_key(m_connection, pass.c_str(), pass.length());
-    if (result == SQLCIPHER_OK) {
-        LogPedantic("Set key on DB");
-    } else {
-        //sqlcipher3_key fails only when m_connection == NULL || key == NULL ||
-        //                            key length == 0
-        LogPedantic("Failed to set key on DB");
-        ThrowMsg(Exception::InvalidArguments, result);
-    }
-
-    m_isKeySet = true;
+void SqlConnection::SetKey(const RawBuffer &rawPass)
+{
+       if (m_connection == NULL) {
+               LogPedantic("Cannot set key. No connection to DB!");
+               return;
+       }
+
+       if (rawPass.size() != SQLITE_RAW_DATA_SIZE)
+               ThrowMsg(Exception::InvalidArguments,
+                                "Binary data for raw password should be 32 bytes long.");
+
+       RawBuffer pass = createHexPass(rawPass);
+       int result = sqlite3_key(m_connection, pass.data(), pass.size());
+
+       if (result == SQLITE_OK) {
+               LogPedantic("Set key on DB");
+       } else {
+               //sqlite3_key fails only when m_connection == NULL || key == NULL ||
+               //                            key length == 0
+               LogError("Failed to set key on DB");
+               ThrowMsg(Exception::InvalidArguments, result);
+       }
+
+       m_isKeySet = true;
 };
 
-void SqlConnection::ResetKey(const std::vector<unsigned char> &rawPassOld,
-                             const std::vector<unsigned char> &rawPassNew) {
-    if (m_connection == NULL) {
-        LogPedantic("Cannot reset key. No connection to DB!");
-        return;
-    }
-    // sqlcipher3_rekey requires for key to be already set
-    if (!m_isKeySet)
-        SetKey(rawPassOld);
-
-    std::string pass = "x'" + rawToHexString(rawPassNew) + "'";
-    int result = sqlcipher3_rekey(m_connection, pass.c_str(), pass.length());
-    if (result == SQLCIPHER_OK) {
-        LogPedantic("Reset key on DB");
-    } else {
-        //sqlcipher3_rekey fails only when m_connection == NULL || key == NULL ||
-        //                              key length == 0
-        LogPedantic("Failed to reset key on DB");
-        ThrowMsg(Exception::InvalidArguments, result);
-    }
-    //Wiping out the key (required)
-    pass.assign(pass.length(), '0');
-    for(std::size_t i = 0; i < pass.length(); i++) {
-        if(pass[i] != '0') {
-            LogPedantic("Wiping key failed.");
-            ThrowMsg(Exception::InternalError, "Wiping key failed");
-        }
-    }
+//LCOV_EXCL_START
+void SqlConnection::ResetKey(const RawBuffer &rawPassOld,
+                                                        const RawBuffer &rawPassNew)
+{
+       if (m_connection == NULL) {
+               LogPedantic("Cannot reset key. No connection to DB!");
+               return;
+       }
+
+       // Binary data for raw password should be 32 bytes long.
+       assert(rawPassOld.size() == SQLITE_RAW_DATA_SIZE &&
+              rawPassNew.size() == SQLITE_RAW_DATA_SIZE);
+
+       // sqlite3_rekey requires for key to be already set
+       if (!m_isKeySet)
+               SetKey(rawPassOld);
+
+       RawBuffer pass = createHexPass(rawPassNew);
+       int result = sqlite3_rekey(m_connection, pass.data(), pass.size());
+
+       if (result == SQLITE_OK) {
+               LogPedantic("Reset key on DB");
+       } else {
+               //sqlite3_rekey fails only when m_connection == NULL || key == NULL ||
+               //                              key length == 0
+               LogError("Failed to reset key on DB");
+               ThrowMsg(Exception::InvalidArguments, result);
+       }
 }
+//LCOV_EXCL_STOP
 
 void SqlConnection::Disconnect()
 {
-    if (m_connection == NULL) {
-        LogPedantic("Already disconnected.");
-        return;
-    }
+       if (m_connection == NULL) {
+               LogPedantic("Already disconnected.");
+               return;
+       }
 
-    LogPedantic("Disconnecting from DB...");
+       LogPedantic("Disconnecting from DB...");
 
-    // All stored data commands must be deleted before disconnect
-    AssertMsg(m_dataCommandsCount == 0,
-           "All stored procedures must be deleted"
-           " before disconnecting SqlConnection");
+       // All stored data commands must be deleted before disconnect
+       assert(m_dataCommandsCount == 0);
 
-    int result;
+       int result;
 
-    result = sqlcipher3_close(m_connection);
+       result = sqlite3_close(m_connection);
 
-    if (result != SQLCIPHER_OK) {
-        const char *error = sqlcipher3_errmsg(m_connection);
-        LogPedantic("SQL close failed");
-        LogPedantic("    Error: " << error);
-        Throw(Exception::InternalError);
-    }
+       if (result != SQLITE_OK) {
+               const char *error = sqlite3_errmsg(m_connection);
+               LogError("SQL close failed");
+               LogError("    Error: " << error);
+               Throw(Exception::InternalError);
+       }
 
-    m_connection = NULL;
+       m_connection = NULL;
 
-    LogPedantic("Disconnected from DB");
+       LogPedantic("Disconnected from DB");
 }
 
 bool SqlConnection::CheckTableExist(const char *tableName)
 {
-    if (m_connection == NULL) {
-        LogPedantic("Cannot execute command. Not connected to DB!");
-        return false;
-    }
+       if (m_connection == NULL) {
+               LogPedantic("Cannot execute command. Not connected to DB!");
+               return false;
+       }
 
-    DataCommandAutoPtr command =
-        PrepareDataCommand("select tbl_name from sqlcipher_master where name=?;");
+       DataCommandUniquePtr command =
+               PrepareDataCommand("select tbl_name from sqlite_master where name=?;");
 
-    command->BindString(1, tableName);
+       command->BindString(1, tableName);
 
-    if (!command->Step()) {
-        LogPedantic("No matching records in table");
-        return false;
-    }
+       if (!command->Step()) {
+               LogPedantic("No matching records in table");
+               return false;
+       }
 
-    return command->GetColumnString(0) == tableName;
+       return command->GetColumnString(0) == tableName;
 }
 
 SqlConnection::SqlConnection(const std::string &address,
-                             Flag::Option option,
-                             SynchronizationObject *synchronizationObject) :
-    m_connection(NULL),
-    m_dataCommandsCount(0),
-    m_synchronizationObject(synchronizationObject),
-    m_isKeySet(false)
+                                                        Flag::Option option,
+                                                        SynchronizationObject *synchronizationObject) :
+       m_connection(NULL),
+       m_dataCommandsCount(0),
+       m_synchronizationObject(synchronizationObject),
+       m_isKeySet(false)
 {
-    LogPedantic("Opening database connection to: " << address);
+       LogPedantic("Opening database connection to: " << address);
 
-    // Connect to DB
-    SqlConnection::Connect(address, option);
+       // Connect to DB
+       SqlConnection::Connect(address, option);
 
-    if (!m_synchronizationObject) {
-        LogPedantic("No synchronization object defined");
-    }
+       if (!m_synchronizationObject)
+               LogPedantic("No synchronization object defined");
 }
 
 SqlConnection::~SqlConnection()
 {
-    LogPedantic("Closing database connection");
+       LogPedantic("Closing database connection");
+
+       // Disconnect from DB
+       try {
+               SqlConnection::Disconnect();
+       } catch (const Exception::Base &) {
+               LogError("Failed to disconnect from database");
+       }
+}
+
+//LCOV_EXCL_START
+int SqlConnection::Output::Callback(void *param, int columns, char **values,
+                                                                       char **names)
+{
+       if (param)
+               static_cast<Output *>(param)->SetResults(columns, values, names);
 
-    // Disconnect from DB
-    Try
-    {
-        SqlConnection::Disconnect();
-    }
-    Catch(Exception::Base)
-    {
-        LogPedantic("Failed to disconnect from database");
-    }
+       return 0;
 }
 
-void SqlConnection::ExecCommand(const char *format, ...)
+void SqlConnection::Output::SetResults(int columns, char **values, char **names)
 {
-    if (m_connection == NULL) {
-        LogPedantic("Cannot execute command. Not connected to DB!");
-        return;
-    }
+       if (m_names.empty()) {
+               for (int i = 0; i < columns; i++)
+                       m_names.push_back(names[i] ? names[i] : "NULL");
+       }
+
+       Row row;
+
+       for (int i = 0; i < columns; i++)
+               row.push_back(values[i] ? values[i] : "NULL");
 
-    if (format == NULL) {
-        LogPedantic("Null query!");
-        ThrowMsg(Exception::SyntaxError, "Null statement");
-    }
+       m_values.push_back(std::move(row));
+}
+//LCOV_EXCL_STOP
+
+void SqlConnection::ExecCommandHelper(Output *out, const char *format,
+                                                                         va_list args)
+{
+       if (m_connection == NULL) {
+               LogError("Cannot execute command. Not connected to DB!");
+               return;
+       }
 
-    char *rawBuffer;
+       if (format == NULL) {
+               LogError("Null query!");
+               ThrowMsg(Exception::SyntaxError, "Null statement");
+       }
 
-    va_list args;
-    va_start(args, format);
+       char *query;
 
-    if (vasprintf(&rawBuffer, format, args) == -1) {
-        rawBuffer = NULL;
-    }
+       if (vasprintf(&query, format, args) == -1) {
+               LogError("Failed to allocate statement string");
+               return;
+       }
 
-    va_end(args);
+       CharUniquePtr queryPtr(query);
 
-    CharUniquePtr buffer(rawBuffer);
+       LogPedantic("Executing SQL command: " << queryPtr.get());
 
-    if (!buffer) {
-        LogPedantic("Failed to allocate statement string");
-        return;
-    }
+       // Notify all after potentially synchronized database connection access
+       ScopedNotifyAll notifyAll(m_synchronizationObject.get());
 
-    LogPedantic("Executing SQL command: " << buffer.get());
+       for (int i = 0; i < MAX_RETRY; i++) {
+               char *errorBuffer;
+               int ret = sqlite3_exec(m_connection,
+                                                                 queryPtr.get(),
+                                                                 out ? &Output::Callback : NULL,
+                                                                 out,
+                                                                 &errorBuffer);
 
-    // Notify all after potentially synchronized database connection access
-    ScopedNotifyAll notifyAll(m_synchronizationObject.get());
+               std::string errorMsg;
 
-    for (;;) {
-        char *errorBuffer;
+               // Take allocated error buffer
+               if (errorBuffer != NULL) {
+                       errorMsg = errorBuffer;
+                       sqlite3_free(errorBuffer);
+               }
 
-        int ret = sqlcipher3_exec(m_connection,
-                               buffer.get(),
-                               NULL,
-                               NULL,
-                               &errorBuffer);
+               if (ret == SQLITE_OK)
+                       return;
 
-        std::string errorMsg;
+               if (ret == SQLITE_BUSY) {
+                       LogPedantic("Collision occurred while executing SQL command");
 
-        // Take allocated error buffer
-        if (errorBuffer != NULL) {
-            errorMsg = errorBuffer;
-            sqlcipher3_free(errorBuffer);
-        }
+                       // Synchronize if synchronization object is available
+                       if (m_synchronizationObject) {
+                               LogPedantic("Performing synchronization");
+                               m_synchronizationObject->Synchronize();
+                               continue;
+                       }
 
-        if (ret == SQLCIPHER_OK) {
-            return;
-        }
+                       // No synchronization object defined. Fail.
+               }
 
-        if (ret == SQLCIPHER_BUSY) {
-            LogPedantic("Collision occurred while executing SQL command");
+               // Fatal error
+               LogError("Failed to execute SQL command. Error: " << errorMsg);
+               ThrowMsg(Exception::SyntaxError, errorMsg);
+       }
 
-            // Synchronize if synchronization object is available
-            if (m_synchronizationObject) {
-                LogPedantic("Performing synchronization");
-                m_synchronizationObject->Synchronize();
-                continue;
-            }
+       LogError("sqlite in the state of possible infinite loop");
+       ThrowMsg(Exception::InternalError, "sqlite permanently busy");
+}
 
-            // No synchronization object defined. Fail.
-        }
+//LCOV_EXCL_START
+void SqlConnection::ExecCommand(Output *out, const char *format, ...)
+{
+       va_list args;
+       va_start(args, format);
+       try {
+               ExecCommandHelper(out, format, args);
+       } catch (...) {
+               va_end(args);
+               throw;
+       }
+       va_end(args);
+}
+//LCOV_EXCL_STOP
 
-        // Fatal error
-        LogPedantic("Failed to execute SQL command. Error: " << errorMsg);
-        ThrowMsg(Exception::SyntaxError, errorMsg);
-    }
+void SqlConnection::ExecCommand(const char *format, ...)
+{
+       va_list args;
+       va_start(args, format);
+       try {
+               ExecCommandHelper(NULL, format, args);
+       } catch (...) {
+               va_end(args);
+               throw;
+       }
+       va_end(args);
 }
 
-SqlConnection::DataCommandAutoPtr SqlConnection::PrepareDataCommand(
-    const char *format,
-    ...)
+SqlConnection::DataCommandUniquePtr SqlConnection::PrepareDataCommand(
+       const char *format,
+       ...)
 {
-    if (m_connection == NULL) {
-        LogPedantic("Cannot execute data command. Not connected to DB!");
-        return DataCommandAutoPtr();
-    }
+       if (m_connection == NULL) {
+               LogError("Cannot execute data command. Not connected to DB!");
+               return DataCommandUniquePtr();
+       }
 
-    char *rawBuffer;
+       char *rawBuffer;
 
-    va_list args;
-    va_start(args, format);
+       va_list args;
+       va_start(args, format);
 
-    if (vasprintf(&rawBuffer, format, args) == -1) {
-        rawBuffer = NULL;
-    }
+       if (vasprintf(&rawBuffer, format, args) == -1)
+               rawBuffer = NULL;
 
-    va_end(args);
+       va_end(args);
 
-    CharUniquePtr buffer(rawBuffer);
+       CharUniquePtr buffer(rawBuffer);
 
-    if (!buffer) {
-        LogPedantic("Failed to allocate statement string");
-        return DataCommandAutoPtr();
-    }
+       if (!buffer) {
+               LogError("Failed to allocate statement string");
+               return DataCommandUniquePtr();
+       }
 
-    LogPedantic("Executing SQL data command: " << buffer.get());
+       LogPedantic("Executing SQL data command: " << buffer.get());
 
-    return DataCommandAutoPtr(new DataCommand(this, buffer.get()));
+       return DataCommandUniquePtr(new DataCommand(this, buffer.get()));
 }
 
+//LCOV_EXCL_START
 SqlConnection::RowID SqlConnection::GetLastInsertRowID() const
 {
-    return static_cast<RowID>(sqlcipher3_last_insert_rowid(m_connection));
+       return static_cast<RowID>(sqlite3_last_insert_rowid(m_connection));
 }
+//LCOV_EXCL_STOP
 
 void SqlConnection::TurnOnForeignKeys()
 {
-    ExecCommand("PRAGMA foreign_keys = ON;");
+       ExecCommand("PRAGMA foreign_keys = ON;");
 }
 
 void SqlConnection::BeginTransaction()
 {
-    ExecCommand("BEGIN;");
+       ExecCommand("BEGIN;");
 }
 
 void SqlConnection::RollbackTransaction()
 {
-    ExecCommand("ROLLBACK;");
+       ExecCommand("ROLLBACK;");
 }
 
 void SqlConnection::CommitTransaction()
 {
-    ExecCommand("COMMIT;");
+       ExecCommand("COMMIT;");
 }
 
 SqlConnection::SynchronizationObject *
 SqlConnection::AllocDefaultSynchronizationObject()
 {
-    return new NaiveSynchronizationObject();
+       return new NaiveSynchronizationObject();
 }
 } // namespace DB
 } // namespace CKM