From 6ffa9de6d05a65d675383a24202bf15eb4173256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Fri, 17 Oct 2025 15:51:35 +0200 Subject: [PATCH] initial commit --- .gitignore | 1 + CMakeLists.txt | 7 ++ .../condition/between_condition_node.hpp | 23 +++++++ .../condition/binary_condition_node.hpp | 31 +++++++++ .../condition/collection_condition_node.hpp | 27 ++++++++ include/matador/condition/column.hpp | 23 +++++++ include/matador/condition/condition_node.hpp | 20 ++++++ .../condition/condition_node_visitor.hpp | 22 +++++++ .../matador/condition/condition_operators.hpp | 65 +++++++++++++++++++ .../condition/logical_condition_node.hpp | 25 +++++++ .../matador/condition/not_condition_node.hpp | 18 +++++ include/matador/condition/types.hpp | 23 +++++++ include/matador/condition/value.hpp | 41 ++++++++++++ src/CMakeLists.txt | 26 ++++++++ src/condition/between_condition_node.cpp | 15 +++++ src/condition/binary_condition_node.cpp | 15 +++++ src/condition/collection_condition_node.cpp | 21 ++++++ src/condition/column.cpp | 36 ++++++++++ src/condition/condition_operators.cpp | 19 ++++++ src/condition/logical_condition_node.cpp | 15 +++++ src/condition/not_condition_node.cpp | 13 ++++ src/main.cpp | 20 ++++++ 22 files changed, 506 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 include/matador/condition/between_condition_node.hpp create mode 100644 include/matador/condition/binary_condition_node.hpp create mode 100644 include/matador/condition/collection_condition_node.hpp create mode 100644 include/matador/condition/column.hpp create mode 100644 include/matador/condition/condition_node.hpp create mode 100644 include/matador/condition/condition_node_visitor.hpp create mode 100644 include/matador/condition/condition_operators.hpp create mode 100644 include/matador/condition/logical_condition_node.hpp create mode 100644 include/matador/condition/not_condition_node.hpp create mode 100644 include/matador/condition/types.hpp create mode 100644 include/matador/condition/value.hpp create mode 100644 src/CMakeLists.txt create mode 100644 src/condition/between_condition_node.cpp create mode 100644 src/condition/binary_condition_node.cpp create mode 100644 src/condition/collection_condition_node.cpp create mode 100644 src/condition/column.cpp create mode 100644 src/condition/condition_operators.cpp create mode 100644 src/condition/logical_condition_node.cpp create mode 100644 src/condition/not_condition_node.cpp create mode 100644 src/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62c8935 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f8a2280 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 4.0) +project(condition) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +add_subdirectory(src) diff --git a/include/matador/condition/between_condition_node.hpp b/include/matador/condition/between_condition_node.hpp new file mode 100644 index 0000000..201cb67 --- /dev/null +++ b/include/matador/condition/between_condition_node.hpp @@ -0,0 +1,23 @@ +#ifndef CONDITION_BETWEEN_CONDITION_NODE_HPP +#define CONDITION_BETWEEN_CONDITION_NODE_HPP + +#include "column.hpp" +#include "condition_node.hpp" +#include "value.hpp" + +namespace matador::condition { + +class between_condition_node final : public condition_node { +public: + between_condition_node() = delete; + between_condition_node(column column, value min, value max); + + void accept(condition_node_visitor& visitor) const override; + +private: + column column_; + value min_; + value max_; +}; +} +#endif //CONDITION_BETWEEN_CONDITION_NODE_HPP \ No newline at end of file diff --git a/include/matador/condition/binary_condition_node.hpp b/include/matador/condition/binary_condition_node.hpp new file mode 100644 index 0000000..1e511d4 --- /dev/null +++ b/include/matador/condition/binary_condition_node.hpp @@ -0,0 +1,31 @@ +#ifndef CONDITION_BINARY_CONDITION_NODE_HPP +#define CONDITION_BINARY_CONDITION_NODE_HPP + +#include "matador/condition/condition_node.hpp" +#include "matador/condition/column.hpp" +#include "matador/condition/value.hpp" + +namespace matador::condition { +enum class binary_operator { + EQUALS, + NOT_EQUALS, + GREATER_THAN, + GREATER_THAN_OR_EQUAL, + LESS_THAN, + LESS_THAN_OR_EQUAL, +}; + +class binary_condition_node final : public condition_node { +public: + binary_condition_node() = delete; + binary_condition_node( column column, binary_operator operator_, value value ); + + void accept( condition_node_visitor& visitor ) const override; + +private: + column column_; + binary_operator operator_{}; + value value_; +}; +} +#endif //CONDITION_BINARY_CONDITION_NODE_HPP \ No newline at end of file diff --git a/include/matador/condition/collection_condition_node.hpp b/include/matador/condition/collection_condition_node.hpp new file mode 100644 index 0000000..d58e4bd --- /dev/null +++ b/include/matador/condition/collection_condition_node.hpp @@ -0,0 +1,27 @@ +#ifndef CONDITION_COLLECTION_CONDITION_NODE_HPP +#define CONDITION_COLLECTION_CONDITION_NODE_HPP + +#include "column.hpp" +#include "condition_node.hpp" +#include "value.hpp" + +namespace matador::condition { +enum class collection_operator { + IN, + OUT +}; + +class collection_condition_node final : public condition_node { +public: + collection_condition_node() = delete; + collection_condition_node(column col, collection_operator operator_, std::vector values); + collection_condition_node(column col, collection_operator operator_, std::initializer_list values); + + void accept(condition_node_visitor& visitor) const override; +private: + column column_; + collection_operator operator_; + std::vector values_; +}; +} +#endif //CONDITION_COLLECTION_CONDITION_NODE_HPP \ No newline at end of file diff --git a/include/matador/condition/column.hpp b/include/matador/condition/column.hpp new file mode 100644 index 0000000..fb9abd0 --- /dev/null +++ b/include/matador/condition/column.hpp @@ -0,0 +1,23 @@ +#ifndef CONDITION_COLUMN_HPP +#define CONDITION_COLUMN_HPP + +#include + +namespace matador::condition { +class column { +public: + explicit column(std::string name); + explicit column(std::string table_name, std::string name); + + [[nodiscard]] const std::string& table() const; + [[nodiscard]] const std::string& name() const; + +private: + std::string table_{}; + std::string name_{}; +}; + +column operator ""_col(const char *name, size_t len); + +} +#endif //CONDITION_COLUMN_HPP \ No newline at end of file diff --git a/include/matador/condition/condition_node.hpp b/include/matador/condition/condition_node.hpp new file mode 100644 index 0000000..c119cef --- /dev/null +++ b/include/matador/condition/condition_node.hpp @@ -0,0 +1,20 @@ +#ifndef CONDITION_CONDITION_NODE_HPP +#define CONDITION_CONDITION_NODE_HPP + +#include + +namespace matador::condition { + +class condition_node_visitor; + +class condition_node { +public: + virtual ~condition_node() = default; + + virtual void accept(condition_node_visitor& visitor) const = 0; +}; + +using condition_node_ptr = std::unique_ptr; + +} +#endif //CONDITION_CONDITION_NODE_HPP \ No newline at end of file diff --git a/include/matador/condition/condition_node_visitor.hpp b/include/matador/condition/condition_node_visitor.hpp new file mode 100644 index 0000000..65dfcea --- /dev/null +++ b/include/matador/condition/condition_node_visitor.hpp @@ -0,0 +1,22 @@ +#ifndef CONDITION_CONDITION_NODE_VISITOR_HPP +#define CONDITION_CONDITION_NODE_VISITOR_HPP + +namespace matador::condition { +class between_condition_node; +class binary_condition_node; +class logical_condition_node; +class not_condition_node; +class collection_condition_node; + +class condition_node_visitor { +public: + virtual ~condition_node_visitor() = default; + + virtual void visit(const between_condition_node &node) = 0; + virtual void visit(const binary_condition_node &node) = 0; + virtual void visit(const collection_condition_node &node) = 0; + virtual void visit(const logical_condition_node &node) = 0; + virtual void visit(const not_condition_node &node) = 0; +}; +} +#endif //CONDITION_CONDITION_NODE_VISITOR_HPP \ No newline at end of file diff --git a/include/matador/condition/condition_operators.hpp b/include/matador/condition/condition_operators.hpp new file mode 100644 index 0000000..813a4fe --- /dev/null +++ b/include/matador/condition/condition_operators.hpp @@ -0,0 +1,65 @@ +#ifndef CONDITION_CONDITION_OPERATORS_HPP +#define CONDITION_CONDITION_OPERATORS_HPP + +#include "matador/condition/binary_condition_node.hpp" +#include "matador/condition/collection_condition_node.hpp" +#include "matador/condition/column.hpp" + +namespace matador::condition { + +template +condition_node_ptr operator==(const column &col, Type val) { + return std::make_unique(col, binary_operator::EQUALS, val); +} + +template +condition_node_ptr operator!=(const column &col, Type val) { + return std::make_unique(col, binary_operator::NOT_EQUALS, val); +} + +template +condition_node_ptr operator>(const column &col, Type val) { + return std::make_unique(col, binary_operator::GREATER_THAN, val); +} + +template +condition_node_ptr operator>=(const column &col, Type val) { + return std::make_unique(col, binary_operator::GREATER_THAN_OR_EQUAL, val); +} + +template +condition_node_ptr operator<(const column &col, Type val) { + return std::make_unique(col, binary_operator::LESS_THAN, val); +} + +template +condition_node_ptr operator<=(const column &col, Type val) { + return std::make_unique(col, binary_operator::LESS_THAN_OR_EQUAL, val); +} + +condition_node_ptr operator&&(condition_node_ptr left, condition_node_ptr right); + +condition_node_ptr operator||(condition_node_ptr left, condition_node_ptr right); + +condition_node_ptr operator!(condition_node_ptr cond); + +template < class Type > +condition_node_ptr in(const 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 > +condition_node_ptr out(const 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); +} + +} +#endif //CONDITION_CONDITION_OPERATORS_HPP \ No newline at end of file diff --git a/include/matador/condition/logical_condition_node.hpp b/include/matador/condition/logical_condition_node.hpp new file mode 100644 index 0000000..fc5ee28 --- /dev/null +++ b/include/matador/condition/logical_condition_node.hpp @@ -0,0 +1,25 @@ +#ifndef CONDITION_LOGICAL_CONDITION_NODE_HPP +#define CONDITION_LOGICAL_CONDITION_NODE_HPP + +#include "condition_node.hpp" + +namespace matador::condition { +enum class logical_operator { + AND, + OR, +}; + +class logical_condition_node final : public condition_node { +public: + logical_condition_node() = delete; + logical_condition_node(condition_node_ptr left, logical_operator op, condition_node_ptr right); + + void accept(condition_node_visitor& visitor) const override; + +private: + std::unique_ptr left_; + logical_operator op_; + std::unique_ptr right_; +}; +} +#endif //CONDITION_LOGICAL_CONDITION_NODE_HPP \ No newline at end of file diff --git a/include/matador/condition/not_condition_node.hpp b/include/matador/condition/not_condition_node.hpp new file mode 100644 index 0000000..df0f3df --- /dev/null +++ b/include/matador/condition/not_condition_node.hpp @@ -0,0 +1,18 @@ +#ifndef CONDITION_NOT_CONDITION_NODE_HPP +#define CONDITION_NOT_CONDITION_NODE_HPP + +#include "matador/condition/condition_node.hpp" + +namespace matador::condition { +class not_condition_node final : public condition_node { +public: + not_condition_node(condition_node_ptr condition); + + void accept(condition_node_visitor& visitor) const override; + +private: + condition_node_ptr condition_; +}; +} + +#endif //CONDITION_NOT_CONDITION_NODE_HPP \ No newline at end of file diff --git a/include/matador/condition/types.hpp b/include/matador/condition/types.hpp new file mode 100644 index 0000000..9d413d8 --- /dev/null +++ b/include/matador/condition/types.hpp @@ -0,0 +1,23 @@ +#ifndef CONDITION_TYPES_HPP +#define CONDITION_TYPES_HPP + +#include +#include +#include + +namespace matador::condition { + +using byte = unsigned char; +using blob = std::vector; + +using basic_types = std::variant< + uint8_t, uint16_t, uint32_t, uint64_t, + int8_t, int16_t, int32_t, int64_t, + float, double, + bool, + const char*, + std::string, + blob, + nullptr_t>; +} +#endif //CONDITION_TYPES_HPP \ No newline at end of file diff --git a/include/matador/condition/value.hpp b/include/matador/condition/value.hpp new file mode 100644 index 0000000..dde9309 --- /dev/null +++ b/include/matador/condition/value.hpp @@ -0,0 +1,41 @@ +#ifndef CONDITION_VALUE_HPP +#define CONDITION_VALUE_HPP + +#include "types.hpp" + +#include + +namespace matador::condition { + +class value final { +public: + value() = default; + template + value(const Type& value) : value_(value) {} + value(const value &x) = default; + value& operator=(const value &x) = default; + value(value &&x) noexcept = default; + value& operator=(value &&x) noexcept = default; + ~value() = default; + + template + std::optional as() const { + if (std::holds_alternative(value_)) { + return std::get(value_); + } + return std::nullopt; + } + + template + bool is() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] std::string str() const; + +private: + basic_types value_; +}; + +} +#endif //CONDITION_VALUE_HPP \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..1aba22a --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,26 @@ +SET(SOURCE + ../include/matador/condition/collection_condition_node.hpp + ../include/matador/condition/column.hpp + ../include/matador/condition/condition_node.hpp + ../include/matador/condition/condition_node_visitor.hpp + ../include/matador/condition/condition_operators.hpp + ../include/matador/condition/logical_condition_node.hpp + ../include/matador/condition/types.hpp + ../include/matador/condition/value.hpp + condition/binary_condition_node.cpp + condition/collection_condition_node.cpp + condition/column.cpp + condition/condition_operators.cpp + condition/not_condition_node.cpp + condition/logical_condition_node.cpp + ../include/matador/condition/between_condition_node.hpp + condition/between_condition_node.cpp +) + +add_library(matador-condition STATIC ${SOURCE}) + +target_include_directories(matador-condition PUBLIC ../include) + +add_executable(main main.cpp) +target_include_directories(main PUBLIC ../include) +target_link_libraries(main matador-condition) diff --git a/src/condition/between_condition_node.cpp b/src/condition/between_condition_node.cpp new file mode 100644 index 0000000..9b89d5c --- /dev/null +++ b/src/condition/between_condition_node.cpp @@ -0,0 +1,15 @@ +#include "matador/condition/between_condition_node.hpp" + +#include "matador/condition/condition_node_visitor.hpp" + +namespace matador::condition { +between_condition_node::between_condition_node( column column, value min, value max ) +: column_(std::move(column)) +, min_(std::move(min)) +, max_(std::move(max)) +{} + +void between_condition_node::accept( condition_node_visitor& visitor ) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/src/condition/binary_condition_node.cpp b/src/condition/binary_condition_node.cpp new file mode 100644 index 0000000..0bf1c59 --- /dev/null +++ b/src/condition/binary_condition_node.cpp @@ -0,0 +1,15 @@ +#include "matador/condition/binary_condition_node.hpp" + +#include "matador/condition/condition_node_visitor.hpp" + +namespace matador::condition { +binary_condition_node::binary_condition_node( column column, const binary_operator operator_, value value ) +: column_(std::move(column)) +, operator_(operator_) +, value_(std::move(value)) +{} + +void binary_condition_node::accept( condition_node_visitor& visitor ) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/src/condition/collection_condition_node.cpp b/src/condition/collection_condition_node.cpp new file mode 100644 index 0000000..67daf71 --- /dev/null +++ b/src/condition/collection_condition_node.cpp @@ -0,0 +1,21 @@ +#include "matador/condition/collection_condition_node.hpp" + +#include "matador/condition/condition_node_visitor.hpp" + +namespace matador::condition { +collection_condition_node::collection_condition_node( column col, collection_operator operator_, std::vector values ) +: column_(std::move(col)) +, operator_(operator_) +, values_(std::move(values)) +{} + +collection_condition_node::collection_condition_node(column col, const collection_operator operator_, const std::initializer_list values ) +: column_(std::move(col)) +, operator_(operator_) +, values_(values) +{} + +void collection_condition_node::accept( condition_node_visitor& visitor ) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/src/condition/column.cpp b/src/condition/column.cpp new file mode 100644 index 0000000..9ea9182 --- /dev/null +++ b/src/condition/column.cpp @@ -0,0 +1,36 @@ +#include "matador/condition/column.hpp" + +#include + +namespace matador::condition { + +column::column( std::string name ) +: name_(std::move(name)) {} + +column::column( std::string table_name, std::string name ) +: table_(std::move(table_name)) +, name_(std::move(name)){} + +const std::string& column::table() const { + return table_; +} + +const std::string& column::name() const { + return name_; +} + +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) { + // Invalid: more than one dot + throw std::invalid_argument("Invalid column name: multiple dots found"); + } + + return column{str.substr(0, pos), str.substr(pos + 1)}; +} +} \ No newline at end of file diff --git a/src/condition/condition_operators.cpp b/src/condition/condition_operators.cpp new file mode 100644 index 0000000..748f37b --- /dev/null +++ b/src/condition/condition_operators.cpp @@ -0,0 +1,19 @@ +#include "matador/condition/condition_operators.hpp" + +#include "matador/condition/logical_condition_node.hpp" +#include "matador/condition/not_condition_node.hpp" + +namespace matador::condition { +condition_node_ptr operator&&(condition_node_ptr left, condition_node_ptr right) { + return std::make_unique(std::move(left), logical_operator::AND, std::move(right)); +} + +condition_node_ptr operator||(condition_node_ptr left, condition_node_ptr right) { + return std::make_unique(std::move(left), logical_operator::OR, std::move(right)); +} + +condition_node_ptr operator!(condition_node_ptr cond) { + return std::make_unique(std::move(cond)); +} + +} \ No newline at end of file diff --git a/src/condition/logical_condition_node.cpp b/src/condition/logical_condition_node.cpp new file mode 100644 index 0000000..c19106f --- /dev/null +++ b/src/condition/logical_condition_node.cpp @@ -0,0 +1,15 @@ +#include "matador/condition/logical_condition_node.hpp" + +#include "matador/condition/condition_node_visitor.hpp" + +namespace matador::condition { +logical_condition_node::logical_condition_node( condition_node_ptr left, const logical_operator op, condition_node_ptr right ) +: left_(std::move(left)) +, op_(op) +, right_(std::move(right)) +{} + +void logical_condition_node::accept(condition_node_visitor& visitor) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/src/condition/not_condition_node.cpp b/src/condition/not_condition_node.cpp new file mode 100644 index 0000000..72cd6d9 --- /dev/null +++ b/src/condition/not_condition_node.cpp @@ -0,0 +1,13 @@ +#include "matador/condition/not_condition_node.hpp" + +#include "matador/condition/condition_node_visitor.hpp" + +namespace matador::condition { +not_condition_node::not_condition_node(condition_node_ptr condition) +: condition_(std::move(condition)) +{} + +void not_condition_node::accept( condition_node_visitor& visitor ) const { + visitor.visit(*this); +} +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..f546fc8 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,20 @@ +#include "matador/condition/column.hpp" +#include "matador/condition/condition_operators.hpp" + +using namespace matador::condition; + +int main() { + auto cond = "age"_col != 7 && "age"_col == 7; + cond = !("person.age"_col == 7); + cond = "age"_col > 7; + cond = "age"_col < 7; + cond = "age"_col >= 7; + cond = "age"_col <= 7; + cond = in("age"_col, {34, 35, 78}); + cond = out("age"_col, {34, 35, 78}); + + + // "age"_col != 7 && in("age"_col, {7,5,5,8}); + + // "(\"age\" <> 7 AND \"age\" IN (7, 5, 5, 8))" +} \ No newline at end of file