added criteria_evaluator and extended all criteria classes with missing methods
This commit is contained in:
@@ -153,6 +153,7 @@ add_library(matador-orm STATIC
|
||||
sql/table.cpp
|
||||
../../include/matador/query/criteria_evaluator.hpp
|
||||
query/criteria_evaluator.cpp
|
||||
../../include/matador/query/criteria/criteria_utils.hpp
|
||||
)
|
||||
|
||||
target_include_directories(matador-orm
|
||||
|
||||
@@ -28,12 +28,12 @@ std::string condition<sql::column, sql::column>::evaluate(const sql::dialect &d,
|
||||
return d.prepare_condition(field_) + " " + operand + " " + d.prepare_condition(other_column_);
|
||||
}
|
||||
|
||||
condition<sql::column, sql::query_context> in(const sql::column &col, sql::query_context &&q)
|
||||
condition<sql::column, sql::query_context> in_old(const sql::column &col, sql::query_context &&q)
|
||||
{
|
||||
return {col, basic_condition::operand_type::IN_LIST, q};
|
||||
}
|
||||
|
||||
condition<sql::column, std::string> like(const sql::column &col, const std::string &val) {
|
||||
condition<sql::column, std::string> like_old(const sql::column &col, const std::string &val) {
|
||||
return { col, basic_condition::operand_type::LIKE, val };
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,31 @@
|
||||
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||
|
||||
namespace matador::query{
|
||||
between_criteria::between_criteria(sql::column column, utils::value min, utils::value max )
|
||||
between_criteria::between_criteria(sql::column column, const int64_t min, const int64_t max)
|
||||
: column_(std::move(column))
|
||||
, min_(std::move(min))
|
||||
, max_(std::move(max))
|
||||
, min_(utils::value{min})
|
||||
, max_(utils::value{max})
|
||||
{}
|
||||
|
||||
between_criteria::between_criteria(sql::column column, utils::placeholder min, utils::placeholder max)
|
||||
: column_(std::move(column))
|
||||
, min_(min)
|
||||
, max_(max)
|
||||
{}
|
||||
|
||||
void between_criteria::accept( criteria_visitor& visitor ) const {
|
||||
visitor.visit(*this);
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const sql::column & between_criteria::column() const {
|
||||
return column_;
|
||||
}
|
||||
|
||||
const criteria_value &between_criteria::min() const {
|
||||
return min_;
|
||||
}
|
||||
|
||||
const criteria_value &between_criteria::max() const {
|
||||
return max_;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,25 @@
|
||||
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
binary_criteria::binary_criteria(sql::column column, const binary_operator operator_, utils::value value)
|
||||
binary_criteria::binary_criteria(sql::column column, const binary_operator operand, criteria_value value)
|
||||
: column_(std::move(column))
|
||||
, operator_(operator_)
|
||||
, operator_(operand)
|
||||
, value_(std::move(value))
|
||||
{}
|
||||
|
||||
void binary_criteria::accept( criteria_visitor& visitor ) const {
|
||||
visitor.visit(*this);
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const sql::column & binary_criteria::column() const {
|
||||
return column_;
|
||||
}
|
||||
|
||||
binary_operator binary_criteria::operand() const {
|
||||
return operator_;
|
||||
}
|
||||
|
||||
const criteria_value& binary_criteria::value() const {
|
||||
return value_;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,19 +3,53 @@
|
||||
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
collection_criteria::collection_criteria(sql::column col, collection_operator operator_, std::vector<utils::value> values )
|
||||
collection_criteria::collection_criteria(sql::column col, const collection_operator operand_, std::vector<criteria_value> values )
|
||||
: column_(std::move(col))
|
||||
, operator_(operator_)
|
||||
, operand_(operand_)
|
||||
, values_(std::move(values))
|
||||
{}
|
||||
|
||||
collection_criteria::collection_criteria(sql::column col, const collection_operator operator_, const std::initializer_list<utils::value> values )
|
||||
collection_criteria::collection_criteria(sql::column col, const collection_operator operand_, const std::initializer_list<criteria_value> values )
|
||||
: column_(std::move(col))
|
||||
, operator_(operator_)
|
||||
, operand_(operand_)
|
||||
, values_(values)
|
||||
{}
|
||||
|
||||
void collection_criteria::accept( criteria_visitor& visitor ) const {
|
||||
visitor.visit(*this);
|
||||
void collection_criteria::accept(criteria_visitor& visitor) const {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const sql::column & collection_criteria::column() const {
|
||||
return column_;
|
||||
}
|
||||
|
||||
collection_operator collection_criteria::operand() const {
|
||||
return operand_;
|
||||
}
|
||||
|
||||
const std::vector<criteria_value>& collection_criteria::values() const {
|
||||
return values_;
|
||||
}
|
||||
|
||||
collection_query_criteria::collection_query_criteria(sql::column col, collection_operator operand_, sql::query_context ctx)
|
||||
: column_(std::move(col))
|
||||
, operand_(operand_)
|
||||
, query_context_(std::move(ctx)){
|
||||
}
|
||||
|
||||
void collection_query_criteria::accept(criteria_visitor &visitor) const {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const sql::column & collection_query_criteria::column() const {
|
||||
return column_;
|
||||
}
|
||||
|
||||
collection_operator collection_query_criteria::operand() const {
|
||||
return operand_;
|
||||
}
|
||||
|
||||
const sql::query_context & collection_query_criteria::context() const {
|
||||
return query_context_;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,23 +6,78 @@
|
||||
#include "matador/query/criteria/not_criteria.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
criteria_ptr operator==(const sql::column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator!=(const sql::column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::NOT_EQUALS, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator>(const sql::column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator>=(const sql::column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN_OR_EQUAL, p);
|
||||
|
||||
}
|
||||
|
||||
criteria_ptr operator<(const sql::column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator<=(const sql::column &col, utils::placeholder p) {
|
||||
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN_OR_EQUAL, p);
|
||||
}
|
||||
|
||||
criteria_ptr operator&&(criteria_ptr left, criteria_ptr right) {
|
||||
return std::make_unique<logical_criteria>(std::move(left), logical_operator::AND, std::move(right));
|
||||
return std::make_unique<logical_criteria>(std::move(left), logical_operator::AND, std::move(right));
|
||||
}
|
||||
|
||||
criteria_ptr operator||(criteria_ptr left, criteria_ptr right) {
|
||||
return std::make_unique<logical_criteria>(std::move(left), logical_operator::OR, std::move(right));
|
||||
return std::make_unique<logical_criteria>(std::move(left), logical_operator::OR, std::move(right));
|
||||
}
|
||||
|
||||
criteria_ptr operator!(criteria_ptr clause) {
|
||||
return std::make_unique<not_criteria>(std::move(clause));
|
||||
return std::make_unique<not_criteria>(std::move(clause));
|
||||
}
|
||||
|
||||
criteria_ptr between(const sql::column &col, utils::value min, utils::value max) {
|
||||
return std::make_unique<between_criteria>(col, std::move(min), std::move(max));
|
||||
template <>
|
||||
criteria_ptr in(const sql::column &col, const std::initializer_list<utils::placeholder> args) {
|
||||
std::vector<criteria_value> values;
|
||||
for ( auto &&arg : args ) {
|
||||
values.emplace_back(arg);
|
||||
}
|
||||
return std::make_unique<collection_criteria>(col, collection_operator::IN, std::move(values));
|
||||
}
|
||||
|
||||
criteria_ptr in(const sql::column &col, sql::query_context &&ctx) {
|
||||
return std::make_unique<collection_query_criteria>(col, collection_operator::IN, std::move(ctx));
|
||||
}
|
||||
|
||||
template <>
|
||||
criteria_ptr out(const sql::column &col, const std::initializer_list<utils::placeholder> args) {
|
||||
std::vector<criteria_value> values;
|
||||
for ( auto &&arg : args ) {
|
||||
values.emplace_back(arg);
|
||||
}
|
||||
return std::make_unique<collection_criteria>(col, collection_operator::OUT, values);
|
||||
}
|
||||
|
||||
criteria_ptr out(const sql::column &col, sql::query_context &&ctx) {
|
||||
return std::make_unique<collection_query_criteria>(col, collection_operator::IN, std::move(ctx));
|
||||
}
|
||||
|
||||
criteria_ptr between(const sql::column &col, const int64_t min, const int64_t max) {
|
||||
return std::make_unique<between_criteria>(col, min, max);
|
||||
}
|
||||
|
||||
criteria_ptr between(const sql::column &col, utils::placeholder min, utils::placeholder max) {
|
||||
return std::make_unique<between_criteria>(col, min, max);
|
||||
}
|
||||
|
||||
criteria_ptr like(const sql::column &col, const std::string &pattern) {
|
||||
return std::make_unique<like_criteria>(col, pattern);
|
||||
return std::make_unique<like_criteria>(col, pattern);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,4 +10,12 @@ like_criteria::like_criteria(sql::column column, std::string pattern)
|
||||
void like_criteria::accept(criteria_visitor &visitor) const {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const sql::column & like_criteria::column() const {
|
||||
return column_;
|
||||
}
|
||||
|
||||
const std::string & like_criteria::pattern() const {
|
||||
return pattern_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,18 @@ logical_criteria::logical_criteria(criteria_ptr left, const logical_operator op,
|
||||
{}
|
||||
|
||||
void logical_criteria::accept(criteria_visitor& visitor) const {
|
||||
visitor.visit(*this);
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const criteria_ptr & logical_criteria::left_clause() const {
|
||||
return left_criteria_;
|
||||
}
|
||||
|
||||
logical_operator logical_criteria::operand() const {
|
||||
return operand_;
|
||||
}
|
||||
|
||||
const criteria_ptr & logical_criteria::right_clause() const {
|
||||
return right_criteria_;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,10 @@ not_criteria::not_criteria(criteria_ptr clause)
|
||||
{}
|
||||
|
||||
void not_criteria::accept(criteria_visitor& visitor) const {
|
||||
visitor.visit(*this);
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const criteria_ptr & not_criteria::clause() const {
|
||||
return criteria_;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,117 @@
|
||||
#include "matador/query/criteria_evaluator.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
criteria_evaluator::criteria_evaluator(const sql::dialect &d, sql::query_context &query)
|
||||
: dialect_(d)
|
||||
, query_(query) {}
|
||||
#include "matador/query/criteria/between_criteria.hpp"
|
||||
#include "matador/query/criteria/binary_criteria.hpp"
|
||||
#include "matador/query/criteria/collection_criteria.hpp"
|
||||
#include "matador/query/criteria/like_criteria.hpp"
|
||||
#include "matador/query/criteria/logical_criteria.hpp"
|
||||
#include "matador/query/criteria/not_criteria.hpp"
|
||||
|
||||
void criteria_evaluator::visit(const between_criteria &node) {
|
||||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/query_context.hpp"
|
||||
|
||||
#include "matador/utils/value.hpp"
|
||||
#include "matador/utils/enum_mapper.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
namespace detail {
|
||||
static const utils::enum_mapper<binary_operator> BinaryOperatorEnum({
|
||||
{binary_operator::EQUALS, "="},
|
||||
{binary_operator::NOT_EQUALS, "<>"},
|
||||
{binary_operator::GREATER_THAN, ">"},
|
||||
{binary_operator::GREATER_THAN_OR_EQUAL, ">="},
|
||||
{binary_operator::LESS_THAN, "<"},
|
||||
{binary_operator::LESS_THAN_OR_EQUAL, "<="},
|
||||
});
|
||||
}
|
||||
|
||||
criteria_evaluator::criteria_evaluator(const sql::dialect &d, sql::query_context &query)
|
||||
: dialect_(d)
|
||||
, query_(query) {
|
||||
}
|
||||
|
||||
std::string criteria_evaluator::evaluate(const abstract_criteria &node) {
|
||||
clause_.clear();
|
||||
node.accept(*this);
|
||||
|
||||
return clause_;
|
||||
}
|
||||
|
||||
void criteria_evaluator::visit(const between_criteria &node) {
|
||||
query_.bind_vars.emplace_back(node.column().name);
|
||||
query_.bind_vars.emplace_back(node.column().name);
|
||||
clause_ += dialect_.prepare_identifier(node.column()) + " " + dialect_.token_at(sql::dialect_token::BETWEEN) + " ";
|
||||
evaluate_value(node.min());
|
||||
clause_ += " " + dialect_.token_at(sql::dialect_token::AND) + " ";
|
||||
evaluate_value(node.max());
|
||||
}
|
||||
|
||||
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts> overload(Ts...) -> overload<Ts...>;
|
||||
|
||||
void criteria_evaluator::visit(const binary_criteria &node) {
|
||||
clause_ += dialect_.prepare_condition(node.column()) + " " + detail::BinaryOperatorEnum.to_string(node.operand()) + " ";
|
||||
|
||||
evaluate_value(node.value());
|
||||
}
|
||||
|
||||
void criteria_evaluator::visit(const collection_criteria &node) {
|
||||
const auto count = node.values().size();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
query_.bind_vars.emplace_back(node.column().name);
|
||||
}
|
||||
|
||||
clause_ += dialect_.prepare_identifier(node.column()) +
|
||||
(node.operand() == collection_operator::OUT ? " " + dialect_.token_at(sql::dialect_token::NOT) + " " : " ") +
|
||||
dialect_.token_at(sql::dialect_token::IN) + " (";
|
||||
if (node.values().size() < 2) {
|
||||
for (const auto &val: node.values()) {
|
||||
evaluate_value(val);
|
||||
}
|
||||
} else {
|
||||
auto it = node.values().begin();
|
||||
evaluate_value(*it++);
|
||||
for (; it != node.values().end(); ++it) {
|
||||
clause_ += ", ";
|
||||
evaluate_value(*it);
|
||||
}
|
||||
}
|
||||
clause_ += ")";
|
||||
}
|
||||
|
||||
void criteria_evaluator::visit(const collection_query_criteria &node) {
|
||||
clause_ += dialect_.prepare_identifier(node.column()) +
|
||||
(node.operand() == collection_operator::OUT ? " " + dialect_.token_at(sql::dialect_token::NOT) + " " : " ") +
|
||||
dialect_.token_at(sql::dialect_token::IN) + " (" +node.context().sql + ")";
|
||||
}
|
||||
|
||||
void criteria_evaluator::visit(const like_criteria &node) {
|
||||
clause_ += dialect_.prepare_condition(node.column()) + " " + dialect_.token_at(sql::dialect_token::LIKE) +
|
||||
" " + dialect_.token_at(sql::dialect_token::BEGIN_STRING_DATA) + node.pattern() + dialect_.token_at(
|
||||
sql::dialect_token::END_STRING_DATA);
|
||||
}
|
||||
|
||||
void criteria_evaluator::visit(const logical_criteria &node) {
|
||||
clause_ += "(";
|
||||
node.left_clause()->accept(*this);
|
||||
clause_ += " " + dialect_.token_at(node.operand() == logical_operator::AND
|
||||
? sql::dialect_token::AND
|
||||
: sql::dialect_token::OR) + " ";
|
||||
node.right_clause()->accept(*this);
|
||||
clause_ += ")";
|
||||
}
|
||||
|
||||
void criteria_evaluator::visit(const not_criteria &node) {
|
||||
clause_ += dialect_.token_at(sql::dialect_token::NOT) + " (";
|
||||
node.clause()->accept(*this);
|
||||
clause_ += ")";
|
||||
}
|
||||
|
||||
void criteria_evaluator::evaluate_value(const criteria_value &value) {
|
||||
std::visit(overload{
|
||||
[this](const utils::value& val){ clause_ += dialect_.to_sql_string(val); },
|
||||
[this](const utils::placeholder&) { clause_ += dialect_.next_placeholder(query_.bind_vars); }
|
||||
}, value);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,17 @@ const std::string& dialect::to_string(const bool val) const
|
||||
return bool_strings_[static_cast<int>(val)];
|
||||
}
|
||||
|
||||
std::string dialect::to_sql_string(const utils::value &val) const {
|
||||
if (val.is_null()) {
|
||||
return "NULL";
|
||||
}
|
||||
if (val.is_string()) {
|
||||
return token_at(dialect_token::BEGIN_STRING_DATA) + val.str() + token_at(dialect_token::BEGIN_STRING_DATA);
|
||||
}
|
||||
|
||||
return val.str();
|
||||
}
|
||||
|
||||
void dialect::bool_strings(const std::string &true_string, const std::string &false_string)
|
||||
{
|
||||
bool_strings_[0] = false_string;
|
||||
|
||||
Reference in New Issue
Block a user