/*------------------------------------------------------------------------------* * Architecture & Implementation of DBMS * *------------------------------------------------------------------------------* * Copyright 2022 Databases and Information Systems Group TU Dortmund * * Visit us at * * http://dbis.cs.tu-dortmund.de/cms/en/home/ * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * * OTHER DEALINGS IN THE SOFTWARE. * * * * Authors: * * Maximilian Berens * * Roland Kühn * * Jan Mühlig * *------------------------------------------------------------------------------* */ #pragma once #include "term.h" #include #include #include #include #include #include namespace beedb::expression { class Operation { public: enum Type : std::uint8_t { Identity = 0, Count = 4, Average = 5, Sum = 6, Min = 7, Max = 8, Add = 16, Sub = 17, Multiply = 18, Divide = 19, And = 32, Or = 33, Equals = 64, NotEquals = 65, Lesser = 66, LesserEquals = 67, Greater = 68, GreaterEquals = 69 }; [[nodiscard]] bool is_nullary() const { return _type == Identity; } [[nodiscard]] bool is_unary() const { return _type >= static_cast(Type::Count) && _type <= static_cast(Type::Max); } [[nodiscard]] bool is_aggregation() const { return _type >= static_cast(Type::Count) && _type <= static_cast(Type::Max); } [[nodiscard]] bool is_logical_connective() const { return _type == Type::And || _type == Type::Or; } [[nodiscard]] bool is_comparison() const { return _type >= static_cast(Type::Equals) && _type <= static_cast(Type::GreaterEquals); } [[nodiscard]] bool is_arithmetic() const { return _type >= static_cast(Type::Add) && _type <= static_cast(Type::Divide); } [[nodiscard]] bool is_binary() const { return is_logical_connective() || is_comparison() || is_arithmetic(); } [[nodiscard]] Type type() const { return _type; } void type(Type type) { _type = type; } [[nodiscard]] const std::optional &result() const { return _result; } [[nodiscard]] std::optional &result() { return _result; } void alias(std::string &&alias) { _result->alias(std::move(alias)); } [[nodiscard]] virtual std::unique_ptr copy() const = 0; virtual ~Operation() = default; protected: explicit Operation(const Type type) : _type(type), _result(std::nullopt) { } Operation(const Type type, Term &&result) : _type(type), _result(std::move(result)) { } Operation(const Type type, std::optional &&result) : _type(type), _result(std::move(result)) { } Type _type; std::optional _result; }; class NullaryOperation : public Operation { public: explicit NullaryOperation(Term &&term) : Operation(Operation::Identity, term) { } NullaryOperation(const NullaryOperation &) = default; NullaryOperation(NullaryOperation &&) = default; ~NullaryOperation() override = default; [[nodiscard]] const Term &term() const { return _result.value(); } [[nodiscard]] Term &term() { return _result.value(); } [[nodiscard]] std::unique_ptr copy() const override { return std::make_unique(Term{_result.value()}); } }; class UnaryOperation : public Operation { public: [[nodiscard]] static std::unique_ptr make_count(std::unique_ptr &&child) { return UnaryOperation::make_operation(Operation::Type::Count, "COUNT", std::move(child)); } [[nodiscard]] static std::unique_ptr make_avg(std::unique_ptr &&child) { return UnaryOperation::make_operation(Operation::Type::Average, "AVG", std::move(child)); } [[nodiscard]] static std::unique_ptr make_sum(std::unique_ptr &&child) { return UnaryOperation::make_operation(Operation::Type::Sum, "SUM", std::move(child)); } [[nodiscard]] static std::unique_ptr make_min(std::unique_ptr &&child) { return UnaryOperation::make_operation(Operation::Type::Min, "MIN", std::move(child)); } [[nodiscard]] static std::unique_ptr make_max(std::unique_ptr &&child) { return UnaryOperation::make_operation(Operation::Type::Max, "MAX", std::move(child)); } UnaryOperation(const Type type, Term &&result, std::unique_ptr &&child) : Operation(type, std::move(result)), _child(std::move(child)) { } UnaryOperation(const Type type, std::optional &&result, std::unique_ptr &&child) : Operation(type, std::move(result)), _child(std::move(child)) { } UnaryOperation(const Type type, std::unique_ptr &&child) : Operation(type), _child(std::move(child)) { } ~UnaryOperation() override = default; [[nodiscard]] const std::unique_ptr &child() const { return _child; } [[nodiscard]] std::unique_ptr &child() { return _child; } [[nodiscard]] std::unique_ptr copy() const override { return std::make_unique( _type, _result.has_value() ? std::make_optional(Term{_result.value()}) : std::nullopt, _child->copy()); } private: std::unique_ptr _child; [[nodiscard]] static std::unique_ptr make_operation(const Operation::Type type, std::string &&name, std::unique_ptr &&child) { return std::make_unique( type, expression::Term{ expression::Attribute{std::move(name) + "(" + static_cast(child->result().value()) + ")"}, std::nullopt, true}, std::move(child)); } }; class BinaryOperation : public Operation { public: [[nodiscard]] static std::unique_ptr make_and(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::And, " AND ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_or(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::Or, " OR ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_equals(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::Equals, " = ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_not_equals(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::NotEquals, " != ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_lesser(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::Lesser, " < ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_lesser_equals(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::LesserEquals, " <= ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_greater(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::Greater, " > ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_greater_equals(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::GreaterEquals, " >= ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_add(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::Add, " + ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_sub(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::Sub, " - ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_mul(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::Multiply, " * ", std::move(left_child), std::move(right_child)); } [[nodiscard]] static std::unique_ptr make_div(std::unique_ptr &&left_child, std::unique_ptr &&right_child) { return BinaryOperation::make_operation(Operation::Type::Divide, " / ", std::move(left_child), std::move(right_child)); } BinaryOperation(const Type type, Term &&result, std::unique_ptr &&left_child, std::unique_ptr &&right_child) : Operation(type, std::move(result)), _left_child(std::move(left_child)), _right_child(std::move(right_child)) { } BinaryOperation(const Type type, std::optional &&result, std::unique_ptr &&left_child, std::unique_ptr &&right_child) : Operation(type, std::move(result)), _left_child(std::move(left_child)), _right_child(std::move(right_child)) { } BinaryOperation(const Type type, std::unique_ptr &&left_child, std::unique_ptr &&right_child) : Operation(type), _left_child(std::move(left_child)), _right_child(std::move(right_child)) { } ~BinaryOperation() override = default; [[nodiscard]] const std::unique_ptr &left_child() const { return _left_child; } [[nodiscard]] const std::unique_ptr &right_child() const { return _right_child; } [[nodiscard]] std::unique_ptr &left_child() { return _left_child; } [[nodiscard]] std::unique_ptr &right_child() { return _right_child; } [[nodiscard]] std::unique_ptr copy() const override { return std::make_unique( _type, _result.has_value() ? std::make_optional(Term{_result.value()}) : std::nullopt, _left_child->copy(), _right_child->copy()); } private: std::unique_ptr _left_child; std::unique_ptr _right_child; [[nodiscard]] static std::unique_ptr make_operation(const Operation::Type type, std::string &&name, std::unique_ptr &&left_child, std::unique_ptr &&right_child) { auto attribute = expression::Attribute{"(" + static_cast(left_child->result().value()) + std::move(name) + static_cast(right_child->result().value()) + ")"}; return std::make_unique(type, expression::Term{std::move(attribute), std::nullopt, true}, std::move(left_child), std::move(right_child)); } }; void visit(std::function &)> &&nullary_callback, std::function &)> &&unary_callback, std::function &)> &&binary_callback, const std::unique_ptr &operation); void for_attribute(const std::unique_ptr &operation, std::function &&callback); std::vector attributes(const std::unique_ptr &operation); std::vector attributes(std::unique_ptr &&operation); std::vector nullaries(const std::unique_ptr &operation, const bool attribute_required = false); std::vector nullaries(std::unique_ptr &&operation, const bool attribute_required = false); } // namespace beedb::expression