aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--manifest6
-rw-r--r--odb/details/buffer.hxx16
-rw-r--r--odb/lazy-ptr-impl.ixx4
-rw-r--r--odb/nested-container.hxx169
-rw-r--r--odb/schema-catalog.cxx3
-rw-r--r--odb/version-build2.hxx.in2
-rw-r--r--odb/version.hxx8
-rw-r--r--version1
8 files changed, 161 insertions, 48 deletions
diff --git a/manifest b/manifest
index e7c40e3..8472d9e 100644
--- a/manifest
+++ b/manifest
@@ -1,6 +1,6 @@
: 1
name: libodb
-version: 2.5.0-b.20.z
+version: 2.5.0-b.22.z
project: odb
summary: Common ODB runtime library
license: GPL-2.0-only
@@ -15,5 +15,5 @@ email: odb-users@codesynthesis.com
build-warning-email: odb-builds@codesynthesis.com
builds: all
requires: c++11
-depends: * build2 >= 0.13.0
-depends: * bpkg >= 0.13.0
+depends: * build2 >= 0.14.0-
+depends: * bpkg >= 0.14.0-
diff --git a/odb/details/buffer.hxx b/odb/details/buffer.hxx
index 2b26e8c..558be9b 100644
--- a/odb/details/buffer.hxx
+++ b/odb/details/buffer.hxx
@@ -64,6 +64,22 @@ namespace odb
{
return static_cast<T*> (data_);
}
+
+ // Note that strictly speaking the return type should be void* const*
+ // but that would make using this function too awkward since we often
+ // store the result as void*.
+ //
+ void**
+ data_ptr ()
+ {
+ return &data_;
+ }
+
+ const void* const*
+ data_ptr () const
+ {
+ return &data_;
+ }
};
typedef basic_buffer<char> buffer;
diff --git a/odb/lazy-ptr-impl.ixx b/odb/lazy-ptr-impl.ixx
index d69b8e4..7843dc9 100644
--- a/odb/lazy-ptr-impl.ixx
+++ b/odb/lazy-ptr-impl.ixx
@@ -84,14 +84,14 @@ namespace odb
{
reset_id ();
id_ = r.id_;
- db_ = r.db_;
- loader_ = r.loader_;
free_ = r.free_;
copy_ = r.copy_;
r.id_ = 0;
}
+ db_ = r.db_;
+ loader_ = r.loader_;
return *this;
}
#endif
diff --git a/odb/nested-container.hxx b/odb/nested-container.hxx
index c7627ed..82abf0b 100644
--- a/odb/nested-container.hxx
+++ b/odb/nested-container.hxx
@@ -19,22 +19,24 @@ 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).
+ // In a nutshell, the idea is to represent a nested container, for example,
+ // vector<vector<V>>, as map<nested_key, V> where nested_key is a composite
+ // key consisting of the outer and inner container indexes.
//
-
- // 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.
+ // 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 1-level nested container mapping (for
+ // example, vector<vector<V>>). Template parameter IC is a tag that allows
+ // us to distinguish keys for unrelated containers in order to assign column
+ // names, etc. Use the inner container type (for example, vector<V>) for IC.
//
- template <typename T,
+ template <typename IC,
typename O = std::size_t,
typename I = std::size_t>
struct nested_key
@@ -54,10 +56,40 @@ namespace odb
return outer < v.outer || (outer == v.outer && inner < v.inner);
}
};
+
+ // Map key that is used to emulate 2-level nested container mapping (for
+ // example, vector<vector<vector<V>>>>). Use the middle container type for
+ // MC (for example, vector<vector<V>>).
+ //
+ template <typename MC,
+ typename O = std::size_t,
+ typename M = std::size_t,
+ typename I = std::size_t>
+ struct nested2_key
+ {
+ using outer_type = O;
+ using middle_type = M;
+ using inner_type = I;
+
+ outer_type outer;
+ middle_type middle;
+ inner_type inner;
+
+ nested2_key () = default;
+ nested2_key (outer_type o, middle_type m, inner_type i)
+ : outer (o), middle (m), inner (i) {}
+
+ bool
+ operator< (const nested2_key& v) const
+ {
+ return outer != v.outer ? outer < v.outer :
+ middle != v.middle ? middle < v.middle :
+ inner < v.inner ;
+ }
+ };
}
#include <map>
-#include <vector>
#include <cstddef> // size_t
#include <utility> // move(), declval()
#include <cassert>
@@ -65,46 +97,109 @@ namespace odb
namespace odb
{
- // vector<vector<>>
- //
- template <typename IC>
- struct nested_value_type:
- std::remove_reference<decltype (std::declval<IC> ()[0])> {};
+ template <typename C>
+ struct nested1_type:
+ std::remove_reference<decltype (std::declval<C> ()[0])> {};
+
+ template <typename C>
+ struct nested2_type:
+ std::remove_reference<decltype (std::declval<C> ()[0][0])> {};
+
+ template <typename C>
+ struct nested3_type:
+ std::remove_reference<decltype (std::declval<C> ()[0][0][0])> {};
- template <typename IC>
- std::map<nested_key<IC>, typename nested_value_type<IC>::type>
- nested_get (const std::vector<IC>& v)
+ // 1-level nesting.
+ //
+ template <typename OC> // For example, OC = vector<vector<V>>.
+ std::map<nested_key<typename nested1_type<OC>::type>,
+ typename nested2_type<OC>::type>
+ nested_get (const OC& oc)
{
using namespace std;
- using I = typename nested_value_type<IC>::type;
+ using IC = typename nested1_type<OC>::type;
+ using V = typename nested2_type<OC>::type;
using K = nested_key<IC>;
- map<K, I> r;
- for (size_t n (0); n != v.size (); ++n)
+ map<K, V> r;
+ for (size_t o (0); o != oc.size (); ++o)
{
- const IC& o (v[n]);
- for (size_t m (0); m != o.size (); ++m)
- r.emplace (K (n, m), o[m]);
+ const IC& ic (oc[o]);
+ for (size_t i (0); i != ic.size (); ++i)
+ r.emplace (K (o, i), ic[i]);
}
return r;
}
- template <typename K, typename I, typename IC>
+ template <typename K, typename V, typename OC>
void
- nested_set (std::vector<IC>& v, std::map<K, I>&& r)
+ nested_set (OC& oc, std::map<K, V>&& r)
{
using namespace std;
for (auto& p: r)
{
- size_t n (p.first.outer);
- size_t m (p.first.inner);
- I& i (p.second);
+ size_t o (p.first.outer);
+ size_t i (p.first.inner);
+ V& v (p.second);
+
+ assert (o < oc.size ());
+ assert (i == oc[o].size ());
+ oc[o].push_back (move (v));
+ }
+ }
+
+ // 2-level nesting.
+ //
+ template <typename OC> // For example, OC = vector<vector<vector<V>>>.
+ std::map<nested2_key<typename nested1_type<OC>::type>,
+ typename nested3_type<OC>::type>
+ nested2_get (const OC& oc)
+ {
+ using namespace std;
+
+ using MC = typename nested1_type<OC>::type;
+ using V = typename nested3_type<OC>::type;
+ using K = nested2_key<MC>;
+
+ map<K, V> r;
+ for (size_t o (0); o != oc.size (); ++o)
+ {
+ const auto& mc (oc[o]);
+ for (size_t m (0); m != mc.size (); ++m)
+ {
+ const auto& ic (mc[m]);
+ for (size_t i (0); i != ic.size (); ++i)
+ r.emplace (K (o, m, i), ic[i]);
+ }
+ }
+ return r;
+ }
+
+ template <typename K, typename V, typename OC>
+ void
+ nested2_set (OC& oc, std::map<K, V>&& r)
+ {
+ using namespace std;
+
+ for (auto& p: r)
+ {
+ size_t o (p.first.outer);
+ size_t m (p.first.middle);
+ size_t i (p.first.inner);
+ V& v (p.second);
+
+ assert (o < oc.size ());
+
+ auto& mc (oc[o]);
+
+ if (m >= mc.size ())
+ mc.resize (m + 1);
+
+ assert (i == mc[m].size ());
- assert (n < v.size ());
- assert (m == v[n].size ());
- v[n].push_back (move (i));
+ mc[m].push_back (move (v));
}
}
}
diff --git a/odb/schema-catalog.cxx b/odb/schema-catalog.cxx
index fb3ab82..1bdc112 100644
--- a/odb/schema-catalog.cxx
+++ b/odb/schema-catalog.cxx
@@ -267,6 +267,9 @@ namespace odb
schema_version i (db.schema_version (name));
+ if (i > v)
+ throw unknown_schema_version (i); // Database too new.
+
// If there is no schema, then "migrate" by creating it.
//
if (i == 0)
diff --git a/odb/version-build2.hxx.in b/odb/version-build2.hxx.in
index 5b4a37d..77a2924 100644
--- a/odb/version-build2.hxx.in
+++ b/odb/version-build2.hxx.in
@@ -5,7 +5,7 @@
// For the ODB compiler (temporary).
//
-#define ODB_VERSION 20470
+#define ODB_VERSION 20472
// The numeric version format is AAAAABBBBBCCCCCDDDE where:
//
diff --git a/odb/version.hxx b/odb/version.hxx
index 38b347f..c607f92 100644
--- a/odb/version.hxx
+++ b/odb/version.hxx
@@ -29,13 +29,13 @@
// ODB interface version: minor, major, and alpha/beta versions.
//
-#define ODB_VERSION 20470
-#define ODB_VERSION_STR "2.5-b.20"
+#define ODB_VERSION 20472
+#define ODB_VERSION_STR "2.5-b.22"
// libodb version: interface version plus the bugfix version.
//
-#define LIBODB_VERSION 2049970
-#define LIBODB_VERSION_STR "2.5.0-b.20"
+#define LIBODB_VERSION 2049972
+#define LIBODB_VERSION_STR "2.5.0-b.22"
#include <odb/post.hxx>
diff --git a/version b/version
deleted file mode 100644
index a60117f..0000000
--- a/version
+++ /dev/null
@@ -1 +0,0 @@
-2.5.0-b.20