added criteria_evaluator and extended all criteria classes with missing methods
This commit is contained in:
parent
5d53addc60
commit
69ce2c34cf
|
|
@ -420,7 +420,7 @@ condition<sql::column, std::initializer_list<V>> in(const sql::column &col, std:
|
||||||
* @param q The query to be executes as sub select
|
* @param q The query to be executes as sub select
|
||||||
* @return The condition object
|
* @return The condition object
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a between condition.
|
* @brief Creates a between condition.
|
||||||
|
|
@ -450,7 +450,7 @@ condition<sql::column, std::pair<T, T>> between(const sql::column &col, T low, T
|
||||||
* @param val The value to the like operator
|
* @param val The value to the like operator
|
||||||
* @return The like condition object
|
* @return The like condition object
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Condition equality operator for a column and a value
|
* @brief Condition equality operator for a column and a value
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define CRITERIA_BETWEEN_CRITERIA_NODE_HPP
|
#define CRITERIA_BETWEEN_CRITERIA_NODE_HPP
|
||||||
|
|
||||||
#include "matador/query/criteria/abstract_criteria.hpp"
|
#include "matador/query/criteria/abstract_criteria.hpp"
|
||||||
|
#include "matador/query/criteria/criteria_utils.hpp"
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column.hpp"
|
||||||
|
|
||||||
|
|
@ -12,14 +13,19 @@ namespace matador::query {
|
||||||
class between_criteria final : public abstract_criteria {
|
class between_criteria final : public abstract_criteria {
|
||||||
public:
|
public:
|
||||||
between_criteria() = delete;
|
between_criteria() = delete;
|
||||||
between_criteria(sql::column column, utils::value min, utils::value max);
|
between_criteria(sql::column column, int64_t min, int64_t max);
|
||||||
|
between_criteria(sql::column column, utils::placeholder min, utils::placeholder max);
|
||||||
|
|
||||||
void accept(criteria_visitor& visitor) const override;
|
void accept(criteria_visitor& visitor) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const sql::column& column() const;
|
||||||
|
[[nodiscard]] const criteria_value &min() const;
|
||||||
|
[[nodiscard]] const criteria_value &max() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sql::column column_;
|
sql::column column_;
|
||||||
utils::value min_;
|
criteria_value min_;
|
||||||
utils::value max_;
|
criteria_value max_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif //CRITERIA_BETWEEN_CRITERIA_NODE_HPP
|
#endif //CRITERIA_BETWEEN_CRITERIA_NODE_HPP
|
||||||
|
|
@ -2,11 +2,10 @@
|
||||||
#define CRITERIA_BINARY_CRITERIA_NODE_HPP
|
#define CRITERIA_BINARY_CRITERIA_NODE_HPP
|
||||||
|
|
||||||
#include "matador/query/criteria/abstract_criteria.hpp"
|
#include "matador/query/criteria/abstract_criteria.hpp"
|
||||||
|
#include "matador/query/criteria/criteria_utils.hpp"
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column.hpp"
|
||||||
|
|
||||||
#include "matador/utils/value.hpp"
|
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
enum class binary_operator {
|
enum class binary_operator {
|
||||||
EQUALS,
|
EQUALS,
|
||||||
|
|
@ -20,14 +19,18 @@ enum class binary_operator {
|
||||||
class binary_criteria final : public abstract_criteria {
|
class binary_criteria final : public abstract_criteria {
|
||||||
public:
|
public:
|
||||||
binary_criteria() = delete;
|
binary_criteria() = delete;
|
||||||
binary_criteria( sql::column column, binary_operator operator_, utils::value value );
|
binary_criteria(sql::column column, binary_operator operand, criteria_value value);
|
||||||
|
|
||||||
void accept( criteria_visitor& visitor ) const override;
|
void accept( criteria_visitor& visitor ) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const sql::column& column() const;
|
||||||
|
[[nodiscard]] binary_operator operand() const;
|
||||||
|
[[nodiscard]] const criteria_value& value() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sql::column column_;
|
sql::column column_;
|
||||||
binary_operator operator_{};
|
binary_operator operator_{};
|
||||||
utils::value value_;
|
criteria_value value_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif //CRITERIA_BINARY_CRITERIA_NODE_HPP
|
#endif //CRITERIA_BINARY_CRITERIA_NODE_HPP
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
#define CRITERIA_COLLECTION_CRITERIA_NODE_HPP
|
#define CRITERIA_COLLECTION_CRITERIA_NODE_HPP
|
||||||
|
|
||||||
#include "matador/query/criteria/abstract_criteria.hpp"
|
#include "matador/query/criteria/abstract_criteria.hpp"
|
||||||
|
#include "matador/query/criteria/criteria_utils.hpp"
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column.hpp"
|
||||||
|
#include "matador/sql/query_context.hpp"
|
||||||
#include "matador/utils/value.hpp"
|
|
||||||
|
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
enum class collection_operator {
|
enum class collection_operator {
|
||||||
|
|
@ -16,14 +16,36 @@ enum class collection_operator {
|
||||||
class collection_criteria final : public abstract_criteria {
|
class collection_criteria final : public abstract_criteria {
|
||||||
public:
|
public:
|
||||||
collection_criteria() = delete;
|
collection_criteria() = delete;
|
||||||
collection_criteria(sql::column col, collection_operator operator_, std::vector<utils::value> values);
|
collection_criteria(sql::column col, collection_operator operand_, std::vector<criteria_value> values);
|
||||||
collection_criteria(sql::column col, collection_operator operator_, std::initializer_list<utils::value> values);
|
collection_criteria(sql::column col, collection_operator operand_, std::initializer_list<criteria_value> values);
|
||||||
|
|
||||||
void accept(criteria_visitor& visitor) const override;
|
void accept(criteria_visitor& visitor) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const sql::column& column() const;
|
||||||
|
[[nodiscard]] collection_operator operand() const;
|
||||||
|
[[nodiscard]] const std::vector<criteria_value>& values() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sql::column column_;
|
sql::column column_;
|
||||||
collection_operator operator_;
|
collection_operator operand_;
|
||||||
std::vector<utils::value> values_;
|
std::vector<criteria_value> values_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class collection_query_criteria final : public abstract_criteria {
|
||||||
|
public:
|
||||||
|
collection_query_criteria() = delete;
|
||||||
|
collection_query_criteria(sql::column col, collection_operator operand_, sql::query_context ctx);
|
||||||
|
|
||||||
|
void accept(criteria_visitor& visitor) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const sql::column& column() const;
|
||||||
|
[[nodiscard]] collection_operator operand() const;
|
||||||
|
[[nodiscard]] const sql::query_context& context() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
sql::column column_;
|
||||||
|
collection_operator operand_;
|
||||||
|
sql::query_context query_context_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif //CRITERIA_COLLECTION_CRITERIA_NODE_HPP
|
#endif //CRITERIA_COLLECTION_CRITERIA_NODE_HPP
|
||||||
|
|
@ -6,40 +6,51 @@
|
||||||
|
|
||||||
#include "matador/sql/column.hpp"
|
#include "matador/sql/column.hpp"
|
||||||
|
|
||||||
|
#include "matador/utils/placeholder.hpp"
|
||||||
#include "matador/utils/value.hpp"
|
#include "matador/utils/value.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
struct query_context;
|
||||||
|
}
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
criteria_ptr operator==(const sql::column &col, Type val) {
|
criteria_ptr operator==(const sql::column &col, Type val) {
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, val);
|
return std::make_unique<binary_criteria>(col, binary_operator::EQUALS, utils::value(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
criteria_ptr operator!=(const sql::column &col, Type val) {
|
criteria_ptr operator!=(const sql::column &col, Type val) {
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::NOT_EQUALS, val);
|
return std::make_unique<binary_criteria>(col, binary_operator::NOT_EQUALS, utils::value(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
criteria_ptr operator>(const sql::column &col, Type val) {
|
criteria_ptr operator>(const sql::column &col, Type val) {
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN, val);
|
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN, utils::value(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
criteria_ptr operator>=(const sql::column &col, Type val) {
|
criteria_ptr operator>=(const sql::column &col, Type val) {
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN_OR_EQUAL, val);
|
return std::make_unique<binary_criteria>(col, binary_operator::GREATER_THAN_OR_EQUAL, utils::value(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
criteria_ptr operator<(const sql::column &col, Type val) {
|
criteria_ptr operator<(const sql::column &col, Type val) {
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN, val);
|
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN, utils::value(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
criteria_ptr operator<=(const sql::column &col, Type val) {
|
criteria_ptr operator<=(const sql::column &col, Type val) {
|
||||||
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN_OR_EQUAL, val);
|
return std::make_unique<binary_criteria>(col, binary_operator::LESS_THAN_OR_EQUAL, utils::value(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
criteria_ptr operator==(const sql::column &col, utils::placeholder p);
|
||||||
|
criteria_ptr operator!=(const sql::column &col, utils::placeholder p);
|
||||||
|
criteria_ptr operator>(const sql::column &col, utils::placeholder p);
|
||||||
|
criteria_ptr operator>=(const sql::column &col, utils::placeholder p);
|
||||||
|
criteria_ptr operator<(const sql::column &col, utils::placeholder p);
|
||||||
|
criteria_ptr operator<=(const sql::column &col, utils::placeholder p);
|
||||||
|
|
||||||
criteria_ptr operator&&(criteria_ptr left, criteria_ptr right);
|
criteria_ptr operator&&(criteria_ptr left, criteria_ptr right);
|
||||||
|
|
||||||
criteria_ptr operator||(criteria_ptr left, criteria_ptr right);
|
criteria_ptr operator||(criteria_ptr left, criteria_ptr right);
|
||||||
|
|
@ -48,23 +59,34 @@ criteria_ptr operator!(criteria_ptr clause);
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
criteria_ptr in(const sql::column &col, std::initializer_list<Type> args) {
|
criteria_ptr in(const sql::column &col, std::initializer_list<Type> args) {
|
||||||
std::vector<utils::value> values;
|
std::vector<criteria_value> values;
|
||||||
for ( auto &&arg : args ) {
|
for ( auto &&arg : args ) {
|
||||||
values.emplace_back(std::move(arg));
|
values.emplace_back(utils::value{std::move(arg)});
|
||||||
}
|
}
|
||||||
return std::make_unique<collection_criteria>(col, collection_operator::IN, std::move(values));
|
return std::make_unique<collection_criteria>(col, collection_operator::IN, std::move(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class V >
|
template <>
|
||||||
criteria_ptr out(const sql::column &col, std::initializer_list<V> args) {
|
criteria_ptr in(const sql::column &col, std::initializer_list<utils::placeholder> args);
|
||||||
std::vector<utils::value> values;
|
|
||||||
|
criteria_ptr in(const sql::column &col, sql::query_context &&ctx);
|
||||||
|
|
||||||
|
template < class Type >
|
||||||
|
criteria_ptr out(const sql::column &col, std::initializer_list<Type> args) {
|
||||||
|
std::vector<criteria_value> values;
|
||||||
for ( auto &&arg : args ) {
|
for ( auto &&arg : args ) {
|
||||||
values.emplace_back(std::move(arg));
|
values.emplace_back(utils::value{std::move(arg)});
|
||||||
}
|
}
|
||||||
return std::make_unique<collection_criteria>(col, collection_operator::OUT, values);
|
return std::make_unique<collection_criteria>(col, collection_operator::OUT, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
criteria_ptr between(const sql::column &col, utils::value min, utils::value max);
|
template <>
|
||||||
|
criteria_ptr out(const sql::column &col, std::initializer_list<utils::placeholder> args);
|
||||||
|
|
||||||
|
criteria_ptr out(const sql::column &col, sql::query_context &&ctx);
|
||||||
|
|
||||||
|
criteria_ptr between(const sql::column &col, int64_t min, int64_t max);
|
||||||
|
criteria_ptr between(const sql::column &col, utils::placeholder min, utils::placeholder max);
|
||||||
|
|
||||||
criteria_ptr like(const sql::column &col, const std::string &pattern);
|
criteria_ptr like(const sql::column &col, const std::string &pattern);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef MATADOR_CRITERIA_UTILS_HPP
|
||||||
|
#define MATADOR_CRITERIA_UTILS_HPP
|
||||||
|
|
||||||
|
#include "matador/utils/placeholder.hpp"
|
||||||
|
#include "matador/utils/value.hpp"
|
||||||
|
|
||||||
|
namespace matador::query {
|
||||||
|
using criteria_value = std::variant<utils::placeholder, utils::value>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MATADOR_CRITERIA_UTILS_HPP
|
||||||
|
|
@ -8,6 +8,7 @@ class like_criteria;
|
||||||
class logical_criteria;
|
class logical_criteria;
|
||||||
class not_criteria;
|
class not_criteria;
|
||||||
class collection_criteria;
|
class collection_criteria;
|
||||||
|
class collection_query_criteria;
|
||||||
|
|
||||||
class criteria_visitor {
|
class criteria_visitor {
|
||||||
public:
|
public:
|
||||||
|
|
@ -16,6 +17,7 @@ public:
|
||||||
virtual void visit(const between_criteria &node) = 0;
|
virtual void visit(const between_criteria &node) = 0;
|
||||||
virtual void visit(const binary_criteria &node) = 0;
|
virtual void visit(const binary_criteria &node) = 0;
|
||||||
virtual void visit(const collection_criteria &node) = 0;
|
virtual void visit(const collection_criteria &node) = 0;
|
||||||
|
virtual void visit(const collection_query_criteria &node) = 0;
|
||||||
virtual void visit(const like_criteria &node) = 0;
|
virtual void visit(const like_criteria &node) = 0;
|
||||||
virtual void visit(const logical_criteria &node) = 0;
|
virtual void visit(const logical_criteria &node) = 0;
|
||||||
virtual void visit(const not_criteria &node) = 0;
|
virtual void visit(const not_criteria &node) = 0;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ public:
|
||||||
|
|
||||||
void accept(criteria_visitor &visitor) const override;
|
void accept(criteria_visitor &visitor) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const sql::column& column() const;
|
||||||
|
[[nodiscard]] const std::string& pattern() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sql::column column_;
|
sql::column column_;
|
||||||
std::string pattern_;
|
std::string pattern_;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@ public:
|
||||||
|
|
||||||
void accept(criteria_visitor& visitor) const override;
|
void accept(criteria_visitor& visitor) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const criteria_ptr& left_clause() const;
|
||||||
|
[[nodiscard]] logical_operator operand() const;
|
||||||
|
[[nodiscard]] const criteria_ptr& right_clause() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<abstract_criteria> left_criteria_;
|
std::unique_ptr<abstract_criteria> left_criteria_;
|
||||||
logical_operator operand_;
|
logical_operator operand_;
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,14 @@
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
class not_criteria final : public abstract_criteria {
|
class not_criteria final : public abstract_criteria {
|
||||||
public:
|
public:
|
||||||
explicit not_criteria(criteria_ptr clause);
|
explicit not_criteria(criteria_ptr clause);
|
||||||
|
|
||||||
void accept(criteria_visitor& visitor) const override;
|
void accept(criteria_visitor& visitor) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const criteria_ptr& clause() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
criteria_ptr criteria_;
|
criteria_ptr criteria_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
#ifndef MATADOR_CRITERIA_EVALUATOR_HPP
|
#ifndef MATADOR_CRITERIA_EVALUATOR_HPP
|
||||||
#define MATADOR_CRITERIA_EVALUATOR_HPP
|
#define MATADOR_CRITERIA_EVALUATOR_HPP
|
||||||
|
|
||||||
|
#include "matador/query/criteria/abstract_criteria.hpp"
|
||||||
#include "matador/query/criteria/criteria_visitor.hpp"
|
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||||
|
#include "matador/query/criteria/criteria_utils.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
class dialect;
|
class dialect;
|
||||||
|
|
@ -13,16 +17,24 @@ namespace matador::query {
|
||||||
class criteria_evaluator final : public criteria_visitor {
|
class criteria_evaluator final : public criteria_visitor {
|
||||||
public:
|
public:
|
||||||
criteria_evaluator(const sql::dialect &d, sql::query_context &query);
|
criteria_evaluator(const sql::dialect &d, sql::query_context &query);
|
||||||
|
|
||||||
|
std::string evaluate(const abstract_criteria &node);
|
||||||
|
|
||||||
void visit(const between_criteria &node) override;
|
void visit(const between_criteria &node) override;
|
||||||
void visit(const binary_criteria &node) override;
|
void visit(const binary_criteria &node) override;
|
||||||
void visit(const collection_criteria &node) override;
|
void visit(const collection_criteria &node) override;
|
||||||
|
void visit(const collection_query_criteria &node) override;
|
||||||
void visit(const like_criteria &node) override;
|
void visit(const like_criteria &node) override;
|
||||||
void visit(const logical_criteria &node) override;
|
void visit(const logical_criteria &node) override;
|
||||||
void visit(const not_criteria &node) override;
|
void visit(const not_criteria &node) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void evaluate_value(const criteria_value &value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const sql::dialect &dialect_;
|
const sql::dialect &dialect_;
|
||||||
sql::query_context &query_;
|
sql::query_context &query_;
|
||||||
|
std::string clause_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif //MATADOR_CRITERIA_EVALUATOR_HPP
|
#endif //MATADOR_CRITERIA_EVALUATOR_HPP
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace matador::utils {
|
||||||
|
class value;
|
||||||
|
}
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
class connection_impl;
|
class connection_impl;
|
||||||
|
|
@ -53,6 +57,8 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] const std::string& to_string(bool val) const;
|
[[nodiscard]] const std::string& to_string(bool val) const;
|
||||||
|
|
||||||
|
[[nodiscard]] std::string to_sql_string(const utils::value &val) const ;
|
||||||
|
|
||||||
void bool_strings(const std::string &true_string, const std::string &false_string);
|
void bool_strings(const std::string &true_string, const std::string &false_string);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -150,7 +156,10 @@ private:
|
||||||
{dialect_token::WHERE, "WHERE"},
|
{dialect_token::WHERE, "WHERE"},
|
||||||
{dialect_token::AND, "AND"},
|
{dialect_token::AND, "AND"},
|
||||||
{dialect_token::OR, "OR"},
|
{dialect_token::OR, "OR"},
|
||||||
|
{dialect_token::NOT, "NOT"},
|
||||||
{dialect_token::LIKE, "LIKE"},
|
{dialect_token::LIKE, "LIKE"},
|
||||||
|
{dialect_token::BETWEEN, "BETWEEN"},
|
||||||
|
{dialect_token::IN, "IN"},
|
||||||
{dialect_token::ORDER_BY, "ORDER BY"},
|
{dialect_token::ORDER_BY, "ORDER BY"},
|
||||||
{dialect_token::GROUP_BY, "GROUP BY"},
|
{dialect_token::GROUP_BY, "GROUP BY"},
|
||||||
{dialect_token::ASC, "ASC"},
|
{dialect_token::ASC, "ASC"},
|
||||||
|
|
@ -171,6 +180,8 @@ private:
|
||||||
{dialect_token::STRING_QUOTE, "'"},
|
{dialect_token::STRING_QUOTE, "'"},
|
||||||
{dialect_token::BEGIN_BINARY_DATA, "X'"},
|
{dialect_token::BEGIN_BINARY_DATA, "X'"},
|
||||||
{dialect_token::END_BINARY_DATA, "'"},
|
{dialect_token::END_BINARY_DATA, "'"},
|
||||||
|
{dialect_token::BEGIN_STRING_DATA, "'"},
|
||||||
|
{dialect_token::END_STRING_DATA, "'"},
|
||||||
{dialect_token::NONE, ""}
|
{dialect_token::NONE, ""}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,10 @@ enum class dialect_token : uint8_t {
|
||||||
WHERE_CLAUSE,
|
WHERE_CLAUSE,
|
||||||
AND,
|
AND,
|
||||||
OR,
|
OR,
|
||||||
|
NOT,
|
||||||
LIKE,
|
LIKE,
|
||||||
|
BETWEEN,
|
||||||
|
IN,
|
||||||
ORDER_BY,
|
ORDER_BY,
|
||||||
GROUP_BY,
|
GROUP_BY,
|
||||||
ASC,
|
ASC,
|
||||||
|
|
@ -49,6 +52,8 @@ enum class dialect_token : uint8_t {
|
||||||
STRING_QUOTE,
|
STRING_QUOTE,
|
||||||
BEGIN_BINARY_DATA,
|
BEGIN_BINARY_DATA,
|
||||||
END_BINARY_DATA,
|
END_BINARY_DATA,
|
||||||
|
BEGIN_STRING_DATA,
|
||||||
|
END_STRING_DATA,
|
||||||
NONE
|
NONE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@ namespace matador::sql {
|
||||||
|
|
||||||
class sql_error;
|
class sql_error;
|
||||||
|
|
||||||
class statement_impl
|
class statement_impl {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
explicit statement_impl(query_context query, size_t start_bind_pos);
|
explicit statement_impl(query_context query, size_t start_bind_pos);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,7 @@ add_library(matador-orm STATIC
|
||||||
sql/table.cpp
|
sql/table.cpp
|
||||||
../../include/matador/query/criteria_evaluator.hpp
|
../../include/matador/query/criteria_evaluator.hpp
|
||||||
query/criteria_evaluator.cpp
|
query/criteria_evaluator.cpp
|
||||||
|
../../include/matador/query/criteria/criteria_utils.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(matador-orm
|
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_);
|
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};
|
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 };
|
return { col, basic_condition::operand_type::LIKE, val };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,31 @@
|
||||||
#include "matador/query/criteria/criteria_visitor.hpp"
|
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||||
|
|
||||||
namespace matador::query{
|
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))
|
: column_(std::move(column))
|
||||||
, min_(std::move(min))
|
, min_(utils::value{min})
|
||||||
, max_(std::move(max))
|
, 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 {
|
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"
|
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
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))
|
: column_(std::move(column))
|
||||||
, operator_(operator_)
|
, operator_(operand)
|
||||||
, value_(std::move(value))
|
, value_(std::move(value))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void binary_criteria::accept( criteria_visitor& visitor ) const {
|
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"
|
#include "matador/query/criteria/criteria_visitor.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
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))
|
: column_(std::move(col))
|
||||||
, operator_(operator_)
|
, operand_(operand_)
|
||||||
, values_(std::move(values))
|
, 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))
|
: column_(std::move(col))
|
||||||
, operator_(operator_)
|
, operand_(operand_)
|
||||||
, values_(values)
|
, values_(values)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void collection_criteria::accept( criteria_visitor& visitor ) const {
|
void collection_criteria::accept(criteria_visitor& visitor) const {
|
||||||
visitor.visit(*this);
|
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"
|
#include "matador/query/criteria/not_criteria.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
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) {
|
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) {
|
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) {
|
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) {
|
template <>
|
||||||
return std::make_unique<between_criteria>(col, std::move(min), std::move(max));
|
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) {
|
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 {
|
void like_criteria::accept(criteria_visitor &visitor) const {
|
||||||
visitor.visit(*this);
|
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 {
|
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 {
|
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"
|
#include "matador/query/criteria_evaluator.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
#include "matador/query/criteria/between_criteria.hpp"
|
||||||
criteria_evaluator::criteria_evaluator(const sql::dialect &d, sql::query_context &query)
|
#include "matador/query/criteria/binary_criteria.hpp"
|
||||||
: dialect_(d)
|
#include "matador/query/criteria/collection_criteria.hpp"
|
||||||
, query_(query) {}
|
#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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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)];
|
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)
|
void dialect::bool_strings(const std::string &true_string, const std::string &false_string)
|
||||||
{
|
{
|
||||||
bool_strings_[0] = false_string;
|
bool_strings_[0] = false_string;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ add_executable(OrmTests
|
||||||
utils/auto_reset_event.hpp
|
utils/auto_reset_event.hpp
|
||||||
sql/StatementCacheTest.cpp
|
sql/StatementCacheTest.cpp
|
||||||
sql/ConnectionPoolFixture.hpp
|
sql/ConnectionPoolFixture.hpp
|
||||||
|
query/CriteriaTests.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(OrmTests matador-orm matador-core Catch2::Catch2WithMain)
|
target_link_libraries(OrmTests matador-orm matador-core Catch2::Catch2WithMain)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace matador::test::orm {
|
namespace matador::test::orm {
|
||||||
test_statement::test_statement(const sql::query_context &query)
|
test_statement::test_statement(const sql::query_context &query)
|
||||||
: statement_impl(query) {}
|
: statement_impl(query, 0) {}
|
||||||
|
|
||||||
utils::result<size_t, utils::error> test_statement::execute(const sql::parameter_binder &/*bindings*/) {
|
utils::result<size_t, utils::error> test_statement::execute(const sql::parameter_binder &/*bindings*/) {
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ TEST_CASE_METHOD(ConditionFixture, "Test in query condition", "[condition][in qu
|
||||||
query_context sub_ctx;
|
query_context sub_ctx;
|
||||||
sub_ctx.sql = R"(SELECT "name" FROM "test")";
|
sub_ctx.sql = R"(SELECT "name" FROM "test")";
|
||||||
|
|
||||||
auto cond = age_col != 7 && in(name_col, std::move(sub_ctx));
|
auto cond = age_col != 7 && in_old(name_col, std::move(sub_ctx));
|
||||||
auto clause = cond.evaluate(dlc, ctx);
|
auto clause = cond.evaluate(dlc, ctx);
|
||||||
REQUIRE(clause == "(\"age\" <> 7 AND \"name\" IN (SELECT \"name\" FROM \"test\"))");
|
REQUIRE(clause == "(\"age\" <> 7 AND \"name\" IN (SELECT \"name\" FROM \"test\"))");
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +106,7 @@ TEST_CASE_METHOD(ConditionFixture, "Test between condition", "[condition][betwee
|
||||||
TEST_CASE_METHOD(ConditionFixture, "Test like condition", "[condition][like]") {
|
TEST_CASE_METHOD(ConditionFixture, "Test like condition", "[condition][like]") {
|
||||||
const auto name_col = "name"_col;
|
const auto name_col = "name"_col;
|
||||||
|
|
||||||
auto cond = like(name_col, "%er%");
|
auto cond = like_old(name_col, "%er%");
|
||||||
auto clause = cond.evaluate(dlc, ctx);
|
auto clause = cond.evaluate(dlc, ctx);
|
||||||
REQUIRE(clause == "\"name\" LIKE '%er%'");
|
REQUIRE(clause == "\"name\" LIKE '%er%'");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include "matador/query/criteria.hpp"
|
||||||
|
#include "matador/query/criteria_evaluator.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/dialect_builder.hpp"
|
||||||
|
#include "matador/sql/query_context.hpp"
|
||||||
|
|
||||||
|
#include "matador/utils/placeholder.hpp"
|
||||||
|
|
||||||
|
using namespace matador::sql;
|
||||||
|
using namespace matador::query;
|
||||||
|
using namespace matador::utils;
|
||||||
|
|
||||||
|
class CriteriaFixture {
|
||||||
|
protected:
|
||||||
|
dialect dlc = dialect_builder::builder()
|
||||||
|
.create()
|
||||||
|
.build();
|
||||||
|
query_context ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(CriteriaFixture, "Test binary criteria", "[criteria][binary]") {
|
||||||
|
const auto name_col = "name"_col;
|
||||||
|
|
||||||
|
REQUIRE(name_col.name == "name");
|
||||||
|
|
||||||
|
auto clause = name_col != "george";
|
||||||
|
|
||||||
|
criteria_evaluator evaluator(dlc, ctx);
|
||||||
|
auto str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "\"name\" <> 'george'");
|
||||||
|
|
||||||
|
clause = "age"_col != 9;
|
||||||
|
str = evaluator.evaluate(*clause);
|
||||||
|
REQUIRE(str == "\"age\" <> 9");
|
||||||
|
|
||||||
|
clause = "age"_col != _;
|
||||||
|
str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "\"age\" <> ?");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(CriteriaFixture, "Test not criteria", "[criteria][not]") {
|
||||||
|
const auto name_col = "name"_col;
|
||||||
|
auto clause = !(name_col == "Hans");
|
||||||
|
|
||||||
|
criteria_evaluator evaluator(dlc, ctx);
|
||||||
|
auto str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "NOT (\"name\" = 'Hans')");
|
||||||
|
|
||||||
|
clause = !(name_col == _);
|
||||||
|
str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "NOT (\"name\" = ?)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(CriteriaFixture, "Test in criteria", "[criteria][in]") {
|
||||||
|
const auto age_col = "age"_col;
|
||||||
|
auto clause = age_col != 7 && in(age_col, {7,5,5,8});
|
||||||
|
|
||||||
|
criteria_evaluator evaluator(dlc, ctx);
|
||||||
|
auto str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "(\"age\" <> 7 AND \"age\" IN (7, 5, 5, 8))");
|
||||||
|
|
||||||
|
clause = age_col != 7 && in(age_col, {_, _, _});
|
||||||
|
str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "(\"age\" <> 7 AND \"age\" IN (?, ?, ?))");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(CriteriaFixture, "Test in query criteria", "[criteria][in query]") {
|
||||||
|
const auto age_col = "age"_col;
|
||||||
|
const auto name_col = "name"_col;
|
||||||
|
|
||||||
|
query_context sub_ctx;
|
||||||
|
sub_ctx.sql = R"(SELECT "name" FROM "test")";
|
||||||
|
|
||||||
|
auto clause = age_col != 7 && in(name_col, std::move(sub_ctx));
|
||||||
|
}
|
||||||
|
TEST_CASE_METHOD(CriteriaFixture, "Test out criteria", "[criteria][out]") {
|
||||||
|
const auto age_col = "age"_col;
|
||||||
|
auto clause = age_col != 7 && out(age_col, {7,5,5,8});
|
||||||
|
|
||||||
|
criteria_evaluator evaluator(dlc, ctx);
|
||||||
|
auto str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "(\"age\" <> 7 AND \"age\" NOT IN (7, 5, 5, 8))");
|
||||||
|
|
||||||
|
clause = age_col != 7 && out(age_col, {_, _, _});
|
||||||
|
str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "(\"age\" <> 7 AND \"age\" NOT IN (?, ?, ?))");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(CriteriaFixture, "Test between criteria", "[criteria][between]") {
|
||||||
|
const auto age_col = "age"_col;
|
||||||
|
auto clause = age_col != 7 || between(age_col, 21, 30);
|
||||||
|
|
||||||
|
criteria_evaluator evaluator(dlc, ctx);
|
||||||
|
auto str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "(\"age\" <> 7 OR \"age\" BETWEEN 21 AND 30)");
|
||||||
|
|
||||||
|
clause = age_col != 7 || between(age_col, _, _);
|
||||||
|
str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "(\"age\" <> 7 OR \"age\" BETWEEN ? AND ?)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(CriteriaFixture, "Test like criteria", "[criteria][like]") {
|
||||||
|
const auto name_col = "name"_col;
|
||||||
|
const auto clause = like(name_col, "%er%");
|
||||||
|
|
||||||
|
criteria_evaluator evaluator(dlc, ctx);
|
||||||
|
auto str = evaluator.evaluate(*clause);
|
||||||
|
|
||||||
|
REQUIRE(str == "\"name\" LIKE '%er%'");
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue