Add type-check-logic on query expression
authorsangwan.kwon <sangwan.kwon@samsung.com>
Mon, 22 Jan 2018 08:04:40 +0000 (17:04 +0900)
committerJaemin Ryu <jm77.ryu@samsung.com>
Mon, 11 Feb 2019 04:22:16 +0000 (13:22 +0900)
Change-Id: I5b51c4e69f1b28a8940d59d187ffdc19f7403376
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
include/klay/db/query-builder/column.hxx
include/klay/db/query-builder/expression.hxx
include/klay/db/query-builder/table-impl.hxx
include/klay/db/query-builder/table.hxx
include/klay/db/query-builder/type.hxx [new file with mode: 0644]
test/query-builder.cpp

index 4c43eeb39c439e1dd7dada67e15994bd644c23f3..6fb99a901865ef9e35c921666e46ac0bb83f59ad 100644 (file)
@@ -24,6 +24,7 @@ namespace qxx {
 template<typename Object, typename Field>
 struct Column {
        typedef Field Object::*Type;
+       using FieldType = Field;
 
        std::string name;
        Type type;
index a7e7db8ba2737b63c1d22ed6d8426fe27dfb874e..37e76bc6ee2146b602fbcfa8de293286854ffab1 100644 (file)
@@ -16,6 +16,9 @@
 
 #pragma once
 
+#include "column.hxx"
+#include "type.hxx"
+
 #include <type_traits>
 
 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<typename L>
+struct Binary<L, const char*> : 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<typename Type>
-Expression<Type> expr(Type value)
+template<typename O, typename F>
+Expression<Column<O, F>> expr(F O::*field)
 {
-       return {value};
+       Column<O, F> anonymous = {"anonymous", field};
+       return {anonymous};
 }
 
 template<typename L, typename R>
index 9a29774d83ecf76cf4f23f338b01335811adf43f..2fa813afd0b07b41e67bf13791824810b368035d 100644 (file)
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include "type.hxx"
+
 #include <string>
 #include <vector>
 
@@ -50,11 +52,7 @@ public:
 
        template<typename ColumnType>
        std::string getColumnName(ColumnType type) const noexcept {
-               // [TO-DO] Do Not Cast.
-               // [ALTER] std::is_same<F, typename T::field_type>{}
-               // [PROBLEM] Cannot multi-table select..
-               // [CRITICAL] (&Data::int == &Data2::int) is same
-               if (reinterpret_cast<ColumnType>(column.type) == type)
+               if (type::compare(column.type, type))
                        return column.name;
 
                return Base::template getColumnName<ColumnType>(type);
index fc26e3463a871bb8442a265e531b13dc60cbcae2..d6a33fef26ce223b04f93894c8d55b0e623d83e0 100644 (file)
@@ -332,7 +332,7 @@ template<typename... Columns>
 template<typename Expr>
 std::string Table<Columns...>::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 (file)
index 0000000..d1a3e3f
--- /dev/null
@@ -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 <type_traits>
+
+namespace qxx {
+namespace type {
+
+template<typename L, typename R>
+inline bool compare(L l, R r)
+{
+       return (l == reinterpret_cast<L>(r));
+}
+
+template<typename L, typename R>
+inline void assert_compare(L l, R r)
+{
+       static_assert(std::is_same<L, R>::value, "Type is unsafe.");
+}
+
+} // namespace type
+} // namespace qxx
index 75639bef1395d4c530ff02c5e5266615a7bd93b4..faa13d41131295490fbe9adbd3fafcb1c44936ee 100644 (file)
@@ -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");
+*/
+}