Apply type-safe query builder
authorsangwan.kwon <sangwan.kwon@samsung.com>
Tue, 30 Jan 2018 10:44:55 +0000 (19:44 +0900)
committerJaemin Ryu <jm77.ryu@samsung.com>
Mon, 14 Jan 2019 06:08:46 +0000 (15:08 +0900)
Change-Id: I87feb3a4a4cabd0d952445ed4b9347922cd4116c
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
server/db-schema.h [new file with mode: 0644]
server/sql-backend.cpp
server/sql-backend.h
tests/CMakeLists.txt
tests/test-query.cpp [new file with mode: 0644]

diff --git a/server/db-schema.h b/server/db-schema.h
new file mode 100644 (file)
index 0000000..5287418
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2018 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.
+ *  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
+ */
+#pragma once
+
+#include <string>
+
+namespace schema {
+
+struct Admin {
+       int id;
+       std::string pkg;
+       int uid;
+       std::string key;
+       int removable;
+};
+
+struct ManagedPolicy {
+       int id;
+       int aid;
+       int pid;
+       int value;
+};
+
+struct PolicyDefinition {
+       int id;
+       int scope;
+       std::string name;
+       int ivalue;
+};
+
+} // namespace schema
index 9445991..57006e2 100644 (file)
  */
 
 #include <klay/exception.h>
+#include <klay/db/query-builder.h>
 
 #include "pil/logger.h"
 
 #include "sql-backend.h"
+#include "db-schema.h"
+
+using namespace query_builder;
+using namespace schema;
+
+namespace {
+
+auto admin = make_table("admin",
+                                               make_column("id", &Admin::id),
+                                               make_column("pkg", &Admin::pkg),
+                                               make_column("uid", &Admin::uid),
+                                               make_column("key", &Admin::key),
+                                               make_column("removable", &Admin::removable));
+
+auto managedPolicy = make_table("managed_policy",
+                                                                make_column("id", &ManagedPolicy::id),
+                                                                make_column("aid", &ManagedPolicy::aid),
+                                                                make_column("pid", &ManagedPolicy::pid),
+                                                                make_column("value", &ManagedPolicy::value));
+
+auto policyDefinition = make_table("policy_definition",
+                                                                  make_column("id", &PolicyDefinition::id),
+                                                                  make_column("scope", &PolicyDefinition::scope),
+                                                                  make_column("name", &PolicyDefinition::name),
+                                                                  make_column("ivalue", &PolicyDefinition::ivalue));
+
+auto dpm = make_database("dpm", admin, managedPolicy, policyDefinition);
+
+} // anonymous namespace
 
 int SQLBackend::open(const std::string& path)
 {
@@ -41,7 +71,9 @@ void SQLBackend::close()
 int SQLBackend::define(const std::string& name, DataSetInt& value)
 {
        int id = -1;
-       std::string query = "SELECT id, ivalue FROM policy_definition WHERE name = ?";
+       std::string query = policyDefinition.select(&PolicyDefinition::id,
+                                                                                               &PolicyDefinition::ivalue)
+                                                                               .where(expr(&PolicyDefinition::name) == name);
        database::Statement stmt(*database, query);
 
        stmt.bind(1, name);
@@ -56,10 +88,12 @@ int SQLBackend::define(const std::string& name, DataSetInt& value)
 bool SQLBackend::strictize(int id, DataSetInt& value, uid_t domain)
 {
        bool updated = false;
-       std::string query = "SELECT managed_policy.value FROM managed_policy " \
-                                               "INNER JOIN policy_definition ON managed_policy.pid = policy_definition.id " \
-                                               "INNER JOIN admin ON managed_policy.aid = admin.id " \
-                                               "WHERE managed_policy.pid = ? ";
+       std::string query = dpm.select(&ManagedPolicy::value)
+                                                  .join<PolicyDefinition>()
+                                                  .on(expr(&ManagedPolicy::pid) == expr(&PolicyDefinition::id))
+                                                  .join<Admin>()
+                                                  .on(expr(&ManagedPolicy::aid) == expr(&Admin::id))
+                                                  .where(expr(&ManagedPolicy::pid) == id);
 
        if (domain) {
                query += "AND admin.uid = ? ";
@@ -78,19 +112,23 @@ bool SQLBackend::strictize(int id, DataSetInt& value, uid_t domain)
        return updated;
 }
 
-void SQLBackend::update(int id, const std::string& admin, uid_t domain, const DataSetInt& value)
+void SQLBackend::update(int id, const std::string& name, uid_t domain, const DataSetInt& value)
 {
-       std::string selectQuery = "SELECT id FROM admin WHERE pkg = ? AND uid = ?";
+       int uid = static_cast<int>(domain);
+       std::string selectQuery = admin.select(&Admin::id).where(expr(&Admin::pkg) == name &&
+                                                                                                                        expr(&Admin::uid) == uid);
        database::Statement stmt0(*database, selectQuery);
-       stmt0.bind(1, admin);
-       stmt0.bind(2, static_cast<int>(domain));
+       stmt0.bind(1, name);
+       stmt0.bind(2, uid);
        if (!stmt0.step()) {
-               throw runtime::Exception("Unknown device admin client: " + admin);
+               throw runtime::Exception("Unknown device admin client: " + name);
        }
 
        int aid = stmt0.getColumn(0);
 
-       std::string updateQuery = "UPDATE managed_policy SET value = ? WHERE pid = ? AND aid = ?";
+       std::string updateQuery = managedPolicy.update(&ManagedPolicy::value)
+                                                                                  .where(expr(&ManagedPolicy::pid) == id &&
+                                                                                                 expr(&ManagedPolicy::aid) == aid);
        database::Statement stmt(*database, updateQuery);
        stmt.bind(1, value);
        stmt.bind(2, id);
@@ -102,22 +140,25 @@ void SQLBackend::update(int id, const std::string& admin, uid_t domain, const Da
 
 int SQLBackend::enroll(const std::string& name, uid_t domain)
 {
-    std::string selectQuery = "SELECT * FROM admin WHERE pkg = ? AND uid = ?";
-    database::Statement stmt0(*database, selectQuery);
-    stmt0.bind(1, name);
-    stmt0.bind(2, static_cast<int>(domain));
-    if (stmt0.step())
+       int uid = static_cast<int>(domain);
+       std::string selectQuery = admin.selectAll().where(expr(&Admin::pkg) == name &&
+                                                                                                         expr(&Admin::uid) == uid);
+       database::Statement stmt0(*database, selectQuery);
+       stmt0.bind(1, name);
+       stmt0.bind(2, uid);
+       if (stmt0.step())
                return -1;
 
-    std::string key = "Not supported";
+       std::string key = "Not supported";
 
-    std::string insertQuery = "INSERT INTO admin (pkg, uid, key, removable) VALUES (?, ?, ?, ?)";
-    database::Statement stmt(*database, insertQuery);
-    stmt.bind(1, name);
-    stmt.bind(2, static_cast<int>(domain));
-    stmt.bind(3, key);
-    stmt.bind(4, true);
-    if (!stmt.exec())
+       std::string insertQuery = admin.insert(&Admin::pkg, &Admin::uid,
+                                                                                  &Admin::key, &Admin::removable);
+       database::Statement stmt(*database, insertQuery);
+       stmt.bind(1, name);
+       stmt.bind(2, uid);
+       stmt.bind(3, key);
+       stmt.bind(4, true);
+       if (!stmt.exec())
                return -1;
 
        return 0;
@@ -125,10 +166,12 @@ int SQLBackend::enroll(const std::string& name, uid_t domain)
 
 int SQLBackend::unenroll(const std::string& name, uid_t domain)
 {
-       std::string query = "DELETE FROM admin WHERE pkg = ? AND uid = ?";
+       int uid = static_cast<int>(domain);
+       std::string query = admin.remove().where(expr(&Admin::pkg) == name &&
+                                                                                        expr(&Admin::uid) == uid);
        database::Statement stmt(*database, query);
        stmt.bind(1, name);
-       stmt.bind(2, static_cast<int>(domain));
+       stmt.bind(2, uid);
        if (!stmt.exec())
                return -1;
 
@@ -138,7 +181,7 @@ int SQLBackend::unenroll(const std::string& name, uid_t domain)
 std::vector<uid_t> SQLBackend::fetchDomains()
 {
        std::vector<uid_t> managedDomains;
-       std::string query = "SELECT DISTINCT uid FROM admin;";
+       std::string query = admin.select(distinct(&Admin::uid));
        database::Statement stmt(*database, query);
        while (stmt.step()) {
                managedDomains.push_back(stmt.getColumn(0).getInt());
index 6527d72..9b322c2 100644 (file)
@@ -35,7 +35,7 @@ public:
 
        bool strictize(int id, DataSetInt& value, uid_t domain);
 
-       void update(int id, const std::string& admin, uid_t domain, const DataSetInt& value);
+       void update(int id, const std::string& name, uid_t domain, const DataSetInt& value);
 
        int enroll(const std::string& name, uid_t domain);
        int unenroll(const std::string& name, uid_t domain);
index 193f299..87b398b 100644 (file)
 
 SET(DPM_TEST_TARGET "dpm-test")
 SET(DPM_TEST_SRCS main.cpp
-                                 test-pil.cpp)
+                                 test-pil.cpp
+                                 test-query.cpp)
 
 PKG_CHECK_MODULES(${DPM_TEST_TARGET}_DEP REQUIRED klay glib-2.0 gio-2.0 vconf)
 
-INCLUDE_DIRECTORIES(SYSTEM ${${DPM_TEST_TARGET}_DEP_INCLUDE_DIRS} ${DPM_LIBS})
+INCLUDE_DIRECTORIES(SYSTEM ${${DPM_TEST_TARGET}_DEP_INCLUDE_DIRS}
+                                                  ${DPM_LIBS}
+                                                  ${DPM_SERVER})
 
 ADD_EXECUTABLE(${DPM_TEST_TARGET} ${DPM_TEST_SRCS})
 
diff --git a/tests/test-query.cpp b/tests/test-query.cpp
new file mode 100644 (file)
index 0000000..b6ee457
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  Copyright (c) 2018 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.
+ *  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
+ */
+
+#include "db-schema.h"
+
+#include <klay/testbench.h>
+
+#include <klay/db/query-builder.h>
+
+using namespace query_builder;
+using namespace schema;
+
+namespace {
+
+auto admin = make_table("admin",
+                                               make_column("id", &Admin::id),
+                                               make_column("pkg", &Admin::pkg),
+                                               make_column("uid", &Admin::uid),
+                                               make_column("key", &Admin::key),
+                                               make_column("removable", &Admin::removable));
+
+auto managedPolicy = make_table("managed_policy",
+                                                                make_column("id", &ManagedPolicy::id),
+                                                                make_column("aid", &ManagedPolicy::aid),
+                                                                make_column("pid", &ManagedPolicy::pid),
+                                                                make_column("value", &ManagedPolicy::value));
+
+auto policyDefinition = make_table("policy_definition",
+                                                                  make_column("id", &PolicyDefinition::id),
+                                                                  make_column("scope", &PolicyDefinition::scope),
+                                                                  make_column("name", &PolicyDefinition::name),
+                                                                  make_column("ivalue", &PolicyDefinition::ivalue));
+
+auto dpm = make_database("dpm", admin, managedPolicy, policyDefinition);
+
+} // anonymous namespace
+
+TESTCASE(DEFINE)
+{
+       std::string name;
+       std::string query = policyDefinition.select(&PolicyDefinition::id,
+                                                                                               &PolicyDefinition::ivalue)
+                                                                               .where(expr(&PolicyDefinition::name) == name);
+
+       std::string expect = "SELECT id, ivalue FROM policy_definition WHERE name = ?";
+
+       TEST_EXPECT(expect, query);
+}
+
+TESTCASE(STRICTIZE)
+{
+       int id = 0;
+       std::string query = dpm.select(&ManagedPolicy::value)
+                                                  .join<PolicyDefinition>()
+                                                  .on(expr(&ManagedPolicy::pid) == expr(&PolicyDefinition::id))
+                                                  .join<Admin>()
+                                                  .on(expr(&ManagedPolicy::aid) == expr(&Admin::id))
+                                                  .where(expr(&ManagedPolicy::pid) == id);
+
+       std::string expect = "SELECT managed_policy.value FROM managed_policy " \
+                                                "INNER JOIN policy_definition ON managed_policy.pid = policy_definition.id " \
+                                                "INNER JOIN admin ON managed_policy.aid = admin.id " \
+                                                "WHERE managed_policy.pid = ?";
+
+       TEST_EXPECT(expect, query);
+}
+
+TESTCASE(UPDATE)
+{
+       std::string name;
+       int uid = 0;
+       std::string selectQuery = admin.select(&Admin::id).where(expr(&Admin::pkg) == name &&
+                                                                                                                        expr(&Admin::uid) == uid);
+
+       std::string selectExpect = "SELECT id FROM admin WHERE pkg = ? AND uid = ?";
+
+       TEST_EXPECT(selectExpect, selectQuery);
+
+       int id = 0, aid = 0;
+       std::string updateQuery = managedPolicy.update(&ManagedPolicy::value)
+                                                                                  .where(expr(&ManagedPolicy::pid) == id &&
+                                                                                                 expr(&ManagedPolicy::aid) == aid);
+
+       std::string updateExpect = "UPDATE managed_policy SET value = ? WHERE pid = ? AND aid = ?";
+
+       TEST_EXPECT(updateExpect, updateQuery);
+}
+
+TESTCASE(ENROLL)
+{
+       std::string name;
+       int uid = 0;
+       std::string selectQuery = admin.selectAll().where(expr(&Admin::pkg) == name &&
+                                                                                                         expr(&Admin::uid) == uid);
+
+       std::string selectExpect = "SELECT * FROM admin WHERE pkg = ? AND uid = ?";
+
+       TEST_EXPECT(selectExpect, selectQuery);
+
+       std::string insertQuery = admin.insert(&Admin::pkg, &Admin::uid,
+                                                                                  &Admin::key, &Admin::removable);
+
+       std::string insertExpect = "INSERT INTO admin (pkg, uid, key, removable) VALUES (?, ?, ?, ?)";
+
+       TEST_EXPECT(insertExpect, insertQuery);
+}
+
+TESTCASE(UNENROLL)
+{
+       std::string name;
+       int uid = 0;
+       std::string query = admin.remove().where(expr(&Admin::pkg) == name &&
+                                                                                        expr(&Admin::uid) == uid);
+
+       std::string expect = "DELETE FROM admin WHERE pkg = ? AND uid = ?";
+
+       TEST_EXPECT(expect, query);
+}
+
+TESTCASE(FETCH_DOMAIN)
+{
+       std::string query = admin.select(distinct(&Admin::uid));
+
+       std::string expect = "SELECT DISTINCT uid FROM admin";
+
+       TEST_EXPECT(expect, query);
+}