From 6bd95f51beb26d87fd5d5db22391c73f333eee6e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 19 Oct 2011 10:47:41 +0200 Subject: Add support for const data members Const data members are automatically treated as readonly. New test: const-member. --- odb/common.cxx | 4 +- odb/context.cxx | 121 ++++++++++++++++++++++++++++----------- odb/context.hxx | 59 ++++++++++++++++--- odb/header.cxx | 5 +- odb/inline.cxx | 18 ++++-- odb/relational/common.cxx | 11 ++-- odb/relational/header.hxx | 29 +++++++--- odb/relational/mysql/common.cxx | 27 +++++++-- odb/relational/mysql/common.hxx | 30 +++++++--- odb/relational/mysql/source.cxx | 42 +++++++++----- odb/relational/oracle/common.cxx | 27 +++++++-- odb/relational/oracle/common.hxx | 30 +++++++--- odb/relational/oracle/schema.cxx | 3 +- odb/relational/oracle/source.cxx | 27 ++++++--- odb/relational/pgsql/common.cxx | 27 +++++++-- odb/relational/pgsql/common.hxx | 30 +++++++--- odb/relational/pgsql/schema.cxx | 3 +- odb/relational/pgsql/source.cxx | 49 ++++++++++------ odb/relational/processor.cxx | 88 +++++++++++++++++----------- odb/relational/schema.cxx | 2 +- odb/relational/schema.hxx | 2 +- odb/relational/source.cxx | 4 +- odb/relational/source.hxx | 78 ++++++++++++++++++------- odb/relational/sqlite/common.cxx | 27 +++++++-- odb/relational/sqlite/common.hxx | 30 +++++++--- odb/relational/sqlite/schema.cxx | 3 +- odb/relational/sqlite/source.cxx | 27 ++++++--- odb/tracer/header.cxx | 10 +++- odb/validator.cxx | 8 +-- 29 files changed, 588 insertions(+), 233 deletions(-) diff --git a/odb/common.cxx b/odb/common.cxx index bc9e214..27b647c 100644 --- a/odb/common.cxx +++ b/odb/common.cxx @@ -163,7 +163,7 @@ traverse (semantics::data_member& m) om_.member_path_.push_back (&m); - semantics::type& t (m.type ()); + semantics::type& t (utype (m)); if (semantics::class_* comp = context::composite_wrapper (t)) { @@ -410,7 +410,7 @@ traverse (semantics::data_member& m) oc_.member_path_.push_back (&m); - semantics::type& t (m.type ()); + semantics::type& t (utype (m)); if (semantics::class_* comp = composite_wrapper (t)) { diff --git a/odb/context.cxx b/odb/context.cxx index 00d894f..9814dc2 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -242,7 +242,7 @@ readonly (semantics::data_member& m) bool context:: null (semantics::data_member& m) { - semantics::type& t (m.type ()); + semantics::type& t (utype (m)); if (object_pointer (t)) { @@ -306,8 +306,8 @@ null (semantics::data_member& m, string const& kp) if (kp.empty ()) return null (m); - semantics::type& c (m.type ()); - semantics::type& t (member_type (m, kp)); + semantics::type& c (utype (m)); + semantics::type& t (member_utype (m, kp)); if (object_pointer (t)) { @@ -362,7 +362,10 @@ null (semantics::data_member& m, string const& kp) // Otherwise, check the wrapped type. // - if (t.get ("wrapper-type")->count ("null")) + semantics::type& wt ( + utype (*t.get ("wrapper-type"))); + + if (wt.count ("null")) return true; } } @@ -415,8 +418,58 @@ restore () } semantics::type& context:: +utype (semantics::type& t) +{ + if (semantics::qualifier* q = dynamic_cast (&t)) + return q->base_type (); + else + return t; +} + +semantics::type& context:: +utype (semantics::type& t, semantics::names*& hint) +{ + if (semantics::qualifier* q = dynamic_cast (&t)) + { + hint = q->qualifies ().hint (); + return q->base_type (); + } + else + return t; +} + +semantics::type& context:: +utype (semantics::data_member& m, semantics::names*& hint) +{ + semantics::type& t (m.type ()); + + if (semantics::qualifier* q = dynamic_cast (&t)) + { + hint = q->qualifies ().hint (); + return q->base_type (); + } + else + { + hint = m.belongs ().hint (); + return t; + } +} + +bool context:: +const_type (semantics::type& t) +{ + if (semantics::qualifier* q = dynamic_cast (&t)) + return q->const_ (); + + return false; +} + +semantics::type& context:: member_type (semantics::data_member& m, string const& key_prefix) { + // This function returns the potentially-qualified type but for + // intermediate types we use unqualified versions. + // if (key_prefix.empty ()) return m.type (); @@ -427,10 +480,10 @@ member_type (semantics::data_member& m, string const& key_prefix) // "See throught" wrappers. // - semantics::type& t (m.type ()); + semantics::type& t (utype (m)); if (semantics::type* wt = wrapper (t)) - return *indirect_value (*wt, key); + return *indirect_value (utype (*wt), key); else return *indirect_value (t, key); } @@ -564,7 +617,7 @@ column_name (data_member_path const& mp) const { semantics::data_member& m (**i); - if (composite_wrapper (m.type ())) + if (composite_wrapper (utype (m))) r += object_columns_base::column_prefix (m); else r += column_name (m); @@ -576,16 +629,22 @@ column_name (data_member_path const& mp) const string context:: column_name (semantics::data_member& m, string const& p, string const& d) const { - // A container column name can be specified for the member of for the + // A container column name can be specified for the member or for the // container type. // string key (p + "-column"); + if (m.count (key)) return m.get (key); - else if (m.type ().count (key)) - return m.type ().get (key); else - return d; + { + semantics::type& t (utype (m)); + + if (t.count (key)) + return t.get (key); + } + + return d; } string context:: @@ -601,7 +660,7 @@ column_options (semantics::data_member& m) { // Accumulate options from both type and member. // - semantics::type& t (m.type ()); + semantics::type& t (utype (m)); string r; @@ -654,8 +713,8 @@ column_options (semantics::data_member& m, string const& kp) // Accumulate options from type, container, and member. // - semantics::type& c (m.type ()); - semantics::type& t (member_type (m, kp)); + semantics::type& c (utype (m)); + semantics::type& t (member_utype (m, kp)); string r; @@ -1120,38 +1179,32 @@ is_a (data_member_path const& mp, semantics::data_member& m (*mp.back ()); if (f & test_pointer) - { r = r || object_pointer (t); - } if (f & test_eager_pointer) - { r = r || (object_pointer (t) && !lazy_pointer (t)); - } if (f & test_lazy_pointer) - { r = r || (object_pointer (t) && lazy_pointer (t)); - } - if (f & test_container) + if ((f & (test_container | + test_straight_container | + test_inverse_container | + test_readonly_container)) != 0) { - r = r || container_wrapper (m.type ()); - } + semantics::type& c (utype (m)); - if (f & test_straight_container) - { - r = r || (container_wrapper (m.type ()) && !inverse (m, kp)); - } + if (f & test_container) + r = r || container_wrapper (c); - if (f & test_inverse_container) - { - r = r || (container_wrapper (m.type ()) && inverse (m, kp)); - } + if (f & test_straight_container) + r = r || (container_wrapper (c) && !inverse (m, kp)); - if (f & test_readonly_container) - { - r = r || (container_wrapper (m.type ()) && readonly (mp, ms)); + if (f & test_inverse_container) + r = r || (container_wrapper (c) && inverse (m, kp)); + + if (f & test_readonly_container) + r = r || (container_wrapper (c) && readonly (mp, ms)); } return r; diff --git a/odb/context.hxx b/odb/context.hxx index 16be673..b52ead3 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -227,9 +227,47 @@ public: upcase (string const&); public: + // Return cvr-unqualified base of the type, or type itself, if it is + // not qualified. + // + static semantics::type& + utype (semantics::type&); + + // The same as above, but also returns the name hint for the unqualified + // type. If the original type is already unqualified, then the hint + // argument is not modified. + // + static semantics::type& + utype (semantics::type&, semantics::names*& hint); + + // The same for a member's type. + // + static semantics::type& + utype (semantics::data_member& m) + { + return utype (m.type ()); + } + + // In addition to the unqualified type, this version also returns the + // name hint for this type. If the member type is already unqualified, + // then the hint is from the belongs edge. Otherwise, it is from the + // qualifies edge. + // + static semantics::type& + utype (semantics::data_member&, semantics::names*& hint); + + static bool + const_type (semantics::type&); + static semantics::type& member_type (semantics::data_member& m, string const& key_prefix); + static semantics::type& + member_utype (semantics::data_member& m, string const& key_prefix) + { + return utype (member_type (m, key_prefix)); + } + // Predicates. // public: @@ -246,7 +284,8 @@ public: } // Check whether the type is a wrapper. Return the wrapped type if - // it is a wrapper and NULL otherwise. + // it is a wrapper and NULL otherwise. Note that the returned type + // may be cvr-qualified. // static semantics::type* wrapper (semantics::type& t) @@ -288,7 +327,7 @@ public: if (semantics::class_* c = composite (t)) return c; else if (semantics::type* wt = wrapper (t)) - return composite (*wt); + return composite (utype (*wt)); else return 0; } @@ -308,8 +347,12 @@ public: if (container (t)) return &t; else if (semantics::type* wt = wrapper (t)) + { + wt = &utype (*wt); return container (*wt) ? wt : 0; - else return 0; + } + else + return 0; } static semantics::class_* @@ -491,7 +534,7 @@ public: static semantics::data_member* inverse (semantics::data_member& m) { - return object_pointer (m.type ()) + return object_pointer (utype (m)) ? m.get ("inverse", 0) : 0; } @@ -502,7 +545,7 @@ public: if (key_prefix.empty ()) return inverse (m); - return object_pointer (member_type (m, key_prefix)) + return object_pointer (member_utype (m, key_prefix)) ? m.get (key_prefix + "-inverse", 0) : 0; } @@ -521,7 +564,7 @@ public: static semantics::type& container_idt (semantics::data_member& m) { - return member_type (m, "id"); + return member_utype (m, "id"); } static semantics::type& @@ -548,7 +591,7 @@ public: if (m.count ("unordered")) return true; - if (semantics::type* c = container_wrapper (m.type ())) + if (semantics::type* c = container_wrapper (utype (m))) return c->count ("unordered"); return false; @@ -573,7 +616,7 @@ public: data_member_scope const& ms, unsigned short flags) { - return is_a (mp, ms, flags, mp.back ()->type (), ""); + return is_a (mp, ms, flags, utype (*mp.back ()), ""); } bool diff --git a/odb/header.cxx b/odb/header.cxx index 7456169..53ab220 100644 --- a/odb/header.cxx +++ b/odb/header.cxx @@ -20,7 +20,10 @@ namespace return; string const& name (public_name (m)); - string const& type (m.type ().fq_name (m.belongs ().hint ())); + + semantics::names* hint; + semantics::type& t (utype (m, hint)); + string const& type (t.fq_name (hint)); os << "static " << type << "&" << endl << name << " (value_type&);" diff --git a/odb/inline.cxx b/odb/inline.cxx index 612219f..6cbb3cc 100644 --- a/odb/inline.cxx +++ b/odb/inline.cxx @@ -24,15 +24,25 @@ namespace if (transient (m)) return; + semantics::type& t (m.type ()); + string const& name (public_name (m)); - string const& type (m.type ().fq_name (m.belongs ().hint ())); + + semantics::names* hint; + semantics::type& ut (utype (m, hint)); + string const& type (ut.fq_name (hint)); os << "inline" << endl << type << "& " << scope_ << "::" << endl << name << " (value_type& v)" - << "{" - << "return v." << m.name () << ";" - << "}"; + << "{"; + + if (const_type (t)) + os << "return const_cast< " << type << "& > (v." << m.name () << ");"; + else + os << "return v." << m.name () << ";"; + + os << "}"; os << "inline" << endl << "const " << type << "& " << scope_ << "::" << endl diff --git a/odb/relational/common.cxx b/odb/relational/common.cxx index 7668063..b7255a2 100644 --- a/odb/relational/common.cxx +++ b/odb/relational/common.cxx @@ -82,7 +82,7 @@ namespace relational bool query_columns_base:: traverse_column (semantics::data_member& m, string const& column, bool) { - semantics::class_* ptr (object_pointer (m.type ())); + semantics::class_* ptr (object_pointer (utype (m))); if (ptr == 0) return false; @@ -211,7 +211,9 @@ namespace relational bool query_columns:: traverse_column (semantics::data_member& m, string const& column, bool) { - semantics::class_* ptr (object_pointer (m.type ())); + semantics::names* hint; + semantics::type& t (utype (m, hint)); + semantics::class_* ptr (object_pointer (t)); if (ptr != 0) { @@ -233,10 +235,11 @@ namespace relational if (ptr != 0) { semantics::data_member& id (*id_member (*ptr)); - type = id.type ().fq_name (id.belongs ().hint ()); + semantics::type& t (utype (id, hint)); + type = t.fq_name (hint); } else - type = m.type ().fq_name (m.belongs ().hint ()); + type = t.fq_name (hint); string type_id (database_type_id (m)); diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 7190e49..7c74d09 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -523,16 +523,24 @@ namespace relational os << "typedef "; { - semantics::type& t (m.type ()); + semantics::names* hint; + semantics::type& t (utype (m, hint)); - if (wrapper (t)) - // Use the hint from the wrapper. + if (semantics::type* wt = wrapper (t)) + { + // Use the hint from the wrapper unless the wrapped type is + // qualified. In this case use the hint for the unqualified + // type. // - os << c.fq_name (t.get ("wrapper-hint")); + hint = t.get ("wrapper-hint"); + utype (*wt, hint); + + os << c.fq_name (hint); + } else // t and c are the same. // - os << c.fq_name (m.belongs ().hint ()); + os << t.fq_name (hint); } os << " container_type;"; @@ -986,10 +994,13 @@ namespace relational } else { - os << "typedef " << id->type ().fq_name (id->belongs ().hint ()) << - " id_type;" - << endl - << "static const bool auto_id = " << + semantics::names* hint; + semantics::type& t (utype (*id, hint)); + + os << "typedef " << t.fq_name (hint) << " id_type;" + << endl; + + os << "static const bool auto_id = " << (auto_id ? "true" : "false") << ";" << endl; diff --git a/odb/relational/mysql/common.cxx b/odb/relational/mysql/common.cxx index c2e6fa3..4c66254 100644 --- a/odb/relational/mysql/common.cxx +++ b/odb/relational/mysql/common.cxx @@ -33,14 +33,20 @@ namespace relational var = name + (name[name.size () - 1] == '_' ? "" : "_"); } - semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); + bool cq (type_override_ != 0 ? false: const_type (m.type ())); + semantics::type& t (type_override_ != 0 ? *type_override_ : utype (m)); if (semantics::class_* c = composite_wrapper (t)) { // If t is a wrapper, pass the wrapped type. Also pass the // original, wrapper type. // - member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, + *c, + (wrapper (t) ? &t : 0), + cq, + var, + fq_type_override_); if (pre (mi)) { traverse_composite (mi); @@ -51,7 +57,12 @@ namespace relational { // The same unwrapping logic as for composite values. // - member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, + *c, + (wrapper (t) ? &t : 0), + cq, + var, + fq_type_override_); if (pre (mi)) { traverse_container (mi); @@ -64,8 +75,12 @@ namespace relational if (semantics::class_* c = object_pointer (t)) { - member_info mi ( - m, id_member (*c)->type (), 0, var, fq_type_override_); + member_info mi (m, + utype (*id_member (*c)), + 0, + cq, + var, + fq_type_override_); mi.st = &st; if (pre (mi)) { @@ -75,7 +90,7 @@ namespace relational } else { - member_info mi (m, t, 0, var, fq_type_override_); + member_info mi (m, t, 0, cq, var, fq_type_override_); mi.st = &st; if (pre (mi)) { diff --git a/odb/relational/mysql/common.hxx b/odb/relational/mysql/common.hxx index a85a75e..66269c6 100644 --- a/odb/relational/mysql/common.hxx +++ b/odb/relational/mysql/common.hxx @@ -29,9 +29,13 @@ namespace relational struct member_info { semantics::data_member& m; // Member. - semantics::type& t; // Member C++ type (m.type () may != t). - semantics::type* wrapper; // Wrapper type if member is a wrapper. + semantics::type& t; // Cvr-unqualified member C++ type, note + // that m.type () may not be the same as t. + semantics::type* wrapper; // Wrapper type if member is a composite or + // container wrapper, also cvr-unqualified. // In this case t is the wrapped type. + bool cq; // True if the original (wrapper) type + // is const-qualified. sql_type const* st; // Member SQL type (only simple values). string& var; // Member variable name with trailing '_'. @@ -40,21 +44,29 @@ namespace relational string fq_type (bool unwrap = true) const { + semantics::names* hint; + if (wrapper != 0 && unwrap) { - // Use the hint from the wrapper. + // Use the hint from the wrapper unless the wrapped type + // is qualified. // - return t.fq_name ( - wrapper->get ("wrapper-hint")); + hint = wrapper->get ("wrapper-hint"); + utype (*context::wrapper (*wrapper), hint); + return t.fq_name (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 // overriden, then the fq_type must be as well. // - return fq_type_.empty () - ? m.type ().fq_name (m.belongs ().hint ()) - : fq_type_; + if (fq_type_.empty ()) + { + semantics::type& t (utype (m, hint)); + return t.fq_name (hint); + } + else + return fq_type_; } string const& fq_type_; @@ -62,11 +74,13 @@ namespace relational member_info (semantics::data_member& m_, semantics::type& t_, semantics::type* wrapper_, + bool cq_, string& var_, string const& fq_type) : m (m_), t (t_), wrapper (wrapper_), + cq (cq_), st (0), var (var_), fq_type_ (fq_type) diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx index 25fac41..d49910f 100644 --- a/odb/relational/mysql/source.cxx +++ b/odb/relational/mysql/source.cxx @@ -629,7 +629,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (semantics::class_* c = object_pointer (mt)) { @@ -702,7 +702,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - if (object_pointer (member_type (mi.m, key_prefix_))) + if (object_pointer (member_utype (mi.m, key_prefix_))) { os << "}"; @@ -876,6 +876,10 @@ namespace relational string const& name (mi.m.name ()); member = "o." + name; + if (mi.cq) + member = "const_cast< " + mi.fq_type (false) + "& > (" + + member + ")"; + os << "// " << name << endl << "//" << endl; } @@ -889,7 +893,7 @@ namespace relational // Here we need the wrapper type, not the wrapped type. // member = "wrapper_traits< " + mi.fq_type (false) + " >::" + - "set_ref (" + member + ")"; + "set_ref (\n" + member + ")"; } if (composite (mi.t)) @@ -899,7 +903,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (semantics::class_* c = object_pointer (mt)) { @@ -950,13 +954,20 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (object_pointer (mt)) { - member = member_override_.empty () - ? "o." + mi.m.name () - : member_override_; + if (!member_override_.empty ()) + member = member_override_; + else + { + member = "o." + mi.m.name (); + + if (mi.cq) + member = "const_cast< " + mi.fq_type (false) + "& > (" + + member + ")"; + } if (lazy_pointer (mt)) os << member << " = ptr_traits::pointer_type (db, id);"; @@ -987,8 +998,9 @@ namespace relational traverse_integer (member_info& mi) { os << traits << "::set_value (" << endl - << member << ", i." << mi.var << "value, " << - "i." << mi.var << "null);" + << member << "," << endl + << "i." << mi.var << "value," << endl + << "i." << mi.var << "null);" << endl; } @@ -996,8 +1008,9 @@ namespace relational traverse_float (member_info& mi) { os << traits << "::set_value (" << endl - << member << ", i." << mi.var << "value, " << - "i." << mi.var << "null);" + << member << "," << endl + << "i." << mi.var << "value," << endl + << "i." << mi.var << "null);" << endl; } @@ -1016,8 +1029,9 @@ namespace relational traverse_date_time (member_info& mi) { os << traits << "::set_value (" << endl - << member << ", i." << mi.var << "value, " << - "i." << mi.var << "null);" + << member << "," << endl + << "i." << mi.var << "value," << endl + << "i." << mi.var << "null);" << endl; } diff --git a/odb/relational/oracle/common.cxx b/odb/relational/oracle/common.cxx index cf8ba6c..f7dddf2 100644 --- a/odb/relational/oracle/common.cxx +++ b/odb/relational/oracle/common.cxx @@ -33,14 +33,20 @@ namespace relational var = name + (name[name.size () - 1] == '_' ? "" : "_"); } - semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); + bool cq (type_override_ != 0 ? false: const_type (m.type ())); + semantics::type& t (type_override_ != 0 ? *type_override_ : utype (m)); if (semantics::class_* c = composite_wrapper (t)) { // If t is a wrapper, pass the wrapped type. Also pass the // original, wrapper type. // - member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, + *c, + (wrapper (t) ? &t : 0), + cq, + var, + fq_type_override_); if (pre (mi)) { traverse_composite (mi); @@ -51,7 +57,12 @@ namespace relational { // The same unwrapping logic as for composite values. // - member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, + *c, + (wrapper (t) ? &t : 0), + cq, + var, + fq_type_override_); if (pre (mi)) { traverse_container (mi); @@ -64,8 +75,12 @@ namespace relational if (semantics::class_* c = object_pointer (t)) { - member_info mi ( - m, id_member (*c)->type (), 0, var, fq_type_override_); + member_info mi (m, + utype (*id_member (*c)), + 0, + cq, + var, + fq_type_override_); mi.st = &st; if (pre (mi)) { @@ -75,7 +90,7 @@ namespace relational } else { - member_info mi (m, t, 0, var, fq_type_override_); + member_info mi (m, t, 0, cq, var, fq_type_override_); mi.st = &st; if (pre (mi)) { diff --git a/odb/relational/oracle/common.hxx b/odb/relational/oracle/common.hxx index 1bd52e8..55768b4 100644 --- a/odb/relational/oracle/common.hxx +++ b/odb/relational/oracle/common.hxx @@ -29,9 +29,13 @@ namespace relational struct member_info { semantics::data_member& m; // Member. - semantics::type& t; // Member C++ type (m.type () may != t). - semantics::type* wrapper; // Wrapper type if member is a wrapper. + semantics::type& t; // Cvr-unqualified member C++ type, note + // that m.type () may not be the same as t. + semantics::type* wrapper; // Wrapper type if member is a composite or + // container wrapper, also cvr-unqualified. // In this case t is the wrapped type. + bool cq; // True if the original (wrapper) type + // is const-qualified. sql_type const* st; // Member SQL type (only simple values). string& var; // Member variable name with trailing '_'. @@ -40,21 +44,29 @@ namespace relational string fq_type (bool unwrap = true) const { + semantics::names* hint; + if (wrapper != 0 && unwrap) { - // Use the hint from the wrapper. + // Use the hint from the wrapper unless the wrapped type + // is qualified. // - return t.fq_name ( - wrapper->get ("wrapper-hint")); + hint = wrapper->get ("wrapper-hint"); + utype (*context::wrapper (*wrapper), hint); + return t.fq_name (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 // overriden, then the fq_type must be as well. // - return fq_type_.empty () - ? m.type ().fq_name (m.belongs ().hint ()) - : fq_type_; + if (fq_type_.empty ()) + { + semantics::type& t (utype (m, hint)); + return t.fq_name (hint); + } + else + return fq_type_; } string const& fq_type_; @@ -62,11 +74,13 @@ namespace relational member_info (semantics::data_member& m_, semantics::type& t_, semantics::type* wrapper_, + bool cq_, string& var_, string const& fq_type) : m (m_), t (t_), wrapper (wrapper_), + cq (cq_), st (0), var (var_), fq_type_ (fq_type) diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx index 2eb44d6..8469761 100644 --- a/odb/relational/oracle/schema.cxx +++ b/odb/relational/oracle/schema.cxx @@ -201,7 +201,8 @@ namespace relational if (inverse (m)) return false; - if (semantics::class_* c = object_pointer (member_type (m, prefix_))) + if (semantics::class_* c = + object_pointer (member_utype (m, prefix_))) { pre_statement (); diff --git a/odb/relational/oracle/source.cxx b/odb/relational/oracle/source.cxx index ad58bb0..800de57 100644 --- a/odb/relational/oracle/source.cxx +++ b/odb/relational/oracle/source.cxx @@ -377,7 +377,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (semantics::class_* c = object_pointer (mt)) { @@ -450,7 +450,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - if (object_pointer (member_type (mi.m, key_prefix_))) + if (object_pointer (member_utype (mi.m, key_prefix_))) { os << "}"; @@ -609,6 +609,10 @@ namespace relational string const& name (mi.m.name ()); member = "o." + name; + if (mi.cq) + member = "const_cast< " + mi.fq_type (false) + "& > (" + + member + ")"; + os << "// " << name << endl << "//" << endl; } @@ -622,7 +626,7 @@ namespace relational // Here we need the wrapper type, not the wrapped type. // member = "wrapper_traits< " + mi.fq_type (false) + " >::" + - "set_ref (" + member + ")"; + "set_ref (\n" + member + ")"; } if (composite (mi.t)) @@ -632,7 +636,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (semantics::class_* c = object_pointer (mt)) { @@ -683,13 +687,20 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (object_pointer (mt)) { - member = member_override_.empty () - ? "o." + mi.m.name () - : member_override_; + if (!member_override_.empty ()) + member = member_override_; + else + { + member = "o." + mi.m.name (); + + if (mi.cq) + member = "const_cast< " + mi.fq_type (false) + "& > (" + + member + ")"; + } if (lazy_pointer (mt)) os << member << " = ptr_traits::pointer_type (db, id);"; diff --git a/odb/relational/pgsql/common.cxx b/odb/relational/pgsql/common.cxx index 26f4b12..4993408 100644 --- a/odb/relational/pgsql/common.cxx +++ b/odb/relational/pgsql/common.cxx @@ -33,14 +33,20 @@ namespace relational var = name + (name[name.size () - 1] == '_' ? "" : "_"); } - semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); + bool cq (type_override_ != 0 ? false: const_type (m.type ())); + semantics::type& t (type_override_ != 0 ? *type_override_ : utype (m)); if (semantics::class_* c = composite_wrapper (t)) { // If t is a wrapper, pass the wrapped type. Also pass the // original, wrapper type. // - member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, + *c, + (wrapper (t) ? &t : 0), + cq, + var, + fq_type_override_); if (pre (mi)) { traverse_composite (mi); @@ -51,7 +57,12 @@ namespace relational { // The same unwrapping logic as for composite values. // - member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, + *c, + (wrapper (t) ? &t : 0), + cq, + var, + fq_type_override_); if (pre (mi)) { traverse_container (mi); @@ -64,8 +75,12 @@ namespace relational if (semantics::class_* c = object_pointer (t)) { - member_info mi ( - m, id_member (*c)->type (), 0, var, fq_type_override_); + member_info mi (m, + utype (*id_member (*c)), + 0, + cq, + var, + fq_type_override_); mi.st = &st; if (pre (mi)) { @@ -75,7 +90,7 @@ namespace relational } else { - member_info mi (m, t, 0, var, fq_type_override_); + member_info mi (m, t, 0, cq, var, fq_type_override_); mi.st = &st; if (pre (mi)) { diff --git a/odb/relational/pgsql/common.hxx b/odb/relational/pgsql/common.hxx index a91c40a..7a92a4a 100644 --- a/odb/relational/pgsql/common.hxx +++ b/odb/relational/pgsql/common.hxx @@ -29,9 +29,13 @@ namespace relational struct member_info { semantics::data_member& m; // Member. - semantics::type& t; // Member C++ type (m.type () may != t). - semantics::type* wrapper; // Wrapper type if member is a wrapper. + semantics::type& t; // Cvr-unqualified member C++ type, note + // that m.type () may not be the same as t. + semantics::type* wrapper; // Wrapper type if member is a composite or + // container wrapper, also cvr-unqualified. // In this case t is the wrapped type. + bool cq; // True if the original (wrapper) type + // is const-qualified. sql_type const* st; // Member SQL type (only simple values). string& var; // Member variable name with trailing '_'. @@ -40,21 +44,29 @@ namespace relational string fq_type (bool unwrap = true) const { + semantics::names* hint; + if (wrapper != 0 && unwrap) { - // Use the hint from the wrapper. + // Use the hint from the wrapper unless the wrapped type + // is qualified. // - return t.fq_name ( - wrapper->get ("wrapper-hint")); + hint = wrapper->get ("wrapper-hint"); + utype (*context::wrapper (*wrapper), hint); + return t.fq_name (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 // overriden, then the fq_type must be as well. // - return fq_type_.empty () - ? m.type ().fq_name (m.belongs ().hint ()) - : fq_type_; + if (fq_type_.empty ()) + { + semantics::type& t (utype (m, hint)); + return t.fq_name (hint); + } + else + return fq_type_; } string const& fq_type_; @@ -62,11 +74,13 @@ namespace relational member_info (semantics::data_member& m_, semantics::type& t_, semantics::type* wrapper_, + bool cq_, string& var_, string const& fq_type) : m (m_), t (t_), wrapper (wrapper_), + cq (cq_), st (0), var (var_), fq_type_ (fq_type) diff --git a/odb/relational/pgsql/schema.cxx b/odb/relational/pgsql/schema.cxx index 70d4979..450d056 100644 --- a/odb/relational/pgsql/schema.cxx +++ b/odb/relational/pgsql/schema.cxx @@ -139,7 +139,8 @@ namespace relational if (inverse (m)) return false; - if (semantics::class_* c = object_pointer (member_type (m, prefix_))) + if (semantics::class_* c = + object_pointer (member_utype (m, prefix_))) { pre_statement (); diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index 8547df3..c45b40e 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -535,7 +535,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (semantics::class_* c = object_pointer (mt)) { @@ -608,7 +608,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - if (object_pointer (member_type (mi.m, key_prefix_))) + if (object_pointer (member_utype (mi.m, key_prefix_))) { os << "}"; @@ -756,6 +756,10 @@ namespace relational string const& name (mi.m.name ()); member = "o." + name; + if (mi.cq) + member = "const_cast< " + mi.fq_type (false) + "& > (" + + member + ")"; + os << "// " << name << endl << "//" << endl; } @@ -769,7 +773,7 @@ namespace relational // Here we need the wrapper type, not the wrapped type. // member = "wrapper_traits< " + mi.fq_type (false) + " >::" + - "set_ref (" + member + ")"; + "set_ref (\n" + member + ")"; } if (composite (mi.t)) @@ -779,7 +783,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (semantics::class_* c = object_pointer (mt)) { @@ -830,13 +834,20 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (object_pointer (mt)) { - member = member_override_.empty () - ? "o." + mi.m.name () - : member_override_; + if (!member_override_.empty ()) + member = member_override_; + else + { + member = "o." + mi.m.name (); + + if (mi.cq) + member = "const_cast< " + mi.fq_type (false) + "& > (" + + member + ")"; + } if (lazy_pointer (mt)) os << member << " = ptr_traits::pointer_type (db, id);"; @@ -867,8 +878,9 @@ namespace relational traverse_integer (member_info& mi) { os << traits << "::set_value (" << endl - << member << ", i." << mi.var << "value, " << - "i." << mi.var << "null);" + << member << "," << endl + << "i." << mi.var << "value," << endl + << "i." << mi.var << "null);" << endl; } @@ -876,8 +888,9 @@ namespace relational traverse_float (member_info& mi) { os << traits << "::set_value (" << endl - << member << ", i." << mi.var << "value, " << - "i." << mi.var << "null);" + << member << "," << endl + << "i." << mi.var << "value," << endl + << "i." << mi.var << "null);" << endl; } @@ -896,8 +909,9 @@ namespace relational traverse_date_time (member_info& mi) { os << traits << "::set_value (" << endl - << member << ", i." << mi.var << "value, " << - "i." << mi.var << "null);" + << member << "," << endl + << "i." << mi.var << "value," << endl + << "i." << mi.var << "null);" << endl; } @@ -942,8 +956,9 @@ namespace relational traverse_uuid (member_info& mi) { os << traits << "::set_value (" << endl - << member << ", i." << mi.var << "value, " << - "i." << mi.var << "null);" + << member << "," << endl + << "i." << mi.var << "value," << endl + << "i." << mi.var << "null);" << endl; } @@ -1190,7 +1205,7 @@ namespace relational { // many(i)-to-many // - if (container_wrapper (inv_m->type ())) + if (container_wrapper (utype (*inv_m))) os << oids[column_sql_type (*inv_m, "value").type]; // many(i)-to-one diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx index d1c3cd8..fdddf9a 100644 --- a/odb/relational/processor.cxx +++ b/odb/relational/processor.cxx @@ -120,16 +120,32 @@ namespace relational if (transient (m)) return; - semantics::type& t (m.type ()); + semantics::names* hint; + semantics::type& t (utype (m, hint)); // Handle wrappers. // - semantics::type* wt (0); - semantics::names* wh (0); + semantics::type* wt (0), *qwt (0); + semantics::names* whint (0); if (process_wrapper (t)) { - wt = t.get ("wrapper-type"); - wh = t.get ("wrapper-hint"); + qwt = t.get ("wrapper-type"); + whint = t.get ("wrapper-hint"); + wt = &utype (*qwt, whint); + } + + // If the type is const and the member is not id or inverse, then + // mark it as readonly. In case of a wrapper, both the wrapper type + // and the wrapped type must be const. To see why, consider these + // possibilities: + // + // auto_ptr - can modify by setting a new pointer + // const auto_ptr - can modify by changing the pointed-to value + // + if (const_type (m.type ()) && !(m.count ("id") || m.count ("inverse"))) + { + if (qwt == 0 || const_type (*qwt)) + m.set ("readonly", true); } // Nothing to do if this is a composite value type. @@ -145,10 +161,12 @@ namespace relational if (semantics::class_* c = process_object_pointer (m, t)) { // This is an object pointer. The column type is the pointed-to - // object id type. Except by default it can be NULL. + // object id type. // semantics::data_member& id (*id_member (*c)); - semantics::type& idt (id.type ()); + + semantics::names* idhint; + semantics::type& idt (utype (id, idhint)); if (type.empty () && id.count ("type")) type = id.get ("type"); @@ -160,7 +178,7 @@ namespace relational type = idt.get ("type"); if (type.empty ()) - type = database_type (idt, id.belongs ().hint (), true); + type = database_type (idt, idhint, true); } else { @@ -178,10 +196,10 @@ namespace relational type = wt->get ("type"); if (type.empty ()) - type = database_type (t, m.belongs ().hint (), m.count ("id")); + type = database_type (t, hint, m.count ("id")); if (type.empty () && wt != 0) - type = database_type (*wt, wh, m.count ("id")); + type = database_type (*wt, whint, m.count ("id")); } if (!type.empty ()) @@ -190,7 +208,7 @@ namespace relational // Issue a warning if we are relaxing null-ness. // - if (m.count ("null") && m.type ().count ("not-null")) + if (m.count ("null") && t.count ("not-null")) { os << m.file () << ":" << m.line () << ":" << m.column () << ":" << " warning: data member declared null while its type is " @@ -208,11 +226,10 @@ namespace relational // If it is none of the above then we have an error. // - string const& fq_type (t.fq_name (m.belongs ().hint ())); - os << m.file () << ":" << m.line () << ":" << m.column () << ":" - << " error: unable to map C++ type '" << fq_type << "' used in " - << "data member '" << m.name () << "' to a database type" << endl; + << " error: unable to map C++ type '" << t.fq_name (hint) + << "' used in data member '" << m.name () << "' to a " + << "database type" << endl; os << m.file () << ":" << m.line () << ":" << m.column () << ":" << " info: use '#pragma db type' to specify the database type" @@ -240,7 +257,7 @@ namespace relational return; string type; - semantics::type& ct (m.type ()); + semantics::type& ct (utype (m)); // Custom mapping can come from these places (listed in the order // of priority): member, container type, value type. To complicate @@ -260,7 +277,9 @@ namespace relational // object id type. Except by default it can be NULL. // semantics::data_member& id (*id_member (*c)); - semantics::type& idt (id.type ()); + + semantics::names* hint; + semantics::type& idt (utype (id, hint)); if (type.empty () && id.count ("type")) type = id.get ("type"); @@ -272,7 +291,7 @@ namespace relational type = idt.get ("type"); if (type.empty ()) - type = database_type (idt, id.belongs ().hint (), true); + type = database_type (idt, hint, true); } else { @@ -908,7 +927,15 @@ namespace relational if (decl == error_mark_node || TREE_CODE (decl) != TYPE_DECL) throw operation_failed (); - tree type (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); + // The wrapped_type alias is a typedef in an instantiation + // that we just instantiated dynamically. As a result there + // is no semantic graph edges corresponding to this typedef + // since we haven't parsed it yet. So to get the tree node + // that can actually be resolved to the graph node, we use + // the source type of this typedef. + // + tree type (DECL_ORIGINAL_TYPE (decl)); + semantics::type& wt ( dynamic_cast (*unit.find (type))); @@ -1300,7 +1327,7 @@ namespace relational throw operation_failed (); } - if (!member_resolver::check_types (src_m->type (), m.type ())) + if (!member_resolver::check_types (utype (*src_m), utype (m))) { warn (e.loc) << "object data member '" << src_m->name () << "' specified " @@ -1400,7 +1427,7 @@ namespace relational { if (src_m->count ("type")) m.set ("column-type", src_m->get ("column-type")); - else if (semantics::class_* c = object_pointer (src_m->type ())) + else if (semantics::class_* c = object_pointer (utype (*src_m))) { semantics::data_member& id (*id_member (*c)); @@ -1446,7 +1473,6 @@ namespace relational check_types (semantics::type& ot, semantics::type& vt) { using semantics::type; - using semantics::derived_type; // Require that the types be the same sans the wrapping and // cvr-qualification. If the object member type is a pointer, @@ -1455,23 +1481,17 @@ namespace relational type* t1; if (semantics::class_* c = object_pointer (ot)) - t1 = &id_member (*c)->type (); + t1 = &utype (*id_member (*c)); else t1 = &ot; type* t2 (&vt); if (type* wt1 = context::wrapper (*t1)) - t1 = wt1; + t1 = &utype (*wt1); if (type* wt2 = context::wrapper (*t2)) - t2 = wt2; - - if (derived_type* dt1 = dynamic_cast (t1)) - t1 = &dt1->base_type (); - - if (derived_type* dt2 = dynamic_cast (t2)) - t2 = &dt2->base_type (); + t2 = &utype (*wt2); if (t1 != t2) return false; @@ -1489,7 +1509,7 @@ namespace relational pub_members_ (pub_members), name_ (m.name ()), pub_name_ (context::current ().public_name (m)), - type_ (m.type ()) + type_ (utype (m)) { } @@ -1539,7 +1559,7 @@ namespace relational if (context::transient (m) || context::inverse (m)) return false; - return check_types (m.type (), type_); + return check_types (utype (m), type_); } assoc_members& members_; @@ -1903,7 +1923,7 @@ namespace relational virtual void traverse_simple (semantics::data_member& m) { - if (semantics::class_* c = object_pointer (m.type ())) + if (semantics::class_* c = object_pointer (utype (m))) { // Ignore inverse sides of the same relationship to avoid // phony conflicts caused by the direct side that will end diff --git a/odb/relational/schema.cxx b/odb/relational/schema.cxx index 0e64408..031bf64 100644 --- a/odb/relational/schema.cxx +++ b/odb/relational/schema.cxx @@ -27,7 +27,7 @@ namespace relational { default_value* dv (0); - semantics::type& t (m.type ()); + semantics::type& t (utype (m)); if (m.count ("default")) dv = &m.get ("default"); diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 29d4ff9..ecafe2c 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -363,7 +363,7 @@ namespace relational virtual void reference (semantics::data_member& m) { - if (semantics::class_* c = object_pointer (member_type (m, prefix_))) + if (semantics::class_* c = object_pointer (member_utype (m, prefix_))) { os << " REFERENCES " << table_qname (*c) << " (" << column_qname (*id_member (*c)) << ")"; diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index fe23ac9..be16309 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -217,7 +217,7 @@ namespace relational // is_null()/is_not_null() will be valid for composite values // as well. // - if (!context::composite_wrapper (m->type ())) + if (!context::composite_wrapper (context::utype (*m))) break; ptt = tt; @@ -259,7 +259,7 @@ namespace relational { using semantics::type; - type* t (&m->type ()); + type* t (&context::utype (*m)); if (type* c = context::container_wrapper (*t)) t = &context::container_vt (*c); diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 3ce3676..a216653 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -94,9 +94,9 @@ namespace relational // if (im != 0) { - semantics::class_* c (object_pointer (m.type ())); + semantics::class_* c (object_pointer (utype (m))); - if (container_wrapper (im->type ())) + if (container_wrapper (utype (*im))) { // This container is a direct member of the class so the table // prefix is just the class table name. We don't assign join @@ -404,7 +404,7 @@ namespace relational virtual bool traverse_column (semantics::data_member& m, string const& column, bool) { - semantics::class_* c (object_pointer (m.type ())); + semantics::class_* c (object_pointer (utype (m))); if (c == 0) return false; @@ -414,7 +414,7 @@ namespace relational if (semantics::data_member* im = inverse (m)) { - if (container_wrapper (im->type ())) + if (container_wrapper (utype (*im))) { // This container is a direct member of the class so the table // prefix is just the class table name. @@ -924,7 +924,7 @@ namespace relational string inv_id; // Other id column. string inv_fid; // Other foreign id column (ref to us). - if (container_wrapper (im->type ())) + if (container_wrapper (utype (*im))) { // many(i)-to-many // @@ -1948,15 +1948,28 @@ namespace relational // if (w != 0) { + semantics::names* hint; + semantics::type& t (utype (*m, hint)); + // Because we cannot have nested containers, m.type () should // be the same as w. // - assert (m != 0 && &m->type () == w); - string const& type (m->type ().fq_name (m->belongs ().hint ())); + assert (&t == w); + + string const& type (t.fq_name (hint)); + + if (call_ == load_call && const_type (m->type ())) + obj_prefix_ = "const_cast< " + type + "& > (\n" + + obj_prefix_ + ")"; obj_prefix_ = "wrapper_traits< " + type + " >::" + (call_ == load_call ? "set_ref" : "get_ref") + - " (" + obj_prefix_ + ")"; + " (\n" + obj_prefix_ + ")"; + } + else if (call_ == load_call && const_type (m->type ())) + { + obj_prefix_ = "const_cast< " + c.fq_name () + "& > (\n" + + obj_prefix_ + ")"; } obj_prefix_ += '.'; @@ -1977,20 +1990,36 @@ namespace relational string sts_name (flat_prefix_ + name); string traits (flat_prefix_ + public_name (m) + "_traits"); + if (call_ == load_call && const_type (m.type ())) + { + + } + + semantics::names* hint; + semantics::type& t (utype (m, hint)); + // If this is a wrapped container, then we need to "unwrap" it. // + if (wrapper (t)) { - semantics::type& t (m.type ()); - if (wrapper (t)) - { - string const& type (t.fq_name (m.belongs ().hint ())); + string const& type (t.fq_name (hint)); - obj_name = "wrapper_traits< " + type + " >::" + - (call_ == load_call ? "set_ref" : "get_ref") + - " (" + obj_name + ")"; - } + // We cannot use traits::container_type here. + // + if (call_ == load_call && const_type (m.type ())) + obj_name = "const_cast< " + type + "& > (\n" + obj_name + ")"; + + obj_name = "wrapper_traits< " + type + " >::" + + (call_ == load_call ? "set_ref" : "get_ref") + + " (\n" + obj_name + ")"; + } + else if (call_ == load_call && const_type (m.type ())) + { + obj_name = "const_cast< " + traits + "::container_type& > (\n" + + obj_name + ")"; } + switch (call_) { case persist_call: @@ -2597,8 +2626,15 @@ namespace relational << endl; if (auto_id) - os << "obj." << id->name () << " = static_cast (st.id ());" + { + if (const_type (id->type ())) + os << "const_cast< id_type& > (obj." << id->name () << ")"; + else + os << "obj." << id->name (); + + os << " = static_cast< id_type > (st.id ());" << endl; + } if (straight_containers) { @@ -3453,11 +3489,12 @@ namespace relational // some sanity checks while at it. // semantics::class_* c (0); + semantics::type& t (utype (m)); - if (semantics::type* cont = container_wrapper (m.type ())) + if (semantics::type* cont = container_wrapper (t)) c = object_pointer (container_vt (*cont)); else - c = object_pointer (m.type ()); + c = object_pointer (t); view_object const* vo (0); @@ -3542,7 +3579,8 @@ namespace relational data_member* im (inverse (m)); semantics::type* cont ( - container_wrapper (im != 0 ? im->type () : m.type ())); + container_wrapper ( + utype (im != 0 ? *im : m))); // Container table. // diff --git a/odb/relational/sqlite/common.cxx b/odb/relational/sqlite/common.cxx index 3429d9f..357fb87 100644 --- a/odb/relational/sqlite/common.cxx +++ b/odb/relational/sqlite/common.cxx @@ -33,14 +33,20 @@ namespace relational var = name + (name[name.size () - 1] == '_' ? "" : "_"); } - semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); + bool cq (type_override_ != 0 ? false: const_type (m.type ())); + semantics::type& t (type_override_ != 0 ? *type_override_ : utype (m)); if (semantics::class_* c = composite_wrapper (t)) { // If t is a wrapper, pass the wrapped type. Also pass the // original, wrapper type. // - member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, + *c, + (wrapper (t) ? &t : 0), + cq, + var, + fq_type_override_); if (pre (mi)) { traverse_composite (mi); @@ -51,7 +57,12 @@ namespace relational { // The same unwrapping logic as for composite values. // - member_info mi (m, *c, (wrapper (t) ? &t : 0), var, fq_type_override_); + member_info mi (m, + *c, + (wrapper (t) ? &t : 0), + cq, + var, + fq_type_override_); if (pre (mi)) { traverse_container (mi); @@ -64,8 +75,12 @@ namespace relational if (semantics::class_* c = object_pointer (t)) { - member_info mi ( - m, id_member (*c)->type (), 0, var, fq_type_override_); + member_info mi (m, + utype (*id_member (*c)), + 0, + cq, + var, + fq_type_override_); mi.st = &st; if (pre (mi)) { @@ -75,7 +90,7 @@ namespace relational } else { - member_info mi (m, t, 0, var, fq_type_override_); + member_info mi (m, t, 0, cq, var, fq_type_override_); mi.st = &st; if (pre (mi)) { diff --git a/odb/relational/sqlite/common.hxx b/odb/relational/sqlite/common.hxx index e8663af..c998607 100644 --- a/odb/relational/sqlite/common.hxx +++ b/odb/relational/sqlite/common.hxx @@ -29,9 +29,13 @@ namespace relational struct member_info { semantics::data_member& m; // Member. - semantics::type& t; // Member C++ type (m.type () may != t). - semantics::type* wrapper; // Wrapper type if member is a wrapper. + semantics::type& t; // Cvr-unqualified member C++ type, note + // that m.type () may not be the same as t. + semantics::type* wrapper; // Wrapper type if member is a composite or + // container wrapper, also cvr-unqualified. // In this case t is the wrapped type. + bool cq; // True if the original (wrapper) type + // is const-qualified. sql_type const* st; // Member SQL type (only simple values). string& var; // Member variable name with trailing '_'. @@ -40,21 +44,29 @@ namespace relational string fq_type (bool unwrap = true) const { + semantics::names* hint; + if (wrapper != 0 && unwrap) { - // Use the hint from the wrapper. + // Use the hint from the wrapper unless the wrapped type + // is qualified. // - return t.fq_name ( - wrapper->get ("wrapper-hint")); + hint = wrapper->get ("wrapper-hint"); + utype (*context::wrapper (*wrapper), hint); + return t.fq_name (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 // overriden, then the fq_type must be as well. // - return fq_type_.empty () - ? m.type ().fq_name (m.belongs ().hint ()) - : fq_type_; + if (fq_type_.empty ()) + { + semantics::type& t (utype (m, hint)); + return t.fq_name (hint); + } + else + return fq_type_; } string const& fq_type_; @@ -62,11 +74,13 @@ namespace relational member_info (semantics::data_member& m_, semantics::type& t_, semantics::type* wrapper_, + bool cq_, string& var_, string const& fq_type) : m (m_), t (t_), wrapper (wrapper_), + cq (cq_), st (0), var (var_), fq_type_ (fq_type) diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx index 1ed835e..589ce7b 100644 --- a/odb/relational/sqlite/schema.cxx +++ b/odb/relational/sqlite/schema.cxx @@ -67,7 +67,8 @@ namespace relational { // In SQLite, by default, constraints are immediate. // - if (semantics::class_* c = object_pointer (member_type (m, prefix_))) + if (semantics::class_* c = + object_pointer (member_utype (m, prefix_))) { os << " REFERENCES " << table_qname (*c) << " (" << column_qname (*id_member (*c)) << ") " << diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx index 92c0941..0516370 100644 --- a/odb/relational/sqlite/source.cxx +++ b/odb/relational/sqlite/source.cxx @@ -337,7 +337,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (semantics::class_* c = object_pointer (mt)) { @@ -410,7 +410,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - if (object_pointer (member_type (mi.m, key_prefix_))) + if (object_pointer (member_utype (mi.m, key_prefix_))) { os << "}"; @@ -502,6 +502,10 @@ namespace relational string const& name (mi.m.name ()); member = "o." + name; + if (mi.cq) + member = "const_cast< " + mi.fq_type (false) + "& > (" + + member + ")"; + os << "// " << name << endl << "//" << endl; } @@ -515,7 +519,7 @@ namespace relational // Here we need the wrapper type, not the wrapped type. // member = "wrapper_traits< " + mi.fq_type (false) + " >::" + - "set_ref (" + member + ")"; + "set_ref (\n" + member + ")"; } if (composite (mi.t)) @@ -525,7 +529,7 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (semantics::class_* c = object_pointer (mt)) { @@ -576,13 +580,20 @@ namespace relational // When handling a pointer, mi.t is the id type of the referenced // object. // - semantics::type& mt (member_type (mi.m, key_prefix_)); + semantics::type& mt (member_utype (mi.m, key_prefix_)); if (object_pointer (mt)) { - member = member_override_.empty () - ? "o." + mi.m.name () - : member_override_; + if (!member_override_.empty ()) + member = member_override_; + else + { + member = "o." + mi.m.name (); + + if (mi.cq) + member = "const_cast< " + mi.fq_type (false) + "& > (" + + member + ")"; + } if (lazy_pointer (mt)) os << member << " = ptr_traits::pointer_type (db, id);"; diff --git a/odb/tracer/header.cxx b/odb/tracer/header.cxx index 4812487..5ba6c95 100644 --- a/odb/tracer/header.cxx +++ b/odb/tracer/header.cxx @@ -44,9 +44,13 @@ namespace tracer // id_type // - os << "typedef " << id.type ().fq_name (id.belongs ().hint ()) << - " id_type;" - << endl; + { + semantics::names* hint; + semantics::type& t (utype (id, hint)); + + os << "typedef " << t.fq_name (hint) << " id_type;" + << endl; + } // type_name () // diff --git a/odb/validator.cxx b/odb/validator.cxx index ffa8aec..59d231f 100644 --- a/odb/validator.cxx +++ b/odb/validator.cxx @@ -57,10 +57,10 @@ namespace return; count_++; - semantics::type& type (m.type ()); - semantics::belongs& b (m.belongs ()); + semantics::names* hint; + semantics::type& t (context::utype (m, hint)); - if (type.fq_anonymous (b.hint ())) + if (t.fq_anonymous (hint)) { cerr << m.file () << ":" << m.line () << ":" << m.column () << ":" << " error: unnamed type in data member declaration" << endl; @@ -561,7 +561,7 @@ namespace virtual void traverse_simple (semantics::data_member& m) { - if (context::object_pointer (m.type ())) + if (context::object_pointer (utype (m))) { semantics::data_member& dm (dm_ != 0 ? *dm_ : m); -- cgit v1.1