aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-10-19 10:47:41 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-10-21 19:25:06 +0200
commit6bd95f51beb26d87fd5d5db22391c73f333eee6e (patch)
tree59621cec994f55fce7a1ced5c3b9edb93a41b084
parent7623fb5259da19c33ffe6623b0f306f6c39ede27 (diff)
Add support for const data members
Const data members are automatically treated as readonly. New test: const-member.
-rw-r--r--odb/common.cxx4
-rw-r--r--odb/context.cxx121
-rw-r--r--odb/context.hxx59
-rw-r--r--odb/header.cxx5
-rw-r--r--odb/inline.cxx18
-rw-r--r--odb/relational/common.cxx11
-rw-r--r--odb/relational/header.hxx29
-rw-r--r--odb/relational/mysql/common.cxx27
-rw-r--r--odb/relational/mysql/common.hxx30
-rw-r--r--odb/relational/mysql/source.cxx42
-rw-r--r--odb/relational/oracle/common.cxx27
-rw-r--r--odb/relational/oracle/common.hxx30
-rw-r--r--odb/relational/oracle/schema.cxx3
-rw-r--r--odb/relational/oracle/source.cxx27
-rw-r--r--odb/relational/pgsql/common.cxx27
-rw-r--r--odb/relational/pgsql/common.hxx30
-rw-r--r--odb/relational/pgsql/schema.cxx3
-rw-r--r--odb/relational/pgsql/source.cxx49
-rw-r--r--odb/relational/processor.cxx88
-rw-r--r--odb/relational/schema.cxx2
-rw-r--r--odb/relational/schema.hxx2
-rw-r--r--odb/relational/source.cxx4
-rw-r--r--odb/relational/source.hxx78
-rw-r--r--odb/relational/sqlite/common.cxx27
-rw-r--r--odb/relational/sqlite/common.hxx30
-rw-r--r--odb/relational/sqlite/schema.cxx3
-rw-r--r--odb/relational/sqlite/source.cxx27
-rw-r--r--odb/tracer/header.cxx10
-rw-r--r--odb/validator.cxx8
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<semantics::type*> ("wrapper-type")->count ("null"))
+ semantics::type& wt (
+ utype (*t.get<semantics::type*> ("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<semantics::qualifier*> (&t))
+ return q->base_type ();
+ else
+ return t;
+}
+
+semantics::type& context::
+utype (semantics::type& t, semantics::names*& hint)
+{
+ if (semantics::qualifier* q = dynamic_cast<semantics::qualifier*> (&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<semantics::qualifier*> (&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<semantics::qualifier*> (&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<semantics::type*> (*wt, key);
+ return *indirect_value<semantics::type*> (utype (*wt), key);
else
return *indirect_value<semantics::type*> (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<string> (key);
- else if (m.type ().count (key))
- return m.type ().get<string> (key);
else
- return d;
+ {
+ semantics::type& t (utype (m));
+
+ if (t.count (key))
+ return t.get<string> (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<semantics::data_member*> ("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<semantics::data_member*> (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<semantics::names*> ("wrapper-hint"));
+ hint = t.get<semantics::names*> ("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<semantics::names*> ("wrapper-hint"));
+ hint = wrapper->get<semantics::names*> ("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<semantics::names*> ("wrapper-hint"));
+ hint = wrapper->get<semantics::names*> ("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<semantics::names*> ("wrapper-hint"));
+ hint = wrapper->get<semantics::names*> ("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<semantics::type*> ("wrapper-type");
- wh = t.get<semantics::names*> ("wrapper-hint");
+ qwt = t.get<semantics::type*> ("wrapper-type");
+ whint = t.get<semantics::names*> ("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<const T> - can modify by setting a new pointer
+ // const auto_ptr<T> - 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<string> ("type");
@@ -160,7 +178,7 @@ namespace relational
type = idt.get<string> ("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<string> ("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<string> ("type");
@@ -272,7 +291,7 @@ namespace relational
type = idt.get<string> ("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<semantics::type&> (*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<string> ("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<derived_type*> (t1))
- t1 = &dt1->base_type ();
-
- if (derived_type* dt2 = dynamic_cast<derived_type*> (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_value> ("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<id_type> (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<semantics::names*> ("wrapper-hint"));
+ hint = wrapper->get<semantics::names*> ("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);