Support AND, OR conditions on where clause 53/167053/4
authorsangwan.kwon <sangwan.kwon@samsung.com>
Mon, 15 Jan 2018 06:51:42 +0000 (15:51 +0900)
committersangwan.kwon <sangwan.kwon@samsung.com>
Thu, 18 Jan 2018 07:37:00 +0000 (16:37 +0900)
Change-Id: I0adc9d253389e64a4cc8679684793df444746343
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
include/klay/db/query-builder/expression.hxx
include/klay/db/query-builder/table.hxx
include/klay/db/query-builder/test-main.cpp

index adc6c2770bf7ef30361850c609497b546bf83dad..ea3ba251638176214fa121ac011a48707ee4ab34 100644 (file)
@@ -1,10 +1,38 @@
 #pragma once
 
+#include <type_traits>
+
 namespace qxx {
 namespace condition {
 
-template<class L, class R>
-struct Binary {
+struct Base {};
+
+template<typename L, typename R>
+struct And : public Base {
+       L l;
+       R r;
+
+       And(L l, R r) : l(l), r(r) {}
+       operator std::string() const
+       {
+               return "AND";
+       }
+};
+
+template<typename L, typename R>
+struct Or : public Base {
+       L l;
+       R r;
+
+       Or(L l, R r) : l(l), r(r) {}
+       operator std::string() const
+       {
+               return "OR";
+       }
+};
+
+template<typename L, typename R>
+struct Binary : public Base {
        L l;
        R r;
 
@@ -13,32 +41,36 @@ struct Binary {
 
 } // namespace condition
 
-template<class Type>
+template<typename Type>
 struct Expression {
        Type value;
 };
 
-template<class Type>
-Expression<Type> expr(Type value) {
+template<typename Type>
+Expression<Type> expr(Type value)
+{
        return {value};
 }
 
-template<class L, class R>
+template<typename L, typename R>
 struct Lesser : public condition::Binary<L, R> {
        using condition::Binary<L, R>::Binary;
 
-       operator std::string() const {
+       operator std::string() const
+       {
                return "<";
        }
 };
 
-template<class L, class R>
-Lesser<L, R> operator<(Expression<L> expr, R r) {
+template<typename L, typename R>
+Lesser<L, R> operator<(Expression<L> expr, R r)
+{
        return {expr.value, r};
 }
 
-template<class L, class R>
-struct Equal : public condition::Binary<L, R> {
+template<typename L, typename R>
+struct Equal : public condition::Binary<L, R>
+{
        using condition::Binary<L, R>::Binary;
 
        operator std::string() const {
@@ -46,13 +78,15 @@ struct Equal : public condition::Binary<L, R> {
        }
 };
 
-template<class L, class R>
-Equal<L, R> operator==(Expression<L> expr, R r) {
+template<typename L, typename R>
+Equal<L, R> operator==(Expression<L> expr, R r)
+{
        return {expr.value, r};
 }
 
-template<class L, class R>
-struct Greater : public condition::Binary<L, R> {
+template<typename L, typename R>
+struct Greater : public condition::Binary<L, R>
+{
        using condition::Binary<L, R>::Binary;
 
        operator std::string() const {
@@ -60,9 +94,34 @@ struct Greater : public condition::Binary<L, R> {
        }
 };
 
-template<class L, class R>
-Equal<L, R> operator>(Expression<L> expr, R r) {
+template<typename L, typename R>
+Greater<L, R> operator>(Expression<L> expr, R r)
+{
        return {expr.value, r};
 }
 
+template<bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+template<typename T>
+using is_condition = typename std::is_base_of<condition::Base, T>;
+
+template<typename L,
+                typename R,
+                typename = typename qxx::enable_if_t<is_condition<L>::value
+                                                        && qxx::is_condition<R>::value>>
+condition::And<L, R> operator&&(const L& l, const R& r)
+{
+       return {l, r};
+}
+
+template<typename L,
+                typename R,
+                typename = typename qxx::enable_if_t<is_condition<L>::value
+                                                        && qxx::is_condition<R>::value>>
+condition::Or<L, R> operator||(const L& l, const R& r)
+{
+       return {l, r};
+}
+
 } // namespace qxx
index d236eda74675459267f33f632396dbab63e3a7c3..f54c3c1c7ce6a79d3a05632a257fd1e221635af9 100644 (file)
@@ -3,6 +3,7 @@
 #include "column.hxx"
 #include "table-impl.hxx"
 #include "tuple-helper.hxx"
+#include "expression.hxx"
 
 #include <vector>
 #include <string>
@@ -58,6 +59,15 @@ private:
                }
        };
 
+       template<typename L, typename R>
+       std::string processWhere(condition::And<L,R>& expr);
+
+       template<typename L, typename R>
+       std::string processWhere(condition::Or<L,R>& expr);
+
+       template<typename Expr>
+       std::string processWhere(Expr expr);
+
        std::string name;
        ImplType impl;
 
@@ -114,10 +124,8 @@ template<typename... Columns>
 template<typename Expr>
 Table<Columns...> Table<Columns...>::where(Expr expr)
 {
-       auto name = this->impl.getColumnName(expr.l); 
-
        std::stringstream ss;
-       ss << "WHERE " << name << " " << std::string(expr) << " ?";
+       ss << "WHERE " << this->processWhere(expr);
 
        this->cache.emplace_back(ss.str());
 
@@ -164,4 +172,36 @@ std::string Table<Columns...>::getColumnName(ColumnType&& type) const noexcept
        return this->impl.getColumnName(std::forward<ColumnType>(type));
 }
 
+template<typename... Columns>
+template<typename L, typename R>
+std::string Table<Columns...>::processWhere(condition::And<L,R>& expr) {
+       std::stringstream ss;
+       ss << this->processWhere(expr.l) << " ";
+       ss << static_cast<std::string>(expr) << " ";
+       ss << this->processWhere(expr.r);
+
+       return ss.str();
+}
+
+template<typename... Columns>
+template<typename L, typename R>
+std::string Table<Columns...>::processWhere(condition::Or<L,R>& expr) {
+       std::stringstream ss;
+       ss << this->processWhere(expr.l) << " ";
+       ss << static_cast<std::string>(expr) << " ";
+       ss << this->processWhere(expr.r);
+
+       return ss.str();
+}
+
+template<typename... Columns>
+template<typename Expr>
+std::string Table<Columns...>::processWhere(Expr expr) {
+       std::stringstream ss;
+       ss << this->impl.getColumnName(expr.l);
+       ss << " = ?";
+
+       return ss.str();
+}
+
 } // namespace qxx
index 30dd09b1cde4205e90f5db122173f86f5b84884b..d24c087fd7997592927c8673a33702e342ceca86 100644 (file)
@@ -25,11 +25,15 @@ int main() {
        std::string select2 = admin.select(&Admin::id, &Admin::uid, &Admin::key);
        std::string select3 = admin.select(&Admin::uid, &Admin::key).where(expr(&Admin::id) > 3);
        std::string select4 = admin.selectAll().where(expr(&Admin::uid) > 3);
+       std::string select5 = admin.selectAll().where(expr(&Admin::uid) > 3 && expr(&Admin::pkg) == "dpm");
+       std::string select6 = admin.selectAll().where(expr(&Admin::uid) > 3 || expr(&Admin::pkg) == "dpm");
 
        std::cout << select1 << '\n'; // SELECT id pkg uid key FROM admin
        std::cout << select2 << '\n'; // SELECT id uid key FROM admin
        std::cout << select3 << '\n'; // SELECT uid key FROM admin WHERE id = ? 
        std::cout << select4 << '\n'; // SELECT * FROM admin WHERE uid = ?
+       std::cout << select5 << '\n'; // SELECT * FROM admin WHERE uid = ? AND pkg = ?
+       std::cout << select6 << '\n'; // SELECT * FROM admin WHERE uid = ? OR pkg = ?
 
        return 0;
 }