Reuse prepared sqlite3_stmt when possible 83/313483/15
authorDaniel Kita <d.kita@samsung.com>
Wed, 26 Jun 2024 15:34:16 +0000 (17:34 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 20 Sep 2024 08:52:11 +0000 (08:52 +0000)
Efficiency test results (tested on 2024/08/13 tizen image on RPi4):
-Average insert statement preparation time: 7[µs]
-Average select statement preparation time: 4[µs]
-Average delete statement preparation time: 4[µs]
-Average insert statement preparation&execution time: 1811[µs]
-Average select statement preparation&execution time: 56[µs]
-Average delete statement preparation&execution time: 1481[µs]
-Average new insert statement preparation time: 20[µs]
-Average new select statement preparation time: 30[µs]
-Average new delete statement preparation time: 51[µs]

Each average was calculated on the basis of 100 measurements.

Change-Id: Iba3b14ef693837fbb0330c356c4438761dc6cb8c

misc/ckm_db_tool/ckm-logic-ext.cpp
src/manager/dpl/db/include/dpl/db/sql_connection.h
src/manager/dpl/db/src/sql_connection.cpp
src/manager/service/db-crypto.cpp
src/manager/service/db-crypto.h
unit-tests/test_sql.cpp

index 2cb55d10daaa420e8a8ac999ad44909110efa75a..0cc5b7d98ecade630c68299456c5345d51fbfb22 100644 (file)
 
 namespace {
 
-const char *DB_CMD_OBJECT_SELECT = "SELECT * FROM [join_name_object_tables];";
-
-const char *DB_CMD_NAME_SELECT_BY_IDX = "SELECT name, label FROM NAMES WHERE idx = ?001;";
+constexpr CKM::DB::CommandBuffer OBJECT_SELECT_CMD_BUF{CKM::DB::DB_CMD_OBJECT_SELECT_ID,
+                                                                                               "SELECT * FROM [join_name_object_tables];"};
+constexpr CKM::DB::CommandBuffer NAME_SELECT_BY_IDX_CMD_BUF{CKM::DB::DB_CMD_NAME_SELECT_BY_IDX_ID,
+                                                                                               "SELECT name, label FROM NAMES WHERE idx = ?001;"};
 
 } // anonymous namespace
 
@@ -43,12 +44,12 @@ DB::SqlConnection::Output CKMLogicExt::Execute(uid_t user, const std::string &cm
 DB::RowVector CKMLogicExt::getRows(uid_t user)
 {
        DB::Crypto& database = m_userDataMap[user].database;
-       DB::SqlConnection::DataCommandUniquePtr selectCommand =
-               database.m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT);
+       auto selectCommand = database.m_connection->PrepareDataCommand(OBJECT_SELECT_CMD_BUF);
 
        DB::RowVector rows;
        while (selectCommand->Step())
                rows.push_back(database.getRow(selectCommand));
+
        return rows;
 }
 
@@ -59,8 +60,8 @@ void CKMLogicExt::saveRow(uid_t user, const DB::Row &row)
 
 NameEntry CKMLogicExt::getNameByIdx(uid_t user, int idx)
 {
-       DB::SqlConnection::DataCommandUniquePtr selectCommand =
-               m_userDataMap[user].database.m_connection->PrepareDataCommand(DB_CMD_NAME_SELECT_BY_IDX);
+       auto selectCommand =
+               m_userDataMap[user].database.m_connection->PrepareDataCommand(NAME_SELECT_BY_IDX_CMD_BUF);
        selectCommand->BindInteger(1, idx);
 
        if (!selectCommand->Step())
index 4ac3d5f9a2bb82a8550ee635e5bafd8464f714ba..46849c2242f0c9f0e1cd3c3850de6efc0a5cb93a 100644 (file)
 #ifndef CKM_SQL_CONNECTION_H
 #define CKM_SQL_CONNECTION_H
 
+#include <map>
 #include <memory>
+#include <utility>
 #include <stdint.h>
 
 #include <boost/optional.hpp>
 #include <sqlite3.h>
-
 #include <dpl/availability.h>
 #include <dpl/exception.h>
 #include <dpl/log/log.h>
 
 namespace CKM {
 namespace DB {
+
+enum DBCommandID {
+       DB_CMD_SCHEMA_SET_ID,
+       DB_CMD_SCHEMA_GET_ID,
+       DB_CMD_NAME_INSERT_ID,
+       DB_CMD_NAME_COUNT_ROWS_ID,
+       DB_CMD_NAME_DELETE_ID,
+       DB_CMD_NAME_DELETE_BY_OWNER_ID,
+       DB_CMD_OBJECT_INSERT_ID,
+       DB_CMD_OBJECT_UPDATE_ID,
+       DB_CMD_OBJECT_SELECT_BY_NAME_AND_OWNER_ID,
+       DB_CMD_KEY_INSERT_ID,
+       DB_CMD_KEY_SELECT_ID,
+       DB_CMD_KEY_DELETE_ID,
+       DB_CMD_PERMISSION_SET_ID,
+       DB_CMD_PERMISSION_SELECT_ID,
+       DB_CMD_PERMISSION_DELETE_ID,
+       DB_CMD_INFO_SELECT_BY_TYPE_AND_PERMISSION_ID,
+       DB_CMD_SELECT_TABLE_ID,
+       DB_CMD_OBJECT_SELECT_ID,
+       DB_CMD_NAME_SELECT_BY_IDX_ID,
+       DB_CMD_TABLE_EXISTS_ID
+};
+
+struct CommandBuffer {
+       DBCommandID id;
+       const char* buffer;
+};
+
 /**
  * SQL connection class
  */
@@ -92,11 +122,10 @@ public:
                void CheckBindResult(int result);
                void CheckColumnIndex(SqlConnection::ColumnIndex column);
 
-               DataCommand(SqlConnection *connection, const char *buffer);
-
                friend class SqlConnection;
 
        public:
+               DataCommand(SqlConnection *connection, const char *buffer);
                NONCOPYABLE(DataCommand);
 
                virtual ~DataCommand();
@@ -260,6 +289,17 @@ public:
                 */
                bool Step();
 
+               /**
+                * Reset prepared statement
+                *
+                * This method is used to reset the prepared statement to it's initial state.
+                * Due to sqlite documentation unfinalized SQL statements typically hold a read
+                * transaction open, so the execution of VACUUM (or different write operations)
+                * command might fail if there are unfinalized SQL statements on the same connection.
+                *
+                */
+               void Reset();
+
                /**
                 * Checks whether column value is null
                 *
@@ -386,8 +426,141 @@ public:
                boost::optional<RawBuffer> GetColumnOptionalBlob(ColumnIndex column);
        };
 
+    class DataCommandHandler {
+    public:
+        explicit DataCommandHandler(DataCommand &dataCommand) : m_dataCommand(dataCommand) {}
+
+        NONCOPYABLE(DataCommandHandler);
+        ~DataCommandHandler();
+
+        void BindNull(ArgumentIndex pos) { m_dataCommand.BindNull(pos); }
+
+        void BindInteger(ArgumentIndex pos, int val) { m_dataCommand.BindInteger(pos, val); }
+
+        void BindInt8(ArgumentIndex pos, int8_t val) { m_dataCommand.BindInt8(pos, val); }
+
+        void BindInt16(ArgumentIndex pos, int8_t val) { m_dataCommand.BindInt16(pos, val); }
+
+        void BindInt32(ArgumentIndex pos, int8_t val) { m_dataCommand.BindInt32(pos, val); }
+
+        void BindInt64(ArgumentIndex pos, int8_t val) { m_dataCommand.BindInt64(pos, val); }
+
+        void BindFloat(ArgumentIndex pos, float val) { m_dataCommand.BindFloat(pos, val); }
+
+        void BindDouble(ArgumentIndex pos, double val) { m_dataCommand.BindDouble(pos, val); }
+
+        void BindString(ArgumentIndex pos, const char *val) { m_dataCommand.BindString(pos, val); }
+
+        void BindBlob(ArgumentIndex pos, const RawBuffer &val) { m_dataCommand.BindBlob(pos, val); }
+
+        void BindInteger(ArgumentIndex pos, const boost::optional<int> &val)
+        {
+            m_dataCommand.BindInteger(pos, val);
+        }
+
+        void BindInt8(ArgumentIndex pos, const boost::optional<int8_t> &val)
+        {
+            m_dataCommand.BindInt8(pos, val);
+        }
+
+        void BindInt16(ArgumentIndex pos, const boost::optional<int16_t> &val)
+        {
+            m_dataCommand.BindInt16(pos, val);
+        }
+
+        void BindInt32(ArgumentIndex pos, const boost::optional<int32_t> &val)
+        {
+            m_dataCommand.BindInt32(pos, val);
+        }
+
+        void BindInt64(ArgumentIndex pos, const boost::optional<int64_t> &val)
+        {
+            m_dataCommand.BindInt64(pos, val);
+        }
+
+        void BindFloat(ArgumentIndex pos, const boost::optional<float> &val)
+        {
+            m_dataCommand.BindFloat(pos, val);
+        }
+
+        void BindDouble(ArgumentIndex pos, const boost::optional<double> &val)
+        {
+            m_dataCommand.BindDouble(pos, val);
+        }
+
+        void BindBlob(ArgumentIndex pos, const boost::optional<RawBuffer> &val)
+        {
+            m_dataCommand.BindBlob(pos, val);
+        }
+
+        bool Step() { return m_dataCommand.Step(); }
+
+        bool IsColumnNull(ColumnIndex col) { return m_dataCommand.IsColumnNull(col); }
+
+        int GetColumnInteger(ColumnIndex col) { return m_dataCommand.GetColumnInteger(col); }
+
+        int8_t GetColumnInt8(ColumnIndex col) { return m_dataCommand.GetColumnInt8(col); }
+
+        int16_t GetColumnInt16(ColumnIndex col) { return m_dataCommand.GetColumnInt16(col); }
+
+        int32_t GetColumnInt32(ColumnIndex col) { return m_dataCommand.GetColumnInt32(col); }
+
+        int64_t GetColumnInt64(ColumnIndex col) { return m_dataCommand.GetColumnInt64(col); }
+
+        float GetColumnFloat(ColumnIndex col) { return m_dataCommand.GetColumnFloat(col); }
+
+        double GetColumnDouble(ColumnIndex col) { return m_dataCommand.GetColumnDouble(col); }
+
+        std::string GetColumnString(ColumnIndex col) { return m_dataCommand.GetColumnString(col); }
+
+        RawBuffer GetColumnBlob(ColumnIndex col) { return m_dataCommand.GetColumnBlob(col); }
+
+        boost::optional<int> GetColumnOptionalInteger(ColumnIndex col)
+        {
+            return m_dataCommand.GetColumnOptionalInteger(col);
+        }
+
+        boost::optional<int8_t> GetColumnOptionalInt8(ColumnIndex col)
+        {
+            return m_dataCommand.GetColumnOptionalInt8(col);
+        }
+
+        boost::optional<int16_t> GetColumnOptionalInt16(ColumnIndex col)
+        {
+            return m_dataCommand.GetColumnOptionalInt16(col);
+        }
+
+        boost::optional<int32_t> GetColumnOptionalInt32(ColumnIndex col)
+        {
+            return m_dataCommand.GetColumnOptionalInt32(col);
+        }
+
+        boost::optional<int64_t> GetColumnOptionalInt64(ColumnIndex col)
+        {
+            return m_dataCommand.GetColumnOptionalInt64(col);
+        }
+
+        boost::optional<float> GetColumnOptionalFloat(ColumnIndex col)
+        {
+            return m_dataCommand.GetColumnOptionalFloat(col);
+        }
+
+        boost::optional<double> GetColumnOptionalDouble(ColumnIndex col)
+        {
+            return m_dataCommand.GetColumnOptionalDouble(col);
+        }
+
+        boost::optional<RawBuffer> GetColumnOptionalBlob(ColumnIndex col)
+        {
+            return m_dataCommand.GetColumnOptionalBlob(col);
+        }
+
+    private:
+        DataCommand &m_dataCommand;
+    };
+
        // Move on copy constructor. No copy semantics
-       typedef std::unique_ptr<DataCommand> DataCommandUniquePtr;
+       typedef std::unique_ptr<DataCommandHandler> DataCommandHandlerUniquePtr;
 
        // Open flags
        class Flag {
@@ -423,11 +596,7 @@ public:
 
 protected:
        sqlite3 *m_connection;
-
-       // Options
-
-       // Stored data procedures
-       int m_dataCommandsCount;
+       std::unordered_map<DBCommandID, DataCommand> m_preparedStatements;
 
        // Synchronization object
        std::unique_ptr<SynchronizationObject> m_synchronizationObject;
@@ -538,8 +707,7 @@ public:
         * @param format SQL statement
         * @return Data command representing stored procedure
         */
-       DataCommandUniquePtr PrepareDataCommand(const char *format, ...);
-
+       DataCommandHandlerUniquePtr PrepareDataCommand(const CommandBuffer &buff, ...);
        /**
         * Check whether given table exists
         *
@@ -555,6 +723,12 @@ public:
         */
        RowID GetLastInsertRowID() const;
 
+       /**
+        * Clear prepared SQL statements map
+        *
+        */
+       void ClearMap();
+
 private:
        void ExecCommandHelper(Output *out, const char *format, va_list args);
 };
index 7a0664ea91ea255e7084f5bb1f472666c30586c2..0bff4c0e3c95ee36d5fdcde5c123123e1db528c5 100644 (file)
@@ -32,7 +32,7 @@
 #include <cstdarg>
 #include <memory>
 #include <noncopyable.h>
-
+#include <utility>
 
 namespace {
 const int MAX_RETRY = 10;
@@ -41,6 +41,10 @@ const int MAX_RETRY = 10;
 namespace CKM {
 namespace DB {
 namespace { // anonymous
+
+constexpr CommandBuffer TABLE_EXISTS_CMD_BUF{DBCommandID::DB_CMD_TABLE_EXISTS_ID,
+                                                                                       "select tbl_name from sqlite_master where name=?;"};
+
 class ScopedNotifyAll {
 private:
        SqlConnection::SynchronizationObject *m_synchronizationObject;
@@ -75,16 +79,14 @@ SqlConnection::DataCommand::DataCommand(SqlConnection *connection,
        // Notify all after potentially synchronized database connection access
        ScopedNotifyAll notifyAll(connection->m_synchronizationObject.get());
 
+       int ret;
        for (int i = 0; i < MAX_RETRY; i++) {
-               int ret = sqlite3_prepare_v2(connection->m_connection,
+               ret = sqlite3_prepare_v2(connection->m_connection,
                                                                                buffer, strlen(buffer),
                                                                                &m_stmt, NULL);
 
                if (ret == SQLITE_OK) {
                        LogPedantic("Prepared data command: " << buffer);
-
-                       // Increment stored data command count
-                       ++m_masterConnection->m_dataCommandsCount;
                        return;
                } else if (ret == SQLITE_BUSY) {
                        LogPedantic("Collision occurred while preparing SQL command");
@@ -117,11 +119,12 @@ SqlConnection::DataCommand::~DataCommand()
 {
        LogPedantic("SQL data command finalizing");
 
-       if (sqlite3_finalize(m_stmt) != SQLITE_OK)
-               LogError("Failed to finalize data command");
-
-       // Decrement stored data command count
-       --m_masterConnection->m_dataCommandsCount;
+       int ret = sqlite3_finalize(m_stmt);
+       if (ret != SQLITE_OK) {
+               const char *error = sqlite3_errmsg(
+                                                               m_masterConnection->m_connection);
+               LogError("SQL Finalize data command failed, Error: " << error);
+       }
 }
 
 void SqlConnection::DataCommand::CheckBindResult(int result)
@@ -378,6 +381,46 @@ bool SqlConnection::DataCommand::Step()
        ThrowMsg(Exception::InternalError, "sqlite permanently busy");
 }
 
+void SqlConnection::DataCommand::Reset()
+{
+       for (int i = 0; i < MAX_RETRY; i++) {
+               int ret = sqlite3_reset(m_stmt);
+
+               // sqlite3_reset() returns SQLITE_OK if sqlite3_step() has never before
+               // been called/has not been called since previous reset or appriopriate
+               // error code indicated in sqlite3_step.
+               // Also it could return it's own error when the process of resetting
+               // prepared statement caused a new error.
+               if (ret == SQLITE_OK || ret == SQLITE_DONE || ret == SQLITE_ROW)
+                       return;
+               else if (ret == SQLITE_BUSY) {
+                       LogPedantic("Collision occurred while executing SQL reset command");
+
+                       // Synchronize if synchronization object is available
+                       if (m_masterConnection->m_synchronizationObject) {
+                               LogPedantic("Performing synchronization");
+
+                               m_masterConnection->
+                               m_synchronizationObject->Synchronize();
+
+                               continue;
+                       }
+
+                       // No synchronization object defined. Fail.
+               }
+               const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
+
+               // This error occurs most often due to an error in DataCommand::Step()
+               // but can also be a DataCommand::Reset() error.
+               LogError("SQL reset data command failed");
+               LogError("    Error: " << error);
+               ThrowMsg(Exception::InternalError, error);
+       }
+
+       LogError("sqlite in the state of possible infinite loop");
+       ThrowMsg(Exception::InternalError, "sqlite permanently busy");
+}
+
 void SqlConnection::DataCommand::CheckColumnIndex(
        SqlConnection::ColumnIndex column)
 {
@@ -627,6 +670,16 @@ boost::optional<RawBuffer> SqlConnection::DataCommand::GetColumnOptionalBlob(
        return boost::optional<RawBuffer>(temp);
 }
 //LCOV_EXCL_STOP
+SqlConnection::DataCommandHandler::~DataCommandHandler() {
+       LogPedantic("SQL DataCommandHandler finalizing");
+       try{
+               m_dataCommand.Reset();
+       } catch (const Exception::InternalError &) {
+               LogError("Couldn't execute reset statement - Internal Error");
+       } catch (...) {
+               LogError("Couldn't execute reset statement - unknown exception");
+       }
+}
 
 void SqlConnection::Connect(const std::string &address,
                                                        Flag::Option flag)
@@ -751,11 +804,9 @@ void SqlConnection::Disconnect()
 
        LogPedantic("Disconnecting from DB...");
 
-       // All stored data commands must be deleted before disconnect
-       assert(m_dataCommandsCount == 0);
-
        int result;
 
+       m_preparedStatements.clear();
        result = sqlite3_close(m_connection);
 
        if (result != SQLITE_OK) {
@@ -777,8 +828,7 @@ bool SqlConnection::CheckTableExist(const char *tableName)
                return false;
        }
 
-       DataCommandUniquePtr command =
-               PrepareDataCommand("select tbl_name from sqlite_master where name=?;");
+       DataCommandHandlerUniquePtr command = PrepareDataCommand(TABLE_EXISTS_CMD_BUF);
 
        command->BindString(1, tableName);
 
@@ -786,7 +836,6 @@ bool SqlConnection::CheckTableExist(const char *tableName)
                LogPedantic("No matching records in table");
                return false;
        }
-
        return command->GetColumnString(0) == tableName;
 }
 
@@ -794,7 +843,6 @@ SqlConnection::SqlConnection(const std::string &address,
                                                         Flag::Option option,
                                                         SynchronizationObject *synchronizationObject) :
        m_connection(NULL),
-       m_dataCommandsCount(0),
        m_synchronizationObject(synchronizationObject),
        m_isKeySet(false)
 {
@@ -941,21 +989,25 @@ void SqlConnection::ExecCommand(const char *format, ...)
        va_end(args);
 }
 
-SqlConnection::DataCommandUniquePtr SqlConnection::PrepareDataCommand(
-       const char *format,
+SqlConnection::DataCommandHandlerUniquePtr SqlConnection::PrepareDataCommand(
+       const CommandBuffer &buff,
        ...)
 {
        if (m_connection == NULL) {
                LogError("Cannot execute data command. Not connected to DB!");
-               return DataCommandUniquePtr();
+               return DataCommandHandlerUniquePtr();
        }
 
+       auto findStatement = m_preparedStatements.find(buff.id);
+       if (findStatement != m_preparedStatements.end())
+               return DataCommandHandlerUniquePtr(new DataCommandHandler(findStatement->second));
+
        char *rawBuffer;
 
        va_list args;
-       va_start(args, format);
+       va_start(args, buff);
 
-       if (vasprintf(&rawBuffer, format, args) == -1)
+       if (vasprintf(&rawBuffer, buff.buffer, args) == -1)
                rawBuffer = NULL;
 
        va_end(args);
@@ -964,12 +1016,21 @@ SqlConnection::DataCommandUniquePtr SqlConnection::PrepareDataCommand(
 
        if (!buffer) {
                LogError("Failed to allocate statement string");
-               return DataCommandUniquePtr();
+               return DataCommandHandlerUniquePtr();
        }
 
        LogPedantic("Executing SQL data command: " << buffer.get());
 
-       return DataCommandUniquePtr(new DataCommand(this, buffer.get()));
+       return DataCommandHandlerUniquePtr(new DataCommandHandler(m_preparedStatements.emplace(
+               std::piecewise_construct,
+               std::forward_as_tuple(buff.id),
+               std::forward_as_tuple(this, buffer.get()))
+               .first->second));
+}
+
+void SqlConnection::ClearMap()
+{
+       m_preparedStatements.clear();
 }
 
 //LCOV_EXCL_START
index f4235ca6de609d410c9fd9d8522b11fc7a8627f2..585436167fb186eac282d1ffc4fae7b9477b4371 100644 (file)
@@ -59,6 +59,13 @@ enum DBVersion : int {
 const char *SCRIPT_CREATE_SCHEMA                = "create_schema";
 const char *SCRIPT_DROP_ALL_ITEMS               = "drop_all";
 const char *SCRIPT_MIGRATE                      = "migrate_";
+const char *DB_SCHEMA_VERSION_FIELD             = "schema_version";
+
+} //anonymous namespace
+
+namespace CKM {
+namespace DB {
+namespace {
 
 // common substitutions:
 // 100 - idx
@@ -67,97 +74,76 @@ const char *SCRIPT_MIGRATE                      = "migrate_";
 // 103 - value
 // 104 - permissionLabel
 // 105 - permissionMask
-const char *DB_CMD_SCHEMA_SET =
-       "REPLACE INTO SCHEMA_INFO(name, value) "
-       "   VALUES(?101, ?103);";
-
-const char *DB_CMD_SCHEMA_GET =
-       "SELECT * FROM SCHEMA_INFO WHERE name=?101;";
-
-const char *DB_SCHEMA_VERSION_FIELD = "schema_version";
-
-
-const char *DB_CMD_NAME_INSERT =
-       "INSERT INTO NAMES("
-       "   name, label) "
-       "   VALUES(?101, ?102);";
-
-const char *DB_CMD_NAME_COUNT_ROWS =
-       "SELECT COUNT(idx) FROM NAMES WHERE name=?101 AND label=?102;";
-
-const char *DB_CMD_NAME_DELETE =
-       "DELETE FROM NAMES WHERE name=?101 AND label=?102;";
-
-const char *DB_CMD_NAME_DELETE_BY_OWNER =
-       "DELETE FROM NAMES WHERE label=?102;";
-
-
-const char *DB_CMD_OBJECT_INSERT =
-       "INSERT INTO OBJECTS("
-       "   exportable, dataType,"
-       "   algorithmType, encryptionScheme,"
-       "   iv, dataSize, data, tag, idx, backendId) "
-       "   VALUES(?001, ?002, ?003, ?004, ?005, "
-       "          ?006, ?007, ?008,"
-       "          (SELECT idx FROM NAMES WHERE name=?101 and label=?102),"
-       "          ?009"
-       "         );";
-
-const char *DB_CMD_OBJECT_UPDATE =
-       "UPDATE OR FAIL OBJECTS SET"
-       "   algorithmType = ?003,"
-       "   encryptionScheme = ?004,"
-       "   iv = ?005,"
-       "   dataSize = ?006,"
-       "   data = ?007,"
-       "   tag = ?008"
-       "   WHERE idx IN (SELECT idx FROM NAMES WHERE name=?101 and label=?102)"
-       "   AND dataType = ?002;";
-
-const char *DB_CMD_OBJECT_SELECT_BY_NAME_AND_OWNER =
-       "SELECT * FROM [join_name_object_tables] "
-       " WHERE (dataType BETWEEN ?001 AND ?002) "
-       " AND name=?101 and label=?102;";
-
-
-const char *DB_CMD_KEY_INSERT =
-       "INSERT INTO KEYS(label, key) VALUES (?, ?);";
-const char *DB_CMD_KEY_SELECT =
-       "SELECT key FROM KEYS WHERE label=?;";
-const char *DB_CMD_KEY_DELETE =
-       "DELETE FROM KEYS WHERE label=?";
-
-
-const char *DB_CMD_PERMISSION_SET = // SQLite does not support updating views
-       "REPLACE INTO PERMISSIONS(permissionLabel, permissionMask, idx) "
-       " VALUES (?104, ?105, (SELECT idx FROM NAMES WHERE name=?101 and label=?102));";
-
-const char *DB_CMD_PERMISSION_SELECT =
-       "SELECT permissionMask FROM [join_name_permission_tables] "
-       " WHERE permissionLabel=?104 "
-       " AND name=?101 and label=?102;";
-
-const char *DB_CMD_PERMISSION_DELETE = // SQLite does not support updating views
-       "DELETE FROM PERMISSIONS WHERE permissionLabel=?104 AND "
-       " idx=(SELECT idx FROM NAMES WHERE name=?101 and label=?102);";
-
-
+constexpr CommandBuffer SCHEMA_SET_CMD_BUF{DB_CMD_SCHEMA_SET_ID,
+                                               "REPLACE INTO SCHEMA_INFO(name, value) "
+                                               "   VALUES(?101, ?103);"};
+constexpr CommandBuffer SCHEMA_GET_CMD_BUF{DB_CMD_SCHEMA_GET_ID,
+                                               "SELECT * FROM SCHEMA_INFO WHERE name=?101;"};
+constexpr CommandBuffer NAME_INSERT_CMD_BUF{DB_CMD_NAME_INSERT_ID,
+                                               "INSERT INTO NAMES("
+                                               "   name, label) "
+                                               "   VALUES(?101, ?102);"};
+constexpr CommandBuffer NAME_COUNT_ROWS_CMD_BUF{DB_CMD_NAME_COUNT_ROWS_ID,
+                                               "SELECT COUNT(idx) FROM NAMES WHERE name=?101 AND label=?102;"};
+constexpr CommandBuffer NAME_DELETE_CMD_BUF{DB_CMD_NAME_DELETE_ID,
+                                               "DELETE FROM NAMES WHERE name=?101 AND label=?102;"};
+constexpr CommandBuffer NAME_DELETE_BY_OWNER_CMD_BUF{DB_CMD_NAME_DELETE_BY_OWNER_ID,
+                                               "DELETE FROM NAMES WHERE label=?102;"};
+constexpr CommandBuffer OBJECT_INSERT_CMD_BUF{DB_CMD_OBJECT_INSERT_ID,
+                                               "INSERT INTO OBJECTS("
+                                               "   exportable, dataType,"
+                                               "   algorithmType, encryptionScheme,"
+                                               "   iv, dataSize, data, tag, idx, backendId) "
+                                               "   VALUES(?001, ?002, ?003, ?004, ?005, "
+                                               "          ?006, ?007, ?008,"
+                                               "          (SELECT idx FROM NAMES WHERE name=?101 and label=?102),"
+                                               "          ?009"
+                                               "         );"};
+constexpr CommandBuffer OBJECT_UPDATE_CMD_BUF{DB_CMD_OBJECT_UPDATE_ID,
+                                               "UPDATE OR FAIL OBJECTS SET"
+                                               "   algorithmType = ?003,"
+                                               "   encryptionScheme = ?004,"
+                                               "   iv = ?005,"
+                                               "   dataSize = ?006,"
+                                               "   data = ?007,"
+                                               "   tag = ?008"
+                                               "   WHERE idx IN (SELECT idx FROM NAMES WHERE name=?101 and label=?102)"
+                                               "   AND dataType = ?002;"};
+constexpr CommandBuffer OBJECT_SELECT_BY_NAME_AND_OWNER_CMD_BUF{
+                                               DB_CMD_OBJECT_SELECT_BY_NAME_AND_OWNER_ID,
+                                               "SELECT * FROM [join_name_object_tables] "
+                                               " WHERE (dataType BETWEEN ?001 AND ?002) "
+                                               " AND name=?101 and label=?102;"};
+constexpr CommandBuffer KEY_INSERT_CMD_BUF{DB_CMD_KEY_INSERT_ID,
+                                               "INSERT INTO KEYS(label, key) VALUES (?, ?);"};
+constexpr CommandBuffer KEY_SELECT_CMD_BUF{DB_CMD_KEY_SELECT_ID,
+                                               "SELECT key FROM KEYS WHERE label=?;"};
+constexpr CommandBuffer KEY_DELETE_CMD_BUF{DB_CMD_KEY_DELETE_ID,
+                                               "DELETE FROM KEYS WHERE label=?"};
+// SQLite does not support updating views
+constexpr CommandBuffer PERMISSION_SET_CMD_BUF{DB_CMD_PERMISSION_SET_ID,
+                                               "REPLACE INTO PERMISSIONS(permissionLabel, permissionMask, idx) "
+                                               " VALUES (?104, ?105, (SELECT idx FROM NAMES WHERE name=?101 and label=?102));"};
+constexpr CommandBuffer PERMISSION_SELECT_CMD_BUF{DB_CMD_PERMISSION_SELECT_ID,
+                                               "SELECT permissionMask FROM [join_name_permission_tables] "
+                                               " WHERE permissionLabel=?104 "
+                                               " AND name=?101 and label=?102;"};
+// SQLite does not support updating views
+constexpr CommandBuffer PERMISSION_DELETE_CMD_BUF{DB_CMD_PERMISSION_DELETE_ID,
+                                               "DELETE FROM PERMISSIONS WHERE permissionLabel=?104 AND "
+                                               " idx=(SELECT idx FROM NAMES WHERE name=?101 and label=?102);"};
 /*
  * GROUP BY is necessary because of the following case:
  * -There are several permissions to L1, N1 (label, name) from other accessors. When listing
  *  objects accessible by L1 the query will produce one result (L1, N1) for each allowed
  *  accessor but GROUP BY will reduce them to one so L1 will have (L1, N1) on its list only once
  */
-const char *DB_CMD_INFO_SELECT_BY_TYPE_AND_PERMISSION =
-       "SELECT label, name, dataType, backendId FROM [join_all_tables] "
-       " WHERE dataType>=?001 AND dataType<=?002 "
-       " AND permissionLabel=?104 AND permissionMask&?004!=0 GROUP BY idx;";
-}
-
-namespace CKM {
-namespace DB {
+constexpr CommandBuffer INFO_SELECT_BY_TYPE_AND_PERMISSION_CMD_BUF{
+                                               DB_CMD_INFO_SELECT_BY_TYPE_AND_PERMISSION_ID,
+                                               "SELECT label, name, dataType, backendId FROM [join_all_tables] "
+                                               " WHERE dataType>=?001 AND dataType<=?002 "
+                                               " AND permissionLabel=?104 AND permissionMask&?004!=0 GROUP BY idx;"};
 
-namespace {
 auto openSqlConnection(const std::string &path, const RawBuffer &rawPass)
 {
        auto conn = std::make_unique<SqlConnection>(path, SqlConnection::Flag::Option::CRW);
@@ -486,7 +472,7 @@ bool Crypto::deleteRow(
 }
 
 Row Crypto::getRow(
-       const SqlConnection::DataCommandUniquePtr &selectCommand) const
+       const SqlConnection::DataCommandHandlerUniquePtr &selectCommand) const
 {
        Row row;
        row.name = selectCommand->GetColumnString(0);
@@ -538,8 +524,8 @@ Crypto::RowOptional Crypto::getRow(
        DataType typeRangeStop)
 {
        try {
-               SqlConnection::DataCommandUniquePtr selectCommand =
-                       m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_OWNER);
+               auto selectCommand =
+                       m_connection->PrepareDataCommand(OBJECT_SELECT_BY_NAME_AND_OWNER_CMD_BUF);
                selectCommand->BindInteger(1, typeRangeStart);
                selectCommand->BindInteger(2, typeRangeStop);
 
@@ -588,8 +574,8 @@ void Crypto::getRows(
        RowVector &output)
 {
        try {
-               SqlConnection::DataCommandUniquePtr selectCommand =
-                       m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_OWNER);
+               auto selectCommand =
+                       m_connection->PrepareDataCommand(OBJECT_SELECT_BY_NAME_AND_OWNER_CMD_BUF);
                selectCommand->BindInteger(1, typeRangeStart);
                selectCommand->BindInteger(2, typeRangeStop);
 
@@ -632,8 +618,8 @@ void Crypto::listInfos(const ClientId &accessor,
 {
        try {
                Transaction transaction(this);
-               SqlConnection::DataCommandUniquePtr selectCommand =
-                       m_connection->PrepareDataCommand(DB_CMD_INFO_SELECT_BY_TYPE_AND_PERMISSION);
+               auto selectCommand =
+                       m_connection->PrepareDataCommand(INFO_SELECT_BY_TYPE_AND_PERMISSION_CMD_BUF);
                selectCommand->BindInteger(1, typeRangeStart);
                selectCommand->BindInteger(2, typeRangeStop);
                selectCommand->BindString(104, accessor.c_str());
@@ -681,8 +667,7 @@ void Crypto::saveKey(
        const RawBuffer &key)
 {
        try {
-               SqlConnection::DataCommandUniquePtr insertCommand =
-                       m_connection->PrepareDataCommand(DB_CMD_KEY_INSERT);
+               auto insertCommand = m_connection->PrepareDataCommand(KEY_INSERT_CMD_BUF);
                insertCommand->BindString(1, owner.c_str());
                insertCommand->BindBlob(2, key);
                insertCommand->Step();
@@ -699,14 +684,15 @@ void Crypto::saveKey(
 Crypto::RawBufferOptional Crypto::getKey(const ClientId &owner)
 {
        try {
-               SqlConnection::DataCommandUniquePtr selectCommand =
-                       m_connection->PrepareDataCommand(DB_CMD_KEY_SELECT);
+               auto selectCommand = m_connection->PrepareDataCommand(KEY_SELECT_CMD_BUF);
                selectCommand->BindString(1, owner.c_str());
 
-               if (selectCommand->Step())
-                       return RawBufferOptional(selectCommand->GetColumnBlob(0));
-               else
+               if (selectCommand->Step()) {
+                       RawBuffer ret = selectCommand->GetColumnBlob(0);
+                       return RawBufferOptional(ret);
+               } else
                        return RawBufferOptional();
+
        } catch (const SqlConnection::Exception::InvalidColumn &) {
                LogError("Select statement invalid column error");
        } catch (const SqlConnection::Exception::SyntaxError &) {
@@ -723,11 +709,9 @@ void Crypto::deleteKey(const ClientId &owner)
        try {
                Transaction transaction(this);
 
-               SqlConnection::DataCommandUniquePtr deleteCommand =
-                       m_connection->PrepareDataCommand(DB_CMD_KEY_DELETE);
+               auto deleteCommand = m_connection->PrepareDataCommand(KEY_DELETE_CMD_BUF);
                deleteCommand->BindString(1, owner.c_str());
                deleteCommand->Step();
-
                NameTable nameTable(m_connection.get());
                nameTable.deleteAllRows(owner);
 
@@ -763,8 +747,7 @@ void Crypto::setPermission(
 
 void Crypto::SchemaInfo::setVersionInfo()
 {
-       SqlConnection::DataCommandUniquePtr insertContextCommand =
-               m_connection->PrepareDataCommand(DB_CMD_SCHEMA_SET);
+       auto insertContextCommand = m_connection->PrepareDataCommand(SCHEMA_SET_CMD_BUF);
        insertContextCommand->BindString(101, DB_SCHEMA_VERSION_FIELD);
        insertContextCommand->BindString(103,
                                                                         std::to_string(DB_VERSION_CURRENT).c_str());
@@ -773,8 +756,7 @@ void Crypto::SchemaInfo::setVersionInfo()
 
 bool Crypto::SchemaInfo::getVersionInfo(int &version)
 {
-       SqlConnection::DataCommandUniquePtr selectCommand =
-               m_connection->PrepareDataCommand(DB_CMD_SCHEMA_GET);
+       auto selectCommand = m_connection->PrepareDataCommand(SCHEMA_GET_CMD_BUF);
        selectCommand->BindString(101, DB_SCHEMA_VERSION_FIELD);
 
        if (selectCommand->Step()) {
@@ -792,16 +774,14 @@ void Crypto::PermissionTable::setPermission(
 {
        if (permissionMask == Permission::NONE) {
                // clear permissions
-               SqlConnection::DataCommandUniquePtr deletePermissionCommand =
-                       m_connection->PrepareDataCommand(DB_CMD_PERMISSION_DELETE);
+               auto deletePermissionCommand = m_connection->PrepareDataCommand(PERMISSION_DELETE_CMD_BUF);
                deletePermissionCommand->BindString(104, accessor.c_str());
                deletePermissionCommand->BindString(101, name.c_str());
                deletePermissionCommand->BindString(102, owner.c_str());
                deletePermissionCommand->Step();
        } else {
                // add new permissions
-               SqlConnection::DataCommandUniquePtr setPermissionCommand =
-                       m_connection->PrepareDataCommand(DB_CMD_PERMISSION_SET);
+               auto setPermissionCommand = m_connection->PrepareDataCommand(PERMISSION_SET_CMD_BUF);
                setPermissionCommand->BindString(104, accessor.c_str());
                setPermissionCommand->BindInteger(105, static_cast<int>(permissionMask));
                setPermissionCommand->BindString(101, name.c_str());
@@ -815,8 +795,7 @@ PermissionMaskOptional Crypto::PermissionTable::getPermissionRow(
        const ClientId &owner,
        const ClientId &accessor) const
 {
-       SqlConnection::DataCommandUniquePtr selectCommand =
-               m_connection->PrepareDataCommand(DB_CMD_PERMISSION_SELECT);
+       auto selectCommand = m_connection->PrepareDataCommand(PERMISSION_SELECT_CMD_BUF);
        selectCommand->BindString(104, accessor.c_str());
 
        // name table reference
@@ -825,8 +804,8 @@ PermissionMaskOptional Crypto::PermissionTable::getPermissionRow(
 
        if (selectCommand->Step()) {
                // there is entry for the <name, owner> pair
-               return PermissionMaskOptional(PermissionMask(selectCommand->GetColumnInteger(
-                                                                                 0)));
+               int ret = selectCommand->GetColumnInteger(0);
+               return PermissionMaskOptional(PermissionMask(ret));
        }
 
        return PermissionMaskOptional();
@@ -837,8 +816,7 @@ void Crypto::NameTable::addRow(
        const ClientId &owner)
 {
        // insert NAMES item
-       SqlConnection::DataCommandUniquePtr insertNameCommand =
-               m_connection->PrepareDataCommand(DB_CMD_NAME_INSERT);
+       auto insertNameCommand = m_connection->PrepareDataCommand(NAME_INSERT_CMD_BUF);
        insertNameCommand->BindString(101, name.c_str());
        insertNameCommand->BindString(102, owner.c_str());
        insertNameCommand->Step();
@@ -848,8 +826,7 @@ void Crypto::NameTable::deleteRow(
        const Name &name,
        const ClientId &ownerOwner)
 {
-       SqlConnection::DataCommandUniquePtr deleteCommand =
-               m_connection->PrepareDataCommand(DB_CMD_NAME_DELETE);
+       auto deleteCommand = m_connection->PrepareDataCommand(NAME_DELETE_CMD_BUF);
        deleteCommand->BindString(101, name.c_str());
        deleteCommand->BindString(102, ownerOwner.c_str());
 
@@ -860,8 +837,7 @@ void Crypto::NameTable::deleteRow(
 
 void Crypto::NameTable::deleteAllRows(const ClientId &owner)
 {
-       SqlConnection::DataCommandUniquePtr deleteData =
-               m_connection->PrepareDataCommand(DB_CMD_NAME_DELETE_BY_OWNER);
+       auto deleteData = m_connection->PrepareDataCommand(NAME_DELETE_BY_OWNER_CMD_BUF);
        deleteData->BindString(102, owner.c_str());
 
        // Step() result code does not provide information whether
@@ -872,8 +848,7 @@ void Crypto::NameTable::deleteAllRows(const ClientId &owner)
 bool Crypto::NameTable::isPresent(const Name &name,
                                                                  const ClientId &owner) const
 {
-       SqlConnection::DataCommandUniquePtr checkCmd =
-               m_connection->PrepareDataCommand(DB_CMD_NAME_COUNT_ROWS);
+       auto checkCmd = m_connection->PrepareDataCommand(NAME_COUNT_ROWS_CMD_BUF);
        checkCmd->BindString(101, name.c_str());
        checkCmd->BindString(102, owner.c_str());
 
@@ -891,8 +866,7 @@ bool Crypto::NameTable::isPresent(const Name &name,
 
 void Crypto::ObjectTable::addRow(const Row &row)
 {
-       SqlConnection::DataCommandUniquePtr insertObjectCommand =
-               m_connection->PrepareDataCommand(DB_CMD_OBJECT_INSERT);
+       auto insertObjectCommand = m_connection->PrepareDataCommand(OBJECT_INSERT_CMD_BUF);
        insertObjectCommand->BindInteger(1, row.exportable);
        insertObjectCommand->BindInteger(2, row.dataType);
        insertObjectCommand->BindInteger(3, static_cast<int>(row.algorithmType));
@@ -912,8 +886,7 @@ void Crypto::ObjectTable::addRow(const Row &row)
 
 void Crypto::ObjectTable::updateRow(const Row &row)
 {
-       SqlConnection::DataCommandUniquePtr updateObjectCommand =
-               m_connection->PrepareDataCommand(DB_CMD_OBJECT_UPDATE);
+       auto updateObjectCommand = m_connection->PrepareDataCommand(OBJECT_UPDATE_CMD_BUF);
        updateObjectCommand->BindInteger(2, row.dataType);
        updateObjectCommand->BindInteger(3, static_cast<int>(row.algorithmType));
        updateObjectCommand->BindInteger(4, row.encryptionScheme);
index 83b13a807890009351d8242f3778d4883452d2e6..ee1441f6fe9a4ee3a3534b6063624db624339439 100644 (file)
@@ -219,7 +219,7 @@ protected:
        std::unique_ptr<SqlConnection> m_connection;
 
        Row getRow(
-               const SqlConnection::DataCommandUniquePtr &selectCommand) const;
+               const SqlConnection::DataCommandHandlerUniquePtr &selectCommand) const;
 
 private:
        bool m_inUserTransaction;
index 54ec4653568cb5a922da81fdb2866cbddf34b649..e6e1d8258845d3246573a9dcccf45a1845031628 100644 (file)
@@ -34,6 +34,7 @@
 #include <test_common.h>
 
 using CKM::DB::SqlConnection;
+using CKM::DB::CommandBuffer;
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
@@ -45,39 +46,45 @@ const char *CREATE_TABLE = "CREATE TABLE t1(a,b);";
 const char *INSERT_TABLE = "INSERT INTO t1(a,b) VALUES ("
                                                   " 'one for the money',"
                                                   " 'two for the show');";
-const char *SELECT_TABLE = "SELECT * FROM t1";
-
-const char *SELECT_COMMAND = "SELECT COUNT(idx) FROM NAMES WHERE name=?101 AND label=?102;";
-const char *INSERT_COMMAND = "INSERT INTO NAMES("
-                                                        "name, label) "
-                                                        "VALUES(?101, ?102);";
-const char *DELETE_COMMAND = "DELETE FROM NAMES WHERE name=?101 AND label=?102;";
-constexpr int TIMES = 100;
 
 CKM::RawBuffer RAW_PASSWORD = createDefaultPass();
 
+constexpr CommandBuffer SELECT_TABLE_BUF{CKM::DB::DB_CMD_SELECT_TABLE_ID,
+                                                                                                       "SELECT * FROM t1"};
+
+constexpr CommandBuffer SELECT_TEST_BUF{CKM::DB::DB_CMD_NAME_COUNT_ROWS_ID,
+                                               "SELECT COUNT(idx) FROM NAMES WHERE name=?101 AND label=?102;"};
+constexpr CommandBuffer INSERT_TEST_BUF{CKM::DB::DB_CMD_NAME_INSERT_ID,
+                                               "INSERT INTO NAMES("
+                                               "       name, label) "
+                                               "       VALUES(?101, ?102);"};
+constexpr CommandBuffer DELETE_TEST_BUF{CKM::DB::DB_CMD_NAME_DELETE_ID,
+                                               "DELETE FROM NAMES WHERE name=?101 AND label=?102;"};
+constexpr int TIMES = 100;
+
 class MockCrypto : public CKM::DB::Crypto {
 public:
        MockCrypto(const std::string &path, const CKM::RawBuffer &rawPass)
                :Crypto("", path, rawPass) {}
 
-       void countTimePreparedStatements(const char * statement){
+       void countTimePreparedStatements(const CommandBuffer &statement)
+       {
                auto begin = std::chrono::steady_clock::now();
                for (int i = 0; i < TIMES; ++i) {
                        BOOST_REQUIRE_NO_THROW(m_connection->PrepareDataCommand(statement));
                }
                auto end = std::chrono::steady_clock::now();
 
-               std::cout << "Average " << statement << "\npreparation time: "
+               std::cout << "Average " << statement.buffer << "\npreparation time: "
                   << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() / TIMES
                   << "[µs]\n";
        }
 
-       void countTimePreparedStatementsSteps(const char * statement)
+       void countTimePreparedStatementsSteps(const CommandBuffer &statement)
        {
                auto begin = std::chrono::steady_clock::now();
                for (int i = 0; i < TIMES; ++i) {
-                       SqlConnection::DataCommandUniquePtr command;
+                       SqlConnection::DataCommandHandlerUniquePtr command;
                        std::string str = "name";
                        str += i;
                        BOOST_REQUIRE_NO_THROW(command = m_connection->PrepareDataCommand(statement));
@@ -86,11 +93,26 @@ public:
                        BOOST_REQUIRE_NO_THROW(command->Step());
                }
                auto end = std::chrono::steady_clock::now();
-               std::cout << "Average " << statement << "\npreparation&execution time: "
+               std::cout << "Average " << statement.buffer << "\npreparation&execution time: "
                   << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() / TIMES
                   << "[µs]\n";
        }
 
+       void countTimePreparedStatementsReset(const CommandBuffer &statement)
+       {
+               auto count = std::chrono::steady_clock::duration::zero();
+               for (int i = 0; i < TIMES; ++i) {
+                       auto begin = std::chrono::steady_clock::now();
+                       BOOST_REQUIRE_NO_THROW(m_connection->PrepareDataCommand(statement));
+                       auto end = std::chrono::steady_clock::now();
+                       count += (end - begin);
+                       m_connection->ClearMap();
+               }
+
+               std::cout << "Average " << statement.buffer << "\npreparation time: "
+                  << std::chrono::duration_cast<std::chrono::microseconds>(count).count() / TIMES
+                  << "[µs]\n";
+       }
 };
 
 BOOST_AUTO_TEST_SUITE(SQL_TEST)
@@ -152,9 +174,9 @@ POSITIVE_TEST_CASE(sqlTestConnectionUnencrypted)
        {
                SqlConnection encrypting_you_not(ENCRYPT_ME_NOT,
                                                                                 SqlConnection::Flag::RW);
-               SqlConnection::DataCommandUniquePtr selectCommand;
+               SqlConnection::DataCommandHandlerUniquePtr selectCommand;
                BOOST_REQUIRE_NO_THROW(selectCommand = encrypting_you_not.
-                                                                                          PrepareDataCommand(SELECT_TABLE));
+                                                                                          PrepareDataCommand(SELECT_TABLE_BUF));
                BOOST_REQUIRE_NO_THROW(selectCommand->Step());
                std::string value;
                BOOST_REQUIRE_NO_THROW(value = selectCommand->GetColumnString(0));
@@ -178,9 +200,9 @@ POSITIVE_TEST_CASE(sqlTestConnectionEncrypted)
                SqlConnection encrypting_you(ENCRYPT_ME,
                                                                         SqlConnection::Flag::RW);
                encrypting_you.SetKey(RAW_PASSWORD);
-               SqlConnection::DataCommandUniquePtr selectCommand;
+               SqlConnection::DataCommandHandlerUniquePtr selectCommand;
                BOOST_REQUIRE_NO_THROW(selectCommand = encrypting_you.
-                                                                                          PrepareDataCommand(SELECT_TABLE));
+                                                                                          PrepareDataCommand(SELECT_TABLE_BUF));
                BOOST_REQUIRE_NO_THROW(selectCommand->Step());
                std::string value;
                BOOST_REQUIRE_NO_THROW(value = selectCommand->GetColumnString(0));
@@ -210,23 +232,25 @@ NEGATIVE_TEST_CASE(sqlTestConnectionEncryptedNegative)
 
                BOOST_REQUIRE_NO_THROW(encrypting_you.SetKey(wrong_password));
 
-               SqlConnection::DataCommandUniquePtr selectCommand;
+               SqlConnection::DataCommandHandlerUniquePtr selectCommand;
                BOOST_REQUIRE_THROW(selectCommand = encrypting_you.PrepareDataCommand(
-                                                                                               SELECT_TABLE),
+                                                                                               SELECT_TABLE_BUF),
                                                        SqlConnection::Exception::SyntaxError);
        }
 }
-
 POSITIVE_TEST_CASE(sqlTestEfficiency)
 {
        MockCrypto mc(TEST_DB_CKM, RAW_PASSWORD);
 
-       mc.countTimePreparedStatements(INSERT_COMMAND);
-       mc.countTimePreparedStatements(SELECT_COMMAND);
-       mc.countTimePreparedStatements(DELETE_COMMAND);
-       mc.countTimePreparedStatementsSteps(INSERT_COMMAND);
-       mc.countTimePreparedStatementsSteps(SELECT_COMMAND);
-       mc.countTimePreparedStatementsSteps(DELETE_COMMAND);
+       mc.countTimePreparedStatements(INSERT_TEST_BUF);
+       mc.countTimePreparedStatements(SELECT_TEST_BUF);
+       mc.countTimePreparedStatements(DELETE_TEST_BUF);
+       mc.countTimePreparedStatementsSteps(INSERT_TEST_BUF);
+       mc.countTimePreparedStatementsSteps(SELECT_TEST_BUF);
+       mc.countTimePreparedStatementsSteps(DELETE_TEST_BUF);
+       mc.countTimePreparedStatementsReset(INSERT_TEST_BUF);
+       mc.countTimePreparedStatementsReset(SELECT_TEST_BUF);
+       mc.countTimePreparedStatementsReset(DELETE_TEST_BUF);
 }
 
 BOOST_AUTO_TEST_SUITE_END()