From ad515f85e807f8d21a1b70f5ed288705e0f2f531 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 1 Oct 2015 11:50:21 +0200 Subject: Add helper header for nested container emulation Still fairly experimental, only supports vector>. --- odb/nested-container.hxx | 115 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 odb/nested-container.hxx diff --git a/odb/nested-container.hxx b/odb/nested-container.hxx new file mode 100644 index 0000000..a4cf564 --- /dev/null +++ b/odb/nested-container.hxx @@ -0,0 +1,115 @@ +// file : odb/nested-container.hxx +// copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_NESTED_CONTAINER_HXX +#define ODB_NESTED_CONTAINER_HXX + +#include + +#include // size_t + +#include +#include // ODB_CXX11 + +#ifndef ODB_CXX11 +# error nested container support is only available in C++11 +#endif + +namespace odb +{ + // Nested container emulation support for ODB. + // + // Note that the outer key in the inner container should strictly + // speaking be a foreign key pointing to the key of the outer + // container. The only way to achieve this currently is to manually + // add the constraint via ALTER TABLE ADD CONSTRAINT. Note, however, + // that as long as we only modify these tables via the ODB container + // interface, not having the foreign key (and not having ON DELETE + // CASCADE) should be harmless (since we have a foreign key pointing + // to the object id). + // + + // Map key that is used to emulate nested container mapping in ODB. + // Template parameter T is a tag that allows us to distinguish keys + // for unrelated containers in order to assign column names, etc. + // Use inner container type for T. + // + template + struct nested_key + { + using outer_type = O; + using inner_type = I; + + outer_type outer; + inner_type inner; + + nested_key () = default; + nested_key (outer_type o, inner_type i): outer (o), inner (i) {} + + bool + operator< (const nested_key& v) const + { + return outer < v.outer || (outer == v.outer && inner < v.inner); + } + }; +} + +#include +#include +#include // size_t +#include // move(), declval() +#include +#include // remove_reference + +namespace odb +{ + // vector> + // + template + struct nested_value_type: + std::remove_reference ()[0])> {}; + + template + std::map, typename nested_value_type::type> + nested_get (const std::vector& v) + { + using namespace std; + + using I = typename nested_value_type::type; + using K = nested_key; + + map r; + for (size_t n (0); n != v.size (); ++n) + { + const IC& o (v[n]); + for (size_t m (0); m != o.size (); ++m) + r.emplace (K (n, m), o[m]); + } + return r; + } + + template + void + nested_set (std::vector& v, std::map&& r) + { + using namespace std; + + for (auto& p: r) + { + size_t n (p.first.outer); + size_t m (p.first.inner); + I& i (p.second); + + assert (n < v.size ()); + assert (m == v[n].size ()); + v[n].push_back (move (i)); + } + } +} + +#include + +#endif // ODB_NESTED_CONTAINER_HXX -- cgit v1.1