From 78abf16f282276e0cfd9db5496f39b19222d48be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Fri, 21 Nov 2025 15:58:33 +0100 Subject: [PATCH] builder progress (attribute, object and constraint class in todo.md) --- include/matador/object/attribute.hpp | 17 + .../object/internal/shadow_repository.hpp | 6 +- include/matador/object/repository_node.hpp | 4 +- include/matador/query/builder.hpp | 50 +-- include/matador/query/column.hpp | 2 +- include/matador/query/query_data.hpp | 2 + include/matador/sql/query_context.hpp | 3 +- .../object/internal/shadow_repository.cpp | 16 +- source/orm/query/builder.cpp | 16 +- todo.md | 361 ++++++++++++++++-- 10 files changed, 392 insertions(+), 85 deletions(-) diff --git a/include/matador/object/attribute.hpp b/include/matador/object/attribute.hpp index a9df82a..e9b7c8a 100644 --- a/include/matador/object/attribute.hpp +++ b/include/matador/object/attribute.hpp @@ -93,6 +93,23 @@ private: std::shared_ptr reference_column_; }; + +class object { +public: + using iterator = std::vector::iterator; + using const_iterator = std::vector::const_iterator; + +private: + std::vector columns_; + std::string name_; + std::string alias_; +}; + +class constraint { +public: +private: + std::shared_ptr column_; +}; /** * User defined literal to have a shortcut creating a column object * @param name Name of the column diff --git a/include/matador/object/internal/shadow_repository.hpp b/include/matador/object/internal/shadow_repository.hpp index 5435c87..472fe89 100644 --- a/include/matador/object/internal/shadow_repository.hpp +++ b/include/matador/object/internal/shadow_repository.hpp @@ -18,9 +18,9 @@ private: using node_ptr = std::shared_ptr; public: - explicit shadow_repository(object::repository& s); + explicit shadow_repository(repository& s); - [[nodiscard]] object::repository& repo() const; + [[nodiscard]] repository& repo() const; [[nodiscard]] bool contains(const std::type_index& ti) const; [[nodiscard]] utils::result find_node(const std::type_index &type_index) const; [[nodiscard]] utils::result find_node(const std::string &name) const; @@ -28,7 +28,7 @@ public: [[nodiscard]] utils::result detach_node(const std::shared_ptr &node) const; private: - object::repository& schema_; + repository& repo_; }; } #endif //SHADOW_SCHEMA_HPP diff --git a/include/matador/object/repository_node.hpp b/include/matador/object/repository_node.hpp index f3ee47d..a09dfd7 100644 --- a/include/matador/object/repository_node.hpp +++ b/include/matador/object/repository_node.hpp @@ -18,7 +18,7 @@ public: template < typename Type > static std::shared_ptr make_node(repository& repo, const std::string& name) { - auto node = std::shared_ptr(new repository_node(repo, name, typeid(Type))); + auto node = std::make_shared( repo, name, typeid( Type ) ); primary_key_resolver resolver; auto pk_info = resolver.resolve(); @@ -74,7 +74,7 @@ public: void update_name(const std::string& name); template - object_info_ref info() const { + [[nodiscard]] object_info_ref info() const { return std::ref(static_cast&>(*info_)); } diff --git a/include/matador/query/builder.hpp b/include/matador/query/builder.hpp index 93ef439..e93ff1c 100644 --- a/include/matador/query/builder.hpp +++ b/include/matador/query/builder.hpp @@ -6,6 +6,7 @@ #include "matador/utils/basic_types.hpp" #include "matador/utils/constraints.hpp" +#include "matador/utils/data_type_traits.hpp" #include @@ -23,26 +24,25 @@ private: std::string alias_; }; -// class attribute { -// public: -// attribute(std::string name, const utils::basic_type type) -// : name_(std::move(name)) -// , type_(type) {} -// -// [[nodiscard]] const std::string& name() const; -// [[nodiscard]] utils::basic_type type() const; -// [[nodiscard]] const attribute_options& options() const; -// -// private: -// friend class entity; -// -// std::string name_; -// std::string alias_; -// utils::basic_type type_{}; -// attribute_options options_; -// -// entity* owner_{nullptr}; -// }; +class data_type { +public: + template + data_type() : type_(utils::data_type_traits()) {} + template + explicit data_type(const size_t size) : type_(utils::data_type_traits()), size_(size) {} + + [[nodiscard]] const utils::basic_type& type() const { return type_; } + [[nodiscard]] size_t size() const { return size_; } + +private: + utils::basic_type type_{}; + size_t size_{0}; +}; + +// using BigInt = data_type(); +// using Real = data_type; +// using double_ = data_type; +// using string = data_type; class constraint { public: @@ -70,13 +70,17 @@ namespace matador::query { class column_builder { public: - explicit column_builder(std::string column_name); + explicit column_builder(std::string column_name, utils::basic_type type, size_t size = 0); // ReSharper disable once CppNonExplicitConversionOperator operator query::column() const; // NOLINT(*-explicit-constructor) + column_builder& not_null(); + private: - std::string column_name; + std::string column_name_; + utils::basic_type type_{}; + utils::constraints constraints_{}; }; class table_builder { @@ -113,7 +117,7 @@ private: constraint_builder constraint(std::string name); table_builder table(std::string name); -column_builder column(std::string name); +column_builder column(std::string name, utils::basic_type type, size_t size = 0); } #endif //MATADOR_BUILDER_HPP \ No newline at end of file diff --git a/include/matador/query/column.hpp b/include/matador/query/column.hpp index 6939232..1217225 100644 --- a/include/matador/query/column.hpp +++ b/include/matador/query/column.hpp @@ -3,7 +3,6 @@ #include "matador/sql/sql_functions.hpp" -#include #include #include @@ -40,6 +39,7 @@ private: std::shared_ptr table_; std::string name; std::string alias_; + sql::sql_function_t function_{sql::sql_function_t::None}; }; diff --git a/include/matador/query/query_data.hpp b/include/matador/query/query_data.hpp index 015e573..4008bb1 100644 --- a/include/matador/query/query_data.hpp +++ b/include/matador/query/query_data.hpp @@ -9,6 +9,8 @@ #include "matador/query/table.hpp" #include "matador/query/query_part.hpp" +#include + namespace matador::query { struct query_data { diff --git a/include/matador/sql/query_context.hpp b/include/matador/sql/query_context.hpp index b6693df..3252fb4 100644 --- a/include/matador/sql/query_context.hpp +++ b/include/matador/sql/query_context.hpp @@ -2,10 +2,11 @@ #define QUERY_QUERY_DATA_HPP #include "matador/object/attribute.hpp" -#include "matador/query/table.hpp" #include "matador/utils/types.hpp" +#include + namespace matador::sql { enum class sql_command { diff --git a/source/core/object/internal/shadow_repository.cpp b/source/core/object/internal/shadow_repository.cpp index 39b54ff..e25d451 100644 --- a/source/core/object/internal/shadow_repository.cpp +++ b/source/core/object/internal/shadow_repository.cpp @@ -4,30 +4,30 @@ #include "matador/object/repository_node.hpp" namespace matador::object::internal { -shadow_repository::shadow_repository( object::repository& s ) -: schema_(s) {} +shadow_repository::shadow_repository( repository& s ) +: repo_(s) {} repository& shadow_repository::repo() const { - return schema_; + return repo_; } bool shadow_repository::contains( const std::type_index& ti ) const { - return schema_.contains(ti); + return repo_.contains(ti); } utils::result shadow_repository::find_node( const std::type_index& type_index ) const { - return schema_.find_node(type_index); + return repo_.find_node(type_index); } utils::result shadow_repository::find_node( const std::string& name ) const { - return schema_.find_node(name); + return repo_.find_node(name); } utils::result shadow_repository::attach_node( const std::shared_ptr& node ) const { - return schema_.attach_node(node, ""); + return repo_.attach_node(node, ""); } utils::result shadow_repository::detach_node( const std::shared_ptr& node ) const { - return schema_.detach(node); + return repo_.detach(node); } } \ No newline at end of file diff --git a/source/orm/query/builder.cpp b/source/orm/query/builder.cpp index c550051..17cf5ef 100644 --- a/source/orm/query/builder.cpp +++ b/source/orm/query/builder.cpp @@ -2,11 +2,17 @@ namespace matador::query { -column_builder::column_builder(std::string column_name) -: column_name( std::move(column_name) ) {} +column_builder::column_builder(std::string column_name, const utils::basic_type type, const size_t size) +: column_name_(std::move(column_name)) +, type_(type){} column_builder::operator class query::column() const { - return {column_name}; + return {column_name_}; +} + +column_builder& column_builder::not_null() { + + return *this; } table_builder::table_builder(std::string name) @@ -55,8 +61,8 @@ table_builder table( std::string name ) { return table_builder(std::move(name)); } -column_builder column( std::string name ) { - return column_builder(std::move(name)); +column_builder column(std::string name, const utils::basic_type type, size_t size) { + return column_builder(std::move(name), type, size); } } \ No newline at end of file diff --git a/todo.md b/todo.md index 7248b6c..116c055 100644 --- a/todo.md +++ b/todo.md @@ -20,12 +20,245 @@ ## book class ```cpp -class book : public matador::sql::aliasable_table { +class Book : public matador::object::typed_object { +public: + using typed_object::as; + + Book() : typed_object("book") {} + explicit Book(std::string alias) + : typed_object("book", std::move(alias)) {} + + const matador::object::attribute id = create_attribute("id", *this); + const matador::object::attribute title = create_attribute("title", *this); + const matador::object::attribute year = create_attribute("year", *this); +}; +``` + +## aliasable_table +```cpp +class object; + +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& attr = utils::null_attributes, + utils::null_option_type null_opt = utils::null_option_type::NotNull); + + [[nodiscard]] const std::string& name() const { return name_; } + void name(const std::string& n); + [[nodiscard]] const utils::field_attributes& attributes() const; + [[nodiscard]] utils::field_attributes& attributes(); + + [[nodiscard]] bool is_nullable() const; + [[nodiscard]] utils::basic_type type() const; + + [[nodiscard]] bool is_integer() const; + [[nodiscard]] bool is_floating_point() const; + [[nodiscard]] bool is_bool() const; + [[nodiscard]] bool is_string() const; + [[nodiscard]] bool is_varchar() const; + [[nodiscard]] bool is_date() const; + [[nodiscard]] bool is_time() const; + [[nodiscard]] bool is_blob() const; + [[nodiscard]] bool is_null() const; + +private: + friend class object; + + std::string name_; + std::string alias_; + utils::basic_type type_{utils::basic_type::type_null}; + utils::field_attributes attributes_; + utils::null_option_type null_option_type_{utils::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}; +}; + +class object { +public: + using iterator = std::vector::iterator; + using const_iterator = std::vector::const_iterator; + + 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)); + } + + iterator begin() { return attributes_.begin(); } + iterator end() { return attributes_.end(); } + + [[nodiscard]] bool empty() const { return attributes_.empty(); } + [[nodiscard]] size_t size() const { return attributes_.size(); } + + [[nodiscard]] const std::string& name() const { return name_; } + [[nodiscard]] const std::string& alias() const { return alias_; } + [[nodiscard]] const std::vector& columns() const { return attributes_; } + +private: + std::string name_; + std::string alias_; + + std::vector attributes_; +}; + +template +class typed_object : public object { +public: + using object::object; + + Type as(std::string alias) { return Type{std::move(alias)}; } +}; +``` + +```cpp +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 matador::sql::column() const { + return matador::sql::column{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)); +} +void foo(const std::initializer_list columns) { + for (const auto& column : columns) { + std::cout << column.name() << std::endl; + } +} + +void foo(const std::vector& columns) { + for (const auto& column : columns) { + std::cout << column.name() << std::endl; + } +} + +template +std::string column_prefix(matador::sql::aliasable_table *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 matador::query::query_table() const { + return {matador::sql::table{table_name}, alias}; + } + std::string table_name; + std::string alias; +}; + +table_builder table(std::string name) { + return table_builder(std::move(name)); +} + +class Book : public matador::sql::aliasable_table { public: using aliasable_table::as; Book() : aliasable_table("book", "") {} - + private: friend class aliasable_table; @@ -37,56 +270,100 @@ public: matador::sql::column title = create_column("title", *this); matador::sql::column year = create_column("year", *this); }; -``` -## aliasable_table -```cpp -class table { -public: - using iterator = std::vector::iterator; - using const_iterator = std::vector::const_iterator; +struct base_node { + base_node() = delete; + base_node(std::string name) + : name(std::move(name)) {} + virtual ~base_node() = default; - explicit table(std::string name) : name_(std::move(name)) {} - table(std::string name, std::vector columns) - : name_(std::move(name)), columns_(std::move(columns)) {} + std::string name; +}; +template < typename Type> +struct node final { + virtual ~node() = default; - void add_column(column column) { - column.table_ = shared_from_this(); - columns_.emplace_back(std::move(column)); - } + Type type; +}; - static const column& create_column(std::string name, table& t) { - column c{std::move(name)}; - c.table_ = &t; - t.columns_.emplace_back(std::move(c)); - return t.columns_.back(); - } - operator const std::vector&() const { return columns_; } - table as_table() const { return {name_, columns_}; } +template < template typename NodeType = node, typename BaseType = base_node > +struct repository { + template + NodeType find(std::string name); - iterator begin() { return columns_.begin(); } - iterator end() { return columns_.end(); } + std::unordered_map nodes; +}; - [[nodiscard]] bool empty() const { return columns_.empty(); } - [[nodiscard]] size_t size() const { return columns_.size(); } +struct base_schema_node : base_node { + base_schema_node() = delete; + base_schema_node(std::string name, std::string table) + : base_node(std::move(name)), table_name(std::move(table)) {} - [[nodiscard]] const std::string& name() const { return name_; } - [[nodiscard]] const std::vector& columns() const { return columns_; } -private: - std::string name_; - std::vector columns_; + std::string table_name; }; template < typename Type > -class aliasable_table : public table { -public: - aliasable_table(std::string name, std::string alias) - : table(std::move(name)) - , alias_(std::move(alias)) {} +struct schema_node final : base_schema_node { + schema_node() = default; + schema_node(std::string name, std::string table) + : base_schema_node(std::move(name), std::move(table)) {} - Type as(std::string alias) { return Type{std::move(alias)}; } - -private: - std::string alias_; + Type type; }; + +int main() { + repository repo1; + repository repo; + + Book BOOK; + + const auto b = BOOK.as("b"); + + foo(b); + foo(BOOK); + foo({ + BOOK.id, + b.title, + column("col1").primary_key(), + column("col2").not_null() + }); + matador::sql::schema schema("test"); + + schema.add_table(BOOK.as_table()); + // query::create() + // .table(BOOK) + // .columns({ + // BOOK.id, + // BOOK.title, + // column("year"), + // column("author_id") + // }) + // .constraints({ + // constraint( "PK" ).primary_key("id"), + // constraint( "FK" ).foreign_key("author_id").references("author", "id") + // }); + // + // query::create() + // .table("book", { + // column("id"), + // column("title"), + // column("year"), + // column("author_id") + // }, { + // constraint( "PK" ).primary_key("id"), + // constraint( "FK" ).foreign_key("author_id").references("author", "id") + // }); + // + // matador::query::query_table book = table("book").as("b"); + // + // query::select({ + // column(book.column("id")), + // column(book.column("title")) + // }) + // .from(book); + // + // query::insert() + // .into(b, {b.title, b.year}) + // .values({"title", 2021}); +} ``` \ No newline at end of file