#include "matador/utils/basic_types.hpp" #include "matador/utils/constraints.hpp" #include "matador/utils/field_attributes.hpp" #include #include namespace object { namespace utils = matador::utils; class object; enum class null_option_type : uint8_t { Nullable, NotNull }; class attribute { public: explicit attribute(std::string name); // NOLINT(*-explicit-constructor) attribute(const attribute&) = default; attribute& operator=(const attribute&) = default; attribute(attribute&&) noexcept = default; attribute& operator=(attribute&&) noexcept = default; attribute() = default; attribute(std::string name, utils::basic_type type, const utils::field_attributes& opts = utils::null_attributes, null_option_type null_opt = null_option_type::NotNull) : name_(std::move(name)), type_(type), options_(opts), null_option_type_(null_opt) {} [[nodiscard]] const std::string& name() const { return name_; } void name(const std::string& n) { name_ = n; } [[nodiscard]] const utils::field_attributes& options() const { return options_; } [[nodiscard]] utils::field_attributes& options(); [[nodiscard]] bool is_nullable() const { return null_option_type_ == null_option_type::Nullable; } [[nodiscard]] utils::basic_type type() const { return type_; } [[nodiscard]] bool is_integer() const { return type_ >= utils::basic_type::type_int8 && type_ <= utils::basic_type::type_uint64; } [[nodiscard]] bool is_floating_point() const { return type_ == utils::basic_type::type_float || type_ == utils::basic_type::type_double; } [[nodiscard]] bool is_bool() const { return type_ == utils::basic_type::type_bool; } [[nodiscard]] bool is_string() const { return type_ == utils::basic_type::type_text; } [[nodiscard]] bool is_varchar() const { return type_ == utils::basic_type::type_varchar; } [[nodiscard]] bool is_date() const { return type_ == utils::basic_type::type_date; } [[nodiscard]] bool is_time() const { return type_ == utils::basic_type::type_time; } [[nodiscard]] bool is_blob() const { return type_ == utils::basic_type::type_blob; } [[nodiscard]] bool is_null() const { return type_ == utils::basic_type::type_null; } private: friend class object; std::string name_; std::string alias_; utils::basic_type type_{utils::basic_type::type_null}; utils::field_attributes options_; null_option_type null_option_type_{null_option_type::NotNull}; object* parent_{nullptr}; }; class constraint { public: constraint() = default; explicit constraint(std::string name) : name_(std::move(name)) {} [[nodiscard]] const std::string& name() const { return name_; } private: friend class object; std::string name_; std::string attribute_name_; utils::constraints options_{utils::constraints::None}; object* parent_{nullptr}; attribute* attribute_{nullptr}; }; class object { public: explicit object(std::string name, std::string alias = ""); void add_attribute(attribute attr) { auto &ref = attributes_.emplace_back(std::move(attr)); ref.parent_ = this; } static const attribute& create_attribute(std::string name, object& obj) { attribute attr{std::move(name)}; attr.parent_ = &obj; return obj.attributes_.emplace_back(std::move(attr)); } void add_constraint(constraint c) { auto &ref = constraints_.emplace_back(std::move(c)); ref.parent_ = this; } [[nodiscard]] const std::string& name() const { return name_; } [[nodiscard]] const std::string& alias() const { return alias_; } [[nodiscard]] bool has_attributes() const { return attributes_.empty(); } [[nodiscard]] size_t attribute_count() const { return attributes_.size(); } [[nodiscard]] const std::vector& attributes() const { return attributes_; } [[nodiscard]] bool has_constraints() const { return constraints_.empty(); } [[nodiscard]] size_t constraint_count() const { return constraints_.size(); } [[nodiscard]] const std::vector& constraints() const { return constraints_; } private: std::string name_; std::string alias_; std::vector attributes_; std::vector constraints_; }; template class typed_object : public object { public: using object::object; Type as(std::string alias) { return Type{std::move(alias)}; } }; struct column_builder { explicit column_builder(std::string column_name) : column_name( std::move(column_name) ) { } column_builder& not_null() { return *this; } column_builder& primary_key() { return *this; } operator attribute() const { return attribute{column_name}; } std::string column_name; }; column_builder column(std::string name) { return column_builder(std::move(name)); } namespace matador::sql { struct constraint { std::string name; }; } struct constraint_builder { constraint_builder& constraint(std::string name) { constraint_name = std::move(name); return *this; } constraint_builder& primary_key(std::string name) { pk_column_name = std::move(name); return *this; } constraint_builder& foreign_key(std::string name) { fk_column_name = std::move(name); return *this; } constraint_builder& references(std::string table, std::string column) { this->table_name = std::move(table); this->column_name = std::move(column); return *this; } operator matador::sql::constraint() const { return matador::sql::constraint{constraint_name}; } std::string constraint_name; std::string pk_column_name; std::string fk_column_name; std::string table_name; std::string column_name; }; constraint_builder constraint(std::string name) { constraint_builder builder; return builder.constraint(std::move(name)); } template std::string column_prefix(typed_object *tab) { if (!tab || tab->empty()) { return ""; } if (!tab->alias().empty()) { return tab->alias(); } return tab->name(); } struct table_builder { explicit table_builder(std::string name) : table_name( std::move(name) ) {} table_builder& as(std::string table_alias) { this->alias = std::move(table_alias); return *this; } operator object() const { return object{table_name, alias}; } std::string table_name; std::string alias; }; table_builder table(std::string name) { return table_builder(std::move(name)); } } int main() { }