preparations for object_generator (generating objects with attributes and constraints)
This commit is contained in:
parent
19b0adf737
commit
e67c0f39a3
|
|
@ -1,4 +1,5 @@
|
||||||
add_executable(demo main.cpp)
|
add_executable(demo main.cpp
|
||||||
|
object.cpp)
|
||||||
target_link_libraries(demo PRIVATE
|
target_link_libraries(demo PRIVATE
|
||||||
matador-core
|
matador-core
|
||||||
matador-orm
|
matador-orm
|
||||||
|
|
@ -23,3 +24,9 @@ target_link_libraries(work PRIVATE
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(work matador-postgres)
|
add_dependencies(work matador-postgres)
|
||||||
|
|
||||||
|
add_executable(object object.cpp)
|
||||||
|
target_link_libraries(object PRIVATE
|
||||||
|
matador-core
|
||||||
|
${CMAKE_DL_LIBS}
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,233 @@
|
||||||
|
#include "matador/utils/basic_types.hpp"
|
||||||
|
#include "matador/utils/constraints.hpp"
|
||||||
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
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<attribute>& 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<constraint>& constraints() const { return constraints_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
std::string alias_;
|
||||||
|
|
||||||
|
std::vector<attribute> attributes_;
|
||||||
|
std::vector<constraint> constraints_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
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<typename Type>
|
||||||
|
std::string column_prefix(typed_object<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 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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ struct attribute_options {
|
||||||
null_option_type null_option{null_option_type::NOT_NULL};
|
null_option_type null_option{null_option_type::NOT_NULL};
|
||||||
int index{-1};
|
int index{-1};
|
||||||
};
|
};
|
||||||
|
class object;
|
||||||
|
|
||||||
class attribute {
|
class attribute {
|
||||||
public:
|
public:
|
||||||
|
|
@ -85,7 +86,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class object;
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
object *owner_{nullptr};
|
||||||
std::string table_name_;
|
std::string table_name_;
|
||||||
attribute_options options_;
|
attribute_options options_;
|
||||||
utils::basic_type type_{utils::basic_type::type_null};
|
utils::basic_type type_{utils::basic_type::type_null};
|
||||||
|
|
@ -94,22 +98,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class object {
|
|
||||||
public:
|
|
||||||
using iterator = std::vector<attribute>::iterator;
|
|
||||||
using const_iterator = std::vector<attribute>::const_iterator;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<attribute> columns_;
|
|
||||||
std::string name_;
|
|
||||||
std::string alias_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class constraint {
|
|
||||||
public:
|
|
||||||
private:
|
|
||||||
std::shared_ptr<attribute> column_;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* User defined literal to have a shortcut creating a column object
|
* User defined literal to have a shortcut creating a column object
|
||||||
* @param name Name of the column
|
* @param name Name of the column
|
||||||
|
|
@ -131,7 +119,7 @@ attribute make_column<std::string>(const std::string &name, utils::field_attribu
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
attribute make_pk_column(const std::string &name, size_t size = 0)
|
attribute make_pk_column(const std::string &name, size_t size = 0)
|
||||||
{
|
{
|
||||||
return make_column<Type>(name, { size, utils::constraints::PRIMARY_KEY });
|
return make_column<Type>(name, { size, utils::constraints::PrimaryKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
@ -139,13 +127,13 @@ attribute make_pk_column<std::string>(const std::string &name, size_t size);
|
||||||
|
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
attribute make_fk_column(const std::string &name, size_t size, const std::shared_ptr<attribute> &ref_column) {
|
attribute make_fk_column(const std::string &name, size_t size, const std::shared_ptr<attribute> &ref_column) {
|
||||||
return {name, utils::data_type_traits<Type>::type(size), ref_column, { size, utils::constraints::FOREIGN_KEY }};
|
return {name, utils::data_type_traits<Type>::type(size), ref_column, { size, utils::constraints::ForeignKey }};
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
[[maybe_unused]] attribute make_fk_column(const std::string &name, const std::shared_ptr<attribute> &ref_column)
|
[[maybe_unused]] attribute make_fk_column(const std::string &name, const std::shared_ptr<attribute> &ref_column)
|
||||||
{
|
{
|
||||||
return {name, utils::data_type_traits<Type>::type(0), 0, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option_type::NOT_NULL};
|
return {name, utils::data_type_traits<Type>::type(0), 0, ref_column, { 0, utils::constraints::ForeignKey }, null_option_type::NOT_NULL};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
@ -155,8 +143,8 @@ template < typename Type >
|
||||||
[[maybe_unused]] attribute make_fk_column(const std::string &name, size_t size, const std::string &ref_table_name, const std::string &ref_column_name) {
|
[[maybe_unused]] attribute make_fk_column(const std::string &name, size_t size, const std::string &ref_table_name, const std::string &ref_column_name) {
|
||||||
return {
|
return {
|
||||||
name, utils::data_type_traits<Type>::type(size), 0,
|
name, utils::data_type_traits<Type>::type(size), 0,
|
||||||
std::make_shared<attribute>(ref_column_name, ref_table_name, utils::data_type_traits<Type>::type(size), utils::constraints::FOREIGN_KEY),
|
std::make_shared<attribute>(ref_column_name, ref_table_name, utils::data_type_traits<Type>::type(size), utils::constraints::ForeignKey),
|
||||||
{ 0, utils::constraints::FOREIGN_KEY }, null_option_type::NOT_NULL
|
{ 0, utils::constraints::ForeignKey }, null_option_type::NOT_NULL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,8 +152,8 @@ template < typename Type >
|
||||||
[[maybe_unused]] attribute make_fk_column(const std::string &name, const std::string &ref_table_name, const std::string &ref_column_name) {
|
[[maybe_unused]] attribute make_fk_column(const std::string &name, const std::string &ref_table_name, const std::string &ref_column_name) {
|
||||||
return {
|
return {
|
||||||
name, utils::data_type_traits<Type>::type(0), 0,
|
name, utils::data_type_traits<Type>::type(0), 0,
|
||||||
std::make_shared<attribute>(ref_column_name, utils::data_type_traits<Type>::type(0), ref_table_name, attribute_options{utils::constraints::FOREIGN_KEY}),
|
std::make_shared<attribute>(ref_column_name, utils::data_type_traits<Type>::type(0), ref_table_name, attribute_options{utils::constraints::ForeignKey}),
|
||||||
{ 0, utils::constraints::FOREIGN_KEY }, null_option_type::NOT_NULL
|
{ 0, utils::constraints::ForeignKey }, null_option_type::NOT_NULL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public:
|
||||||
template<class Type>
|
template<class Type>
|
||||||
attribute generate(const char *id, Type &x, const std::shared_ptr<attribute> &ref_column) {
|
attribute generate(const char *id, Type &x, const std::shared_ptr<attribute> &ref_column) {
|
||||||
access::process(*this, x);
|
access::process(*this, x);
|
||||||
return attribute{id, type_, 0, ref_column, {utils::constraints::FOREIGN_KEY }, null_option_type::NOT_NULL};
|
return attribute{id, type_, 0, ref_column, {utils::constraints::ForeignKey }, null_option_type::NOT_NULL};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
|
|
@ -133,7 +133,7 @@ private:
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void attribute_generator::on_primary_key(const char *id, ValueType &x, const utils::primary_key_attribute& attr) {
|
void attribute_generator::on_primary_key(const char *id, ValueType &x, const utils::primary_key_attribute& attr) {
|
||||||
on_attribute(id, x, { attr.size(), utils::constraints::PRIMARY_KEY });
|
on_attribute(id, x, { attr.size(), utils::constraints::PrimaryKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef MATADOR_CONSTRAINT_HPP
|
||||||
|
#define MATADOR_CONSTRAINT_HPP
|
||||||
|
|
||||||
|
#include "matador/utils/constraints.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::object {
|
||||||
|
|
||||||
|
class attribute;
|
||||||
|
class constraint_builder;
|
||||||
|
class object;
|
||||||
|
|
||||||
|
class constraint {
|
||||||
|
public:
|
||||||
|
constraint() = default;
|
||||||
|
explicit constraint(std::string name);
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& name() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class constraint_builder;
|
||||||
|
friend class object;
|
||||||
|
|
||||||
|
std::string name_;
|
||||||
|
attribute* attr_{nullptr};
|
||||||
|
object *owner_{nullptr};
|
||||||
|
utils::constraints options_{utils::constraints::None};
|
||||||
|
std::string ref_table_name_{};
|
||||||
|
std::string ref_column_name_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class constraint_builder {
|
||||||
|
public:
|
||||||
|
constraint_builder& constraint(std::string name);
|
||||||
|
constraint_builder& primary_key(std::string name);
|
||||||
|
constraint_builder& foreign_key(std::string name);
|
||||||
|
constraint_builder& references(std::string table, std::string column);
|
||||||
|
|
||||||
|
operator class constraint() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string constraint_name;
|
||||||
|
utils::constraints options_{utils::constraints::None};
|
||||||
|
std::string column_name;
|
||||||
|
std::string ref_table_name;
|
||||||
|
std::string ref_column_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
constraint_builder constraint(std::string name);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //MATADOR_CONSTRAINT_HPP
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef MATADOR_OBJECT_GENERATOR_HPP
|
||||||
|
#define MATADOR_OBJECT_GENERATOR_HPP
|
||||||
|
|
||||||
|
#include "matador/object/attribute.hpp"
|
||||||
|
#include "matador/object/attribute_generator.hpp"
|
||||||
|
#include "matador/object/constraint.hpp"
|
||||||
|
|
||||||
|
namespace matador::object {
|
||||||
|
|
||||||
|
class object_generator;
|
||||||
|
|
||||||
|
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.owner_ = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const attribute& create_attribute(std::string name, object& obj) {
|
||||||
|
attribute attr{std::move(name)};
|
||||||
|
attr.owner_ = &obj;
|
||||||
|
return obj.attributes_.emplace_back(std::move(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_constraint(class constraint c) {
|
||||||
|
auto &ref = constraints_.emplace_back(std::move(c));
|
||||||
|
ref.owner_ = 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<attribute>& 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<class constraint>& constraints() const { return constraints_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class object_generator;
|
||||||
|
|
||||||
|
std::string name_;
|
||||||
|
std::string alias_;
|
||||||
|
|
||||||
|
std::vector<attribute> attributes_;
|
||||||
|
std::vector<class constraint> constraints_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class object_generator {
|
||||||
|
public:
|
||||||
|
template<typename Type>
|
||||||
|
object generate(std::string name, std::string alias = "") {
|
||||||
|
object obj{std::move(name), std::move(alias)};
|
||||||
|
attribute_generator::generate<Type>(*this);
|
||||||
|
Type obj2;
|
||||||
|
access::process(gen, obj2);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif //MATADOR_OBJECT_GENERATOR_HPP
|
||||||
|
|
@ -48,7 +48,7 @@ public:
|
||||||
auto info = std::make_unique<object_info<Type>>(
|
auto info = std::make_unique<object_info<Type>>(
|
||||||
result.value(),
|
result.value(),
|
||||||
attribute_generator::generate(*obj, repo),
|
attribute_generator::generate(*obj, repo),
|
||||||
std::move(creator)
|
std::forward<CreatorFunc>(creator)
|
||||||
);
|
);
|
||||||
result.value()->info_ = std::move(info);
|
result.value()->info_ = std::move(info);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,12 @@ class field {
|
||||||
public:
|
public:
|
||||||
explicit field(std::string name);
|
explicit field(std::string name);
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
field(std::string name, Type value, const utils::constraints type = utils::constraints::NONE, const size_t size = 0, const int index = -1)
|
field(std::string name, Type value, const utils::constraints type = utils::constraints::None, const size_t size = 0, const int index = -1)
|
||||||
: name_(std::move(name))
|
: name_(std::move(name))
|
||||||
, type_(type)
|
, type_(type)
|
||||||
, index_(index)
|
, index_(index)
|
||||||
, value_(value, size) {}
|
, value_(value, size) {}
|
||||||
field(std::string name, utils::basic_type dt, utils::constraints type = utils::constraints::NONE, size_t size = 0, int index = -1);
|
field(std::string name, utils::basic_type dt, utils::constraints type = utils::constraints::None, size_t size = 0, int index = -1);
|
||||||
field(const field &x) = default;
|
field(const field &x) = default;
|
||||||
field& operator=(const field &x) = default;
|
field& operator=(const field &x) = default;
|
||||||
field(field &&x) noexcept;
|
field(field &&x) noexcept;
|
||||||
|
|
@ -71,7 +71,7 @@ private:
|
||||||
friend class record;
|
friend class record;
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
utils::constraints type_{utils::constraints::NONE};
|
utils::constraints type_{utils::constraints::None};
|
||||||
int index_{-1};
|
int index_{-1};
|
||||||
|
|
||||||
utils::value value_;
|
utils::value value_;
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
|
|
||||||
enum class constraints : unsigned char {
|
enum class constraints : unsigned char {
|
||||||
NONE = 0,
|
None = 0,
|
||||||
INDEX = 1 << 0,
|
Index = 1 << 0,
|
||||||
UNIQUE = 1 << 1,
|
Unique = 1 << 1,
|
||||||
PRIMARY_KEY = 1 << 2,
|
PrimaryKey = 1 << 2,
|
||||||
FOREIGN_KEY = 1 << 3,
|
ForeignKey = 1 << 3,
|
||||||
DEFAULT = 1 << 4
|
Default = 1 << 4
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constraints operator|(constraints a, constraints b) { return static_cast<constraints>(static_cast<unsigned int>(a) | static_cast<unsigned int>(b)); }
|
inline constraints operator|(constraints a, constraints b) { return static_cast<constraints>(static_cast<unsigned int>(a) | static_cast<unsigned int>(b)); }
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t size_ = 0;
|
size_t size_ = 0;
|
||||||
constraints options_ = constraints::NONE;
|
constraints options_ = constraints::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
const field_attributes null_attributes {};
|
const field_attributes null_attributes {};
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,12 @@ add_library(matador-core STATIC
|
||||||
../../include/matador/object/attribute.hpp
|
../../include/matador/object/attribute.hpp
|
||||||
../../include/matador/object/attribute_generator.hpp
|
../../include/matador/object/attribute_generator.hpp
|
||||||
../../include/matador/object/basic_object_info.hpp
|
../../include/matador/object/basic_object_info.hpp
|
||||||
|
../../include/matador/object/constraint.hpp
|
||||||
../../include/matador/object/error_code.hpp
|
../../include/matador/object/error_code.hpp
|
||||||
../../include/matador/object/foreign_node_completer.hpp
|
../../include/matador/object/foreign_node_completer.hpp
|
||||||
../../include/matador/object/internal/shadow_repository.hpp
|
../../include/matador/object/internal/shadow_repository.hpp
|
||||||
../../include/matador/object/many_to_many_relation.hpp
|
../../include/matador/object/many_to_many_relation.hpp
|
||||||
|
../../include/matador/object/object_generator.hpp
|
||||||
../../include/matador/object/object_info.hpp
|
../../include/matador/object/object_info.hpp
|
||||||
../../include/matador/object/object_proxy.hpp
|
../../include/matador/object/object_proxy.hpp
|
||||||
../../include/matador/object/object_ptr.hpp
|
../../include/matador/object/object_ptr.hpp
|
||||||
|
|
@ -77,6 +79,7 @@ add_library(matador-core STATIC
|
||||||
object/attribute.cpp
|
object/attribute.cpp
|
||||||
object/attribute_generator.cpp
|
object/attribute_generator.cpp
|
||||||
object/basic_object_info.cpp
|
object/basic_object_info.cpp
|
||||||
|
object/constraint.cpp
|
||||||
object/error_code.cpp
|
object/error_code.cpp
|
||||||
object/foreign_node_completer.cpp
|
object/foreign_node_completer.cpp
|
||||||
object/internal/shadow_repository.cpp
|
object/internal/shadow_repository.cpp
|
||||||
|
|
|
||||||
|
|
@ -147,14 +147,14 @@ attribute make_column<std::string>(const std::string &name, utils::field_attribu
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
attribute make_pk_column<std::string>(const std::string &name, size_t size) {
|
attribute make_pk_column<std::string>(const std::string &name, size_t size) {
|
||||||
return make_column<std::string>(name, {size, utils::constraints::PRIMARY_KEY});
|
return make_column<std::string>(name, {size, utils::constraints::PrimaryKey});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
attribute make_fk_column<std::string>(const std::string &name, size_t size, const std::shared_ptr<attribute> &ref_column) {
|
attribute make_fk_column<std::string>(const std::string &name, size_t size, const std::shared_ptr<attribute> &ref_column) {
|
||||||
return {
|
return {
|
||||||
name, utils::data_type_traits<std::string>::type(size), 0, ref_column,
|
name, utils::data_type_traits<std::string>::type(size), 0, ref_column,
|
||||||
{size, utils::constraints::FOREIGN_KEY}, null_option_type::NOT_NULL
|
{size, utils::constraints::ForeignKey}, null_option_type::NOT_NULL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,17 +162,17 @@ template<>
|
||||||
attribute make_fk_column<std::string>( const std::string& name, const std::string& ref_table_name, const std::string& ref_column_name ) {
|
attribute make_fk_column<std::string>( const std::string& name, const std::string& ref_table_name, const std::string& ref_column_name ) {
|
||||||
return {
|
return {
|
||||||
name, utils::basic_type::type_varchar, 0,
|
name, utils::basic_type::type_varchar, 0,
|
||||||
std::make_shared<attribute>(ref_column_name, utils::basic_type::type_varchar, ref_table_name, attribute_options{utils::constraints::FOREIGN_KEY}),
|
std::make_shared<attribute>(ref_column_name, utils::basic_type::type_varchar, ref_table_name, attribute_options{utils::constraints::ForeignKey}),
|
||||||
{ 0, utils::constraints::FOREIGN_KEY }, null_option_type::NOT_NULL
|
{ 0, utils::constraints::ForeignKey }, null_option_type::NOT_NULL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
attribute make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table_name, const std::string &ref_column_name) {
|
attribute make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table_name, const std::string &ref_column_name) {
|
||||||
const auto ref_column = std::make_shared<attribute>(ref_column_name, utils::basic_type::type_varchar, ref_table_name, attribute_options{utils::constraints::FOREIGN_KEY});
|
const auto ref_column = std::make_shared<attribute>(ref_column_name, utils::basic_type::type_varchar, ref_table_name, attribute_options{utils::constraints::ForeignKey});
|
||||||
return {
|
return {
|
||||||
name, utils::data_type_traits<std::string>::type(size), 0, ref_column,
|
name, utils::data_type_traits<std::string>::type(size), 0, ref_column,
|
||||||
{size, utils::constraints::FOREIGN_KEY}, null_option_type::NOT_NULL
|
{size, utils::constraints::ForeignKey}, null_option_type::NOT_NULL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "matador/object/constraint.hpp"
|
||||||
|
|
||||||
|
namespace matador::object {
|
||||||
|
constraint::constraint(std::string name)
|
||||||
|
: name_(std::move(name)) {}
|
||||||
|
|
||||||
|
const std::string & constraint::name() const {
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint_builder & constraint_builder::constraint(std::string name) {
|
||||||
|
constraint_name = std::move(name);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint_builder & constraint_builder::primary_key(std::string name) {
|
||||||
|
column_name = std::move(name);
|
||||||
|
options_ |= utils::constraints::PrimaryKey;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint_builder & constraint_builder::foreign_key(std::string name) {
|
||||||
|
column_name = std::move(name);
|
||||||
|
options_ |= utils::constraints::ForeignKey;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint_builder & constraint_builder::references(std::string table, std::string column) {
|
||||||
|
ref_table_name = std::move(table);
|
||||||
|
ref_column_name = std::move(column);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint_builder::operator class constraint() const {
|
||||||
|
class constraint c;
|
||||||
|
c.name_ = constraint_name;
|
||||||
|
c.options_ = options_;
|
||||||
|
c.ref_column_name_ = ref_column_name;
|
||||||
|
c.ref_table_name_ = ref_table_name;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint_builder constraint(std::string name) {
|
||||||
|
constraint_builder builder;
|
||||||
|
return builder.constraint(std::move(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -110,7 +110,7 @@ std::shared_ptr<attribute> repository_node::determine_reference_column(const std
|
||||||
repository& repo) {
|
repository& repo) {
|
||||||
const auto it = repo.missing_references_.find(ti);
|
const auto it = repo.missing_references_.find(ti);
|
||||||
if (it == repo.missing_references_.end()) {
|
if (it == repo.missing_references_.end()) {
|
||||||
return std::make_shared<attribute>(pk_info.pk_column_name, pk_info.type, table_name, attribute_options{utils::constraints::FOREIGN_KEY});
|
return std::make_shared<attribute>(pk_info.pk_column_name, pk_info.type, table_name, attribute_options{utils::constraints::ForeignKey});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ref_column = it->second;
|
auto ref_column = it->second;
|
||||||
|
|
@ -118,7 +118,7 @@ std::shared_ptr<attribute> repository_node::determine_reference_column(const std
|
||||||
ref_column->name(pk_info.pk_column_name);
|
ref_column->name(pk_info.pk_column_name);
|
||||||
ref_column->table_name(table_name);
|
ref_column->table_name(table_name);
|
||||||
ref_column->change_type(pk_info.type);
|
ref_column->change_type(pk_info.type);
|
||||||
ref_column->attributes() = utils::constraints::FOREIGN_KEY;
|
ref_column->attributes() = utils::constraints::ForeignKey;
|
||||||
|
|
||||||
if (table_name.empty()) {
|
if (table_name.empty()) {
|
||||||
repo.missing_references_.insert({ti, ref_column});
|
repo.missing_references_.insert({ti, ref_column});
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ field_attributes::field_attributes(const size_t size, const constraints options)
|
||||||
|
|
||||||
field_attributes& field_attributes::operator=(const size_t size) {
|
field_attributes& field_attributes::operator=(const size_t size) {
|
||||||
size_ = size;
|
size_ = size;
|
||||||
options_ = constraints::NONE;
|
options_ = constraints::None;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
field_attributes& field_attributes::operator=(constraints opt) {
|
field_attributes& field_attributes::operator=(constraints opt) {
|
||||||
|
|
|
||||||
|
|
@ -396,13 +396,13 @@ std::string build_create_column(const object::attribute &col, const sql::dialect
|
||||||
if (!col.is_nullable()) {
|
if (!col.is_nullable()) {
|
||||||
result.append(" NOT NULL");
|
result.append(" NOT NULL");
|
||||||
}
|
}
|
||||||
if (is_constraint_set(col.attributes().options(), utils::constraints::UNIQUE)) {
|
if (is_constraint_set(col.attributes().options(), utils::constraints::Unique)) {
|
||||||
result.append(" UNIQUE");
|
result.append(" UNIQUE");
|
||||||
}
|
}
|
||||||
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
|
if (is_constraint_set(col.attributes().options(), utils::constraints::PrimaryKey)) {
|
||||||
context.primary_keys.emplace_back(col.name());
|
context.primary_keys.emplace_back(col.name());
|
||||||
}
|
}
|
||||||
if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) {
|
if (is_constraint_set(col.attributes().options(), utils::constraints::ForeignKey)) {
|
||||||
context.foreign_contexts.push_back({col.name(), col.reference_column()});
|
context.foreign_contexts.push_back({col.name(), col.reference_column()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,11 +101,11 @@ bool field::is_null() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool field::is_primary_key() const {
|
bool field::is_primary_key() const {
|
||||||
return type_ == utils::constraints::PRIMARY_KEY;
|
return type_ == utils::constraints::PrimaryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool field::is_foreign_key() const {
|
bool field::is_foreign_key() const {
|
||||||
return type_ == utils::constraints::FOREIGN_KEY;
|
return type_ == utils::constraints::ForeignKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool field::is_attribute() const {
|
bool field::is_attribute() const {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
namespace matador::sql::internal {
|
namespace matador::sql::internal {
|
||||||
void query_result_pk_resolver::on_attribute(const char *id, const utils::value &x, const utils::field_attributes &attr) {
|
void query_result_pk_resolver::on_attribute(const char *id, const utils::value &x, const utils::field_attributes &attr) {
|
||||||
if (is_constraint_set(attr.options(), utils::constraints::PRIMARY_KEY)) {
|
if (is_constraint_set(attr.options(), utils::constraints::PrimaryKey)) {
|
||||||
if (x.is_integer()) {
|
if (x.is_integer()) {
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
utils::data_type_traits<uint64_t>::read_value(reader_, id, column_index_++, val);
|
utils::data_type_traits<uint64_t>::read_value(reader_, id, column_index_++, val);
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ TEST_CASE("Generate column definitions from object", "[column][definition][gener
|
||||||
auto columns = attribute_generator::generate<matador::test::product>(repo);
|
auto columns = attribute_generator::generate<matador::test::product>(repo);
|
||||||
|
|
||||||
const std::vector expected_columns = {
|
const std::vector expected_columns = {
|
||||||
attribute{"product_name", basic_type::type_varchar, constraints::PRIMARY_KEY, null_option_type::NOT_NULL },
|
attribute{"product_name", basic_type::type_varchar, constraints::PrimaryKey, null_option_type::NOT_NULL },
|
||||||
attribute{"supplier_id", basic_type::type_uint32, constraints::FOREIGN_KEY, null_option_type::NOT_NULL },
|
attribute{"supplier_id", basic_type::type_uint32, constraints::ForeignKey, null_option_type::NOT_NULL },
|
||||||
attribute{"category_id", basic_type::type_uint32, constraints::FOREIGN_KEY, null_option_type::NOT_NULL },
|
attribute{"category_id", basic_type::type_uint32, constraints::ForeignKey, null_option_type::NOT_NULL },
|
||||||
attribute{"quantity_per_unit", basic_type::type_varchar, null_attributes, null_option_type::NOT_NULL },
|
attribute{"quantity_per_unit", basic_type::type_varchar, null_attributes, null_option_type::NOT_NULL },
|
||||||
attribute{"unit_price", basic_type::type_uint32, null_attributes, null_option_type::NOT_NULL },
|
attribute{"unit_price", basic_type::type_uint32, null_attributes, null_option_type::NOT_NULL },
|
||||||
attribute{"units_in_stock", basic_type::type_uint32, null_attributes, null_option_type::NOT_NULL },
|
attribute{"units_in_stock", basic_type::type_uint32, null_attributes, null_option_type::NOT_NULL },
|
||||||
|
|
@ -46,7 +46,7 @@ TEST_CASE("Generate columns from object with nullable columns", "[column generat
|
||||||
auto columns = attribute_generator::generate<matador::test::optional>(repo);
|
auto columns = attribute_generator::generate<matador::test::optional>(repo);
|
||||||
|
|
||||||
const std::vector expected_columns = {
|
const std::vector expected_columns = {
|
||||||
attribute{"id", basic_type::type_uint32, constraints::PRIMARY_KEY, null_option_type::NOT_NULL },
|
attribute{"id", basic_type::type_uint32, constraints::PrimaryKey, null_option_type::NOT_NULL },
|
||||||
attribute{"name", basic_type::type_varchar, null_attributes, null_option_type::NOT_NULL },
|
attribute{"name", basic_type::type_varchar, null_attributes, null_option_type::NOT_NULL },
|
||||||
attribute{"age", basic_type::type_uint32, null_attributes, null_option_type::NOT_NULL }
|
attribute{"age", basic_type::type_uint32, null_attributes, null_option_type::NOT_NULL }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,25 @@ TEST_CASE("Test field attribute", "[field-attribute]") {
|
||||||
field_attributes attr;
|
field_attributes attr;
|
||||||
|
|
||||||
REQUIRE(attr.size() == 0);
|
REQUIRE(attr.size() == 0);
|
||||||
REQUIRE(attr.options() == constraints::NONE);
|
REQUIRE(attr.options() == constraints::None);
|
||||||
|
|
||||||
attr = 255;
|
attr = 255;
|
||||||
REQUIRE(attr.size() == 255);
|
REQUIRE(attr.size() == 255);
|
||||||
REQUIRE(attr.options() == constraints::NONE);
|
REQUIRE(attr.options() == constraints::None);
|
||||||
|
|
||||||
attr = constraints::INDEX;
|
attr = constraints::Index;
|
||||||
REQUIRE(attr.size() == 0);
|
REQUIRE(attr.size() == 0);
|
||||||
REQUIRE(attr.options() == constraints::INDEX);
|
REQUIRE(attr.options() == constraints::Index);
|
||||||
|
|
||||||
attr = { 255, constraints::DEFAULT };
|
attr = { 255, constraints::Default };
|
||||||
REQUIRE(attr.size() == 255);
|
REQUIRE(attr.size() == 255);
|
||||||
REQUIRE(attr.options() == constraints::DEFAULT);
|
REQUIRE(attr.options() == constraints::Default);
|
||||||
|
|
||||||
field_attributes attr2{255};
|
field_attributes attr2{255};
|
||||||
REQUIRE(attr2.size() == 255);
|
REQUIRE(attr2.size() == 255);
|
||||||
REQUIRE(attr2.options() == constraints::NONE);
|
REQUIRE(attr2.options() == constraints::None);
|
||||||
|
|
||||||
field_attributes attr3{constraints::UNIQUE};
|
field_attributes attr3{constraints::Unique};
|
||||||
REQUIRE(attr3.size() == 0);
|
REQUIRE(attr3.size() == 0);
|
||||||
REQUIRE(attr3.options() == constraints::UNIQUE);
|
REQUIRE(attr3.options() == constraints::Unique);
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +48,7 @@ TEST_CASE_METHOD(QueryFixture, "Test create table sql statement string", "[query
|
||||||
auto ctx = query::create()
|
auto ctx = query::create()
|
||||||
.table("person", {
|
.table("person", {
|
||||||
make_pk_column<uint32_t>("id"),
|
make_pk_column<uint32_t>("id"),
|
||||||
make_column<std::string>("name", {255, constraints::UNIQUE}, null_option_type::NOT_NULL),
|
make_column<std::string>("name", {255, constraints::Unique}, null_option_type::NOT_NULL),
|
||||||
make_column<unsigned short>("age"),
|
make_column<unsigned short>("age"),
|
||||||
make_fk_column<uint32_t>("address", "address", "id")
|
make_fk_column<uint32_t>("address", "address", "id")
|
||||||
}).compile(*db);
|
}).compile(*db);
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ TEST_CASE("Test copy and move column", "[column]") {
|
||||||
"name",
|
"name",
|
||||||
basic_type::type_varchar,
|
basic_type::type_varchar,
|
||||||
2,
|
2,
|
||||||
std::make_shared<attribute>("author", basic_type::type_uint32, "books", attribute_options{constraints::FOREIGN_KEY}),
|
std::make_shared<attribute>("author", basic_type::type_uint32, "books", attribute_options{constraints::ForeignKey}),
|
||||||
{255, constraints::FOREIGN_KEY},
|
{255, constraints::ForeignKey},
|
||||||
null_option_type::NOT_NULL
|
null_option_type::NOT_NULL
|
||||||
);
|
);
|
||||||
REQUIRE(c.name() == "name");
|
REQUIRE(c.name() == "name");
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ TEST_CASE("Test field", "[field]") {
|
||||||
REQUIRE(bool_val.has_value());
|
REQUIRE(bool_val.has_value());
|
||||||
REQUIRE(bool_val.value());
|
REQUIRE(bool_val.value());
|
||||||
|
|
||||||
f = sql::field("name", utils::blob{ 7,8,6,5,4,3 }, utils::constraints::NONE, 0, 1);
|
f = sql::field("name", utils::blob{ 7,8,6,5,4,3 }, utils::constraints::None, 0, 1);
|
||||||
REQUIRE(f.index() == 1);
|
REQUIRE(f.index() == 1);
|
||||||
REQUIRE(!f.is_null());
|
REQUIRE(!f.is_null());
|
||||||
REQUIRE(!f.is_integer());
|
REQUIRE(!f.is_integer());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue