From: Sangwan Kwon Date: Tue, 4 Feb 2020 12:23:11 +0000 (+0900) Subject: query-builder: Refactor expression interface X-Git-Tag: accepted/tizen/unified/20200810.122954~81 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e895741c8fe8a18da434ba5d33af9944f5885614;p=platform%2Fcore%2Fsecurity%2Fvist.git query-builder: Refactor expression interface Signed-off-by: Sangwan Kwon --- diff --git a/src/vist/policy/policy-storage.cpp b/src/vist/policy/policy-storage.cpp index d5cae2c..6fe7a7c 100644 --- a/src/vist/policy/policy-storage.cpp +++ b/src/vist/policy/policy-storage.cpp @@ -177,7 +177,7 @@ void PolicyStorage::disenroll(const std::string& name) this->admins.erase(name); } - std::string query = schema::AdminTable.remove().where(expr(&Admin::name) == name); + std::string query = schema::AdminTable.remove().where(Admin::Name == name); database::Statement stmt(*database, query); stmt.bind(1, name); if (!stmt.exec()) @@ -195,7 +195,7 @@ void PolicyStorage::activate(const std::string& admin, bool state) DEBUG(VIST) << "Activate admin: " << admin; /// Admin::Activated std::string query = schema::AdminTable.update(Admin::Activated) - .where(expr(&Admin::name) == admin); + .where(Admin::Name == admin); database::Statement stmt(*this->database, query); stmt.bind(1, static_cast(state)); stmt.bind(2, admin); @@ -237,8 +237,8 @@ void PolicyStorage::update(const std::string& admin, THROW(ErrCode::LogicError) << "Not exist policy: " << policy; std::string query = schema::PolicyManagedTable.update(PolicyManaged::Value) - .where(expr(&PolicyManaged::admin) == admin && - expr(&PolicyManaged::policy) == policy); + .where(PolicyManaged::Admin == admin && + PolicyManaged::Policy == policy); database::Statement stmt(*this->database, query); stmt.bind(1, value.dump()); stmt.bind(2, admin); diff --git a/src/vist/query-builder.hpp b/src/vist/query-builder.hpp index 50963d8..b957b33 100644 --- a/src/vist/query-builder.hpp +++ b/src/vist/query-builder.hpp @@ -20,7 +20,6 @@ #pragma once #include "query-builder/column.hpp" -#include "query-builder/condition.hpp" #include "query-builder/database.hpp" #include "query-builder/expression.hpp" #include "query-builder/macro.hpp" diff --git a/src/vist/query-builder/column.hpp b/src/vist/query-builder/column.hpp index 5782fa2..b37b514 100644 --- a/src/vist/query-builder/column.hpp +++ b/src/vist/query-builder/column.hpp @@ -16,6 +16,8 @@ #pragma once +#include "expression.hpp" + #include #include @@ -34,7 +36,35 @@ struct Column final { std::string name; Type type; + + template + Equal, Value> operator==(Value value) const; + template + Greater, Value> operator>(Value value) const; + template + Lesser, Value> operator<(Value value) const; }; +template +template +Equal, Value> Column::operator==(Value value) const +{ + return {*this, value}; +} + +template +template +Greater, Value> Column::operator>(Value value) const +{ + return {*this, value}; +} + +template +template +Lesser, Value> Column::operator<(Value value) const +{ + return {*this, value}; +} + } // namespace tsqb } // namespace vist diff --git a/src/vist/query-builder/condition.hpp b/src/vist/query-builder/condition.hpp deleted file mode 100644 index 54fdcce..0000000 --- a/src/vist/query-builder/condition.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2017-present 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 "type.hpp" - -namespace vist { -namespace tsqb { -namespace condition { - -struct Base {}; - -template -struct And : public Base { - L l; - R r; - - And(L l, R r) : l(l), r(r) {} - operator std::string() const - { - return "AND"; - } -}; - -template -struct Or : public Base { - L l; - R r; - - Or(L l, R r) : l(l), r(r) {} - operator std::string() const - { - return "OR"; - } -}; - -template -struct Binary : public Base { - L l; - R r; - - Binary(L l, R r) : l(l), r(r) - { - using FieldType = typename L::FieldType; - type::assert_compare(FieldType(), r); - } -}; - -template -struct Binary : public Base { - L l; - std::string r; - - Binary(L l, const char* r) : l(l), r(r) - { - using FieldType = typename L::FieldType; - type::assert_compare(FieldType(), std::string()); - } -}; - -enum class Join : int { - INNER, - CROSS, - LEFT_OUTER, - RIGHT_OUTER, - FULL_OUTER -}; - -inline std::string to_string(Join type) -{ - switch (type) { - case Join::CROSS: return "CROSS"; - case Join::LEFT_OUTER: return "LEFT OUTER"; - case Join::RIGHT_OUTER: return "RIGHT OUTER"; - case Join::FULL_OUTER: return "FULL OUTER"; - case Join::INNER: - default: - return "INNER"; - } -} - -} // namespace condition -} // namespace tsqb -} // namespace vist diff --git a/src/vist/query-builder/crud.hpp b/src/vist/query-builder/crud.hpp index 72805cf..80c1b81 100644 --- a/src/vist/query-builder/crud.hpp +++ b/src/vist/query-builder/crud.hpp @@ -50,10 +50,10 @@ public: private: template - std::string processWhere(condition::And& expr); + std::string processWhere(And& expr); template - std::string processWhere(condition::Or& expr); + std::string processWhere(Or& expr); template std::string processWhere(Expr expr); @@ -210,7 +210,7 @@ T& Crud::where(Expr expr) template template -std::string Crud::processWhere(condition::And& expr) +std::string Crud::processWhere(And& expr) { std::stringstream ss; ss << this->processWhere(expr.l) << " "; @@ -222,7 +222,7 @@ std::string Crud::processWhere(condition::And& expr) template template -std::string Crud::processWhere(condition::Or& expr) +std::string Crud::processWhere(Or& expr) { std::stringstream ss; ss << this->processWhere(expr.l) << " "; diff --git a/src/vist/query-builder/database.hpp b/src/vist/query-builder/database.hpp index 6de1be0..f9e5466 100644 --- a/src/vist/query-builder/database.hpp +++ b/src/vist/query-builder/database.hpp @@ -17,7 +17,6 @@ #pragma once #include "column.hpp" -#include "condition.hpp" #include "crud.hpp" #include "expression.hpp" #include "util.hpp" @@ -40,12 +39,6 @@ public: explicit Database(const std::string& name, Tables ...tables) : name(name), tables(tables...) {} - template - Self& join(condition::Join type = condition::Join::INNER); - - template - Self& on(Expr expr); - std::size_t size() const noexcept; operator std::string(); @@ -69,38 +62,6 @@ private: }; template -template -Database& Database::join(condition::Join type) -{ - std::stringstream ss; - ss << condition::to_string(type) << " "; - ss << "JOIN "; - ss << this->getTableName(Table()); - - this->cache.emplace_back(ss.str()); - return *this; -} - -template -template -Database& Database::on(Expr expr) -{ - std::stringstream ss; - ss << "ON "; - - auto lname = this->getColumnName(std::move(expr.l.type)); - ss << lname << " "; - - ss << std::string(expr) << " "; - - auto rname = this->getColumnName(std::move(expr.r.type)); - ss << rname; - - this->cache.emplace_back(ss.str()); - return *this; -} - -template Database::operator std::string() { std::stringstream ss; diff --git a/src/vist/query-builder/expression.hpp b/src/vist/query-builder/expression.hpp index a1525f5..583b41e 100644 --- a/src/vist/query-builder/expression.hpp +++ b/src/vist/query-builder/expression.hpp @@ -18,65 +18,69 @@ #include "column.hpp" #include "type.hpp" -#include "condition.hpp" +#include #include namespace vist { namespace tsqb { -template -struct Expression { - Type value; -}; +struct Expression {}; -template -Expression> expr(F O::*field) -{ - Column anonymous = {"anonymous", field}; - return {anonymous}; -} +template +using is_expression = typename std::is_base_of; template -struct Lesser : public condition::Binary { - using condition::Binary::Binary; +struct Binary : public Expression { + L l; + R r; - operator std::string() const + /// L is Column and R is Value + Binary(L l, R r) : l(l), r(r) { - return "<"; + /// preventing logical expressions like &&, || and == + if constexpr(!is_expression::value) { + using FieldType = typename L::FieldType; + type::assert_compare(FieldType(), r); + } } }; -template -Lesser operator<(Expression expr, R r) -{ - return {expr.value, r}; -} +template +struct Binary : public Expression { + L l; + std::string r; + + Binary(L l, const char* r) : l(l), r(r) + { + using FieldType = typename L::FieldType; + type::assert_compare(FieldType(), std::string()); + } +}; template -struct Equal : public condition::Binary -{ - using condition::Binary::Binary; +struct Greater : public Binary { + using Binary::Binary; operator std::string() const { - return "="; + return ">"; } }; template -Equal operator==(Expression expr, R r) -{ - return {expr.value, r}; -} +struct Lesser : public Binary { + using Binary::Binary; -namespace join { + operator std::string() const + { + return "<"; + } +}; template -struct Equal -{ - L l; - R r; +struct Equal : public Binary { + using Binary::Binary; operator std::string() const { @@ -84,51 +88,40 @@ struct Equal } }; -} // namespace join - -template -join::Equal operator==(Expression l, Expression r) -{ - return {l.value, r.value}; -} - template -struct Greater : public condition::Binary -{ - using condition::Binary::Binary; +struct And : public Binary { + using Binary::Binary; operator std::string() const { - return ">"; + return "AND"; } }; template -Greater operator>(Expression expr, R r) -{ - return {expr.value, r}; -} - -template -using enable_if_t = typename std::enable_if::type; +struct Or : public Binary { + using Binary::Binary; -template -using is_condition = typename std::is_base_of; + operator std::string() const + { + return "OR"; + } +}; template::value - && tsqb::is_condition::value>> -condition::And operator&&(const L& l, const R& r) + typename = typename std::enable_if_t::value && + is_expression::value>> +And operator&&(const L& l, const R& r) { return {l, r}; } template::value - && tsqb::is_condition::value>> -condition::Or operator||(const L& l, const R& r) + typename = typename std::enable_if_t::value && + is_expression::value>> +Or operator||(const L& l, const R& r) { return {l, r}; } diff --git a/src/vist/query-builder/tests/expression.cpp b/src/vist/query-builder/tests/expression.cpp new file mode 100644 index 0000000..558c657 --- /dev/null +++ b/src/vist/query-builder/tests/expression.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-present 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 + +#include "schema.hpp" + +using namespace vist::tsqb; +using namespace vist::test; + +TEST(QueryBuilderExpressionTests, equal) +{ + std::string dump = (Table1::Column1 == 3); + EXPECT_EQ(dump, "="); +} + +TEST(QueryBuilderExpressionTests, greater) +{ + std::string dump = (Table1::Column1 > 3); + EXPECT_EQ(dump, ">"); +} + +TEST(QueryBuilderExpressionTests, lesser) +{ + std::string dump = (Table1::Column1 < 3); + EXPECT_EQ(dump, "<"); +} diff --git a/src/vist/query-builder/tests/query-builder.cpp b/src/vist/query-builder/tests/query-builder.cpp index 9fccaae..7f4da4b 100644 --- a/src/vist/query-builder/tests/query-builder.cpp +++ b/src/vist/query-builder/tests/query-builder.cpp @@ -108,12 +108,12 @@ TEST(QueryBuilderTsqbTests, SELECT_ALL) TEST(QueryBuilderTsqbTests, SELECT_WHERE) { std::string select1 = AdminTable.select(Admin::Uid, Admin::Key) - .where(expr(&Admin::id) > 3); - std::string select2 = admin.selectAll().where(expr(&Admin::uid) > 3); - std::string select3 = admin.selectAll().where(expr(&Admin::uid) > 3 && - expr(&Admin::pkg) == "dpm"); - std::string select4 = admin.selectAll().where(expr(&Admin::uid) > 3 || - expr(&Admin::pkg) == "dpm"); + .where(Admin::Id > 3); + std::string select2 = admin.selectAll().where(Admin::Uid > 3); + std::string select3 = admin.selectAll().where(Admin::Uid > 3 && + Admin::Pkg == "dpm"); + std::string select4 = admin.selectAll().where(Admin::Uid > 3 || + Admin::Pkg == "dpm"); EXPECT_EQ(select1, "SELECT uid, key FROM admin WHERE id > ?"); EXPECT_EQ(select2, "SELECT * FROM admin WHERE uid > ?"); @@ -125,10 +125,10 @@ TEST(QueryBuilderTsqbTests, UPDATE) { int uid = 0, id = 1; std::string update1 = admin.update(Admin::Id, Admin::Pkg, Admin::Uid, Admin::Key); - std::string update2 = admin.update(Admin::Key).where(expr(&Admin::uid) == uid && - expr(&Admin::id) == id); + std::string update2 = admin.update(Admin::Key).where((Admin::Uid == uid) && + (Admin::Id == id)); std::string update3 = admin.update(Admin::Key, Admin::Pkg) - .where(expr(&Admin::uid) == 0 && expr(&Admin::id) == 1); + .where((Admin::Uid == 0) && (Admin::Id == 1)); EXPECT_EQ(update1, "UPDATE admin SET id = ?, pkg = ?, uid = ?, key = ?"); EXPECT_EQ(update2, "UPDATE admin SET key = ? WHERE uid = ? AND id = ?"); @@ -138,8 +138,8 @@ TEST(QueryBuilderTsqbTests, UPDATE) TEST(QueryBuilderTsqbTests, DELETE) { std::string delete1 = admin.remove(); - std::string delete2 = admin.remove().where(expr(&Admin::pkg) == "dpm" && - expr(&Admin::uid) == 3); + std::string delete2 = admin.remove().where((Admin::Pkg == "dpm") && + (Admin::Uid == 3)); EXPECT_EQ(delete1, "DELETE FROM admin"); EXPECT_EQ(delete2, "DELETE FROM admin WHERE pkg = ? AND uid = ?"); @@ -159,13 +159,13 @@ TEST(QueryBuilderTsqbTests, TYPE_SAFE) /* * Below cause complie error since expression types are dismatch. - std::string type_unsafe1 = admin.selectAll().where(expr(&Admin::uid) > "dpm"); - std::string type_unsafe2 = admin.selectAll().where(expr(&Admin::uid) == "dpm"); - std::string type_unsafe3 = admin.selectAll().where(expr(&Admin::pkg) == 3); + std::string type_unsafe1 = admin.selectAll().where(Admin::Uid > "dpm"); + std::string type_unsafe2 = admin.selectAll().where(Admin::Uid == "dpm"); + std::string type_unsafe3 = admin.selectAll().where(Admin::Pkg == 3); int pkg = 3; - std::string type_unsafe4 = admin.selectAll().where(expr(&Admin::pkg) < pkg); - std::string type_unsafe5 = admin.remove().where(expr(&Admin::pkg) == "dpm" && - expr(&Admin::uid) == "dpm"); + std::string type_unsafe4 = admin.selectAll().where(Admin::Pkg) < pkg); + std::string type_unsafe5 = admin.remove().where(Admin::Pkg) == "dpm" && + Admin::Uid) == "dpm"); */ } @@ -175,7 +175,7 @@ TEST(QueryBuilderTsqbTests, MULTI_SELECT) ManagedPolicy::Id, ManagedPolicy::Value); std::string multiSelect2 = db.select(Admin::Uid, Admin::Key, ManagedPolicy::Id, ManagedPolicy::Value) - .where(expr(&Admin::uid) > 0 && expr(&ManagedPolicy::id) == 3); + .where((Admin::Uid > 0) && (ManagedPolicy::Id == 3)); EXPECT_EQ(multiSelect1, "SELECT admin.uid, admin.key, managed_policy.id, " "managed_policy.value FROM admin, managed_policy"); @@ -193,10 +193,10 @@ TEST(QueryBuilderTsqbTests, JOIN) .join(condition::Join::CROSS); std::string join3 = db.select(ManagedPolicy::Value) .join() - .on(expr(&ManagedPolicy::pid) == expr(&PolicyDefinition::id)) + .on(ManagedPolicy::Pid) == PolicyDefinition::Id)) .join() - .on(expr(&ManagedPolicy::aid) == expr(&Admin::id)) - .where(expr(&ManagedPolicy::pid) == 99); + .on(ManagedPolicy::Aid) == Admin::Id)) + .where(ManagedPolicy::Pid) == 99); EXPECT_EQ(join1, "SELECT admin.uid, admin.key FROM admin " "LEFT OUTER JOIN policy_definition");