/*------------------------------------------------------------------------------* * 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 "attribute.h" #include #include #include #include #include namespace beedb::expression { using NullValue = std::nullptr_t; class Term { public: Term() = default; explicit Term(Attribute &&reference) : _attribute_or_value(std::move(reference)) { } explicit Term(const Attribute &reference) : _attribute_or_value(reference) { } explicit Term(std::string &&value) : _attribute_or_value(std::move(value)) { } explicit Term(std::int64_t value) : _attribute_or_value(value) { } explicit Term(std::int32_t value) : _attribute_or_value(value) { } explicit Term(double value) : _attribute_or_value(value) { } explicit Term(NullValue) : _attribute_or_value(NullValue{}) { } explicit Term(table::Value &&value) { std::visit([&attr_or_value = _attribute_or_value](auto &v) { attr_or_value = std::move(v); }, value.value()); } Term(Attribute &&reference, std::optional &&alias) : _attribute_or_value(std::move(reference)), _alias(std::move(alias)) { } Term(Attribute &&reference, std::optional &&alias, bool is_generated) : _attribute_or_value(std::move(reference)), _alias(std::move(alias)), _is_generated(is_generated) { } Term(const Attribute &reference, std::optional &&alias) : _attribute_or_value(reference), _alias(std::move(alias)) { } Term(std::string &&value, std::optional &&alias) : _attribute_or_value(std::move(value)), _alias(std::move(alias)) { } Term(std::int64_t value, std::optional &&alias) : _attribute_or_value(value), _alias(std::move(alias)) { } Term(std::int32_t value, std::optional &&alias) : _attribute_or_value(value), _alias(std::move(alias)) { } Term(double value, std::optional &&alias) : _attribute_or_value(value), _alias(std::move(alias)) { } Term(NullValue, std::optional &&alias) : _attribute_or_value(NullValue{}), _alias(std::move(alias)) { } Term(Term &&) = default; Term(const Term &) = default; ~Term() = default; Term &operator=(const Term &) = default; Term &operator=(Term &&) = default; [[nodiscard]] static Term make_attribute(std::string &&table_name, std::string &&column_name, const bool display_table = false) { return Term{Attribute{std::move(table_name), std::move(column_name), display_table}}; } [[nodiscard]] static Term make_attribute(const std::string &table_name, std::string &&column_name, const bool display_table = false) { return Term{Attribute{table_name, std::move(column_name), display_table}}; } [[nodiscard]] static Term make_attribute(const std::string &table_name, const std::string &column_name) { return Term{Attribute{table_name, column_name}}; } [[nodiscard]] static Term make_attribute(std::string &&column_name) { return Term{Attribute{std::nullopt, std::move(column_name)}}; } [[nodiscard]] const auto &attribute_or_value() const { return _attribute_or_value; } [[nodiscard]] const std::optional alias() const { return _alias; } void alias(const std::string &alias) { _alias = alias; } void alias(std::string &&alias) { _alias = std::move(alias); } [[nodiscard]] bool is_attribute() const { return std::holds_alternative(_attribute_or_value); } [[nodiscard]] bool is_null() const { return std::holds_alternative(_attribute_or_value); } [[nodiscard]] bool is_value() const { return std::holds_alternative(_attribute_or_value) || std::holds_alternative(_attribute_or_value) || std::holds_alternative(_attribute_or_value) || std::holds_alternative(_attribute_or_value); } template [[nodiscard]] const T &get() const { return std::get(_attribute_or_value); } template [[nodiscard]] T &get() { return std::get(_attribute_or_value); } [[nodiscard]] bool is_generated() const { return _is_generated; } bool operator==(const Term &other) const { return _attribute_or_value == other._attribute_or_value && _alias == other._alias; } explicit operator std::string() const { if (_alias.has_value()) { return _alias.value(); } if (std::holds_alternative(_attribute_or_value)) { return static_cast(std::get(_attribute_or_value)); } else if (std::holds_alternative(_attribute_or_value)) { return std::get(_attribute_or_value); } else if (std::holds_alternative(_attribute_or_value)) { return std::to_string(std::get(_attribute_or_value)); } else if (std::holds_alternative(_attribute_or_value)) { return std::to_string(std::get(_attribute_or_value)); } else if (std::holds_alternative(_attribute_or_value)) { return std::to_string(std::get(_attribute_or_value)); } else if (std::holds_alternative(_attribute_or_value)) { return std::string{"NULL"}; } return ""; } private: std::variant _attribute_or_value{NullValue{}}; std::optional _alias{std::nullopt}; bool _is_generated{false}; }; } // namespace beedb::expression namespace std { template <> struct hash { public: std::size_t operator()(const beedb::expression::Term &term) const { std::size_t h = std::hash()(term.alias().value_or("")); std::visit( [&h](const auto &v) { using T = std::decay_t; h ^= std::hash()(v); }, term.attribute_or_value()); return h; } }; } // namespace std