template<typename Object, typename Field>
struct Column {
typedef Field Object::*Type;
+ using FieldType = Field;
std::string name;
Type type;
#pragma once
+#include "column.hxx"
+#include "type.hxx"
+
#include <type_traits>
namespace qxx {
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
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>
#pragma once
+#include "type.hxx"
+
#include <string>
#include <vector>
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);
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();
--- /dev/null
+/*
+ * 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
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");
+*/
+}