| @@ -19,74 +19,17 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| bool recreate; | bool recreate; | ||||
| }; | }; | ||||
| /* create context */ | |||||
| /* create_update_context */ | |||||
| struct create_context | |||||
| struct create_update_context | |||||
| { | { | ||||
| bool is_update; | |||||
| const schema_t& schema; | const schema_t& schema; | ||||
| const filter_t& filter; | |||||
| const table_t* derived_table; | const table_t* derived_table; | ||||
| const field_t* owner_field; | const field_t* owner_field; | ||||
| ::cppmariadb::connection& connection; | ::cppmariadb::connection& connection; | ||||
| }; | }; | ||||
| template<typename T_dataset> | |||||
| struct generic_create_context | |||||
| : public create_context | |||||
| { | |||||
| using dataset_type = mp::decay_t<T_dataset>; | |||||
| dataset_type& dataset; | |||||
| template<typename T_new_dataset> | |||||
| constexpr decltype(auto) change(T_new_dataset& new_dataset, const field_t* owner = nullptr) const | |||||
| { | |||||
| return generic_create_context<T_new_dataset> | |||||
| { | |||||
| { | |||||
| schema, | |||||
| nullptr, | |||||
| owner, | |||||
| connection | |||||
| }, | |||||
| new_dataset | |||||
| }; | |||||
| } | |||||
| }; | |||||
| /* update context */ | |||||
| struct update_context | |||||
| : public create_context | |||||
| { | |||||
| const filter_t& filter; | |||||
| }; | |||||
| template<typename T_dataset> | |||||
| struct generic_update_context | |||||
| : public update_context | |||||
| { | |||||
| using dataset_type = mp::decay_t<T_dataset>; | |||||
| dataset_type& dataset; | |||||
| template<typename T_new_dataset> | |||||
| constexpr decltype(auto) change(T_new_dataset& new_dataset, const field_t* owner = nullptr) const | |||||
| { | |||||
| return generic_update_context<T_new_dataset> | |||||
| { | |||||
| { | |||||
| { | |||||
| schema, | |||||
| nullptr, | |||||
| owner, | |||||
| connection | |||||
| }, | |||||
| filter, | |||||
| }, | |||||
| new_dataset | |||||
| }; | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| end_namespace_cpphibernate_driver_mariadb | end_namespace_cpphibernate_driver_mariadb | ||||
| @@ -15,6 +15,8 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| virtual ~reference_lock() = default; | virtual ~reference_lock() = default; | ||||
| }; | }; | ||||
| using reference_lock_ptr = std::unique_ptr<reference_lock>; | |||||
| /* reference_stack */ | /* reference_stack */ | ||||
| template<typename T_dataset> | template<typename T_dataset> | ||||
| @@ -1,4 +1,4 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <cpphibernate/driver/mariadb/impl/init.h> | #include <cpphibernate/driver/mariadb/impl/init.h> | ||||
| #include <cpphibernate/driver/mariadb/impl/create.h> | |||||
| #include <cpphibernate/driver/mariadb/impl/create_update.h> | |||||
| @@ -1,95 +0,0 @@ | |||||
| #pragma once | |||||
| #include <cppmariadb.h> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* create_impl_t */ | |||||
| template<typename T_context, typename = void> | |||||
| struct create_impl_t | |||||
| { | |||||
| using context_type = T_context; | |||||
| using dataset_type = typename context_type::dataset_type; | |||||
| using reference_stack_type = reference_stack<dataset_type>; | |||||
| static inline value_t apply(const context_type& context, bool strict = true) | |||||
| { | |||||
| value_t ret; | |||||
| auto dataset_id = misc::get_type_id(hana::type_c<dataset_type>); | |||||
| auto& connection = context.connection; | |||||
| auto& schema = context.schema; | |||||
| auto& table = schema.table(dataset_id); | |||||
| auto& dataset = context.dataset; | |||||
| auto ref_lock = reference_stack_type::push(dataset); | |||||
| transaction_lock trans(connection); | |||||
| ret = table.create(context); | |||||
| trans.commit(); | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| /* create_impl_t - nullable */ | |||||
| template<typename T_context> | |||||
| struct create_impl_t< | |||||
| T_context, | |||||
| mp::enable_if<misc::is_nullable<typename T_context::dataset_type>>> | |||||
| { | |||||
| using context_type = T_context; | |||||
| using dataset_type = typename context_type::dataset_type; | |||||
| using nullable_helper_type = misc::nullable_helper<dataset_type>; | |||||
| static inline value_t apply(const context_type& context, bool strict = true) | |||||
| { | |||||
| value_t ret; | |||||
| auto& dataset = context.dataset; | |||||
| auto* value = nullable_helper_type::get(dataset); | |||||
| if (value) | |||||
| { | |||||
| using new_context_type = mp::decay_t<decltype(context.change(*value))>; | |||||
| using new_create_impl_type = create_impl_t<new_context_type>; | |||||
| ret = new_create_impl_type::apply(context.change(*value)); | |||||
| } | |||||
| else if (strict) | |||||
| { | |||||
| throw misc::hibernate_exception("can not create nullable type with no value!"); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| /* create_impl_t - container */ | |||||
| template<typename T_context> | |||||
| struct create_impl_t< | |||||
| T_context, | |||||
| mp::enable_if<misc::is_container<typename T_context::dataset_type>>> | |||||
| { | |||||
| using context_type = T_context; | |||||
| static inline value_t apply(const context_type& context, bool strict = true) | |||||
| { | |||||
| value_t ret; | |||||
| auto& connection = context.connection; | |||||
| auto& dataset = context.dataset; | |||||
| transaction_lock trans(connection); | |||||
| for (auto& x : dataset) | |||||
| { | |||||
| using new_context_type = mp::decay_t<decltype(context.change(x))>; | |||||
| using new_create_impl_type = create_impl_t<new_context_type>; | |||||
| new_create_impl_type::apply(context.change(x, context.owner_field)); | |||||
| } | |||||
| trans.commit(); | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,105 @@ | |||||
| #pragma once | |||||
| #include <cppmariadb.h> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* create_update_impl_t */ | |||||
| template<typename T_dataset, typename = void> | |||||
| struct create_update_impl_t | |||||
| { | |||||
| using dataset_type = T_dataset; | |||||
| using reference_stack_type = reference_stack<dataset_type>; | |||||
| static inline value_t apply(dataset_type& dataset, const create_update_context& context, bool strict = true) | |||||
| { | |||||
| value_t ret; | |||||
| auto dataset_id = misc::get_type_id(hana::type_c<dataset_type>); | |||||
| auto& connection = context.connection; | |||||
| auto& schema = context.schema; | |||||
| auto& table = schema.table(dataset_id); | |||||
| auto ref_lock = reference_stack_type::push(dataset); | |||||
| assert(table.primary_key_field); | |||||
| transaction_lock trans(connection); | |||||
| if (table.primary_key_field->is_default()) | |||||
| { | |||||
| ret = table.create_update(context); | |||||
| } | |||||
| else if (strict) | |||||
| { | |||||
| throw misc::hibernate_exception("dataset have already a primary key assigned!"); | |||||
| } | |||||
| else | |||||
| { | |||||
| auto update_context = context; | |||||
| update_context.is_update = true; | |||||
| ret = table.create_update(update_context); | |||||
| } | |||||
| trans.commit(); | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| /* create_update_impl_t - nullable */ | |||||
| template<typename T_dataset> | |||||
| struct create_update_impl_t< | |||||
| T_dataset, | |||||
| mp::enable_if<misc::is_nullable<T_dataset>>> | |||||
| { | |||||
| using dataset_type = T_dataset; | |||||
| using nullable_helper_type = misc::nullable_helper<dataset_type>; | |||||
| static inline value_t apply(dataset_type& dataset, const create_update_context& context, bool strict = true) | |||||
| { | |||||
| value_t ret; | |||||
| auto* value = nullable_helper_type::get(dataset); | |||||
| if (value) | |||||
| { | |||||
| using new_dataset_type = mp::decay_t<decltype(*value)>; | |||||
| using new_create_update_impl_type = create_update_impl_t<new_dataset_type>; | |||||
| ret = new_create_update_impl_type::apply(*value, context, strict); | |||||
| } | |||||
| else if (strict) | |||||
| { | |||||
| throw misc::hibernate_exception("can not create nullable type with no value!"); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| /* create_update_impl_t - container */ | |||||
| template<typename T_dataset> | |||||
| struct create_update_impl_t< | |||||
| T_dataset, | |||||
| mp::enable_if<misc::is_container<T_dataset>>> | |||||
| { | |||||
| using dataset_type = T_dataset; | |||||
| static inline value_t apply(dataset_type& dataset, const create_update_context& context, bool strict = true) | |||||
| { | |||||
| value_t ret; | |||||
| auto& connection = context.connection; | |||||
| transaction_lock trans(connection); | |||||
| for (auto& x : dataset) | |||||
| { | |||||
| using new_dataset_type = mp::decay_t<decltype(x)>; | |||||
| using new_create_update_impl_type = create_update_impl_t<new_dataset_type>; | |||||
| new_create_update_impl_type::apply(x, context, strict); | |||||
| } | |||||
| trans.commit(); | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -4,6 +4,7 @@ | |||||
| #include <cpphibernate/config.h> | #include <cpphibernate/config.h> | ||||
| #include <cpphibernate/driver/mariadb/impl.h> | #include <cpphibernate/driver/mariadb/impl.h> | ||||
| #include <cpphibernate/driver/mariadb/schema.h> | #include <cpphibernate/driver/mariadb/schema.h> | ||||
| #include <cpphibernate/driver/mariadb/schema/filter.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | beg_namespace_cpphibernate_driver_mariadb | ||||
| { | { | ||||
| @@ -13,6 +14,7 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| private: | private: | ||||
| ::cppmariadb::connection& _connection; | ::cppmariadb::connection& _connection; | ||||
| schema_t _schema; | schema_t _schema; | ||||
| filter_t _filter; | |||||
| public: | public: | ||||
| template<typename T_schema> | template<typename T_schema> | ||||
| @@ -38,17 +40,17 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| template<typename T_dataset> | template<typename T_dataset> | ||||
| inline void create_impl(T_dataset& dataset) const | inline void create_impl(T_dataset& dataset) const | ||||
| { | { | ||||
| using create_context_type = generic_create_context<T_dataset>; | |||||
| create_impl_t<create_context_type>::apply(create_context_type | |||||
| { | |||||
| create_update_impl_t<T_dataset>::apply( | |||||
| dataset, | |||||
| create_update_context | |||||
| { | { | ||||
| true, | |||||
| _schema, | _schema, | ||||
| _filter, | |||||
| nullptr, | nullptr, | ||||
| nullptr, | nullptr, | ||||
| _connection | _connection | ||||
| }, | |||||
| dataset | |||||
| }); | |||||
| }); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -48,14 +48,14 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| void print(std::ostream& os) const; | void print(std::ostream& os) const; | ||||
| /* CRUD */ | /* CRUD */ | ||||
| virtual value_t foreign_create(const create_context& context) const; | |||||
| virtual value_t foreign_update(const update_context& context) const; | |||||
| virtual value_t foreign_create_update(const create_update_context& context) const; | |||||
| /* properties */ | /* properties */ | ||||
| virtual std::string type () const; | virtual std::string type () const; | ||||
| virtual std::string create_table_arguments () const; | virtual std::string create_table_arguments () const; | ||||
| virtual std::string generate_value (::cppmariadb::connection& connection) const; | virtual std::string generate_value (::cppmariadb::connection& connection) const; | ||||
| virtual bool is_auto_generated () const; | virtual bool is_auto_generated () const; | ||||
| virtual bool is_default () const; | |||||
| virtual std::string convert_to_open () const; | virtual std::string convert_to_open () const; | ||||
| virtual std::string convert_to_close () const; | virtual std::string convert_to_close () const; | ||||
| virtual std::string convert_from_open () const; | virtual std::string convert_from_open () const; | ||||
| @@ -102,7 +102,6 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| using ref_stack = typename base_type::ref_stack; | using ref_stack = typename base_type::ref_stack; | ||||
| using type_props = type_properties<value_type>; | using type_props = type_properties<value_type>; | ||||
| using base_type::base_type; | using base_type::base_type; | ||||
| virtual std::string type() const override; | virtual std::string type() const override; | ||||
| @@ -120,6 +119,7 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| using schema_type = typename base_type::schema_type; | using schema_type = typename base_type::schema_type; | ||||
| using field_type = typename base_type::field_type; | using field_type = typename base_type::field_type; | ||||
| using value_type = typename base_type::value_type; | using value_type = typename base_type::value_type; | ||||
| using ref_stack = typename base_type::ref_stack; | |||||
| using key_props = key_properties<value_type>; | using key_props = key_properties<value_type>; | ||||
| using base_type::base_type; | using base_type::base_type; | ||||
| @@ -127,6 +127,7 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| virtual std::string create_table_arguments () const override; | virtual std::string create_table_arguments () const override; | ||||
| virtual std::string generate_value (::cppmariadb::connection& connection) const override; | virtual std::string generate_value (::cppmariadb::connection& connection) const override; | ||||
| virtual bool is_auto_generated () const override; | virtual bool is_auto_generated () const override; | ||||
| virtual bool is_default () const override; | |||||
| virtual std::string convert_to_open () const override; | virtual std::string convert_to_open () const override; | ||||
| virtual std::string convert_to_close () const override; | virtual std::string convert_to_close () const override; | ||||
| virtual std::string convert_from_open () const override; | virtual std::string convert_from_open () const override; | ||||
| @@ -158,8 +159,7 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| using base_type::base_type; | using base_type::base_type; | ||||
| public: | public: | ||||
| virtual value_t foreign_create(const create_context& context) const override; | |||||
| virtual value_t foreign_update(const update_context& context) const override; | |||||
| virtual value_t foreign_create_update(const create_update_context& context) const override; | |||||
| }; | }; | ||||
| namespace __impl | namespace __impl | ||||
| @@ -1,7 +1,7 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <cpphibernate/driver/mariadb/impl/create.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/field.h> | #include <cpphibernate/driver/mariadb/schema/field.h> | ||||
| #include <cpphibernate/driver/mariadb/impl/create_update.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | beg_namespace_cpphibernate_driver_mariadb | ||||
| { | { | ||||
| @@ -40,6 +40,10 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| bool primary_key_field_t<T_schema, T_field>::is_auto_generated() const | bool primary_key_field_t<T_schema, T_field>::is_auto_generated() const | ||||
| { return key_props::auto_generated::value; } | { return key_props::auto_generated::value; } | ||||
| template<typename T_schema, typename T_field> | |||||
| bool primary_key_field_t<T_schema, T_field>::is_default() const | |||||
| { return key_props::is_default(this->field.getter(ref_stack::top())); } | |||||
| template<typename T_schema, typename T_field> | template<typename T_schema, typename T_field> | ||||
| std::string primary_key_field_t<T_schema, T_field>::convert_to_open() const | std::string primary_key_field_t<T_schema, T_field>::convert_to_open() const | ||||
| { return key_props::convert_to_open; } | { return key_props::convert_to_open; } | ||||
| @@ -60,34 +64,17 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| template<typename T_schema, typename T_field> | template<typename T_schema, typename T_field> | ||||
| value_t foreign_table_field_t<T_schema, T_field> | value_t foreign_table_field_t<T_schema, T_field> | ||||
| ::foreign_create(const create_context& context) const | |||||
| ::foreign_create_update(const create_update_context& context) const | |||||
| { | { | ||||
| auto& ref = ref_stack::top(); | auto& ref = ref_stack::top(); | ||||
| auto& foreign = this->field.getter(ref); | auto& foreign = this->field.getter(ref); | ||||
| using foreign_dataset_type = mp::decay_t<decltype(foreign)>; | using foreign_dataset_type = mp::decay_t<decltype(foreign)>; | ||||
| using create_context_type = generic_create_context<foreign_dataset_type>; | |||||
| return create_impl_t<create_context_type>::apply( | |||||
| create_context_type | |||||
| { | |||||
| context, | |||||
| foreign, | |||||
| }, | |||||
| false); | |||||
| } | |||||
| template<typename T_schema, typename T_field> | |||||
| value_t foreign_table_field_t<T_schema, T_field> | |||||
| ::foreign_update(const update_context& ctx) const | |||||
| { | |||||
| /* | |||||
| auto& context = static_cast<const generic_create_context<dataset_type>&>(ctx); | |||||
| auto& ref = ref_stack::top(); | |||||
| auto& foreign = this->field.getter(ref); | |||||
| return foreign_create_update_helper<update_impl_t>(context.change(foreign)); | |||||
| */ | |||||
| return value_t { }; | |||||
| return create_update_impl_t<foreign_dataset_type>::apply( | |||||
| foreign, | |||||
| context, | |||||
| false); | |||||
| } | } | ||||
| } | } | ||||
| @@ -70,16 +70,19 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| inline void init(const init_context& context) const | inline void init(const init_context& context) const | ||||
| { return init_exec(context); } | { return init_exec(context); } | ||||
| inline decltype(auto) create(const create_context& context) const | |||||
| { return create_intern(context); } | |||||
| inline decltype(auto) create_update(const create_update_context& context) const | |||||
| { return create_update_intern(context); } | |||||
| inline void read() const | inline void read() const | ||||
| { } | { } | ||||
| inline void update(const update_context& context) const | |||||
| { update_intern(context); } | |||||
| private: | private: | ||||
| template<typename T_schema, typename T_table, typename T_base_dataset> | |||||
| friend struct table_simple_t; | |||||
| template<typename T_schema, typename T_table, typename T_base_dataset> | |||||
| friend struct table_polymorphic_t; | |||||
| using statement_ptr = std::unique_ptr<::cppmariadb::statement>; | using statement_ptr = std::unique_ptr<::cppmariadb::statement>; | ||||
| mutable statement_ptr _statement_create_table; | mutable statement_ptr _statement_create_table; | ||||
| @@ -89,18 +92,17 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| ::cppmariadb::statement& get_statement_insert_into() const; | ::cppmariadb::statement& get_statement_insert_into() const; | ||||
| std::string execute_insert_update( | std::string execute_insert_update( | ||||
| const create_context& context, | |||||
| ::cppmariadb::statement& statement, | |||||
| const filter_t* filter) const; | |||||
| const create_update_context& context, | |||||
| ::cppmariadb::statement& statement, | |||||
| const filter_t* filter) const; | |||||
| protected: | |||||
| void init_exec (const init_context& context) const; | |||||
| virtual std::string create_update_base(const create_update_context& context) const; | |||||
| virtual std::string create_intern (const create_context& context) const; | |||||
| std::string create_exec (const create_context& context) const; | |||||
| protected: | |||||
| void init_exec (const init_context& context) const; | |||||
| virtual std::string update_intern (const update_context& context) const; | |||||
| std::string update_exec (const update_context& context) const; | |||||
| virtual std::string create_update_intern(const create_update_context& context) const; | |||||
| std::string create_update_exec (const create_update_context& context) const; | |||||
| }; | }; | ||||
| /* table_simple_t */ | /* table_simple_t */ | ||||
| @@ -152,7 +154,10 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| constexpr void for_each_derived(T_dataset& dataset, const T_include_self& include_self, const T_pred& pred) const; | constexpr void for_each_derived(T_dataset& dataset, const T_include_self& include_self, const T_pred& pred) const; | ||||
| protected: | protected: | ||||
| virtual std::string create_intern(const create_context& context) const override; | |||||
| virtual std::string create_update_intern(const create_update_context& context) const override; | |||||
| private: | |||||
| virtual std::string create_update_base(const create_update_context& context) const override; | |||||
| }; | }; | ||||
| namespace __impl | namespace __impl | ||||
| @@ -33,11 +33,10 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| template<typename T_schema, typename T_table, typename T_base_dataset> | template<typename T_schema, typename T_table, typename T_base_dataset> | ||||
| std::string table_polymorphic_t<T_schema, T_table, T_base_dataset> | std::string table_polymorphic_t<T_schema, T_table, T_base_dataset> | ||||
| ::create_intern(const create_context& ctx) const | |||||
| ::create_update_intern(const create_update_context& context) const | |||||
| { | { | ||||
| bool done = false; | bool done = false; | ||||
| auto& context = static_cast<const generic_create_context<dataset_type>&>(ctx); | |||||
| auto& dataset = context.dataset; | |||||
| auto& dataset = reference_stack<dataset_type>::top(); | |||||
| for_each_derived(dataset, hana::false_c, [&](auto& derived_dataset){ | for_each_derived(dataset, hana::false_c, [&](auto& derived_dataset){ | ||||
| if (!done) | if (!done) | ||||
| { | { | ||||
| @@ -46,16 +45,40 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| auto derived_dataset_id = misc::get_type_id(hana::type_c<derived_dataset_type>); | auto derived_dataset_id = misc::get_type_id(hana::type_c<derived_dataset_type>); | ||||
| auto derived_table = this->get_derived(derived_dataset_id); | auto derived_table = this->get_derived(derived_dataset_id); | ||||
| if (!derived_table) | if (!derived_table) | ||||
| throw misc::hibernate_exception(std::string("unable to find derived table info for dataset '") + utl::type_helper<derived_dataset_type>::name() + "'!"); | |||||
| { | |||||
| throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { } | |||||
| << "unable to find derived table info for dataset '" | |||||
| << utl::type_helper<derived_dataset_type>::name() << "'!").str()); | |||||
| } | |||||
| auto ref_lock = reference_stack_type::push(derived_dataset); | auto ref_lock = reference_stack_type::push(derived_dataset); | ||||
| derived_table->create(context.change(derived_dataset, context.owner_field)); | |||||
| derived_table->create_update(context); | |||||
| done = true; | done = true; | ||||
| } | } | ||||
| }); | }); | ||||
| return done | return done | ||||
| ? *this->primary_key_field->get() | ? *this->primary_key_field->get() | ||||
| : this->create_exec(context); | |||||
| : this->create_update_exec(context); | |||||
| } | |||||
| template<typename T_schema, typename T_table, typename T_base_dataset> | |||||
| std::string table_polymorphic_t<T_schema, T_table, T_base_dataset> | |||||
| ::create_update_base(const create_update_context& context) const | |||||
| { | |||||
| return hana::eval_if( | |||||
| mp::is_same<base_dataset_type, void> { }, | |||||
| [this]()->std::string { | |||||
| throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { } | |||||
| << "'" << this->table_name << "' does not have a base table").str()); | |||||
| }, | |||||
| [this, &context](auto _)->std::string { | |||||
| using tmp_type = misc::decay_unwrap_t<decltype(_(hana::type_c<base_dataset_type>))>; | |||||
| assert(base_table); | |||||
| auto& dataset = reference_stack<dataset_type>::top(); | |||||
| auto& base = static_cast<tmp_type&>(dataset); | |||||
| auto lock = reference_stack<tmp_type>::push(base); | |||||
| return this->base_table->create_update_exec(context); | |||||
| }); | |||||
| } | } | ||||
| } | } | ||||
| @@ -41,11 +41,11 @@ void field_t::print(std::ostream& os) const | |||||
| /* CRUD */ | /* CRUD */ | ||||
| throw_not_implemented(value_t, foreign_create, const create_context&) | |||||
| throw_not_implemented(value_t, foreign_update, const update_context&) | |||||
| throw_not_implemented(value_t, foreign_create_update, const create_update_context&) | |||||
| /* properties */ | /* properties */ | ||||
| throw_not_implemented(bool, is_default) | |||||
| throw_not_implemented(string, type) | throw_not_implemented(string, type) | ||||
| throw_not_implemented(string, create_table_arguments) | throw_not_implemented(string, create_table_arguments) | ||||
| throw_not_implemented(string, generate_value, ::cppmariadb::connection&) | throw_not_implemented(string, generate_value, ::cppmariadb::connection&) | ||||
| @@ -472,9 +472,9 @@ std::string build_insert_update_query(const table_t& table, const filter_t* filt | |||||
| /* execute_insert_update */ | /* execute_insert_update */ | ||||
| std::string table_t::execute_insert_update( | std::string table_t::execute_insert_update( | ||||
| const create_context& context, | |||||
| ::cppmariadb::statement& statement, | |||||
| const filter_t* filter) const | |||||
| const create_update_context& context, | |||||
| ::cppmariadb::statement& statement, | |||||
| const filter_t* filter) const | |||||
| { | { | ||||
| auto& connection = context.connection; | auto& connection = context.connection; | ||||
| @@ -503,21 +503,10 @@ std::string table_t::execute_insert_update( | |||||
| && ( !is_update | && ( !is_update | ||||
| || filter->contains(base_table, true))) | || filter->contains(base_table, true))) | ||||
| { | { | ||||
| std::string key; | |||||
| if (is_update) | |||||
| { | |||||
| auto new_context = static_cast<const update_context&>(context); | |||||
| if (!new_context.derived_table) | |||||
| new_context.derived_table = this; | |||||
| key = base_table->update_exec(new_context); | |||||
| } | |||||
| else | |||||
| { | |||||
| auto new_context = context; | |||||
| if (!new_context.derived_table) | |||||
| new_context.derived_table = this; | |||||
| key = base_table->create_exec(new_context); | |||||
| } | |||||
| auto new_context = context; | |||||
| if (!new_context.derived_table) | |||||
| new_context.derived_table = this; | |||||
| std::string key = create_update_base(new_context); | |||||
| statement.set(index, std::move(key)); | statement.set(index, std::move(key)); | ||||
| ++index; | ++index; | ||||
| } | } | ||||
| @@ -531,9 +520,7 @@ std::string table_t::execute_insert_update( | |||||
| assert(ptr); | assert(ptr); | ||||
| if (is_update && !filter->contains(ptr)) | if (is_update && !filter->contains(ptr)) | ||||
| continue; | continue; | ||||
| value_t key = !is_update | |||||
| ? ptr->foreign_create(context) | |||||
| : ptr->foreign_update(static_cast<const update_context&>(context)); | |||||
| value_t key = ptr->foreign_create_update(context); | |||||
| if (key.has_value()) statement.set(index, std::move(key)); | if (key.has_value()) statement.set(index, std::move(key)); | ||||
| else statement.set_null(index); | else statement.set_null(index); | ||||
| ++index; | ++index; | ||||
| @@ -621,18 +608,9 @@ std::string table_t::execute_insert_update( | |||||
| || !filter->contains(ptr->referenced_table, true))) | || !filter->contains(ptr->referenced_table, true))) | ||||
| continue; | continue; | ||||
| if (!is_update) | |||||
| { | |||||
| auto next_context = context; | |||||
| next_context.owner_field = ptr; | |||||
| ptr->foreign_create(next_context); | |||||
| } | |||||
| else | |||||
| { | |||||
| auto next_context = static_cast<const update_context&>(context); | |||||
| next_context.owner_field = ptr; | |||||
| ptr->foreign_update(next_context); | |||||
| } | |||||
| auto next_context = context; | |||||
| next_context.owner_field = ptr; | |||||
| ptr->foreign_create_update(next_context); | |||||
| } | } | ||||
| return primary_key; | return primary_key; | ||||
| @@ -708,6 +686,12 @@ const table_t* table_t::get_derived(size_t id) const | |||||
| return *_statement_create_table; | return *_statement_create_table; | ||||
| } | } | ||||
| std::string table_t::create_update_base(const create_update_context& context) const | |||||
| { | |||||
| throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { } | |||||
| << "'" << this->table_name << "' does not implement create_update_base!").str()); | |||||
| } | |||||
| void table_t::init_exec(const init_context& context) const | void table_t::init_exec(const init_context& context) const | ||||
| { | { | ||||
| auto& statement = get_statement_create_table(); | auto& statement = get_statement_create_table(); | ||||
| @@ -716,19 +700,11 @@ void table_t::init_exec(const init_context& context) const | |||||
| connection.execute(statement); | connection.execute(statement); | ||||
| } | } | ||||
| std::string table_t::create_exec(const create_context& context) const | |||||
| std::string table_t::create_update_exec(const create_update_context& context) const | |||||
| { | { | ||||
| auto& statement = get_statement_insert_into(); | auto& statement = get_statement_insert_into(); | ||||
| return execute_insert_update(context, statement, nullptr); | return execute_insert_update(context, statement, nullptr); | ||||
| } | } | ||||
| std::string table_t::update_exec(const update_context& context) const | |||||
| { | |||||
| return std::string(); | |||||
| } | |||||
| std::string table_t::create_intern(const create_context& context) const | |||||
| { return create_exec(context); } | |||||
| std::string table_t::update_intern(const update_context& context) const | |||||
| { return update_exec(context); } | |||||
| std::string table_t::create_update_intern(const create_update_context& context) const | |||||
| { return create_update_exec(context); } | |||||
| @@ -6,7 +6,7 @@ | |||||
| using namespace ::testing; | using namespace ::testing; | ||||
| using namespace ::cpphibernate; | using namespace ::cpphibernate; | ||||
| /* | |||||
| TEST(CppHibernateTests, create_test1) | TEST(CppHibernateTests, create_test1) | ||||
| { | { | ||||
| StrictMock<mariadb_mock> mock; | StrictMock<mariadb_mock> mock; | ||||
| @@ -279,7 +279,7 @@ TEST(CppHibernateTests, create_derived2) | |||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | auto context = make_context<driver::mariadb>(test_schema, connection); | ||||
| context.create(static_cast<base&>(d2)); | context.create(static_cast<base&>(d2)); | ||||
| } | } | ||||
| */ | |||||
| TEST(CppHibernateTests, create_derived3) | TEST(CppHibernateTests, create_derived3) | ||||
| { | { | ||||
| StrictMock<mariadb_mock> mock; | StrictMock<mariadb_mock> mock; | ||||
| @@ -435,5 +435,5 @@ TEST(CppHibernateTests, create_derived3) | |||||
| ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111)); | ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111)); | ||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | auto context = make_context<driver::mariadb>(test_schema, connection); | ||||
| context.create(static_cast<base&>(d3)); | |||||
| } | |||||
| context.create(static_cast<derived2&>(d3)); | |||||
| } | |||||