Dynamic configuration stored in a database 31/25531/5
authorJan Olszak <j.olszak@samsung.com>
Mon, 4 Aug 2014 09:09:08 +0000 (11:09 +0200)
committerJan Olszak <j.olszak@samsung.com>
Fri, 8 Aug 2014 12:09:07 +0000 (14:09 +0200)
[Bug/Feature]   Storing configuration in SQLite3 database
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, install, run tests

Change-Id: If14be7c9e0c62c985215f904d308d2d172c71fff

CMakeLists.txt
packaging/libConfig.spec
src/CMakeLists.txt
src/config/kvstore.cpp [new file with mode: 0644]
src/config/kvstore.hpp [new file with mode: 0644]
src/config/sqlite3/connection.cpp [new file with mode: 0644]
src/config/sqlite3/connection.hpp [new file with mode: 0644]
src/config/sqlite3/statement.cpp [new file with mode: 0644]
src/config/sqlite3/statement.hpp [new file with mode: 0644]
src/libConfig.pc.in

index 1ee9397..c223d8a 100644 (file)
@@ -19,7 +19,8 @@
 CMAKE_MINIMUM_REQUIRED (VERSION 2.6.2)
 PROJECT(Config)
 
-SET(_VERSION_ "0.0.1")
+SET(_LIB_VERSION_ "0.0.1")
+SET(_LIB_SOVERSION_ "0")
 
 ## pkgconfig ###################################################################
 INCLUDE(FindPkgConfig)
@@ -66,7 +67,7 @@ IF(NOT DEFINED LIB_INSTALL_DIR)
 ENDIF(NOT DEFINED LIB_INSTALL_DIR)
 
 IF(NOT DEFINED INCLUDE_INSTALL_DIR)
-    SET(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_FULL_INCLUDEDIR})
+    SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
 ENDIF(NOT DEFINED INCLUDE_INSTALL_DIR)
 
 ADD_SUBDIRECTORY(${SRC_FOLDER})
index f65c1fb..99c1dd5 100644 (file)
@@ -9,13 +9,22 @@ Group:         Security/Other
 Summary:       Config library
 
 BuildRequires: cmake
+BuildRequires: pkgconfig(sqlite3)
+
 
 %description
 The package provides libConfig library.
 
+%files
+%manifest packaging/libConfig.manifest
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_libdir}/libConfig.so.0.0.1
+%{_libdir}/libConfig.so.0
+
 %package       devel
 Summary:       Development package for config library
 Group:         Development/Libraries
+Requires:      libConfig = %{version}-%{release}
 Requires:      boost-devel
 Requires:      pkgconfig(libLogger)
 Requires:      libjson-devel
@@ -25,6 +34,7 @@ The package provides libConfig development tools and libs.
 
 %files         devel
 %defattr(644,root,root,755)
+%{_libdir}/libConfig.so
 %{_includedir}/sc-tools
 %{_libdir}/pkgconfig/*.pc
 
@@ -51,3 +61,7 @@ make -k %{?jobs:-j%jobs}
 
 %clean
 rm -rf %{buildroot}
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
\ No newline at end of file
index 9c1d5c8..911e71a 100644 (file)
 SET(PC_FILE "${SRC_FOLDER}/lib${PROJECT_NAME}.pc")
 
 MESSAGE(STATUS "Generating makefile for the libConfig sources...")
-FILE(GLOB         HEADERS       "${SRC_FOLDER}/config/*.hpp")
-FILE(GLOB_RECURSE SRCS          "${SRC_FOLDER}" *.hpp *.cpp)
+FILE(GLOB         HEADERS         "${SRC_FOLDER}/config/*.hpp")
+FILE(GLOB         HEADERS_SQLITE3 "${SRC_FOLDER}/config/sqlite3/*.hpp")
+FILE(GLOB_RECURSE SRCS            "${SRC_FOLDER}" *.hpp *.cpp)
 
 ## Setup target ################################################################
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY SOVERSION ${_LIB_SOVERSION_})
+SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY   VERSION ${_LIB_VERSION_})
 
 ## Link libraries #############################################################
+PKG_CHECK_MODULES(CONFIG_DEPS REQUIRED sqlite3)
 INCLUDE_DIRECTORIES(${SRC_FOLDER})
 INCLUDE_DIRECTORIES(SYSTEM ${CONFIG_DEPS_INCLUDE_DIRS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${CONFIG_DEPS_LIBRARIES})
+
 
 ## Install #####################################################################
 CONFIGURE_FILE(${PC_FILE}.in "${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE}" @ONLY)
 
+INSTALL(TARGETS ${PROJECT_NAME}                        DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
 INSTALL(FILES ${HEADERS}                               DESTINATION "${INCLUDE_INSTALL_DIR}/sc-tools/config")
+INSTALL(FILES ${HEADERS_SQLITE3}                       DESTINATION "${INCLUDE_INSTALL_DIR}/sc-tools/config/sqlite3")
 INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE}" DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
diff --git a/src/config/kvstore.cpp b/src/config/kvstore.cpp
new file mode 100644 (file)
index 0000000..f48ee6f
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief  Definition of a class for key-value storage in a sqlite3 database
+ */
+
+
+#include "config/kvstore.hpp"
+#include "config/exception.hpp"
+
+#include <limits>
+#include <memory>
+#include <algorithm>
+#include <set>
+
+namespace config {
+
+namespace {
+
+const int AUTO_DETERM_SIZE = -1;
+const int FIRST_COLUMN = 0;
+
+struct Transaction {
+    Transaction(sqlite3::Connection& connRef)
+        : mConnRef(connRef)
+    {
+        mConnRef.exec("BEGIN EXCLUSIVE TRANSACTION");
+    }
+    ~Transaction()
+    {
+        mConnRef.exec("COMMIT TRANSACTION");
+    }
+private:
+    sqlite3::Connection& mConnRef;
+};
+
+
+std::string escape(const std::string& in)
+{
+    const std::set<char> toEscape({'?', '*', '[', ']'});
+
+    // Compute the out size
+    auto isEscapeChar = [&](char c) {
+        return toEscape.count(c) == 1;
+    };
+    size_t numEscape = std::count_if(in.begin(),
+                                     in.end(),
+                                     isEscapeChar);
+    if (numEscape == 0) {
+        return in;
+    }
+
+    // Escape characters
+    std::string out(in.size() + 2 * numEscape, 'x');
+    for (size_t i = 0, j = 0;
+            i < in.size();
+            ++i, ++j) {
+        if (isEscapeChar(in[i])) {
+            out[j] = '[';
+            ++j;
+            out[j] = in[i];
+            ++j;
+            out[j] = ']';
+        } else {
+            out[j] = in[i];
+        }
+    }
+    return out;
+}
+
+} // namespace
+
+KVStore::KVStore(const std::string& path)
+    : mConn(path)
+{
+    setupDb();
+    prepareStatements();
+}
+
+KVStore::~KVStore()
+{
+
+}
+
+void KVStore::setupDb()
+{
+    Lock lock(mConnMtx);
+    const std::string setupScript = R"setupScript(
+                                        BEGIN EXCLUSIVE TRANSACTION;
+
+                                        CREATE TABLE IF NOT EXISTS data (
+                                        key TEXT PRIMARY KEY,
+                                        value TEXT NOT NULL
+                                        );
+
+                                        COMMIT TRANSACTION;
+                                      )setupScript";
+
+    mConn.exec(setupScript);
+}
+
+void KVStore::prepareStatements()
+{
+    mGetValueStmt.reset(
+        new sqlite3::Statement(mConn, "SELECT value FROM data WHERE key GLOB ? LIMIT 1"));
+    mGetValueListStmt.reset(
+        new sqlite3::Statement(mConn, "SELECT value FROM data WHERE key GLOB ? ||'*' ORDER BY key"));
+    mGetValueCountStmt.reset(
+        new sqlite3::Statement(mConn, "SELECT count(key) FROM data WHERE key GLOB ? ||'*' "));
+    mGetSizeStmt.reset(
+        new sqlite3::Statement(mConn, "SELECT count(key) FROM data"));
+    mSetValueStmt.reset(
+        new sqlite3::Statement(mConn, "INSERT OR REPLACE INTO data (key, value) VALUES (?,?)"));
+    mRemoveValuesStmt.reset(
+        new sqlite3::Statement(mConn, "DELETE FROM data WHERE key GLOB ? ||'*' "));
+
+}
+
+void KVStore::clear()
+{
+    Lock lock(mConnMtx);
+    Transaction transaction(mConn);
+    mConn.exec("DELETE FROM data");
+}
+
+unsigned int KVStore::size()
+{
+    mGetSizeStmt->reset();
+
+    if (::sqlite3_step(mGetSizeStmt->get()) != SQLITE_ROW) {
+        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+    }
+
+    return static_cast<unsigned int>(::sqlite3_column_int(mGetSizeStmt->get(), FIRST_COLUMN));
+}
+
+unsigned int KVStore::count(const std::string& key)
+{
+    Lock lock(mConnMtx);
+    Transaction transaction(mConn);
+    return countInternal(key);
+}
+
+unsigned int KVStore::countInternal(const std::string& key)
+{
+    mGetValueCountStmt->reset();
+
+    ::sqlite3_bind_text(mGetValueCountStmt->get(), 1, escape(key).c_str(), AUTO_DETERM_SIZE, 0);
+
+    if (::sqlite3_step(mGetValueCountStmt->get()) != SQLITE_ROW) {
+        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+    }
+
+    return static_cast<unsigned int>(::sqlite3_column_int(mGetValueCountStmt->get(), FIRST_COLUMN));
+}
+
+void KVStore::remove(const std::string& key)
+{
+    Lock lock(mConnMtx);
+    Transaction transaction(mConn);
+    removeInternal(key);
+}
+
+void KVStore::removeInternal(const std::string& key)
+{
+    mRemoveValuesStmt->reset();
+    ::sqlite3_bind_text(mRemoveValuesStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, 0);
+
+    if (::sqlite3_step(mRemoveValuesStmt->get()) != SQLITE_DONE) {
+        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+    }
+}
+
+void KVStore::set(const std::string& key, const std::string& value)
+{
+    Lock lock(mConnMtx);
+    mSetValueStmt->reset();
+
+    ::sqlite3_bind_text(mSetValueStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, 0);
+    ::sqlite3_bind_text(mSetValueStmt->get(), 2, value.c_str(), AUTO_DETERM_SIZE, 0);
+
+    Transaction transaction(mConn);
+    if (::sqlite3_step(mSetValueStmt->get()) != SQLITE_DONE) {
+        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+    }
+}
+
+void KVStore::set(const std::string& key, const std::initializer_list<std::string>& values)
+{
+    set(key, std::vector<std::string>(values));
+}
+
+void KVStore::set(const std::string& key, const std::vector<std::string>& values)
+{
+    if (values.size() > std::numeric_limits<unsigned int>::max()) {
+        throw ConfigException("Too many values to insert");
+    }
+
+    Lock lock(mConnMtx);
+    Transaction transaction(mConn);
+
+    removeInternal(key);
+
+    for (unsigned int i = 0; i < values.size(); ++i) {
+        mSetValueStmt->reset();
+        const std::string modifiedKey = key + "." + std::to_string(i);;
+
+        ::sqlite3_bind_text(mSetValueStmt->get(), 1, modifiedKey.c_str(), AUTO_DETERM_SIZE, 0);
+        ::sqlite3_bind_text(mSetValueStmt->get(), 2, values[i].c_str(), AUTO_DETERM_SIZE, 0);
+
+        if (::sqlite3_step(mSetValueStmt->get()) != SQLITE_DONE) {
+            throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+        }
+    }
+}
+
+std::string KVStore::get(const std::string& key)
+{
+    Lock lock(mConnMtx);
+
+    mGetValueStmt->reset();
+    ::sqlite3_bind_text(mGetValueStmt->get(), 1, escape(key).c_str(), AUTO_DETERM_SIZE, 0);
+
+    Transaction transaction(mConn);
+
+    int ret = ::sqlite3_step(mGetValueStmt->get());
+    if (ret == SQLITE_DONE) {
+        throw ConfigException("No value corresponding to the key");
+    }
+    if (ret != SQLITE_ROW) {
+        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+    }
+
+    return reinterpret_cast<const char*>(sqlite3_column_text(mGetValueStmt->get(), FIRST_COLUMN));
+}
+
+std::vector<std::string> KVStore::list(const std::string& key)
+{
+    Lock lock(mConnMtx);
+
+    mGetValueListStmt->reset();
+    ::sqlite3_bind_text(mGetValueListStmt->get(), 1, escape(key).c_str(), AUTO_DETERM_SIZE, 0);
+
+    Transaction transaction(mConn);
+
+    unsigned int valuesSize = countInternal(key);
+    if (valuesSize == 0) {
+        throw ConfigException("No value corresponding to the key");
+    }
+
+    std::vector<std::string> values(valuesSize);
+    for (std::string& value : values) {
+        if (::sqlite3_step(mGetValueListStmt->get()) != SQLITE_ROW) {
+            throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+        }
+        value = reinterpret_cast<const char*>(
+                    sqlite3_column_text(mGetValueListStmt->get(), FIRST_COLUMN));
+    }
+
+    return values;
+}
+} // namespace config
diff --git a/src/config/kvstore.hpp b/src/config/kvstore.hpp
new file mode 100644 (file)
index 0000000..991625b
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief  Declaration of a class for key-value storage in a sqlite3 database
+ */
+
+#ifndef COMMON_CONFIG_KVSTORE_HPP
+#define COMMON_CONFIG_KVSTORE_HPP
+
+#include "config/sqlite3/statement.hpp"
+#include "config/sqlite3/connection.hpp"
+
+#include <sqlite3.h>
+#include <vector>
+#include <string>
+#include <memory>
+#include <initializer_list>
+#include <mutex>
+
+namespace config {
+
+class KVStore {
+
+public:
+
+    /**
+     * @param path configuration database file path
+     */
+    KVStore(const std::string& path);
+    ~KVStore();
+
+    /**
+     * Clears all the stored data
+     */
+    void clear();
+
+
+    /**
+     * @return Number of all stored values
+     */
+    unsigned int size();
+
+    /**
+     * @param key string regexp of the stored values
+     *
+     * @return Number of values corresponding to the passed key
+     */
+    unsigned int count(const std::string& key);
+
+    /**
+     * Removes values corresponding to the passed key.
+     * Many values may correspond to one key, so many values may
+     * need to be deleted
+     *
+     * @param key string regexp of the stored values
+     */
+    void remove(const std::string& key);
+
+    /**
+     * Stores a single value corresponding to the passed key
+     * @param key string key of the value
+     * @param value string value
+     */
+    void set(const std::string& key, const std::string& value);
+
+    /**
+     * Stores a vector of values.
+     * Generates new keys using appending a '.' and consecutive integers.
+     * Removes values corresponding to this key before anything is added.
+     *
+     * @param key string key of the value
+     * @param value string value
+     */
+    void set(const std::string& key, const std::vector<std::string>& values);
+
+    /**
+     * Stores values from the list.
+     *
+     * @see KVStore::set(const std::string& key, const std::vector<std::string>& values)
+     * @param key string key of the value
+     * @param values [description]
+     */
+    void set(const std::string& key, const std::initializer_list<std::string>& values);
+
+    /**
+     * @param key string key of the value
+     * @return string value corresponding to this particular key
+     */
+    std::string get(const std::string& key);
+
+    /**
+     * @param key string key of the value
+     * @return vector of values corresponding to the key
+     */
+    std::vector<std::string> list(const std::string& key);
+
+private:
+    typedef std::lock_guard<std::mutex> Lock;
+
+    std::mutex mConnMtx;
+
+    sqlite3::Connection mConn;
+    std::unique_ptr<sqlite3::Statement> mGetValueStmt;
+    std::unique_ptr<sqlite3::Statement> mGetValueCountStmt;
+    std::unique_ptr<sqlite3::Statement> mGetSizeStmt;
+    std::unique_ptr<sqlite3::Statement> mGetValueListStmt;
+    std::unique_ptr<sqlite3::Statement> mSetValueStmt;
+    std::unique_ptr<sqlite3::Statement> mRemoveValuesStmt;
+
+    void setupDb();
+    void prepareStatements();
+
+    void removeInternal(const std::string& key);
+    unsigned int countInternal(const std::string& key);
+
+};
+
+} // namespace config
+
+#endif // COMMON_CONFIG_KVSTORE_HPP
+
+
diff --git a/src/config/sqlite3/connection.cpp b/src/config/sqlite3/connection.cpp
new file mode 100644 (file)
index 0000000..e5d0552
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief  Definition of the class managing a sqlite3 database connection
+ */
+
+
+#include "config/sqlite3/connection.hpp"
+#include "config/exception.hpp"
+
+namespace config {
+namespace sqlite3 {
+
+Connection::Connection(const std::string& path)
+{
+    if (::sqlite3_open_v2(path.c_str(),
+                          &mDbPtr,
+                          SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+                          NULL) != SQLITE_OK) {
+        throw ConfigException("Error opening the database: " + getErrorMessage());
+    }
+
+    if (mDbPtr == NULL) {
+        throw ConfigException("Error opening the database: Unable to allocate memory.");
+    }
+}
+
+Connection::~Connection()
+{
+    if (::sqlite3_close(mDbPtr) != SQLITE_OK) {
+        throw ConfigException("Error during closing the database. Error: " + getErrorMessage());
+    }
+}
+
+void Connection::exec(const std::string& query)
+{
+    char* mess;
+    if (::sqlite3_exec(mDbPtr, query.c_str(), 0, 0, &mess) != SQLITE_OK) {
+        throw ConfigException("Error during executing statement " + std::string(mess));
+    }
+}
+
+::sqlite3* Connection::get()
+{
+    return mDbPtr;
+}
+
+std::string Connection::getErrorMessage()
+{
+    return std::string(sqlite3_errmsg(mDbPtr));
+}
+
+} // namespace sqlite3
+} // namespace config
diff --git a/src/config/sqlite3/connection.hpp b/src/config/sqlite3/connection.hpp
new file mode 100644 (file)
index 0000000..bf53afc
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief  Declaration of the class managing a sqlite3 database connection
+ */
+
+#ifndef COMMON_CONFIG_SQLITE3_CONNECTION_HPP
+#define COMMON_CONFIG_SQLITE3_CONNECTION_HPP
+
+#include <sqlite3.h>
+#include <string>
+
+namespace config {
+namespace sqlite3 {
+
+struct Connection {
+    /**
+     * @param path database file path
+     */
+    Connection(const std::string& path);
+    ~Connection();
+
+    /**
+     * @return pointer to the corresponding sqlite3 database object
+     */
+    ::sqlite3* get();
+
+    /**
+     * @return last error message in the database
+     */
+    std::string getErrorMessage();
+
+    /**
+     * Executes the query in the database.
+     *
+     * @param query query to be executed
+     */
+    void exec(const std::string& query);
+
+private:
+    ::sqlite3* mDbPtr;
+};
+
+} // namespace sqlite3
+} // namespace config
+
+#endif // COMMON_CONFIG_SQLITE3_CONNECTION_HPP
diff --git a/src/config/sqlite3/statement.cpp b/src/config/sqlite3/statement.cpp
new file mode 100644 (file)
index 0000000..287cb1c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief  Definition of the class managing a sqlite3 statement
+ */
+
+#include "config/sqlite3/statement.hpp"
+#include "config/exception.hpp"
+
+
+namespace config {
+namespace sqlite3 {
+
+Statement::Statement(sqlite3::Connection& connRef, const std::string& query)
+    : mConnRef(connRef)
+{
+    if (::sqlite3_prepare_v2(connRef.get(),
+                             query.c_str(),
+                             query.size(),
+                             &mStmtPtr,
+                             NULL)
+            != SQLITE_OK) {
+        throw ConfigException("Error during preparing statement " +
+                              mConnRef.getErrorMessage());
+    }
+
+    if (mStmtPtr == NULL) {
+        throw ConfigException("Wrong query: " + query);
+    }
+}
+
+Statement::Statement::~Statement()
+{
+    if (::sqlite3_finalize(mStmtPtr) != SQLITE_OK) {
+        throw ConfigException("Error during finalizing statement " +
+                              mConnRef.getErrorMessage());
+    }
+}
+
+sqlite3_stmt* Statement::get()
+{
+    return mStmtPtr;
+}
+
+void Statement::reset()
+{
+    if (::sqlite3_clear_bindings(mStmtPtr) != SQLITE_OK) {
+        throw ConfigException("Error unbinding statement: " +
+                              mConnRef.getErrorMessage());
+    }
+
+    if (::sqlite3_reset(mStmtPtr) != SQLITE_OK) {
+        throw ConfigException("Error reseting statement: " +
+                              mConnRef.getErrorMessage());
+    }
+}
+
+} // namespace sqlite3
+} // namespace config
diff --git a/src/config/sqlite3/statement.hpp b/src/config/sqlite3/statement.hpp
new file mode 100644 (file)
index 0000000..48a1fca
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief  Declaration of the class managing a sqlite3 statement
+ */
+
+#ifndef COMMON_CONFIG_SQLITE3_STATEMENT_HPP
+#define COMMON_CONFIG_SQLITE3_STATEMENT_HPP
+
+#include "config/sqlite3/connection.hpp"
+
+#include <sqlite3.h>
+#include <string>
+
+namespace config {
+namespace sqlite3 {
+
+struct Statement {
+
+    /**
+     * @param connRef reference to the Connection object
+     * @param query query to be executed
+     */
+    Statement(sqlite3::Connection& connRef, const std::string& query);
+    ~Statement();
+
+    /**
+     * @return pointer to the sqlite3 statement
+     */
+    sqlite3_stmt* get();
+
+    /**
+     * Clears the bindings and resets the statement.
+     * After this the statement can be executed again
+     */
+    void reset();
+
+private:
+    ::sqlite3_stmt* mStmtPtr;
+    sqlite3::Connection& mConnRef;
+};
+
+} // namespace sqlite3
+} // namespace config
+
+#endif // COMMON_CONFIG_SQLITE3_STATEMENT_HPP
+
+
index d18f860..281a5b9 100644 (file)
@@ -1,8 +1,10 @@
 # Package Information for pkg-config
 
+libdir=@LIB_INSTALL_DIR@
 includedir=@INCLUDE_INSTALL_DIR@
 
 Name: libConfig
 Description: Config library
-Version: @_VERSION_@
-Cflags: -I${includedir}/sc_tools
+Version: @_LIB_VERSION_@
+Libs: -L${libdir} -lConfig
+Cflags: -I${includedir}/sc-tools