| @@ -32,7 +32,7 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| if (!strict) | if (!strict) | ||||
| { | { | ||||
| auto update_context = context; | auto update_context = context; | ||||
| update_context.is_update = true; | |||||
| update_context.is_update = !update_context.is_update; | |||||
| ret = table.create_update(update_context); | ret = table.create_update(update_context); | ||||
| } | } | ||||
| else if (context.is_update) | else if (context.is_update) | ||||
| @@ -12,6 +12,8 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| namespace __impl | namespace __impl | ||||
| { | { | ||||
| /* declaration */ | |||||
| template<typename T, typename = void> | template<typename T, typename = void> | ||||
| struct make_read_context_impl | struct make_read_context_impl | ||||
| { | { | ||||
| @@ -20,6 +22,8 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_read_context(...)!"); } | { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_read_context(...)!"); } | ||||
| }; | }; | ||||
| /* normal datasets */ | |||||
| template<typename T_dataset, typename... T_args> | template<typename T_dataset, typename... T_args> | ||||
| struct make_read_context_impl< | struct make_read_context_impl< | ||||
| mp::list<T_dataset, T_args...>, | mp::list<T_dataset, T_args...>, | ||||
| @@ -69,6 +73,8 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| { return context_impl(dataset, std::forward<T_args>(args)...); } | { return context_impl(dataset, std::forward<T_args>(args)...); } | ||||
| }; | }; | ||||
| /* nullable datasets */ | |||||
| template<typename T_dataset, typename... T_args> | template<typename T_dataset, typename... T_args> | ||||
| struct make_read_context_impl< | struct make_read_context_impl< | ||||
| mp::list<T_dataset, T_args...>, | mp::list<T_dataset, T_args...>, | ||||
| @@ -131,6 +137,8 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| { return context_impl(dataset, std::forward<T_args>(args)...); } | { return context_impl(dataset, std::forward<T_args>(args)...); } | ||||
| }; | }; | ||||
| /* container datasets */ | |||||
| template<typename T_dataset, typename... T_args> | template<typename T_dataset, typename... T_args> | ||||
| struct make_read_context_impl< | struct make_read_context_impl< | ||||
| mp::list<T_dataset, T_args...>, | mp::list<T_dataset, T_args...>, | ||||
| @@ -58,6 +58,13 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| table.read(context); | table.read(context); | ||||
| trans.commit(); | trans.commit(); | ||||
| } | } | ||||
| template<typename T_dataset> | |||||
| inline void update_impl(T_dataset& dataset) const | |||||
| { | |||||
| create_update_impl_t<T_dataset>::apply( | |||||
| create_update_context(dataset, _schema, _connection, _filter, true)); | |||||
| } | |||||
| }; | }; | ||||
| } | } | ||||
| @@ -17,6 +17,7 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| struct field_t | struct field_t | ||||
| { | { | ||||
| public: | |||||
| size_t id { 0 }; // unique id of the field | size_t id { 0 }; // unique id of the field | ||||
| size_t dataset_id { 0 }; // unique id of the dataset type | size_t dataset_id { 0 }; // unique id of the dataset type | ||||
| size_t real_dataset_id { 0 }; // unique id of the real/unwrapped dataset type | size_t real_dataset_id { 0 }; // unique id of the real/unwrapped dataset type | ||||
| @@ -86,6 +87,16 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| virtual void set (const data_context& context, const value_t&) const; | virtual void set (const data_context& context, const value_t&) const; | ||||
| virtual bool is_default (const data_context& context) const; | virtual bool is_default (const data_context& context) const; | ||||
| virtual std::string generate_value (::cppmariadb::connection& connection) const; | virtual std::string generate_value (::cppmariadb::connection& connection) const; | ||||
| /* statements */ | |||||
| virtual ::cppmariadb::statement& get_statement_foreign_one_delete(bool key_known) const; | |||||
| virtual ::cppmariadb::statement& get_statement_foreign_many_update() const; | |||||
| protected: | |||||
| using statement_ptr = std::unique_ptr<::cppmariadb::statement>; | |||||
| ::cppmariadb::statement& get_statement_foreign_one_delete_impl(bool key_known, statement_ptr& known, statement_ptr& unknown) const; | |||||
| ::cppmariadb::statement& get_statement_foreign_many_update_impl(statement_ptr& statement) const; | |||||
| }; | }; | ||||
| /* simple_field_t */ | /* simple_field_t */ | ||||
| @@ -181,8 +192,20 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| using base_type::base_type; | using base_type::base_type; | ||||
| public: | public: | ||||
| /* CRUD */ | |||||
| virtual value_t foreign_create_update(const create_update_context& context) const override; | virtual value_t foreign_create_update(const create_update_context& context) const override; | ||||
| virtual read_context_ptr foreign_read (const read_context& context, bool fake_context) const override; | virtual read_context_ptr foreign_read (const read_context& context, bool fake_context) const override; | ||||
| /* statements */ | |||||
| virtual ::cppmariadb::statement& get_statement_foreign_one_delete(bool key_known) const override; | |||||
| virtual ::cppmariadb::statement& get_statement_foreign_many_update() const override; | |||||
| private: | |||||
| using statement_ptr = std::unique_ptr<::cppmariadb::statement>; | |||||
| mutable statement_ptr _statement_foreign_one_delete_key_known; | |||||
| mutable statement_ptr _statement_foreign_one_delete_key_unknown; | |||||
| mutable statement_ptr _statement_foreign_many_update; | |||||
| }; | }; | ||||
| } | } | ||||
| @@ -108,6 +108,21 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| } | } | ||||
| } | } | ||||
| template<typename T_field> | |||||
| ::cppmariadb::statement& foreign_table_field_t<T_field> | |||||
| ::get_statement_foreign_one_delete(bool key_known) const | |||||
| { | |||||
| return base_type::get_statement_foreign_one_delete_impl( | |||||
| key_known, | |||||
| _statement_foreign_one_delete_key_known, | |||||
| _statement_foreign_one_delete_key_unknown); | |||||
| } | |||||
| template<typename T_field> | |||||
| ::cppmariadb::statement& foreign_table_field_t<T_field> | |||||
| ::get_statement_foreign_many_update() const | |||||
| { return base_type::get_statement_foreign_many_update_impl(_statement_foreign_many_update); } | |||||
| namespace __impl | namespace __impl | ||||
| { | { | ||||
| @@ -90,23 +90,27 @@ beg_namespace_cpphibernate_driver_mariadb | |||||
| friend struct table_polymorphic_t; | friend struct table_polymorphic_t; | ||||
| using statement_ptr = std::unique_ptr<::cppmariadb::statement>; | using statement_ptr = std::unique_ptr<::cppmariadb::statement>; | ||||
| using statement_map = std::map<size_t, ::cppmariadb::statement>; | |||||
| using map_key = std::tuple<size_t, const field_t*>; | |||||
| using statement_map = std::map<map_key, ::cppmariadb::statement>; | |||||
| mutable statement_ptr _statement_create_table; | mutable statement_ptr _statement_create_table; | ||||
| mutable statement_ptr _statement_alter_table; | mutable statement_ptr _statement_alter_table; | ||||
| mutable statement_ptr _statement_insert_into; | mutable statement_ptr _statement_insert_into; | ||||
| mutable statement_map _statement_select_static; | mutable statement_map _statement_select_static; | ||||
| mutable statement_map _statement_select_dynamic; | mutable statement_map _statement_select_dynamic; | ||||
| mutable statement_map _statement_update; | |||||
| mutable statement_ptr _statement_foreign_many_delete; | |||||
| ::cppmariadb::statement& get_statement_create_table() const; | ::cppmariadb::statement& get_statement_create_table() const; | ||||
| ::cppmariadb::statement* get_statement_alter_table() const; | ::cppmariadb::statement* get_statement_alter_table() const; | ||||
| ::cppmariadb::statement& get_statement_insert_into() const; | ::cppmariadb::statement& get_statement_insert_into() const; | ||||
| ::cppmariadb::statement& get_statement_select(const read_context& context) const; | ::cppmariadb::statement& get_statement_select(const read_context& context) const; | ||||
| ::cppmariadb::statement& get_statement_update(const filter_t& filter, const field_t* owner) const; | |||||
| ::cppmariadb::statement& get_statement_foreign_many_delete() const; | |||||
| std::string execute_create_update( | std::string execute_create_update( | ||||
| const create_update_context& context, | const create_update_context& context, | ||||
| ::cppmariadb::statement& statement, | |||||
| const filter_t* filter) const; | |||||
| ::cppmariadb::statement& statement) const; | |||||
| virtual std::string create_update_base(const create_update_context& context) const; | virtual std::string create_update_base(const create_update_context& context) const; | ||||
| @@ -158,4 +158,116 @@ throw_not_implemented(read_context_ptr, foreign_read, const read_contex | |||||
| throw_not_implemented(bool, is_default, const data_context& context) | throw_not_implemented(bool, is_default, const data_context& context) | ||||
| throw_not_implemented(string, generate_value, ::cppmariadb::connection&) | throw_not_implemented(string, generate_value, ::cppmariadb::connection&) | ||||
| throw_not_implemented(value_t, get, const data_context& context) | throw_not_implemented(value_t, get, const data_context& context) | ||||
| throw_not_implemented(void, set, const data_context& context, const value_t&) | |||||
| throw_not_implemented(void, set, const data_context& context, const value_t&) | |||||
| /* statements */ | |||||
| throw_not_implemented(::cppmariadb::statement&, get_statement_foreign_one_delete, bool) | |||||
| throw_not_implemented(::cppmariadb::statement&, get_statement_foreign_many_update) | |||||
| ::cppmariadb::statement& field_t::get_statement_foreign_one_delete_impl(bool key_known, statement_ptr& known, statement_ptr& unknown) const | |||||
| { | |||||
| assert(table); | |||||
| assert(table->primary_key_field); | |||||
| assert(referenced_table); | |||||
| assert(referenced_table->primary_key_field); | |||||
| if (key_known) | |||||
| { | |||||
| if (!known) | |||||
| { | |||||
| auto& key_info = *table->primary_key_field; | |||||
| auto& ref_key_info = *referenced_table->primary_key_field; | |||||
| std::ostringstream os; | |||||
| os << "DELETE FROM `" | |||||
| << ref_key_info.table_name | |||||
| << "` WHERE `" | |||||
| << ref_key_info.field_name | |||||
| << "` IN (SELECT `" | |||||
| << ref_key_info.table_name | |||||
| << "_id_" | |||||
| << field_name | |||||
| << "` FROM `" | |||||
| << key_info.table_name | |||||
| << "` WHERE `" | |||||
| << key_info.field_name | |||||
| << "`=" | |||||
| << key_info.convert_to_open | |||||
| << "?\?" | |||||
| << key_info.convert_to_close | |||||
| << " AND `" | |||||
| << ref_key_info.table_name | |||||
| << "_id_" | |||||
| << field_name | |||||
| << "`!= " | |||||
| << ref_key_info.convert_to_open | |||||
| << "?\?" | |||||
| << ref_key_info.convert_to_close | |||||
| << ")"; | |||||
| known.reset(new ::cppmariadb::statement(os.str())); | |||||
| } | |||||
| return *known; | |||||
| } | |||||
| else | |||||
| { | |||||
| if (!unknown) | |||||
| { | |||||
| auto& key_info = *table->primary_key_field; | |||||
| auto& ref_key_info = *referenced_table->primary_key_field; | |||||
| std::ostringstream os; | |||||
| os << "DELETE FROM `" | |||||
| << ref_key_info.table_name | |||||
| << "` WHERE `" | |||||
| << ref_key_info.field_name | |||||
| << "` IN (SELECT `" | |||||
| << ref_key_info.table_name | |||||
| << "_id_" | |||||
| << field_name | |||||
| << "` FROM `" | |||||
| << key_info.table_name | |||||
| << "` WHERE `" | |||||
| << key_info.field_name | |||||
| << "`=" | |||||
| << key_info.convert_to_open | |||||
| << "?\?" | |||||
| << key_info.convert_to_close | |||||
| << ")"; | |||||
| unknown.reset(new ::cppmariadb::statement(os.str())); | |||||
| } | |||||
| return *unknown; | |||||
| } | |||||
| } | |||||
| ::cppmariadb::statement& field_t::get_statement_foreign_many_update_impl(statement_ptr& statement) const | |||||
| { | |||||
| assert(referenced_table); | |||||
| assert(referenced_table->primary_key_field); | |||||
| if (!statement) | |||||
| { | |||||
| auto& ref_key_info = *referenced_table->primary_key_field; | |||||
| std::ostringstream os; | |||||
| os << "UPDATE `" | |||||
| << ref_key_info.table_name | |||||
| << "` SET `" | |||||
| << ref_key_info.table_name | |||||
| << "_id_" | |||||
| << field_name | |||||
| << "`=NULL, `" | |||||
| << ref_key_info.table_name | |||||
| << "_index_" | |||||
| << field_name | |||||
| << "`=0 WHERE `" | |||||
| << ref_key_info.table_name | |||||
| << "_id_" | |||||
| << field_name | |||||
| << "`=" | |||||
| << ref_key_info.convert_to_open | |||||
| << "?\?" | |||||
| << ref_key_info.convert_to_close; | |||||
| statement.reset(new ::cppmariadb::statement(os.str())); | |||||
| } | |||||
| return *statement; | |||||
| } | |||||
| @@ -910,8 +910,9 @@ std::string build_create_update_query(const table_t& table, const filter_t* filt | |||||
| } | } | ||||
| /* type field for derived tables */ | /* type field for derived tables */ | ||||
| if (!table.derived_tables.empty() && | |||||
| !table.base_table) | |||||
| if ( !table.derived_tables.empty() | |||||
| && !table.base_table | |||||
| && !is_update) | |||||
| { | { | ||||
| if (index++) | if (index++) | ||||
| os << ", "; | os << ", "; | ||||
| @@ -948,13 +949,13 @@ std::string build_select_query( | |||||
| std::string table_t::execute_create_update( | std::string table_t::execute_create_update( | ||||
| const create_update_context& context, | const create_update_context& context, | ||||
| ::cppmariadb::statement& statement, | |||||
| const filter_t* filter) const | |||||
| ::cppmariadb::statement& statement) const | |||||
| { | { | ||||
| auto& connection = context.connection; | auto& connection = context.connection; | ||||
| auto& filter = context.filter; | |||||
| size_t index = 0; | size_t index = 0; | ||||
| bool is_update = static_cast<bool>(filter); | |||||
| bool is_update = context.is_update; | |||||
| std::string primary_key; | std::string primary_key; | ||||
| statement.clear(); | statement.clear(); | ||||
| @@ -976,7 +977,7 @@ std::string table_t::execute_create_update( | |||||
| /* base_key */ | /* base_key */ | ||||
| if ( base_table | if ( base_table | ||||
| && ( !is_update | && ( !is_update | ||||
| || !filter->is_excluded(*base_table))) | |||||
| || !filter.is_excluded(*base_table))) | |||||
| { | { | ||||
| auto new_context = context; | auto new_context = context; | ||||
| if (!new_context.derived_table) | if (!new_context.derived_table) | ||||
| @@ -986,19 +987,37 @@ std::string table_t::execute_create_update( | |||||
| ++index; | ++index; | ||||
| } | } | ||||
| if (is_update && filter->is_excluded(*this)) | |||||
| if (is_update && filter.is_excluded(*this)) | |||||
| return primary_key; | return primary_key; | ||||
| /* foreign table one fields */ | /* foreign table one fields */ | ||||
| for (auto& ptr : foreign_table_one_fields) | for (auto& ptr : foreign_table_one_fields) | ||||
| { | { | ||||
| assert(ptr); | assert(ptr); | ||||
| if (is_update && filter->is_excluded(*ptr)) | |||||
| auto& field = *ptr; | |||||
| if (is_update && filter.is_excluded(field)) | |||||
| continue; | continue; | ||||
| value_t key = ptr->foreign_create_update(context); | |||||
| if (key.has_value()) statement.set(index, std::move(key)); | |||||
| else statement.set_null(index); | |||||
| /* insert/update dataset */ | |||||
| value_t key = field.foreign_create_update(context); | |||||
| if (key.has_value()) | |||||
| statement.set(index, std::move(key)); | |||||
| else if (field.value_is_nullable) | |||||
| statement.set_null(index); | |||||
| else | |||||
| throw misc::hibernate_exception("Received null key for non nullable foreign dataset!"); | |||||
| ++index; | ++index; | ||||
| /* cleanup old dataset (if new one was created) */ | |||||
| if (context.is_update) | |||||
| { | |||||
| auto& delete_statement = field.get_statement_foreign_one_delete(key.has_value()); | |||||
| delete_statement.set(0, primary_key); | |||||
| if (key.has_value()) | |||||
| delete_statement.set(1, *key); | |||||
| cpphibernate_debug_log("execute DELETE old foreign one query: " << delete_statement.query(connection)); | |||||
| connection.execute(delete_statement); | |||||
| } | |||||
| } | } | ||||
| /* foreign fields */ | /* foreign fields */ | ||||
| @@ -1036,7 +1055,7 @@ std::string table_t::execute_create_update( | |||||
| for (auto& ptr : data_fields) | for (auto& ptr : data_fields) | ||||
| { | { | ||||
| assert(ptr); | assert(ptr); | ||||
| if (is_update && filter->is_excluded(*ptr)) | |||||
| if (is_update && filter.is_excluded(*ptr)) | |||||
| continue; | continue; | ||||
| auto& field_info = *ptr; | auto& field_info = *ptr; | ||||
| @@ -1048,8 +1067,9 @@ std::string table_t::execute_create_update( | |||||
| } | } | ||||
| /* type field for derived tables */ | /* type field for derived tables */ | ||||
| if (!derived_tables.empty() && | |||||
| !base_table) | |||||
| if ( !derived_tables.empty() | |||||
| && !base_table | |||||
| && !is_update) | |||||
| { | { | ||||
| statement.set(index, context.derived_table | statement.set(index, context.derived_table | ||||
| ? context.derived_table->table_id | ? context.derived_table->table_id | ||||
| @@ -1084,6 +1104,8 @@ std::string table_t::execute_create_update( | |||||
| else | else | ||||
| { | { | ||||
| auto count = connection.execute_rows(statement); | auto count = connection.execute_rows(statement); | ||||
| if (count != 1) | |||||
| throw misc::hibernate_exception("Expected exaclty one row to be inserted/updated!"); | |||||
| cpphibernate_debug_log(count << " rows inserted/updated"); | cpphibernate_debug_log(count << " rows inserted/updated"); | ||||
| } | } | ||||
| primary_key_field->set(context, primary_key); | primary_key_field->set(context, primary_key); | ||||
| @@ -1092,16 +1114,39 @@ std::string table_t::execute_create_update( | |||||
| for (auto& ptr : foreign_table_many_fields) | for (auto& ptr : foreign_table_many_fields) | ||||
| { | { | ||||
| assert(ptr); | assert(ptr); | ||||
| assert(ptr->referenced_table); | |||||
| auto& field = *ptr; | |||||
| auto& ref_table = *field.referenced_table; | |||||
| if ( is_update | if ( is_update | ||||
| && ( filter->is_excluded(*ptr) | |||||
| || filter->is_excluded(*ptr->referenced_table))) | |||||
| && ( filter.is_excluded(field) | |||||
| || filter.is_excluded(ref_table))) | |||||
| continue; | continue; | ||||
| /* set foreign keys of existing elements to null */ | |||||
| if (context.is_update) | |||||
| { | |||||
| auto& update_statement = field.get_statement_foreign_many_update(); | |||||
| update_statement.set(0, primary_key); | |||||
| cpphibernate_debug_log("execute UPDATE old foreign many query: " << update_statement.query(connection)); | |||||
| connection.execute(update_statement); | |||||
| } | |||||
| /* update elements */ | |||||
| auto next_context = context; | auto next_context = context; | ||||
| next_context.owner_field = ptr; | next_context.owner_field = ptr; | ||||
| next_context.owner_key = primary_key; | next_context.owner_key = primary_key; | ||||
| next_context.derived_table = nullptr; | next_context.derived_table = nullptr; | ||||
| ptr->foreign_create_update(next_context); | |||||
| field.foreign_create_update(next_context); | |||||
| /* delete non referenced elements */ | |||||
| if (context.is_update) | |||||
| { | |||||
| auto& delete_statement = ref_table.get_statement_foreign_many_delete(); | |||||
| cpphibernate_debug_log("execute DELETE old foreign many query: " << delete_statement.query(connection)); | |||||
| connection.execute(delete_statement); | |||||
| } | |||||
| } | } | ||||
| return primary_key; | return primary_key; | ||||
| @@ -1210,15 +1255,56 @@ void table_t::emplace(const read_context& context) const | |||||
| auto& map = context.is_dynamic | auto& map = context.is_dynamic | ||||
| ? _statement_select_dynamic | ? _statement_select_dynamic | ||||
| : _statement_select_static; | : _statement_select_static; | ||||
| auto it = map.find(context.filter.cache_id); | |||||
| auto key = std::make_tuple(context.filter.cache_id, static_cast<const field_t*>(nullptr)); | |||||
| auto it = map.find(key); | |||||
| if (it == map.end()) | if (it == map.end()) | ||||
| { | { | ||||
| auto query = build_select_query(*this, context.filter, context.is_dynamic); | auto query = build_select_query(*this, context.filter, context.is_dynamic); | ||||
| it = map.emplace(context.filter.cache_id, ::cppmariadb::statement(query)).first; | |||||
| it = map.emplace(key, ::cppmariadb::statement(query)).first; | |||||
| } | } | ||||
| return it->second; | return it->second; | ||||
| } | } | ||||
| ::cppmariadb::statement& table_t::get_statement_update(const filter_t& filter, const field_t* owner) const | |||||
| { | |||||
| auto key = std::make_tuple(filter.cache_id, owner); | |||||
| auto it = _statement_update.find(key); | |||||
| if (it == _statement_update.end()) | |||||
| { | |||||
| auto query = build_create_update_query(*this, &filter, owner); | |||||
| it = _statement_update.emplace(key, ::cppmariadb::statement(query)).first; | |||||
| } | |||||
| return it->second; | |||||
| } | |||||
| ::cppmariadb::statement& table_t::get_statement_foreign_many_delete() const | |||||
| { | |||||
| if (!_statement_foreign_many_delete) | |||||
| { | |||||
| std::ostringstream os; | |||||
| os << "DELETE FROM `" | |||||
| << table_name | |||||
| << "` WHERE"; | |||||
| auto first = true; | |||||
| for (auto ptr : foreign_key_fields) | |||||
| { | |||||
| assert(ptr); | |||||
| auto& field = *ptr; | |||||
| if (first) | |||||
| first = false; | |||||
| else | |||||
| os << " AND"; | |||||
| os << " (`" | |||||
| << field.table_name | |||||
| << "_id_" | |||||
| << field.field_name | |||||
| << "` IS NULL)"; | |||||
| } | |||||
| _statement_foreign_many_delete.reset(new ::cppmariadb::statement(os.str())); | |||||
| } | |||||
| return *_statement_foreign_many_delete; | |||||
| } | |||||
| std::string table_t::create_update_base(const create_update_context& context) const | std::string table_t::create_update_base(const create_update_context& context) const | ||||
| { | { | ||||
| throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { } | throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { } | ||||
| @@ -1244,8 +1330,10 @@ void table_t::init_stage2_exec(const init_context& context) const | |||||
| std::string table_t::create_update_exec(const create_update_context& context) const | std::string table_t::create_update_exec(const create_update_context& context) const | ||||
| { | { | ||||
| auto& statement = get_statement_insert_into(); | |||||
| return execute_create_update(context, statement, nullptr); | |||||
| auto& statement = context.is_update | |||||
| ? get_statement_update(context.filter, context.owner_field) | |||||
| : get_statement_insert_into(); | |||||
| return execute_create_update(context, statement); | |||||
| } | } | ||||
| std::string table_t::create_update_intern(const create_update_context& context) const | std::string table_t::create_update_intern(const create_update_context& context) const | ||||
| @@ -0,0 +1,525 @@ | |||||
| #include <cpphibernate/driver/mariadb.h> | |||||
| #include "test_helper.h" | |||||
| #include "test_schema.h" | |||||
| #include "mariadb_mock.h" | |||||
| using namespace ::testing; | |||||
| using namespace ::cpphibernate; | |||||
| TEST(CppHibernateTests, update_test1) | |||||
| { | |||||
| StrictMock<mariadb_mock> mock; | |||||
| expect_query(mock, "START TRANSACTION"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test1` " | |||||
| "SET " | |||||
| "`str_data`='Xstr_data of class `test1` object `t1`X', " | |||||
| "`str64_data`='Xstr64_data of class `test1` object `t1`X', " | |||||
| "`u32_nullable`=null, " | |||||
| "`u32_ptr_u`='X456X', " | |||||
| "`u32_ptr_s`='X789X' " | |||||
| "WHERE " | |||||
| "`tbl_test1_id`=UuidToBin('X3d12697a-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "COMMIT"); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_real_escape_string(reinterpret_cast<MYSQL*>(0x1111), _, _, _)) | |||||
| .Times(AnyNumber()) | |||||
| .WillRepeatedly(WithArgs<1, 2, 3>(EscapeString())); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_close( | |||||
| reinterpret_cast<MYSQL*>(0x1111))); | |||||
| test1 t1; | |||||
| t1.id = uuid("3d12697a-abb9-11e8-98d0-529269fb1459"); | |||||
| t1.str_data = "str_data of class `test1` object `t1`"; | |||||
| t1.str64_data = "str64_data of class `test1` object `t1`"; | |||||
| t1.u32_ptr_u = std::make_unique<uint32_t>(456); | |||||
| t1.u32_ptr_s = std::make_shared<uint32_t>(789); | |||||
| ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111)); | |||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | |||||
| context.update(t1); | |||||
| } | |||||
| TEST(CppHibernateTests, update_test2) | |||||
| { | |||||
| StrictMock<mariadb_mock> mock; | |||||
| expect_query(mock, "START TRANSACTION"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test2` " | |||||
| "SET " | |||||
| "`u8_data`='X1X', " | |||||
| "`i8_data`='X2X', " | |||||
| "`u16_data`='X3X', " | |||||
| "`i16_data`='X4X' " | |||||
| "WHERE " | |||||
| "`tbl_test2_id`=UuidToBin('X3d1270dc-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "COMMIT"); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_real_escape_string(reinterpret_cast<MYSQL*>(0x1111), _, _, _)) | |||||
| .Times(AnyNumber()) | |||||
| .WillRepeatedly(WithArgs<1, 2, 3>(EscapeString())); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_close( | |||||
| reinterpret_cast<MYSQL*>(0x1111))); | |||||
| test2 t2; | |||||
| t2.id = uuid("3d1270dc-abb9-11e8-98d0-529269fb1459"); | |||||
| t2.u8_data = 1; | |||||
| t2.i8_data = 2; | |||||
| t2.u16_data = 3; | |||||
| t2.i16_data = 4; | |||||
| ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111)); | |||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | |||||
| context.update(t2); | |||||
| } | |||||
| TEST(CppHibernateTests, update_test3) | |||||
| { | |||||
| StrictMock<mariadb_mock> mock; | |||||
| expect_query(mock, "START TRANSACTION"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test3` " | |||||
| "SET " | |||||
| "`u32_data`='X5X', " | |||||
| "`i32_data`='X6X', " | |||||
| "`u64_data`='X7X', " | |||||
| "`i64_data`='X8X' " | |||||
| "WHERE " | |||||
| "`tbl_test3_id`=UuidToBin('X3d12737a-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "COMMIT"); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_real_escape_string(reinterpret_cast<MYSQL*>(0x1111), _, _, _)) | |||||
| .Times(AnyNumber()) | |||||
| .WillRepeatedly(WithArgs<1, 2, 3>(EscapeString())); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_close( | |||||
| reinterpret_cast<MYSQL*>(0x1111))); | |||||
| test3 t3; | |||||
| t3.id = uuid("3d12737a-abb9-11e8-98d0-529269fb1459"); | |||||
| t3.u32_data = 5; | |||||
| t3.i32_data = 6; | |||||
| t3.u64_data = 7; | |||||
| t3.i64_data = 8; | |||||
| ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111)); | |||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | |||||
| context.update(t3); | |||||
| } | |||||
| TEST(CppHibernateTests, update_derived1) | |||||
| { | |||||
| StrictMock<mariadb_mock> mock; | |||||
| expect_query(mock, "START TRANSACTION"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_base` " | |||||
| "SET " | |||||
| "`name`='Xderived1X' " | |||||
| "WHERE " | |||||
| "`tbl_base_id`=UuidToBin('X3d12778a-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "SELECT Uuid()", result_used({ | |||||
| { "e2488a64-b843-11e8-96f8-529269fb1459" } | |||||
| })); | |||||
| expect_query(mock, "INSERT INTO " | |||||
| "`tbl_test1` " | |||||
| "SET " | |||||
| "`tbl_test1_id`=UuidToBin('Xe2488a64-b843-11e8-96f8-529269fb1459X'), " | |||||
| "`str_data`='Xstr_data of class `test1` object `d1.test1_data`X', " | |||||
| "`str64_data`='Xstr64_data of class `test1` object `d1.test1_data`X', " | |||||
| "`u32_nullable`='X32X', " | |||||
| "`u32_ptr_u`=null, " | |||||
| "`u32_ptr_s`='X789X'", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test1` " | |||||
| "WHERE " | |||||
| "`tbl_test1_id` IN (" | |||||
| "SELECT " | |||||
| "`tbl_test1_id_test1_data` " | |||||
| "FROM " | |||||
| "`tbl_derived1` " | |||||
| "WHERE " | |||||
| "`tbl_derived1_id`=UuidToBin('X3d12758c-abb9-11e8-98d0-529269fb1459X') AND " | |||||
| "`tbl_test1_id_test1_data`!= UuidToBin('Xe2488a64-b843-11e8-96f8-529269fb1459X')" | |||||
| ")"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_derived1` " | |||||
| "SET " | |||||
| "`tbl_base_id`=UuidToBin('X3d12778a-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_test1_id_test1_data`=UuidToBin('Xe2488a64-b843-11e8-96f8-529269fb1459X'), " | |||||
| "`enum_data`='Xtest2X' " | |||||
| "WHERE " | |||||
| "`tbl_derived1_id`=UuidToBin('X3d12758c-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "COMMIT"); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_real_escape_string(reinterpret_cast<MYSQL*>(0x1111), _, _, _)) | |||||
| .Times(AnyNumber()) | |||||
| .WillRepeatedly(WithArgs<1, 2, 3>(EscapeString())); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_close( | |||||
| reinterpret_cast<MYSQL*>(0x1111))); | |||||
| derived1 d1; | |||||
| d1.id = uuid("3d12778a-abb9-11e8-98d0-529269fb1459"); | |||||
| d1.name = "derived1"; | |||||
| d1.derived1_id = uuid("3d12758c-abb9-11e8-98d0-529269fb1459"); | |||||
| d1.enum_data = test_enum::test2; | |||||
| d1.test1_data.str_data = "str_data of class `test1` object `d1.test1_data`"; | |||||
| d1.test1_data.str64_data = "str64_data of class `test1` object `d1.test1_data`"; | |||||
| d1.test1_data.u32_nullable = 32; | |||||
| d1.test1_data.u32_ptr_s = std::make_shared<uint32_t>(789); | |||||
| ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111)); | |||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | |||||
| context.update(static_cast<base&>(d1)); | |||||
| } | |||||
| TEST(CppHibernateTests, update_derived2) | |||||
| { | |||||
| StrictMock<mariadb_mock> mock; | |||||
| expect_query(mock, "START TRANSACTION"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_base` " | |||||
| "SET " | |||||
| "`name`='Xderived2X' " | |||||
| "WHERE " | |||||
| "`tbl_base_id`=UuidToBin('X3d127db6-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test2` " | |||||
| "SET " | |||||
| "`u8_data`='X10X', " | |||||
| "`i8_data`='X11X', " | |||||
| "`u16_data`='X12X', " | |||||
| "`i16_data`='X13X' " | |||||
| "WHERE " | |||||
| "`tbl_test2_id`=UuidToBin('X3d1283a6-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test2` " | |||||
| "WHERE " | |||||
| "`tbl_test2_id` IN (" | |||||
| "SELECT " | |||||
| "`tbl_test2_id_test2_nullable` " | |||||
| "FROM " | |||||
| "`tbl_derived2` " | |||||
| "WHERE " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d127bcc-abb9-11e8-98d0-529269fb1459X') AND " | |||||
| "`tbl_test2_id_test2_nullable`!= UuidToBin('X3d1283a6-abb9-11e8-98d0-529269fb1459X')" | |||||
| ")"); | |||||
| expect_query(mock, "SELECT Uuid()", | |||||
| result_used({ | |||||
| { "ec0f0aac-b8b9-11e8-96f8-529269fb1459" } | |||||
| })); | |||||
| expect_query(mock, "INSERT INTO " | |||||
| "`tbl_test2` " | |||||
| "SET " | |||||
| "`tbl_test2_id`=UuidToBin('Xec0f0aac-b8b9-11e8-96f8-529269fb1459X'), " | |||||
| "`u8_data`='X20X', " | |||||
| "`i8_data`='X21X', " | |||||
| "`u16_data`='X22X', " | |||||
| "`i16_data`='X23X'", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test2` " | |||||
| "WHERE " | |||||
| "`tbl_test2_id` IN (" | |||||
| "SELECT " | |||||
| "`tbl_test2_id_test2_ptr_u` " | |||||
| "FROM " | |||||
| "`tbl_derived2` " | |||||
| "WHERE " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d127bcc-abb9-11e8-98d0-529269fb1459X') AND " | |||||
| "`tbl_test2_id_test2_ptr_u`!= UuidToBin('Xec0f0aac-b8b9-11e8-96f8-529269fb1459X')" | |||||
| ")"); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test2` " | |||||
| "WHERE " | |||||
| "`tbl_test2_id` IN (" | |||||
| "SELECT " | |||||
| "`tbl_test2_id_test2_ptr_s` " | |||||
| "FROM " | |||||
| "`tbl_derived2` " | |||||
| "WHERE " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d127bcc-abb9-11e8-98d0-529269fb1459X')" | |||||
| ")"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_derived2` " | |||||
| "SET " | |||||
| "`tbl_base_id`=UuidToBin('X3d127db6-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_test2_id_test2_nullable`=UuidToBin('X3d1283a6-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_test2_id_test2_ptr_u`=UuidToBin('Xec0f0aac-b8b9-11e8-96f8-529269fb1459X'), " | |||||
| "`tbl_test2_id_test2_ptr_s`=UuidToBin(null) " | |||||
| "WHERE " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d127bcc-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "COMMIT"); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_real_escape_string(reinterpret_cast<MYSQL*>(0x1111), _, _, _)) | |||||
| .Times(AnyNumber()) | |||||
| .WillRepeatedly(WithArgs<1, 2, 3>(EscapeString())); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_close( | |||||
| reinterpret_cast<MYSQL*>(0x1111))); | |||||
| derived2 d2; | |||||
| d2.id = uuid("3d127db6-abb9-11e8-98d0-529269fb1459"); | |||||
| d2.name = "derived2"; | |||||
| d2.derived2_id = uuid("3d127bcc-abb9-11e8-98d0-529269fb1459"); | |||||
| d2.test2_nullable = test2 { }; | |||||
| d2.test2_nullable->id = uuid("3d1283a6-abb9-11e8-98d0-529269fb1459"); | |||||
| d2.test2_nullable->u8_data = 10; | |||||
| d2.test2_nullable->i8_data = 11; | |||||
| d2.test2_nullable->u16_data = 12; | |||||
| d2.test2_nullable->i16_data = 13; | |||||
| d2.test2_ptr_u = std::make_unique<test2>(); | |||||
| d2.test2_ptr_u->u8_data = 20; | |||||
| d2.test2_ptr_u->i8_data = 21; | |||||
| d2.test2_ptr_u->u16_data = 22; | |||||
| d2.test2_ptr_u->i16_data = 23; | |||||
| ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111)); | |||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | |||||
| context.update(static_cast<base&>(d2)); | |||||
| } | |||||
| TEST(CppHibernateTests, update_derived3) | |||||
| { | |||||
| StrictMock<mariadb_mock> mock; | |||||
| expect_query(mock, "START TRANSACTION"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_base` " | |||||
| "SET " | |||||
| "`name`='Xderived3X' " | |||||
| "WHERE " | |||||
| "`tbl_base_id`=UuidToBin('X3d1288ce-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test2` " | |||||
| "WHERE " | |||||
| "`tbl_test2_id` IN (" | |||||
| "SELECT " | |||||
| "`tbl_test2_id_test2_nullable` " | |||||
| "FROM " | |||||
| "`tbl_derived2` " | |||||
| "WHERE " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d1287a2-abb9-11e8-98d0-529269fb1459X')" | |||||
| ")"); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test2` " | |||||
| "WHERE " | |||||
| "`tbl_test2_id` IN (" | |||||
| "SELECT " | |||||
| "`tbl_test2_id_test2_ptr_u` " | |||||
| "FROM " | |||||
| "`tbl_derived2` " | |||||
| "WHERE " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d1287a2-abb9-11e8-98d0-529269fb1459X')" | |||||
| ")"); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test2` " | |||||
| "WHERE " | |||||
| "`tbl_test2_id` IN (" | |||||
| "SELECT " | |||||
| "`tbl_test2_id_test2_ptr_s` " | |||||
| "FROM " | |||||
| "`tbl_derived2` " | |||||
| "WHERE " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d1287a2-abb9-11e8-98d0-529269fb1459X')" | |||||
| ")"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_derived2` " | |||||
| "SET " | |||||
| "`tbl_base_id`=UuidToBin('X3d1288ce-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_test2_id_test2_nullable`=UuidToBin(null), " | |||||
| "`tbl_test2_id_test2_ptr_u`=UuidToBin(null), " | |||||
| "`tbl_test2_id_test2_ptr_s`=UuidToBin(null) " | |||||
| "WHERE " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d1287a2-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_derived3` " | |||||
| "SET " | |||||
| "`tbl_derived2_id`=UuidToBin('X3d1287a2-abb9-11e8-98d0-529269fb1459X') " | |||||
| "WHERE " | |||||
| "`tbl_derived3_id`=UuidToBin('X3d12866c-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test3` " | |||||
| "SET " | |||||
| "`tbl_test3_id_test3_list`=NULL, " | |||||
| "`tbl_test3_index_test3_list`=0 " | |||||
| "WHERE " | |||||
| "`tbl_test3_id_test3_list`=UuidToBin('X3d12866c-abb9-11e8-98d0-529269fb1459X')"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test3` " | |||||
| "SET " | |||||
| "`tbl_derived3_id_test3_list`=UuidToBin('X3d12866c-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_derived3_index_test3_list`='X0X', " | |||||
| "`u32_data`='X100X', " | |||||
| "`i32_data`='X101X', " | |||||
| "`u64_data`='X102X', " | |||||
| "`i64_data`='X103X' " | |||||
| "WHERE " | |||||
| "`tbl_test3_id`=UuidToBin('X3d1289f0-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "SELECT Uuid()", | |||||
| result_used({ | |||||
| { "435bd976-b8c3-11e8-96f8-529269fb1459" } | |||||
| })); | |||||
| expect_query(mock, "INSERT INTO " | |||||
| "`tbl_test3` " | |||||
| "SET " | |||||
| "`tbl_test3_id`=UuidToBin('X435bd976-b8c3-11e8-96f8-529269fb1459X'), " | |||||
| "`tbl_derived3_id_test3_list`=UuidToBin('X3d12866c-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_derived3_index_test3_list`='X1X', " | |||||
| "`tbl_derived3_id_test3_vector`=UuidToBin(null), " | |||||
| "`tbl_derived3_index_test3_vector`='X0X', " | |||||
| "`u32_data`='X110X', " | |||||
| "`i32_data`='X111X', " | |||||
| "`u64_data`='X112X', " | |||||
| "`i64_data`='X113X'", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test3` " | |||||
| "WHERE " | |||||
| "(`tbl_derived3_id_test3_list` IS NULL) AND " | |||||
| "(`tbl_derived3_id_test3_vector` IS NULL)"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test3` " | |||||
| "SET " | |||||
| "`tbl_test3_id_test3_vector`=NULL, " | |||||
| "`tbl_test3_index_test3_vector`=0 " | |||||
| "WHERE " | |||||
| "`tbl_test3_id_test3_vector`=UuidToBin('X3d12866c-abb9-11e8-98d0-529269fb1459X')"); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test3` " | |||||
| "SET " | |||||
| "`tbl_derived3_id_test3_vector`=UuidToBin('X3d12866c-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_derived3_index_test3_vector`='X0X', " | |||||
| "`u32_data`='X200X', " | |||||
| "`i32_data`='X201X', " | |||||
| "`u64_data`='X202X', " | |||||
| "`i64_data`='X203X' " | |||||
| "WHERE " | |||||
| "`tbl_test3_id`=UuidToBin('X3d128eb4-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "SELECT Uuid()", | |||||
| result_used({ | |||||
| { "1c0a3592-b8c4-11e8-96f8-529269fb1459" } | |||||
| })); | |||||
| expect_query(mock, "INSERT INTO " | |||||
| "`tbl_test3` " | |||||
| "SET " | |||||
| "`tbl_test3_id`=UuidToBin('X1c0a3592-b8c4-11e8-96f8-529269fb1459X'), " | |||||
| "`tbl_derived3_id_test3_list`=UuidToBin(null), " | |||||
| "`tbl_derived3_index_test3_list`='X0X', " | |||||
| "`tbl_derived3_id_test3_vector`=UuidToBin('X3d12866c-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_derived3_index_test3_vector`='X1X', " | |||||
| "`u32_data`='X210X', " | |||||
| "`i32_data`='X211X', " | |||||
| "`u64_data`='X212X', " | |||||
| "`i64_data`='X213X'", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "UPDATE " | |||||
| "`tbl_test3` " | |||||
| "SET " | |||||
| "`tbl_derived3_id_test3_vector`=UuidToBin('X3d12866c-abb9-11e8-98d0-529269fb1459X'), " | |||||
| "`tbl_derived3_index_test3_vector`='X2X', " | |||||
| "`u32_data`='X220X', " | |||||
| "`i32_data`='X221X', " | |||||
| "`u64_data`='X222X', " | |||||
| "`i64_data`='X223X' " | |||||
| "WHERE " | |||||
| "`tbl_test3_id`=UuidToBin('X3d129134-abb9-11e8-98d0-529269fb1459X')", | |||||
| result_affected_rows(1)); | |||||
| expect_query(mock, "DELETE FROM " | |||||
| "`tbl_test3` " | |||||
| "WHERE " | |||||
| "(`tbl_derived3_id_test3_list` IS NULL) AND " | |||||
| "(`tbl_derived3_id_test3_vector` IS NULL)"); | |||||
| expect_query(mock, "COMMIT"); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_real_escape_string(reinterpret_cast<MYSQL*>(0x1111), _, _, _)) | |||||
| .Times(AnyNumber()) | |||||
| .WillRepeatedly(WithArgs<1, 2, 3>(EscapeString())); | |||||
| EXPECT_CALL( | |||||
| mock, | |||||
| mysql_close( | |||||
| reinterpret_cast<MYSQL*>(0x1111))); | |||||
| derived3 d3; | |||||
| d3.id = uuid("3d1288ce-abb9-11e8-98d0-529269fb1459"); | |||||
| d3.name = "derived3"; | |||||
| d3.derived2_id = uuid("3d1287a2-abb9-11e8-98d0-529269fb1459"); | |||||
| d3.derived3_id = uuid("3d12866c-abb9-11e8-98d0-529269fb1459"); | |||||
| d3.test3_list.emplace_back(); | |||||
| d3.test3_list.back().id = uuid("3d1289f0-abb9-11e8-98d0-529269fb1459"); | |||||
| d3.test3_list.back().u32_data = 100; | |||||
| d3.test3_list.back().i32_data = 101; | |||||
| d3.test3_list.back().u64_data = 102; | |||||
| d3.test3_list.back().i64_data = 103; | |||||
| d3.test3_list.emplace_back(); | |||||
| d3.test3_list.back().u32_data = 110; | |||||
| d3.test3_list.back().i32_data = 111; | |||||
| d3.test3_list.back().u64_data = 112; | |||||
| d3.test3_list.back().i64_data = 113; | |||||
| d3.test3_vector.emplace_back(); | |||||
| d3.test3_vector.back().id = uuid("3d128eb4-abb9-11e8-98d0-529269fb1459"); | |||||
| d3.test3_vector.back().u32_data = 200; | |||||
| d3.test3_vector.back().i32_data = 201; | |||||
| d3.test3_vector.back().u64_data = 202; | |||||
| d3.test3_vector.back().i64_data = 203; | |||||
| d3.test3_vector.emplace_back(); | |||||
| d3.test3_vector.back().u32_data = 210; | |||||
| d3.test3_vector.back().i32_data = 211; | |||||
| d3.test3_vector.back().u64_data = 212; | |||||
| d3.test3_vector.back().i64_data = 213; | |||||
| d3.test3_vector.emplace_back(); | |||||
| d3.test3_vector.back().id = uuid("3d129134-abb9-11e8-98d0-529269fb1459"); | |||||
| d3.test3_vector.back().u32_data = 220; | |||||
| d3.test3_vector.back().i32_data = 221; | |||||
| d3.test3_vector.back().u64_data = 222; | |||||
| d3.test3_vector.back().i64_data = 223; | |||||
| ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111)); | |||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | |||||
| context.update(static_cast<derived2&>(d3)); | |||||
| } | |||||