diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-08-28 11:39:17 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-08-28 14:15:45 +0200 |
commit | 475a7c89e1c858ae8fec466670af4628129a42d4 (patch) | |
tree | 371d7084250767ae927e685fb7a5da630626280f | |
parent | 64d0ceffaaf5f57a3d24a5210bf0ad2a8474a618 (diff) |
Add wrapper support for containers
-rw-r--r-- | odb/common.cxx | 8 | ||||
-rw-r--r-- | odb/common.hxx | 5 | ||||
-rw-r--r-- | odb/context.cxx | 19 | ||||
-rw-r--r-- | odb/context.hxx | 21 | ||||
-rw-r--r-- | odb/relational/header.hxx | 30 | ||||
-rw-r--r-- | odb/relational/mysql/common.cxx | 11 | ||||
-rw-r--r-- | odb/relational/mysql/common.hxx | 9 | ||||
-rw-r--r-- | odb/relational/pgsql/common.cxx | 11 | ||||
-rw-r--r-- | odb/relational/pgsql/common.hxx | 9 | ||||
-rw-r--r-- | odb/relational/pgsql/schema.cxx | 3 | ||||
-rw-r--r-- | odb/relational/pgsql/source.cxx | 11 | ||||
-rw-r--r-- | odb/relational/schema.hxx | 7 | ||||
-rw-r--r-- | odb/relational/source.hxx | 33 | ||||
-rw-r--r-- | odb/relational/sqlite/common.cxx | 11 | ||||
-rw-r--r-- | odb/relational/sqlite/common.hxx | 9 | ||||
-rw-r--r-- | odb/relational/type-processor.cxx | 7 |
16 files changed, 134 insertions, 70 deletions
diff --git a/odb/common.cxx b/odb/common.cxx index 794afc1..18d1580 100644 --- a/odb/common.cxx +++ b/odb/common.cxx @@ -17,7 +17,7 @@ simple (semantics::data_member&) } void object_members_base:: -container (semantics::data_member&) +container (semantics::data_member&, semantics::type&) { } @@ -172,9 +172,9 @@ traverse (semantics::data_member& m) if (om_.build_prefix_) om_.prefix_ = old_prefix; } - else if (context::container (t)) + else if (semantics::type* c = context::container_wrapper (t)) { - om_.container (m); + om_.container (m, *c); } else { @@ -307,7 +307,7 @@ traverse (semantics::data_member& m) prefix_ = old_prefix; } - else if (container (t)) + else if (container_wrapper (t)) { // Container gets its own table, so nothing to do here. // diff --git a/odb/common.hxx b/odb/common.hxx index 86a39c7..e3b4285 100644 --- a/odb/common.hxx +++ b/odb/common.hxx @@ -18,8 +18,11 @@ struct object_members_base: traversal::class_, virtual context virtual void simple (semantics::data_member&); + // The second argument is the actual container type in case m.type () + // is a wrapper. + // virtual void - container (semantics::data_member&); + container (semantics::data_member&, semantics::type&); // If you override this function, you can call the base to traverse // bases and members. The first argument is the data member and can diff --git a/odb/context.cxx b/odb/context.cxx index 9d89879..fc82f29 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -318,7 +318,14 @@ member_type (semantics::data_member& m, string const& key_prefix) if (m.count (key)) return *indirect_value<semantics::type*> (m, key); - return *indirect_value<semantics::type*> (m.type (), key); + // "See throught" wrappers. + // + semantics::type& t (m.type ()); + + if (semantics::type* wt = wrapper (t)) + return *indirect_value<semantics::type*> (*wt, key); + else + return *indirect_value<semantics::type*> (t, key); } bool context:: @@ -938,7 +945,7 @@ namespace } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type& c) { // We don't cross the container boundaries (separate table). // @@ -947,7 +954,7 @@ namespace flags_ & (context::test_container | context::test_straight_container | context::test_inverse_container), - context::container_vt (m.type ()), + context::container_vt (c), "value"); } @@ -982,17 +989,17 @@ is_a (semantics::data_member& m, if (f & test_container) { - r = r || container (m.type ()); + r = r || container_wrapper (m.type ()); } if (f & test_straight_container) { - r = r || (container (m.type ()) && !inverse (m, kp)); + r = r || (container_wrapper (m.type ()) && !inverse (m, kp)); } if (f & test_inverse_container) { - r = r || (container (m.type ()) && inverse (m, kp)); + r = r || (container_wrapper (m.type ()) && inverse (m, kp)); } return r; diff --git a/odb/context.hxx b/odb/context.hxx index 3a09805..6449daf 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -132,6 +132,19 @@ public: return t.count ("container-kind"); } + // As above but also "sees through" wrappers. Returns the actual + // container type or NULL if not a container. + // + static semantics::type* + container_wrapper (semantics::type& t) + { + if (container (t)) + return &t; + else if (semantics::type* wt = wrapper (t)) + return container (*wt) ? wt : 0; + else return 0; + } + static semantics::class_* object_pointer (semantics::type& t) { @@ -320,7 +333,13 @@ public: static bool unordered (semantics::data_member& m) { - return m.count ("unordered") || m.type ().count ("unordered"); + if (m.count ("unordered")) + return true; + + if (semantics::type* c = container_wrapper (m.type ())) + return c->count ("unordered"); + + return false; } // The 'is a' and 'has a' tests. The has_a test currently does not diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index fb18598..900fb45 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -212,7 +212,7 @@ namespace relational } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type& c) { using semantics::type; using semantics::class_; @@ -233,10 +233,9 @@ namespace relational abst = true; // Always abstract. } - type& t (m.type ()); - container_kind_type ck (container_kind (t)); + container_kind_type ck (container_kind (c)); - type& vt (container_vt (t)); + type& vt (container_vt (c)); type* it (0); type* kt (0); @@ -249,7 +248,7 @@ namespace relational { if (!unordered (m)) { - it = &container_it (t); + it = &container_it (c); ordered = true; } break; @@ -257,7 +256,7 @@ namespace relational case ck_map: case ck_multimap: { - kt = &container_kt (t); + kt = &container_kt (c); break; } case ck_set: @@ -387,8 +386,23 @@ namespace relational // key_type // value_type // - os << "typedef " << t.fq_name (m.belongs ().hint ()) << - " container_type;"; + os << "typedef "; + + { + semantics::type& t (m.type ()); + + if (wrapper (t)) + // Use the hint from the wrapper. + // + os << c.fq_name (t.get<semantics::names*> ("wrapper-hint")); + else + // t and c are the same. + // + os << c.fq_name (m.belongs ().hint ()); + } + + os << " container_type;"; + os << "typedef odb::access::container_traits< container_type > " << "container_traits;"; diff --git a/odb/relational/mysql/common.cxx b/odb/relational/mysql/common.cxx index f9028d7..4599b87 100644 --- a/odb/relational/mysql/common.cxx +++ b/odb/relational/mysql/common.cxx @@ -35,22 +35,23 @@ namespace relational semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); - if (semantics::class_* comp = comp_value_wrapper (t)) + if (semantics::class_* c = comp_value_wrapper (t)) { // If t is a wrapper, pass the wrapped type. Also pass the // original, wrapper type. // - member_info mi ( - m, *comp, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); if (pre (mi)) { traverse_composite (mi); post (mi); } } - else if (container (t)) + else if (semantics::type* c = container_wrapper (t)) { - member_info mi (m, t, 0, var, fq_type_override_); + // The same unwrapping logic as for composite values. + // + member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); if (pre (mi)) { traverse_container (mi); diff --git a/odb/relational/mysql/common.hxx b/odb/relational/mysql/common.hxx index 69ee515..a85a75e 100644 --- a/odb/relational/mysql/common.hxx +++ b/odb/relational/mysql/common.hxx @@ -40,10 +40,13 @@ namespace relational string fq_type (bool unwrap = true) const { - // At the moment a wrapped type can only be a composite value. - // if (wrapper != 0 && unwrap) - return t.fq_name (); + { + // Use the hint from the wrapper. + // + return t.fq_name ( + wrapper->get<semantics::names*> ("wrapper-hint")); + } // Use the original type from 'm' instead of 't' since the hint // may be invalid for a different type. Plus, if a type is diff --git a/odb/relational/pgsql/common.cxx b/odb/relational/pgsql/common.cxx index d6ef9c3..e4d97cc 100644 --- a/odb/relational/pgsql/common.cxx +++ b/odb/relational/pgsql/common.cxx @@ -35,22 +35,23 @@ namespace relational semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); - if (semantics::class_* comp = comp_value_wrapper (t)) + if (semantics::class_* c = comp_value_wrapper (t)) { // If t is a wrapper, pass the wrapped type. Also pass the // original, wrapper type. // - member_info mi ( - m, *comp, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); if (pre (mi)) { traverse_composite (mi); post (mi); } } - else if (container (t)) + else if (semantics::type* c = container_wrapper (t)) { - member_info mi (m, t, 0, var, fq_type_override_); + // The same unwrapping logic as for composite values. + // + member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); if (pre (mi)) { traverse_container (mi); diff --git a/odb/relational/pgsql/common.hxx b/odb/relational/pgsql/common.hxx index f41ca8c..a91c40a 100644 --- a/odb/relational/pgsql/common.hxx +++ b/odb/relational/pgsql/common.hxx @@ -40,10 +40,13 @@ namespace relational string fq_type (bool unwrap = true) const { - // At the moment a wrapped type can only be a composite value. - // if (wrapper != 0 && unwrap) - return t.fq_name (); + { + // Use the hint from the wrapper. + // + return t.fq_name ( + wrapper->get<semantics::names*> ("wrapper-hint")); + } // Use the original type from 'm' instead of 't' since the hint // may be invalid for a different type. Plus, if a type is diff --git a/odb/relational/pgsql/schema.cxx b/odb/relational/pgsql/schema.cxx index 5bfbc71..0e66e79 100644 --- a/odb/relational/pgsql/schema.cxx +++ b/odb/relational/pgsql/schema.cxx @@ -186,7 +186,7 @@ namespace relational } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type& t) { using semantics::type; using semantics::data_member; @@ -201,7 +201,6 @@ namespace relational if (tables_.count (name)) return; - type& t (m.type ()); type& vt (container_vt (t)); // object_id diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index 1bba68a..331463d 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -1003,7 +1003,7 @@ namespace relational container_traits (base const& x): base (x) {} virtual void - container_extra (semantics::data_member& m) + container_extra (semantics::data_member& m, semantics::type& t) { if (!c_.count ("object") || abstract (c_)) return; @@ -1039,8 +1039,7 @@ namespace relational semantics::data_member* inv_m (inverse (m, "value")); bool inv (inv_m != 0); - semantics::type& mt (m.type ()); - semantics::type& vt (container_vt (mt)); + semantics::type& vt (container_vt (t)); string id_oid (oids[column_sql_type (m, "id").type]); @@ -1055,7 +1054,7 @@ namespace relational { // many(i)-to-many // - if (context::container (inv_m->type ())) + if (container_wrapper (inv_m->type ())) os << oids[column_sql_type (*inv_m, "value").type]; // many(i)-to-one @@ -1080,7 +1079,7 @@ namespace relational { os << id_oid << ","; - switch (container_kind (mt)) + switch (container_kind (t)) { case ck_ordered: { @@ -1093,7 +1092,7 @@ namespace relational case ck_multimap: { if (semantics::class_* ktc = - comp_value_wrapper (container_kt (mt))) + comp_value_wrapper (container_kt (t))) { instance<statement_oids> st; st->traverse_composite (m, *ktc, "key", "key"); diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 5f253c4..5c985da 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -83,7 +83,7 @@ namespace relational } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type& c) { // Ignore inverse containers of object pointers. // @@ -109,7 +109,7 @@ namespace relational drop_index (name, column_name (m, "id", "object_id")); post_statement (); - if (container_kind (m.type ()) == ck_ordered && !unordered (m)) + if (container_kind (c) == ck_ordered && !unordered (m)) { pre_statement (); drop_index (name, column_name (m, "index", "index")); @@ -372,7 +372,7 @@ namespace relational } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type& t) { using semantics::type; using semantics::data_member; @@ -382,7 +382,6 @@ namespace relational if (inverse (m, "value")) return; - type& t (m.type ()); container_kind_type ck (container_kind (t)); type& vt (container_vt (t)); diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 7d0c079..c825159 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -86,7 +86,7 @@ namespace relational { semantics::class_* c (object_pointer (m.type ())); - if (container (im->type ())) + if (container_wrapper (im->type ())) { // This container is a direct member of the class so the table // prefix is just the class table name. @@ -220,7 +220,7 @@ namespace relational if (semantics::data_member* im = inverse (m)) { - if (container (im->type ())) + if (container_wrapper (im->type ())) { // This container is a direct member of the class so the table // prefix is just the class table name. @@ -619,12 +619,12 @@ namespace relational } virtual void - container_extra (semantics::data_member&) + container_extra (semantics::data_member&, semantics::type&) { } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type& t) { using semantics::type; @@ -644,7 +644,6 @@ namespace relational abst = true; // Always abstract. } - type& t (m.type ()); container_kind_type ck (container_kind (t)); type& vt (container_vt (t)); @@ -695,7 +694,7 @@ namespace relational << "//" << endl << endl; - container_extra (m); + container_extra (m, t); // // Statements. @@ -717,7 +716,7 @@ namespace relational string inv_id; // Other id column. string inv_fid; // Other foreign id column (ref to us). - if (context::container (im->type ())) + if (container_wrapper (im->type ())) { // many(i)-to-many // @@ -1637,7 +1636,7 @@ namespace relational } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type&) { string traits (prefix_ + public_name (m) + "_traits"); os << db << "::container_statements_impl< " << traits << " > " << @@ -1655,7 +1654,7 @@ namespace relational } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type&) { if (first_) { @@ -1732,7 +1731,7 @@ namespace relational } virtual void - container (semantics::data_member& m) + container (semantics::data_member& m, semantics::type&) { using semantics::type; @@ -1743,6 +1742,20 @@ namespace relational string sts_name (prefix_ + name); string traits (prefix_ + public_name (m) + "_traits"); + // If this is a wrapped container, then we need to "unwrap" it. + // + { + semantics::type& t (m.type ()); + if (wrapper (t)) + { + string const& type (t.fq_name (m.belongs ().hint ())); + + obj_name = "wrapper_traits< " + type + " >::" + + (call_ == load_call ? "set_ref" : "get_ref") + + " (" + obj_name + ")"; + } + } + switch (call_) { case persist_call: diff --git a/odb/relational/sqlite/common.cxx b/odb/relational/sqlite/common.cxx index d9f79b0..1531e75 100644 --- a/odb/relational/sqlite/common.cxx +++ b/odb/relational/sqlite/common.cxx @@ -35,22 +35,23 @@ namespace relational semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); - if (semantics::class_* comp = comp_value_wrapper (t)) + if (semantics::class_* c = comp_value_wrapper (t)) { // If t is a wrapper, pass the wrapped type. Also pass the // original, wrapper type. // - member_info mi ( - m, *comp, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); if (pre (mi)) { traverse_composite (mi); post (mi); } } - else if (container (t)) + else if (semantics::type* c = container_wrapper (t)) { - member_info mi (m, t, 0, var, fq_type_override_); + // The same unwrapping logic as for composite values. + // + member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); if (pre (mi)) { traverse_container (mi); diff --git a/odb/relational/sqlite/common.hxx b/odb/relational/sqlite/common.hxx index e3f81a5..e8663af 100644 --- a/odb/relational/sqlite/common.hxx +++ b/odb/relational/sqlite/common.hxx @@ -40,10 +40,13 @@ namespace relational string fq_type (bool unwrap = true) const { - // At the moment a wrapped type can only be a composite value. - // if (wrapper != 0 && unwrap) - return t.fq_name (); + { + // Use the hint from the wrapper. + // + return t.fq_name ( + wrapper->get<semantics::names*> ("wrapper-hint")); + } // Use the original type from 'm' instead of 't' since the hint // may be invalid for a different type. Plus, if a type is diff --git a/odb/relational/type-processor.cxx b/odb/relational/type-processor.cxx index 24a7325..e53126f 100644 --- a/odb/relational/type-processor.cxx +++ b/odb/relational/type-processor.cxx @@ -195,7 +195,8 @@ namespace relational // See if this is a container type. // - if (process_container (m)) + if (process_container (m, t) || + (wt != 0 && process_container (m, *wt))) return; // If it is none of the above then we have an error. @@ -306,7 +307,7 @@ namespace relational } bool - process_container (semantics::data_member& m) + process_container (semantics::data_member& m, semantics::type& t) { // The overall idea is as follows: try to instantiate the container // traits class template. If we are successeful, then this is a @@ -314,8 +315,6 @@ namespace relational // the instantiation. Otherwise, this is not a container. // - semantics::type& t (m.type ()); - container_kind_type ck; semantics::type* vt (0); semantics::type* it (0); |