|
- #pragma once
-
- #include "read_context.h"
-
- #include "data_context.inl"
- #include "../helper/nullable_helper.inl"
- #include "../helper/container_helper.inl"
-
- namespace cpphibernate {
- namespace mariadb {
-
- read_context::read_context(
- const schema_t& p_schema,
- ::cppmariadb::connection& p_connection,
- const filter_t& p_filter,
- size_t p_real_dataset_id)
- : data_context (p_schema, p_connection)
- , filter (p_filter)
- , real_dataset_id (p_real_dataset_id)
- , is_dynamic (false)
- { }
-
- template<typename T_dataset>
- T_dataset& read_context::emplace(const table_t * table) const
- {
- using dataset_type = mp::decay_t<T_dataset>;
-
- /* check table */
- auto dataset_id = get_type_id(hana::type_c<dataset_type>);
- if (!table)
- table = &schema.table(dataset_id);
- else if (table->dataset_id != dataset_id)
- throw exception("wrong table passed!");
-
- /* check base */
- auto tbl = table;
- while (tbl && tbl->dataset_id != real_dataset_id)
- tbl = tbl->base_table;
- if (!tbl)
- {
- throw exception(cppcore::type_helper<dataset_type>::name() +
- " is not a derived type of dataset with id " + std::to_string(real_dataset_id));
- }
-
- /* create dataset */
- auto ptr = std::make_unique<dataset_type>();
- auto data = emplace_intern(ptr.get(), dataset_id);
- if (!data)
- throw exception("unable to store created dataset in context!");
- ptr.release();
- return *static_cast<dataset_type*>(data);
- }
-
- void read_context::emplace() const
- { emplace_intern(nullptr, 0); }
-
- void read_context::finish() const
- { finish_intern(); }
-
- namespace __impl
- {
-
- /* read_context_builder */
-
- template<typename X, typename>
- struct read_context_builder
- {
- template<typename... T_args>
- static constexpr decltype(auto) apply(T_args&&... args)
- { static_assert(sizeof...(args) == -1, "Invalid parameters for make_read_context(...)!"); }
- };
-
- /* read_context_builder - fake */
-
- template<
- typename T_schema,
- typename T_connection,
- typename T_dataset,
- typename T_filter>
- struct read_context_builder<
- mp::list<T_schema, T_connection, T_dataset, T_filter>,
- mp::enable_if_t<
- mp::is_same_v<hana::type_tag, hana::tag_of_t<mp::decay_t<T_dataset>>>
- >>
- {
- using dataset_type = typename mp::decay_t<T_dataset>::type;
-
- struct context_impl
- : public read_context
- {
- public:
- inline context_impl(
- const schema_t& p_schema,
- ::cppmariadb::connection& p_connection,
- T_dataset& p_dataset,
- const filter_t& p_filter)
- : read_context (p_schema, p_connection, p_filter,
- get_type_id(hana::type_c<real_dataset_t<mp::decay_t<dataset_type>>>))
- { }
-
- private:
- void * emplace_intern(void* data, size_t dataset_id) const override
- { return nullptr; }
-
- void finish_intern() const override
- { clear(); }
- };
-
- template<typename... X_args>
- static constexpr decltype(auto) apply(X_args&&... args)
- { return context_impl(std::forward<X_args>(args)...); }
- };
-
- /* read_context_builder - normal types */
-
- template<
- typename T_schema,
- typename T_connection,
- typename T_dataset,
- typename T_filter>
- struct read_context_builder<
- mp::list<T_schema, T_connection, T_dataset, T_filter>,
- mp::enable_if_t<
- !is_container_v<mp::decay_t<T_dataset>>
- && !is_nullable_v<mp::decay_t<T_dataset>>
- && !mp::is_same_v<hana::type_tag, hana::tag_of_t<mp::decay_t<T_dataset>>>
- >>
- {
- using dataset_type = mp::decay_t<T_dataset>;
-
- struct context_impl
- : public read_context
- {
- private:
- mutable size_t _count;
- dataset_type& _dataset;
-
- public:
- inline context_impl(
- const schema_t& p_schema,
- ::cppmariadb::connection& p_connection,
- T_dataset& p_dataset,
- const filter_t& p_filter)
- : read_context (p_schema, p_connection, p_filter,
- get_type_id(hana::type_c<real_dataset_t<mp::decay_t<T_dataset>>>))
- , _count (0)
- , _dataset (p_dataset)
- { }
-
- private:
- void * emplace_intern(void* data, size_t dataset_id) const override
- {
- if (data || dataset_id != 0)
- throw exception("Static datasets can not be assigned!");
- ++_count;
- if (_count > 1)
- throw exception("Expected exactly one dataset, but received more!");
- return set(_dataset);
- }
-
- void finish_intern() const override
- {
- if (_count < 1)
- throw exception("Expected exactly one dataset, but received none!");
- clear();
- }
- };
-
- template<typename... X_args>
- static constexpr decltype(auto) apply(X_args&&... args)
- { return context_impl(std::forward<X_args>(args)...); }
- };
-
- /* read_context_builder - nullable */
-
- template<
- typename T_schema,
- typename T_connection,
- typename T_dataset,
- typename T_filter>
- struct read_context_builder<
- mp::list<T_schema, T_connection, T_dataset, T_filter>,
- mp::enable_if_t<
- !is_container_v<mp::decay_t<T_dataset>>
- && is_nullable_v<mp::decay_t<T_dataset>>
- >>
- {
- using dataset_type = mp::decay_t<T_dataset>;
- using nullable_helper_type = nullable_helper<dataset_type>;
- using value_type = typename nullable_helper_type::value_type;
-
- struct context_impl
- : public read_context
- {
- private:
- dataset_type& _dataset;
- mutable size_t _count;
-
- public:
- inline context_impl(
- const schema_t& p_schema,
- ::cppmariadb::connection& p_connection,
- T_dataset& p_dataset,
- const filter_t& p_filter)
- : read_context (p_schema, p_connection, p_filter,
- get_type_id(hana::type_c<real_dataset_t<mp::decay_t<T_dataset>>>))
- , _count (0)
- , _dataset (p_dataset)
- {
- is_dynamic = is_pointer_v<dataset_type>;
- nullable_helper_type::clear(_dataset);
- }
-
- private:
- void * emplace_intern(void * data, size_t dataset_id) const override
- {
- if (data && !is_pointer_v<dataset_type>)
- throw exception("None pointer type can not be assigned!");
- ++_count;
- if (_count > 1)
- throw exception("Expected exactly one dataset, but received more!");
-
- if (data)
- {
- auto* cast = static_cast<value_type*>(data);
- auto& value = nullable_helper_type::set(_dataset, cast);
- if (cast != &value)
- throw exception("Nullable pointer value has changed!");
- return set(value, dataset_id);
- }
- else
- {
- auto& value = nullable_helper_type::set(_dataset, value_type { });
- return set(value);
- }
- }
-
- void finish_intern() const override
- { clear(); }
- };
-
- template<typename... X_args>
- static constexpr decltype(auto) apply(X_args&&... args)
- { return context_impl(std::forward<X_args>(args)...); }
- };
-
- /* container_emplace_helper */
-
- template<typename T_dataset, typename = void>
- struct container_emplace_helper;
-
- template<typename T_dataset>
- struct container_emplace_helper<
- T_dataset,
- mp::enable_if_t<
- mp::is_valid_v<typename container_helper<T_dataset>::value_type>
- && !is_pointer_v<typename container_helper<T_dataset>::value_type>
- >>
- {
- static inline decltype(auto) emplace(T_dataset& dataset, void * data, size_t& data_id)
- {
- using container_helper_type = container_helper<T_dataset>;
- using value_type = typename container_helper_type::value_type;
-
- if (data || data_id != 0)
- throw exception("Static datasets can not be assigned!");
- auto& value = container_helper_type::emplace(dataset);
- data_id = get_type_id(hana::type_c<value_type>);
-
- return value;
- }
- };
-
- template<typename T_dataset>
- struct container_emplace_helper<
- T_dataset,
- mp::enable_if_t<
- mp::is_valid_v<typename container_helper<T_dataset>::value_type>
- && is_pointer_v<typename container_helper<T_dataset>::value_type>
- >>
- {
- static inline decltype(auto) emplace(T_dataset& dataset, void * data, size_t& data_id)
- {
- using container_helper_type = container_helper<T_dataset>;
- using nullable_type = typename container_helper_type::value_type;
- using nullable_helper_type = nullable_helper<nullable_type>;
- using inner_value_type = typename nullable_helper_type::value_type;
-
- if (!data)
- throw exception("Expected dynamic data for pointer type!");
- if (data_id == 0)
- throw exception("Expected dataset id for pointer type!");
- if (!is_pointer_v<nullable_type>)
- throw exception("None pointer type can not be assigned!");
-
- auto& nullable = container_helper_type::emplace(dataset);
- auto* cast = static_cast<inner_value_type*>(data);
- auto& value = nullable_helper_type::set(nullable, cast);
- if (cast != &value)
- throw exception("Nullable pointer value has changed!");
-
- return value;
- }
- };
-
- /* read_context_builder - container */
-
- template<
- typename T_schema,
- typename T_connection,
- typename T_dataset,
- typename T_filter>
- struct read_context_builder<
- mp::list<T_schema, T_connection, T_dataset, T_filter>,
- mp::enable_if_t<
- is_container_v<mp::decay_t<T_dataset>>
- && !is_nullable_v<mp::decay_t<T_dataset>>
- >>
- {
- using dataset_type = mp::decay_t<T_dataset>;
- using real_dataset_type = real_dataset_t<dataset_type>;
- using container_helper_type = container_helper<dataset_type>;
- using value_type = typename container_helper_type::value_type;
- using emplace_helper_type = container_emplace_helper<dataset_type>;
-
- struct context_impl
- : public read_context
- {
- private:
- dataset_type& _dataset;
-
- public:
- inline context_impl(
- const schema_t& p_schema,
- ::cppmariadb::connection& p_connection,
- T_dataset& p_dataset,
- const filter_t& p_filter)
- : read_context (p_schema, p_connection, p_filter,
- get_type_id(hana::type_c<real_dataset_t<mp::decay_t<T_dataset>>>))
- , _dataset (p_dataset)
- {
- is_dynamic = is_pointer_v<value_type>;
- container_helper_type::clear(_dataset);
- }
-
- private:
- void * emplace_intern(void * data, size_t dataset_id) const override
- {
- auto& value = emplace_helper_type::emplace(_dataset, data, dataset_id);
- return set(value, dataset_id);
- }
-
- void finish_intern() const override
- { clear(); }
- };
-
- template<typename... X_args>
- static constexpr decltype(auto) apply(X_args&&... args)
- { return context_impl(std::forward<X_args>(args)...); }
- };
-
- }
-
- } }
|