diff --git a/backends/postgres/test/CMakeLists.txt b/backends/postgres/test/CMakeLists.txt index 29dcd44..96bcda9 100644 --- a/backends/postgres/test/CMakeLists.txt +++ b/backends/postgres/test/CMakeLists.txt @@ -3,7 +3,7 @@ CPMAddPackage("gh:catchorg/Catch2@3.7.1") list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) #set(POSTGRES_CONNECTION_STRING "postgres://news:news@127.0.0.1:15432/matador") -set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:15442/matador") +set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:5432/matador") configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE) diff --git a/include/matador/query/criteria.hpp b/include/matador/query/criteria.hpp new file mode 100644 index 0000000..f58ce6e --- /dev/null +++ b/include/matador/query/criteria.hpp @@ -0,0 +1,13 @@ +#ifndef CRITERIA_CRITERIA_HPP +#define CRITERIA_CRITERIA_HPP + +#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" + +#include "matador/query/criteria/criteria_operators.hpp" + +#endif //CRITERIA_CRITERIA_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/abstract_criteria.hpp b/include/matador/query/criteria/abstract_criteria.hpp new file mode 100644 index 0000000..5c5f549 --- /dev/null +++ b/include/matador/query/criteria/abstract_criteria.hpp @@ -0,0 +1,20 @@ +#ifndef CRITERIA_CRITERIA_NODE_HPP +#define CRITERIA_CRITERIA_NODE_HPP + +#include + +namespace matador::query { + +class criteria_visitor; + +class abstract_criteria { +public: + virtual ~abstract_criteria() = default; + + virtual void accept(criteria_visitor& visitor) const = 0; +}; + +using criteria_ptr = std::unique_ptr; + +} +#endif //CRITERIA_CRITERIA_NODE_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/between_criteria.hpp b/include/matador/query/criteria/between_criteria.hpp new file mode 100644 index 0000000..f79baaa --- /dev/null +++ b/include/matador/query/criteria/between_criteria.hpp @@ -0,0 +1,25 @@ +#ifndef CRITERIA_BETWEEN_CRITERIA_NODE_HPP +#define CRITERIA_BETWEEN_CRITERIA_NODE_HPP + +#include "matador/query/criteria/abstract_criteria.hpp" + +#include "matador/sql/column.hpp" + +#include "matador/utils/value.hpp" + +namespace matador::query { + +class between_criteria final : public abstract_criteria { +public: + between_criteria() = delete; + between_criteria(sql::column column, utils::value min, utils::value max); + + void accept(criteria_visitor& visitor) const override; + +private: + sql::column column_; + utils::value min_; + utils::value max_; +}; +} +#endif //CRITERIA_BETWEEN_CRITERIA_NODE_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/binary_criteria.hpp b/include/matador/query/criteria/binary_criteria.hpp new file mode 100644 index 0000000..d872a72 --- /dev/null +++ b/include/matador/query/criteria/binary_criteria.hpp @@ -0,0 +1,33 @@ +#ifndef CRITERIA_BINARY_CRITERIA_NODE_HPP +#define CRITERIA_BINARY_CRITERIA_NODE_HPP + +#include "matador/query/criteria/abstract_criteria.hpp" + +#include "matador/sql/column.hpp" + +#include "matador/utils/value.hpp" + +namespace matador::query { +enum class binary_operator { + EQUALS, + NOT_EQUALS, + GREATER_THAN, + GREATER_THAN_OR_EQUAL, + LESS_THAN, + LESS_THAN_OR_EQUAL, +}; + +class binary_criteria final : public abstract_criteria { +public: + binary_criteria() = delete; + binary_criteria( sql::column column, binary_operator operator_, utils::value value ); + + void accept( criteria_visitor& visitor ) const override; + +private: + sql::column column_; + binary_operator operator_{}; + utils::value value_; +}; +} +#endif //CRITERIA_BINARY_CRITERIA_NODE_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/collection_criteria.hpp b/include/matador/query/criteria/collection_criteria.hpp new file mode 100644 index 0000000..53f3c0c --- /dev/null +++ b/include/matador/query/criteria/collection_criteria.hpp @@ -0,0 +1,29 @@ +#ifndef CRITERIA_COLLECTION_CRITERIA_NODE_HPP +#define CRITERIA_COLLECTION_CRITERIA_NODE_HPP + +#include "matador/query/criteria/abstract_criteria.hpp" + +#include "matador/sql/column.hpp" + +#include "matador/utils/value.hpp" + +namespace matador::query { +enum class collection_operator { + IN, + OUT +}; + +class collection_criteria final : public abstract_criteria { +public: + collection_criteria() = delete; + collection_criteria(sql::column col, collection_operator operator_, std::vector values); + collection_criteria(sql::column col, collection_operator operator_, std::initializer_list values); + + void accept(criteria_visitor& visitor) const override; +private: + sql::column column_; + collection_operator operator_; + std::vector values_; +}; +} +#endif //CRITERIA_COLLECTION_CRITERIA_NODE_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/criteria_operators.hpp b/include/matador/query/criteria/criteria_operators.hpp new file mode 100644 index 0000000..7ac98f8 --- /dev/null +++ b/include/matador/query/criteria/criteria_operators.hpp @@ -0,0 +1,72 @@ +#ifndef CRITERIA_CRITERIA_OPERATORS_HPP +#define CRITERIA_CRITERIA_OPERATORS_HPP + +#include "matador/query/criteria/binary_criteria.hpp" +#include "matador/query/criteria/collection_criteria.hpp" + +#include "matador/sql/column.hpp" + +#include "matador/utils/value.hpp" + +namespace matador::query { + +template +criteria_ptr operator==(const sql::column &col, Type val) { + return std::make_unique(col, binary_operator::EQUALS, val); +} + +template +criteria_ptr operator!=(const sql::column &col, Type val) { + return std::make_unique(col, binary_operator::NOT_EQUALS, val); +} + +template +criteria_ptr operator>(const sql::column &col, Type val) { + return std::make_unique(col, binary_operator::GREATER_THAN, val); +} + +template +criteria_ptr operator>=(const sql::column &col, Type val) { + return std::make_unique(col, binary_operator::GREATER_THAN_OR_EQUAL, val); +} + +template +criteria_ptr operator<(const sql::column &col, Type val) { + return std::make_unique(col, binary_operator::LESS_THAN, val); +} + +template +criteria_ptr operator<=(const sql::column &col, Type val) { + return std::make_unique(col, binary_operator::LESS_THAN_OR_EQUAL, val); +} + +criteria_ptr operator&&(criteria_ptr left, criteria_ptr right); + +criteria_ptr operator||(criteria_ptr left, criteria_ptr right); + +criteria_ptr operator!(criteria_ptr clause); + +template < class Type > +criteria_ptr in(const sql::column &col, std::initializer_list args) { + std::vector values; + for ( auto &&arg : args ) { + values.emplace_back(std::move(arg)); + } + return std::make_unique(col, collection_operator::IN, std::move(values)); +} + +template < class V > +criteria_ptr out(const sql::column &col, std::initializer_list args) { + std::vector values; + for ( auto &&arg : args ) { + values.emplace_back(std::move(arg)); + } + return std::make_unique(col, collection_operator::OUT, values); +} + +criteria_ptr between(const sql::column &col, utils::value min, utils::value max); + +criteria_ptr like(const sql::column &col, const std::string &pattern); + +} +#endif //CRITERIA_CRITERIA_OPERATORS_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/criteria_visitor.hpp b/include/matador/query/criteria/criteria_visitor.hpp new file mode 100644 index 0000000..6585096 --- /dev/null +++ b/include/matador/query/criteria/criteria_visitor.hpp @@ -0,0 +1,24 @@ +#ifndef CRITERIA_CRITERIA_NODE_VISITOR_HPP +#define CRITERIA_CRITERIA_NODE_VISITOR_HPP + +namespace matador::query { +class between_criteria; +class binary_criteria; +class like_criteria; +class logical_criteria; +class not_criteria; +class collection_criteria; + +class criteria_visitor { +public: + virtual ~criteria_visitor() = default; + + virtual void visit(const between_criteria &node) = 0; + virtual void visit(const binary_criteria &node) = 0; + virtual void visit(const collection_criteria &node) = 0; + virtual void visit(const like_criteria &node) = 0; + virtual void visit(const logical_criteria &node) = 0; + virtual void visit(const not_criteria &node) = 0; +}; +} +#endif //CRITERIA_CRITERIA_NODE_VISITOR_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/like_criteria.hpp b/include/matador/query/criteria/like_criteria.hpp new file mode 100644 index 0000000..b439723 --- /dev/null +++ b/include/matador/query/criteria/like_criteria.hpp @@ -0,0 +1,21 @@ +#ifndef CRITERIA_LIKE_CRITERIA_NODE_HPP +#define CRITERIA_LIKE_CRITERIA_NODE_HPP + +#include "matador/query/criteria/abstract_criteria.hpp" + +#include "matador/sql/column.hpp" + +namespace matador::query { +class like_criteria final : public abstract_criteria { +public: + like_criteria() = delete; + like_criteria(sql::column column, std::string pattern); + + void accept(criteria_visitor &visitor) const override; + +private: + sql::column column_; + std::string pattern_; +}; +} +#endif //CRITERIA_LIKE_CRITERIA_NODE_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/logical_criteria.hpp b/include/matador/query/criteria/logical_criteria.hpp new file mode 100644 index 0000000..ec63851 --- /dev/null +++ b/include/matador/query/criteria/logical_criteria.hpp @@ -0,0 +1,25 @@ +#ifndef CRITERIA_LOGICAL_CRITERIA_NODE_HPP +#define CRITERIA_LOGICAL_CRITERIA_NODE_HPP + +#include "matador/query/criteria/abstract_criteria.hpp" + +namespace matador::query { +enum class logical_operator { + AND, + OR, +}; + +class logical_criteria final : public abstract_criteria { +public: + logical_criteria() = delete; + logical_criteria(criteria_ptr left, logical_operator op, criteria_ptr right); + + void accept(criteria_visitor& visitor) const override; + +private: + std::unique_ptr left_criteria_; + logical_operator operand_; + std::unique_ptr right_criteria_; +}; +} +#endif //CRITERIA_LOGICAL_CRITERIA_NODE_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/not_criteria.hpp b/include/matador/query/criteria/not_criteria.hpp new file mode 100644 index 0000000..b0f583c --- /dev/null +++ b/include/matador/query/criteria/not_criteria.hpp @@ -0,0 +1,18 @@ +#ifndef CRITERIA_NOT_CRITERIA_NODE_HPP +#define CRITERIA_NOT_CRITERIA_NODE_HPP + +#include "matador/query/criteria/abstract_criteria.hpp" + +namespace matador::query { +class not_criteria final : public abstract_criteria { +public: + explicit not_criteria(criteria_ptr clause); + + void accept(criteria_visitor& visitor) const override; + +private: + criteria_ptr criteria_; +}; +} + +#endif //CRITERIA_NOT_CRITERIA_NODE_HPP \ No newline at end of file diff --git a/include/matador/query/criteria_evaluator.hpp b/include/matador/query/criteria_evaluator.hpp new file mode 100644 index 0000000..ddc459c --- /dev/null +++ b/include/matador/query/criteria_evaluator.hpp @@ -0,0 +1,28 @@ +#ifndef MATADOR_CRITERIA_EVALUATOR_HPP +#define MATADOR_CRITERIA_EVALUATOR_HPP + +#include "matador/query/criteria/criteria_visitor.hpp" + +namespace matador::sql { +class dialect; +struct query_context; +} + +namespace matador::query { + +class criteria_evaluator final : public criteria_visitor { +public: + criteria_evaluator(const sql::dialect &d, sql::query_context &query); + void visit(const between_criteria &node) override; + void visit(const binary_criteria &node) override; + void visit(const collection_criteria &node) override; + void visit(const like_criteria &node) override; + void visit(const logical_criteria &node) override; + void visit(const not_criteria &node) override; + +private: + const sql::dialect &dialect_; + sql::query_context &query_; +}; +} +#endif //MATADOR_CRITERIA_EVALUATOR_HPP \ No newline at end of file diff --git a/source/orm/CMakeLists.txt b/source/orm/CMakeLists.txt index 9725edc..39d106d 100644 --- a/source/orm/CMakeLists.txt +++ b/source/orm/CMakeLists.txt @@ -6,6 +6,14 @@ add_library(matador-orm STATIC ../../include/matador/orm/session_query_builder.hpp ../../include/matador/query/attribute_string_writer.hpp ../../include/matador/query/basic_condition.hpp + ../../include/matador/query/criteria/abstract_criteria.hpp + ../../include/matador/query/criteria/between_criteria.hpp + ../../include/matador/query/criteria/collection_criteria.hpp + ../../include/matador/query/criteria.hpp + ../../include/matador/query/criteria/criteria_operators.hpp + ../../include/matador/query/criteria/criteria_visitor.hpp + ../../include/matador/query/criteria/like_criteria.hpp + ../../include/matador/query/criteria/logical_criteria.hpp ../../include/matador/query/condition.hpp ../../include/matador/query/fk_value_extractor.hpp ../../include/matador/query/intermediates/executable_query.hpp @@ -78,6 +86,13 @@ add_library(matador-orm STATIC orm/session_query_builder.cpp query/attribute_string_writer.cpp query/basic_condition.cpp + query/criteria/between_criteria.cpp + query/criteria/binary_criteria.cpp + query/criteria/collection_criteria.cpp + query/criteria/criteria_operators.cpp + query/criteria/like_criteria.cpp + query/criteria/logical_criteria.cpp + query/criteria/not_criteria.cpp query/condition.cpp query/intermediates/executable_query.cpp query/intermediates/fetchable_query.cpp @@ -136,6 +151,8 @@ add_library(matador-orm STATIC sql/statement.cpp sql/statement_cache.cpp sql/table.cpp + ../../include/matador/query/criteria_evaluator.hpp + query/criteria_evaluator.cpp ) target_include_directories(matador-orm diff --git a/source/orm/query/criteria/between_criteria.cpp b/source/orm/query/criteria/between_criteria.cpp new file mode 100644 index 0000000..92bf65c --- /dev/null +++ b/source/orm/query/criteria/between_criteria.cpp @@ -0,0 +1,15 @@ +#include "matador/query/criteria/between_criteria.hpp" + +#include "matador/query/criteria/criteria_visitor.hpp" + +namespace matador::query{ +between_criteria::between_criteria(sql::column column, utils::value min, utils::value max ) +: column_(std::move(column)) +, min_(std::move(min)) +, max_(std::move(max)) +{} + +void between_criteria::accept( criteria_visitor& visitor ) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/source/orm/query/criteria/binary_criteria.cpp b/source/orm/query/criteria/binary_criteria.cpp new file mode 100644 index 0000000..0564057 --- /dev/null +++ b/source/orm/query/criteria/binary_criteria.cpp @@ -0,0 +1,15 @@ +#include "matador/query/criteria/binary_criteria.hpp" + +#include "matador/query/criteria/criteria_visitor.hpp" + +namespace matador::query { +binary_criteria::binary_criteria(sql::column column, const binary_operator operator_, utils::value value) +: column_(std::move(column)) +, operator_(operator_) +, value_(std::move(value)) +{} + +void binary_criteria::accept( criteria_visitor& visitor ) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/source/orm/query/criteria/collection_criteria.cpp b/source/orm/query/criteria/collection_criteria.cpp new file mode 100644 index 0000000..02490f9 --- /dev/null +++ b/source/orm/query/criteria/collection_criteria.cpp @@ -0,0 +1,21 @@ +#include "matador/query/criteria/collection_criteria.hpp" + +#include "matador/query/criteria/criteria_visitor.hpp" + +namespace matador::query { +collection_criteria::collection_criteria(sql::column col, collection_operator operator_, std::vector values ) +: column_(std::move(col)) +, operator_(operator_) +, values_(std::move(values)) +{} + +collection_criteria::collection_criteria(sql::column col, const collection_operator operator_, const std::initializer_list values ) +: column_(std::move(col)) +, operator_(operator_) +, values_(values) +{} + +void collection_criteria::accept( criteria_visitor& visitor ) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/source/orm/query/criteria/criteria_operators.cpp b/source/orm/query/criteria/criteria_operators.cpp new file mode 100644 index 0000000..a8aba16 --- /dev/null +++ b/source/orm/query/criteria/criteria_operators.cpp @@ -0,0 +1,28 @@ +#include "matador/query/criteria/criteria_operators.hpp" + +#include "matador/query/criteria/between_criteria.hpp" +#include "matador/query/criteria/like_criteria.hpp" +#include "matador/query/criteria/logical_criteria.hpp" +#include "matador/query/criteria/not_criteria.hpp" + +namespace matador::query { +criteria_ptr operator&&(criteria_ptr left, criteria_ptr right) { + return std::make_unique(std::move(left), logical_operator::AND, std::move(right)); +} + +criteria_ptr operator||(criteria_ptr left, criteria_ptr right) { + return std::make_unique(std::move(left), logical_operator::OR, std::move(right)); +} + +criteria_ptr operator!(criteria_ptr clause) { + return std::make_unique(std::move(clause)); +} + +criteria_ptr between(const sql::column &col, utils::value min, utils::value max) { + return std::make_unique(col, std::move(min), std::move(max)); +} + +criteria_ptr like(const sql::column &col, const std::string &pattern) { + return std::make_unique(col, pattern); +} +} diff --git a/source/orm/query/criteria/like_criteria.cpp b/source/orm/query/criteria/like_criteria.cpp new file mode 100644 index 0000000..6ec85e4 --- /dev/null +++ b/source/orm/query/criteria/like_criteria.cpp @@ -0,0 +1,13 @@ +#include "matador/query/criteria/like_criteria.hpp" + +#include "matador/query/criteria/criteria_visitor.hpp" + +namespace matador::query { +like_criteria::like_criteria(sql::column column, std::string pattern) +: column_(std::move(column)) +, pattern_(std::move(pattern)){} + +void like_criteria::accept(criteria_visitor &visitor) const { + visitor.visit(*this); +} +} diff --git a/source/orm/query/criteria/logical_criteria.cpp b/source/orm/query/criteria/logical_criteria.cpp new file mode 100644 index 0000000..88e33a3 --- /dev/null +++ b/source/orm/query/criteria/logical_criteria.cpp @@ -0,0 +1,15 @@ +#include "matador/query/criteria/logical_criteria.hpp" + +#include "matador/query/criteria/criteria_visitor.hpp" + +namespace matador::query { +logical_criteria::logical_criteria(criteria_ptr left, const logical_operator op, criteria_ptr right) +: left_criteria_(std::move(left)) +, operand_(op) +, right_criteria_(std::move(right)) +{} + +void logical_criteria::accept(criteria_visitor& visitor) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/source/orm/query/criteria/not_criteria.cpp b/source/orm/query/criteria/not_criteria.cpp new file mode 100644 index 0000000..5fb1156 --- /dev/null +++ b/source/orm/query/criteria/not_criteria.cpp @@ -0,0 +1,13 @@ +#include "matador/query/criteria/not_criteria.hpp" + +#include "matador/query/criteria/criteria_visitor.hpp" + +namespace matador::query { +not_criteria::not_criteria(criteria_ptr clause) +: criteria_(std::move(clause)) +{} + +void not_criteria::accept(criteria_visitor& visitor) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/source/orm/query/criteria_evaluator.cpp b/source/orm/query/criteria_evaluator.cpp new file mode 100644 index 0000000..ed931a5 --- /dev/null +++ b/source/orm/query/criteria_evaluator.cpp @@ -0,0 +1,25 @@ +#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) {} + +void criteria_evaluator::visit(const between_criteria &node) { +} + +void criteria_evaluator::visit(const binary_criteria &node) { +} + +void criteria_evaluator::visit(const collection_criteria &node) { +} + +void criteria_evaluator::visit(const like_criteria &node) { +} + +void criteria_evaluator::visit(const logical_criteria &node) { +} + +void criteria_evaluator::visit(const not_criteria &node) { +} +} diff --git a/source/orm/sql/column.cpp b/source/orm/sql/column.cpp index 128945f..6c7339c 100644 --- a/source/orm/sql/column.cpp +++ b/source/orm/sql/column.cpp @@ -1,13 +1,25 @@ +#include "matador/sql/column.hpp" + +#include "matador/sql/table.hpp" + +#include #include -#include "matador/sql/column.hpp" -#include "matador/sql/table.hpp" namespace matador::sql { -column operator ""_col(const char *name, size_t len) -{ - return column{{name, len}}; +column operator ""_col(const char *name, size_t len) { + const std::string str(name, len); + const auto pos = str.find('.'); + if (pos == std::string::npos) { + return column{str}; + } + + if (str.find('.', pos + 1) != std::string::npos) { + throw std::invalid_argument("Invalid column name: multiple dots found"); + } + + return column{str.substr(0, pos), str.substr(pos + 1)}; } column::column(const char *name, const std::string& as)