#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;
} // 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 {
}
};
-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 {
}
};
-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
#include "column.hxx"
#include "table-impl.hxx"
#include "tuple-helper.hxx"
+#include "expression.hxx"
#include <vector>
#include <string>
}
};
+ 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;
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());
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
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;
}