#pragma once #include "create_update.h" #include "../classes/schema/schema.inl" #include "../helper/nullable_helper.inl" #include "../context/create_update_context.inl" namespace cpphibernate { namespace mariadb { /* create_update_impl_t - default (normal dataset) */ template struct create_update_impl_t { using dataset_type = T_dataset; static inline value_t apply(const create_update_context& context, bool strict = true) { using namespace ::cppmariadb; value_t ret; auto dataset_id = get_type_id(hana::type_c); auto& connection = context.connection; auto& schema = context.schema; auto& table = schema.table(dataset_id); assert(table.primary_key_field); transaction_lock trans(connection); /* if the value of primary key field does not match the operation of the context */ if (table.primary_key_field->is_default(context) != context.is_create()) { /* if we are not in strict mode, change the context to an update context */ if (!strict) { static const filter_t dummy; ret = table.create_update(context.is_create() ? context.make_update_context(dummy) : context.make_create_context()); } /* if we expect an update operation in strict mode throw an exception * because an update operation needs an primary key assigned */ else if (context.is_update()) { throw exception("can not update dataset with no primary key assigned!"); } /* if we expect an create operation in strict mode throw an exception because an create operation expects the primary key to not be assigned */ else { throw exception("can not create dataset with primary key assigned!"); } } else { ret = table.create_update(context); } trans.commit(); return ret; } }; /* create_update_impl_t - nullable */ template struct create_update_impl_t< T_dataset, mp::enable_if_t>> { using dataset_type = T_dataset; using nullable_helper_type = nullable_helper; static inline value_t apply(const create_update_context& context, bool strict = true) { value_t ret; auto& dataset = context.get(); auto* value = nullable_helper_type::get(dataset); if (value) { using new_dataset_type = mp::decay_t; using new_create_update_impl_type = create_update_impl_t; ret = new_create_update_impl_type::apply(change_context(context, *value), strict); } else if (strict) { throw exception("can not create nullable type with no value!"); } return ret; } }; /* create_update_impl_t - container */ template struct create_update_impl_t< T_dataset, mp::enable_if_t>> { using dataset_type = T_dataset; static inline value_t apply(const create_update_context& context, bool strict = true) { using namespace ::cppmariadb; value_t ret; auto& connection = context.connection; auto& dataset = context.get(); transaction_lock trans(connection); ssize_t index = 0; for (auto& x : dataset) { using new_dataset_type = mp::decay_t; using new_create_update_impl_type = create_update_impl_t; auto new_context = change_context(context, x); new_context.index = index++; new_create_update_impl_type::apply(new_context, strict); } trans.commit(); return ret; } }; } }