#pragma once #include "data_context.h" #include "base_context.inl" #include "../classes/schema/schema.inl" namespace cpphibernate { namespace mariadb { /* data_context */ data_context::data_context( const schema_t& p_schema, ::cppmariadb::connection& p_connection) : base_context (p_schema, p_connection) , _dataset_id (0) , _dataset (nullptr) , _table (nullptr) { } template data_context::data_context( const schema_t& p_schema, ::cppmariadb::connection& p_connection, T_dataset& p_dataset) : base_context (p_schema, p_connection) , _dataset_id (0) , _dataset (nullptr) , _table (nullptr) { set(p_dataset); } template decltype(auto) data_context::get() const { using dataset_type = mp::decay_t; /* check if tha context has a dataset assigned (should never fail) */ if (!_dataset) throw exception("no data assigned!"); auto dataset_id = get_type_id(hana::type_c); /* if the dataset IDs does not match, search in the base tables for a matching ID */ if (dataset_id != _dataset_id) { /* get the table of the stored dataset */ if (!_table) _table = &schema.table(_dataset_id); /* check if the table matches the stored dataset (should never happen) */ else if (_table->dataset_id != _dataset_id) throw exception("invalid table!"); /* walk through base tables until we have found a matching ID */ auto table = _table; while(table && table->dataset_id != dataset_id) table = table->base_table; /* check if we have found a suitable table, if not throw an exception */ if (!table) { throw exception(cppcore::type_helper::name() + " is not a derived type of dataset with id " + std::to_string(_dataset_id)); } } /* return the dataset */ return *static_cast(_dataset); } template void * data_context::set(T_dataset& dataset, size_t dataset_id) const { _dataset_id = dataset_id ? dataset_id : get_type_id(hana::type_c>); _dataset = &dataset; _table = nullptr; return _dataset; } void data_context::clear() const { _dataset_id = 0; _dataset = nullptr; _table = nullptr; } namespace __impl { /* change_context_builder */ template struct change_context_builder { template static constexpr decltype(auto) apply(T_args&&...) { static_assert(sizeof...(T_args) == -1, "Invalid parameters for change_context(...)!"); } }; template struct change_context_builder< mp::list, mp::enable_if_t< mp::is_base_of_v>>> { static constexpr decltype(auto) apply(const T_context& context, T_dataset& dataset) { auto new_context = context; new_context.set(dataset); return new_context; } }; } } }