query/todo.md

369 lines
9.9 KiB
Markdown

# Todo
- move `object_definition` and `attribute_definition` to `table` and `column` in query
and add `contraint` class
- replace mk_column with builder style (see `query/builder.hpp`)
- fix corresponding tests
- enhance query helper macro to look like the `book` class below
- add `aliasable_table`(see class below)
- add `as()` methode to table class
- move `sql_function_t` to own header in namespace `matador::sql`
- move `prepare_*` methods from `dialect` to `query_compiler`
- add `session_insert_builder` and `session_update_builder` (returning multiple statements)
- finish `attribued_definition` (also in `repository` class -> dependencies)
- fix compile errors
- finish fetch eager has-many/belongs-to relations
- implement lazy loading
- implement polymorphic class hierarchies
- finish `schema` and `schema_repository` classes (move add/drop from `session` to `schema`)
- implement a flag class for enumerations
## book class
```cpp
class Book : public matador::object::typed_object<Book> {
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<attribute>::iterator;
using const_iterator = std::vector<attribute>::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<attribute>& columns() const { return attributes_; }
private:
std::string name_;
std::string alias_;
std::vector<attribute> attributes_;
};
template<typename Type>
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<matador::sql::column> columns) {
for (const auto& column : columns) {
std::cout << column.name() << std::endl;
}
}
void foo(const std::vector<matador::sql::column>& columns) {
for (const auto& column : columns) {
std::cout << column.name() << std::endl;
}
}
template<typename Type>
std::string column_prefix(matador::sql::aliasable_table<Type> *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<Book> {
public:
using aliasable_table::as;
Book() : aliasable_table("book", "") {}
private:
friend class aliasable_table;
explicit Book(std::string alias)
: aliasable_table("book", std::move(alias)) {}
public:
matador::sql::column id = create_column("id", *this);
matador::sql::column title = create_column("title", *this);
matador::sql::column year = create_column("year", *this);
};
struct base_node {
base_node() = delete;
base_node(std::string name)
: name(std::move(name)) {}
virtual ~base_node() = default;
std::string name;
};
template < typename Type>
struct node final {
virtual ~node() = default;
Type type;
};
template < template<typename> typename NodeType = node, typename BaseType = base_node >
struct repository {
template<typename Type>
NodeType<Type> find(std::string name);
std::unordered_map<std::string, BaseType> nodes;
};
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)) {}
std::string table_name;
};
template < typename Type >
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 type;
};
int main() {
repository repo1;
repository<schema_node, base_schema_node> 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});
}
```