From 9394ed9af8b4cc0a05c15bb24267d34ee2f3468d Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Mon, 22 Jan 2018 17:04:40 +0900 Subject: [PATCH] Add type-check-logic on query expression Change-Id: I5b51c4e69f1b28a8940d59d187ffdc19f7403376 Signed-off-by: sangwan.kwon --- include/klay/db/query-builder/column.hxx | 1 + include/klay/db/query-builder/expression.hxx | 28 ++++++++++++--- include/klay/db/query-builder/table-impl.hxx | 8 ++--- include/klay/db/query-builder/table.hxx | 2 +- include/klay/db/query-builder/type.hxx | 37 ++++++++++++++++++++ test/query-builder.cpp | 15 ++++++++ 6 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 include/klay/db/query-builder/type.hxx diff --git a/include/klay/db/query-builder/column.hxx b/include/klay/db/query-builder/column.hxx index 4c43eeb..6fb99a9 100644 --- a/include/klay/db/query-builder/column.hxx +++ b/include/klay/db/query-builder/column.hxx @@ -24,6 +24,7 @@ namespace qxx { template struct Column { typedef Field Object::*Type; + using FieldType = Field; std::string name; Type type; diff --git a/include/klay/db/query-builder/expression.hxx b/include/klay/db/query-builder/expression.hxx index a7e7db8..37e76bc 100644 --- a/include/klay/db/query-builder/expression.hxx +++ b/include/klay/db/query-builder/expression.hxx @@ -16,6 +16,9 @@ #pragma once +#include "column.hxx" +#include "type.hxx" + #include namespace qxx { @@ -52,7 +55,23 @@ struct Binary : public Base { L l; R r; - Binary(L l, R r) : 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()); + } }; } // namespace condition @@ -62,10 +81,11 @@ struct Expression { Type value; }; -template -Expression expr(Type value) +template +Expression> expr(F O::*field) { - return {value}; + Column anonymous = {"anonymous", field}; + return {anonymous}; } template diff --git a/include/klay/db/query-builder/table-impl.hxx b/include/klay/db/query-builder/table-impl.hxx index 9a29774..2fa813a 100644 --- a/include/klay/db/query-builder/table-impl.hxx +++ b/include/klay/db/query-builder/table-impl.hxx @@ -16,6 +16,8 @@ #pragma once +#include "type.hxx" + #include #include @@ -50,11 +52,7 @@ public: template std::string getColumnName(ColumnType type) const noexcept { - // [TO-DO] Do Not Cast. - // [ALTER] std::is_same{} - // [PROBLEM] Cannot multi-table select.. - // [CRITICAL] (&Data::int == &Data2::int) is same - if (reinterpret_cast(column.type) == type) + if (type::compare(column.type, type)) return column.name; return Base::template getColumnName(type); diff --git a/include/klay/db/query-builder/table.hxx b/include/klay/db/query-builder/table.hxx index fc26e34..d6a33fe 100644 --- a/include/klay/db/query-builder/table.hxx +++ b/include/klay/db/query-builder/table.hxx @@ -332,7 +332,7 @@ template template std::string Table::processWhere(Expr expr) { std::stringstream ss; - ss << this->impl.getColumnName(expr.l); + ss << this->impl.getColumnName(expr.l.type); ss << " " << std::string(expr) << " ?"; return ss.str(); diff --git a/include/klay/db/query-builder/type.hxx b/include/klay/db/query-builder/type.hxx new file mode 100644 index 0000000..d1a3e3f --- /dev/null +++ b/include/klay/db/query-builder/type.hxx @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 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 + +namespace qxx { +namespace type { + +template +inline bool compare(L l, R r) +{ + return (l == reinterpret_cast(r)); +} + +template +inline void assert_compare(L l, R r) +{ + static_assert(std::is_same::value, "Type is unsafe."); +} + +} // namespace type +} // namespace qxx diff --git a/test/query-builder.cpp b/test/query-builder.cpp index 75639be..faa13d4 100644 --- a/test/query-builder.cpp +++ b/test/query-builder.cpp @@ -109,3 +109,18 @@ TESTCASE(INSERT) TEST_EXPECT(true, insert1 == "INSERT INTO admin (id, pkg, uid, key) VALUES (?, ?, ?, ?)"); TEST_EXPECT(true, insert2 == "INSERT INTO admin (id, pkg, key) VALUES (?, ?, ?)"); } + +TESTCASE(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); + 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"); +*/ +} -- 2.34.1