aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/common.cxx46
-rw-r--r--odb/common.hxx20
-rw-r--r--odb/context.cxx49
-rw-r--r--odb/context.hxx15
-rw-r--r--odb/relational/common.cxx53
-rw-r--r--odb/relational/common.hxx6
-rw-r--r--odb/relational/header.hxx138
-rw-r--r--odb/relational/inline.hxx54
-rw-r--r--odb/relational/mysql/source.cxx4
-rw-r--r--odb/relational/source.hxx176
-rw-r--r--odb/validator.cxx160
11 files changed, 496 insertions, 225 deletions
diff --git a/odb/common.cxx b/odb/common.cxx
index f82d3d9..bf163d4 100644
--- a/odb/common.cxx
+++ b/odb/common.cxx
@@ -53,15 +53,26 @@ traverse (semantics::class_& c)
if (obj && build_table_prefix_)
{
- table_prefix_.prefix = table_name (c);
- table_prefix_.prefix += '_';
- table_prefix_.level = 1;
+ // Don't reset the table prefix if we are traversing a base.
+ //
+ bool tb (false);
+
+ if (table_prefix_.level == 0)
+ {
+ table_prefix_.prefix = table_name (c);
+ table_prefix_.prefix += '_';
+ table_prefix_.level = 1;
+ tb = true;
+ }
inherits (c);
names (c);
- table_prefix_.level = 0;
- table_prefix_.prefix.clear ();
+ if (tb)
+ {
+ table_prefix_.level = 0;
+ table_prefix_.prefix.clear ();
+ }
}
else
{
@@ -154,7 +165,14 @@ flush ()
}
void object_columns_base::
-composite (semantics::data_member&, semantics::class_& c)
+composite (semantics::data_member*, semantics::class_& c)
+{
+ inherits (c);
+ names (c);
+}
+
+void object_columns_base::
+object (semantics::class_& c)
{
inherits (c);
names (c);
@@ -182,7 +200,7 @@ traverse_composite (semantics::data_member& m,
member_.prefix_ += '_';
}
- composite (m, c);
+ composite (&m, c);
if (!member_.first_)
flush ();
@@ -206,15 +224,17 @@ traverse (semantics::class_& c)
semantics::class_* prev;
if (obj)
{
- prev = object;
- object = &c;
+ prev = context::object;
+ context::object = &c;
}
- inherits (c);
- names (c);
+ if (obj)
+ object (c);
+ else
+ composite (0, c);
if (obj)
- object = prev;
+ context::object = prev;
if (f && !member_.first_)
flush ();
@@ -248,7 +268,7 @@ traverse (semantics::data_member& m)
prefix_ += '_';
}
- oc_.composite (m, *comp);
+ oc_.composite (&m, *comp);
prefix_ = old_prefix;
}
diff --git a/odb/common.hxx b/odb/common.hxx
index f0c2d5a..2d220b8 100644
--- a/odb/common.hxx
+++ b/odb/common.hxx
@@ -93,7 +93,8 @@ private:
traversal::inherits inherits_;
};
-// Traverse object columns recursively by going into composite members.
+// Traverse object columns recursively by going into composite members
+// and bases.
//
struct object_columns_base: traversal::class_, virtual context
{
@@ -103,12 +104,20 @@ struct object_columns_base: traversal::class_, virtual context
virtual bool
column (semantics::data_member&, std::string const& name, bool first) = 0;
- // If you override this function, always call the base. The second argument
- // is the actual composite type, which is not necessarily the same as
- // m.type ().
+ // If you override this function, you can call the base to traverse
+ // bases and members. The first argument is the data member and can
+ // be NULL if we are traversing the root type or a base. The second
+ // argument is the actual composite type, which is not necessarily
+ // the same as m.type ().
//
virtual void
- composite (semantics::data_member&, semantics::class_&);
+ composite (semantics::data_member*, semantics::class_&);
+
+ // If you override this function, you can call the base to traverse
+ // bases and members.
+ //
+ virtual void
+ object (semantics::class_&);
// Called after the last column, provided at least one column hasn't
// been ignored.
@@ -139,7 +148,6 @@ public:
semantics::class_&,
std::string const& key_prefix,
std::string const& default_name);
-
private:
void
init ()
diff --git a/odb/context.cxx b/odb/context.cxx
index 31f0865..2d64885 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -629,55 +629,6 @@ out_column_count (semantics::class_& c)
namespace
{
- // Find id member.
- //
- struct id_member_impl: traversal::class_
- {
- id_member_impl ()
- {
- *this >> names_ >> member_;
- }
-
- virtual void
- traverse (semantics::class_& c)
- {
- member_.m_ = 0;
- names (c);
- c.set ("id-member", member_.m_);
- }
-
- private:
- struct member: traversal::data_member
- {
- virtual void
- traverse (semantics::data_member& m)
- {
- if (m.count ("id"))
- m_ = &m;
- }
-
- semantics::data_member* m_;
- };
-
- member member_;
- traversal::names names_;
- };
-}
-
-semantics::data_member& context::
-id_member (semantics::class_& c)
-{
- if (!c.count ("id-member"))
- {
- id_member_impl t;
- t.traverse (c);
- }
-
- return *c.get<semantics::data_member*> ("id-member");
-}
-
-namespace
-{
struct has_a_impl: object_members_base
{
has_a_impl (unsigned short flags)
diff --git a/odb/context.hxx b/odb/context.hxx
index f08878d..a09d040 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -102,6 +102,12 @@ public:
return t.get<semantics::class_*> ("element-type", 0);
}
+ static bool
+ abstract (semantics::class_& c)
+ {
+ return c.count ("abstract");
+ }
+
// Database names and types.
//
public:
@@ -112,7 +118,7 @@ public:
//
struct table_prefix
{
- table_prefix () {}
+ table_prefix (): level (0) {}
table_prefix (string const& p, size_t l): prefix (p), level (l) {}
string prefix;
@@ -174,7 +180,12 @@ public:
out_column_count (semantics::class_&);
static semantics::data_member&
- id_member (semantics::class_&);
+ id_member (semantics::class_& c)
+ {
+ // Set by the validator.
+ //
+ return *c.get<semantics::data_member*> ("id-member");
+ }
// Object pointer information.
//
diff --git a/odb/relational/common.cxx b/odb/relational/common.cxx
index 3e6461b..6032548 100644
--- a/odb/relational/common.cxx
+++ b/odb/relational/common.cxx
@@ -25,17 +25,37 @@ namespace relational
}
query_columns::
- query_columns (semantics::class_& cl) //@@ context::object
+ query_columns (semantics::class_& c) //@@ context::object
: ptr_ (true), decl_ (false)
{
- scope_ = "access::object_traits< " + cl.fq_name () + " >::query_type";
- table_ = table_qname (cl);
+ scope_ = "access::object_traits< " + c.fq_name () + " >::query_columns";
+ table_ = table_qname (c);
}
void query_columns::
- composite (semantics::data_member& m, semantics::class_& c)
+ object (semantics::class_& c)
{
- string name (public_name (m));
+ // We only want members for objects unless we are traversing a
+ // pointer, in which case we need the whole thing.
+ //
+ if (!ptr_)
+ inherits (c);
+
+ names (c);
+ }
+
+ void query_columns::
+ composite (semantics::data_member* m, semantics::class_& c)
+ {
+ // Base type.
+ //
+ if (m == 0)
+ {
+ object_columns_base::composite (m, c);
+ return;
+ }
+
+ string name (public_name (*m));
if (decl_)
{
@@ -73,6 +93,16 @@ namespace relational
// in queries). So we will have to duplicate the columns (sans
// the pointers).
//
+ // There are a number of problems with this approach: Regarding (1),
+ // the class have to be defined during ODB compilation in which
+ // case the ODB compiler will hunt down the #include statement
+ // and add it to the generated code. Regarding (2), things get
+ // complicated really quickly once we bring inheritance into
+ // the picture (name conflicts, etc). Plus, it is nice to reuse
+ // things. So the long-term solution is probably to make it a
+ // template with the table name as an argument.
+ //
+
if (ptr_)
{
ptr_ = false;
@@ -123,7 +153,18 @@ namespace relational
}
else
{
- string column (table_ + '.' + quote_id (col_name));
+ // Use the default table alias unless we are generating members
+ // for a referenced object.
+ //
+ string column;
+
+ if (!ptr_)
+ column = table_;
+ else
+ column = "_";
+
+ column += '.';
+ column += quote_id (col_name);
os << "const " << db << "::query_column<" << endl
<< " " << type << "," << endl
diff --git a/odb/relational/common.hxx b/odb/relational/common.hxx
index c7c1c44..6d8ef1a 100644
--- a/odb/relational/common.hxx
+++ b/odb/relational/common.hxx
@@ -68,12 +68,14 @@ namespace relational
}
virtual void
- composite (semantics::data_member&, semantics::class_&);
+ object (semantics::class_&);
+
+ virtual void
+ composite (semantics::data_member*, semantics::class_&);
virtual bool
column (semantics::data_member&, string const&, bool);
-
protected:
bool ptr_;
bool decl_;
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 662e3cb..c0661fb 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -13,6 +13,10 @@ namespace relational
{
namespace header
{
+ //
+ // image_type
+ //
+
struct image_member: virtual member_base
{
typedef image_member base;
@@ -40,9 +44,11 @@ namespace relational
virtual void
traverse (type& c)
{
+ bool obj (c.count ("object"));
+
// Ignore transient bases.
//
- if (!(c.count ("object") || comp_value (c)))
+ if (!(obj || comp_value (c)))
return;
if (first_)
@@ -56,7 +62,10 @@ namespace relational
<< " ";
}
- os << "composite_value_traits< " << c.fq_name () << " >::image_type";
+ if (obj)
+ os << "object_traits< " << c.fq_name () << " >::image_type";
+ else
+ os << "composite_value_traits< " << c.fq_name () << " >::image_type";
}
private:
@@ -104,6 +113,68 @@ namespace relational
traversal::names names_member_;
};
+ //
+ // query_type
+ //
+
+ struct query_base: traversal::class_, virtual context
+ {
+ typedef query_base base;
+
+ query_base (): first_ (true) {}
+
+ virtual void
+ traverse (type& c)
+ {
+ // Ignore transient bases.
+ //
+ if (!c.count ("object"))
+ return;
+
+ if (first_)
+ {
+ os << ": ";
+ first_ = false;
+ }
+ else
+ {
+ os << "," << endl
+ << " ";
+ }
+
+ os << "object_traits< " << c.fq_name () << " >::query_columns";
+ }
+
+ private:
+ bool first_;
+ };
+
+ struct query_type: traversal::class_, virtual context
+ {
+ typedef query_type base;
+
+ virtual void
+ traverse (type& c)
+ {
+ os << "struct query_columns";
+
+ {
+ instance<query_base> b;
+ traversal::inherits i (*b);
+ inherits (c, i);
+ }
+
+ os << "{";
+
+ {
+ instance<query_columns> t;
+ t->traverse (c);
+ }
+
+ os << "};";
+ }
+ };
+
// Member-specific traits types for container members.
//
struct container_traits: object_members_base, virtual context
@@ -611,6 +682,7 @@ namespace relational
semantics::data_member& id (id_member (c));
bool auto_id (id.count ("auto"));
+ bool base_id (&id.scope () != &c); // Id comes from a base class.
os << "// " << c.name () << endl
<< "//" << endl;
@@ -625,30 +697,45 @@ namespace relational
os << "typedef " << type << " object_type;"
<< "typedef " << c.get<string> ("object-pointer") << " pointer_type;";
- // id_type
+ // id_type & id_image_type
//
- os << "typedef " << id.type ().fq_name (id.belongs ().hint ()) <<
- " id_type;"
- << endl;
+ if (base_id)
+ {
+ string const& base (id.scope ().fq_name ());
- // image_type
- //
- image_type_->traverse (c);
+ os << "typedef object_traits< " << base << " >::id_type id_type;"
+ << endl
+ << "typedef object_traits< " << base << " >::id_image_type " <<
+ "id_image_type;"
+ << endl;
+ }
+ else
+ {
+ os << "typedef " << id.type ().fq_name (id.belongs ().hint ()) <<
+ " id_type;"
+ << endl;
- // id_image_type
- //
- os << "struct id_image_type"
- << "{";
+ os << "struct id_image_type"
+ << "{";
- id_image_member_->traverse (id);
+ id_image_member_->traverse (id);
- os << "std::size_t version;"
- << "};";
+ os << "std::size_t version;"
+ << "};";
+ }
+
+ // image_type
+ //
+ image_type_->traverse (c);
- // query_type & query_base_type
+ // query types
//
if (options.generate_query ())
{
+ // query_columns
+ //
+ query_type_->traverse (c);
+
// query_base_type
//
os << "typedef " << db << "::query query_base_type;"
@@ -656,15 +743,9 @@ namespace relational
// query_type
//
- os << "struct query_type: query_base_type"
- << "{";
-
- {
- instance<query_columns> t;
- t->traverse (c);
- }
-
- os << "query_type ();"
+ os << "struct query_type: query_base_type, query_columns"
+ << "{"
+ << "query_type ();"
<< "query_type (const std::string&);"
<< "query_type (const query_base_type&);"
<< "};";
@@ -723,7 +804,7 @@ namespace relational
// grow ()
//
- os << "static void" << endl
+ os << "static bool" << endl
<< "grow (image_type&, " << truncated_vector << ");"
<< endl;
@@ -741,7 +822,7 @@ namespace relational
// init (image, object)
//
- os << "static void" << endl
+ os << "static bool" << endl
<< "init (image_type&, const object_type&);"
<< endl;
@@ -886,6 +967,7 @@ namespace relational
private:
instance<image_type> image_type_;
+ instance<query_type> query_type_;
instance<image_member> id_image_member_;
};
diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx
index 1b3c492..9e76dea 100644
--- a/odb/relational/inline.hxx
+++ b/odb/relational/inline.hxx
@@ -34,7 +34,9 @@ namespace relational
{
string const& type (c.fq_name ());
string traits ("access::object_traits< " + type + " >");
+
semantics::data_member& id (id_member (c));
+ bool base_id (&id.scope () != &c); // Id comes from a base class.
os << "// " << c.name () << endl
<< "//" << endl
@@ -65,15 +67,59 @@ namespace relational
<< "}";
}
- // id ()
+ // id (object_type)
//
os << "inline" << endl
<< traits << "::id_type" << endl
<< traits << "::" << endl
<< "id (const object_type& obj)"
- << "{"
- << "return obj." << id.name () << ";" << endl
- << "}";
+ << "{";
+
+ if (base_id)
+ os << "return object_traits< " << id.scope ().fq_name () <<
+ " >::id (obj);";
+ else
+ os << "return obj." << id.name () << ";";
+
+ os << "}";
+
+ // id (image_type)
+ //
+ if (options.generate_query () && base_id)
+ {
+ os << "inline" << endl
+ << traits << "::id_type" << endl
+ << traits << "::" << endl
+ << "id (const image_type& i)"
+ << "{"
+ << "return object_traits< " << id.scope ().fq_name () <<
+ " >::id (i);"
+ << "}";
+ }
+
+ // bind (id_image_type)
+ //
+ if (base_id)
+ {
+ os << "inline" << endl
+ << "void " << traits << "::" << endl
+ << "bind (" << bind_vector << " b, id_image_type& i)"
+ << "{"
+ << "object_traits< " << id.scope ().fq_name () <<
+ " >::bind (b, i);"
+ << "}";
+ }
+
+ if (base_id)
+ {
+ os << "inline" << endl
+ << "void " << traits << "::" << endl
+ << "init (id_image_type& i, const id_type& id)"
+ << "{"
+ << "object_traits< " << id.scope ().fq_name () <<
+ " >::init (i, id);"
+ << "}";
+ }
// load_()
//
diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx
index 825a67e..17bffdc 100644
--- a/odb/relational/mysql/source.cxx
+++ b/odb/relational/mysql/source.cxx
@@ -122,7 +122,7 @@ namespace relational
if (!table.empty ())
{
- line_ += table;
+ line_ += table == table_name_ ? "_" : table;
line_ += '.';
}
@@ -131,7 +131,7 @@ namespace relational
if (!table.empty ())
{
- line_ += table;
+ line_ += table == table_name_ ? "_" : table;
line_ += '.';
}
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 44c4959..f3d9db9 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -132,7 +132,9 @@ namespace relational
{
if (!table.empty ())
{
- line_ += table;
+ // Use alias for the main table.
+ //
+ line_ += table == table_name_ ? "_" : table;
line_ += '.';
}
@@ -155,9 +157,9 @@ namespace relational
bool out_;
string suffix_;
string line_;
+ string table_name_;
private:
- string table_name_;
bool last_;
};
@@ -228,8 +230,7 @@ namespace relational
t = table_qname (*im, tp);
string const& val (column_qname (*im, "value", "value"));
- cond << t << '.' << val << " = " << table_ << '.' <<
- column_qname (id_);
+ cond << t << '.' << val << " = _." << column_qname (id_);
// Add the join for the object itself so that we are able to
// use it in the WHERE clause.
@@ -247,8 +248,8 @@ namespace relational
{
t = table_qname (*c);
- cond << t << '.' << column_qname (*im) << " = " <<
- table_ << '.' << column_qname (id_);
+ cond << t << '.' << column_qname (*im) << " = _." <<
+ column_qname (id_);
}
}
else if (query_)
@@ -258,8 +259,8 @@ namespace relational
//
t = table_qname (*c);
- cond << t << '.' << column_qname (id_member (*c)) << " = " <<
- table_ << '.' << quote_id (col_name);
+ cond << t << '.' << column_qname (id_member (*c)) << " = _." <<
+ quote_id (col_name);
}
if (!t.empty ())
@@ -311,7 +312,7 @@ namespace relational
private:
bool query_;
- string table_;
+ string table_; //@@ No longer used because of the _ alias.
semantics::data_member& id_;
typedef std::set<string> conditions;
@@ -372,16 +373,24 @@ namespace relational
virtual void
traverse (type& c)
{
+ bool obj (c.count ("object"));
+
// Ignore transient bases.
//
- if (!(c.count ("object") || comp_value (c)))
+ if (!(obj || comp_value (c)))
return;
os << "// " << c.name () << " base" << endl
- << "//" << endl
- << "composite_value_traits< " << c.fq_name () <<
- " >::bind (b + n, i);"
- << "n += " << in_column_count (c) << "UL;"
+ << "//" << endl;
+
+ if (obj)
+ os << "object_traits< " << c.fq_name () <<
+ " >::bind (b + n, i, out);";
+ else
+ os << "composite_value_traits< " << c.fq_name () <<
+ " >::bind (b + n, i);";
+
+ os << "n += " << in_column_count (c) << "UL;"
<< endl;
}
};
@@ -421,18 +430,20 @@ namespace relational
virtual void
traverse (type& c)
{
+ bool obj (c.count ("object"));
+
// Ignore transient bases.
//
- if (!(c.count ("object") || comp_value (c)))
+ if (!(obj || comp_value (c)))
return;
os << "// " << c.name () << " base" << endl
- << "//" << endl
- << "if (composite_value_traits< " << c.fq_name () <<
- " >::grow (i, t + " << index_ << "UL))"
- << "{"
+ << "//" << endl;
+
+ os << "if (" << (obj ? "object" : "composite_value") << "_traits< " <<
+ c.fq_name () << " >::grow (i, t + " << index_ << "UL))" << endl
<< "grew = true;"
- << "}";
+ << endl;
index_ += in_column_count (c);
}
@@ -477,18 +488,19 @@ namespace relational
virtual void
traverse (type& c)
{
+ bool obj (c.count ("object"));
+
// Ignore transient bases.
//
- if (!(c.count ("object") || comp_value (c)))
+ if (!(obj || comp_value (c)))
return;
os << "// " << c.name () << " base" << endl
<< "//" << endl
- << "if (composite_value_traits< " << c.fq_name () <<
- " >::init (i, o))"
- << "{"
+ << "if (" << (obj ? "object" : "composite_value") << "_traits< " <<
+ c.fq_name () << " >::init (i, o))" << endl
<< "grew = true;"
- << "}";
+ << endl;
}
};
@@ -527,15 +539,17 @@ namespace relational
virtual void
traverse (type& c)
{
+ bool obj (c.count ("object"));
+
// Ignore transient bases.
//
- if (!(c.count ("object") || comp_value (c)))
+ if (!(obj || comp_value (c)))
return;
os << "// " << c.name () << " base" << endl
<< "//" << endl
- << "composite_value_traits< " << c.fq_name () <<
- " >::init (o, i, db);"
+ << (obj ? "object" : "composite_value") << "_traits< " <<
+ c.fq_name () << " >::init (o, i, db);"
<< endl;
}
};
@@ -660,17 +674,17 @@ namespace relational
}
os << strlit ("SELECT ") << endl
- << strlit (inv_table + '.' + inv_fid + ',') << endl
- << strlit (inv_table + '.' + inv_id) << endl
- << strlit (" FROM " + inv_table +
- " WHERE " + inv_table + '.' + inv_fid + " = ?");
+ << strlit ("_." + inv_fid + ',') << endl
+ << strlit ("_." + inv_id) << endl
+ << strlit (" FROM " + inv_table + " AS _"
+ " WHERE _." + inv_fid + " = ?");
}
else
{
string const& id_col (column_qname (m, "id", "object_id"));
os << strlit ("SELECT ") << endl
- << strlit (table + '.' + id_col + ',') << endl;
+ << strlit ("_." + id_col + ',') << endl;
switch (ck)
{
@@ -718,13 +732,15 @@ namespace relational
t->flush ();
}
- os << strlit (" FROM " + table +
- " WHERE " + table + '.' + id_col + " = ?") << endl;
+ os << strlit (" FROM " + table + " AS _"
+ " WHERE _." + id_col + " = ?");
if (ordered)
{
string const& col (column_qname (m, "index", "index"));
- os << strlit (" ORDER BY " + table + '.' + col) << endl;
+
+ os << endl
+ << strlit (" ORDER BY _." + col) << endl;
}
}
@@ -1747,6 +1763,7 @@ namespace relational
semantics::data_member& id (id_member (c));
bool auto_id (id.count ("auto"));
bool grow_id (context::grow (id));
+ bool base_id (&id.scope () != &c); // Id comes from a base class.
os << "// " << c.name () << endl
<< "//" << endl
@@ -1825,7 +1842,7 @@ namespace relational
t->traverse (c);
}
- os << strlit (" FROM " + table) << endl;
+ os << strlit (" FROM " + table + " AS _") << endl;
{
bool f (false);
@@ -1834,7 +1851,7 @@ namespace relational
t->write ();
}
- os << strlit (" WHERE " + table + '.' + id_col + " = ?") << ";"
+ os << strlit (" WHERE _." + id_col + " = ?") << ";"
<< endl;
// update_statement
@@ -1847,14 +1864,14 @@ namespace relational
t->traverse (c);
}
- os << strlit (" WHERE " + table + '.' + id_col + " = ?") << ";"
+ os << strlit (" WHERE " + id_col + " = ?") << ";"
<< endl;
// erase_statement
//
os << "const char* const " << traits << "::erase_statement =" << endl
<< strlit ("DELETE FROM " + table) << endl
- << strlit (" WHERE " + table + '.' + id_col + " = ?") << ";"
+ << strlit (" WHERE " + id_col + " = ?") << ";"
<< endl;
// query_clause
@@ -1876,15 +1893,15 @@ namespace relational
oc->traverse (c);
}
- os << strlit (" FROM " + table) << endl;
+ os << strlit (" FROM " + table + " AS _") << endl;
oj->write ();
os << strlit (" ") << ";"
<< endl;
}
- // id
+ // id (image_type)
//
- if (options.generate_query ())
+ if (options.generate_query () && !base_id)
{
os << traits << "::id_type" << endl
<< traits << "::" << endl
@@ -1898,9 +1915,12 @@ namespace relational
// grow ()
//
- os << "void " << traits << "::" << endl
+ os << "bool " << traits << "::" << endl
<< "grow (image_type& i, " << truncated_vector << " t)"
<< "{"
+ << "ODB_POTENTIALLY_UNUSED (i);"
+ << "ODB_POTENTIALLY_UNUSED (t);"
+ << endl
<< "bool grew (false);"
<< endl;
@@ -1908,8 +1928,7 @@ namespace relational
inherits (c, grow_base_inherits_);
names (c, grow_member_names_);
- os << "if (grew)" << endl
- << "i.version++;" << endl
+ os << "return grew;"
<< "}";
// bind (image_type)
@@ -1929,26 +1948,31 @@ namespace relational
// bind (id_image_type)
//
- os << "void " << traits << "::" << endl
- << "bind (" << bind_vector << " b, id_image_type& i)"
- << "{"
- << "std::size_t n (0);";
- bind_id_member_->traverse (id);
- os << "}";
+ if (!base_id)
+ {
+ os << "void " << traits << "::" << endl
+ << "bind (" << bind_vector << " b, id_image_type& i)"
+ << "{"
+ << "std::size_t n (0);";
+ bind_id_member_->traverse (id);
+ os << "}";
+ }
// init (image, object)
//
- os << "void " << traits << "::" << endl
+ os << "bool " << traits << "::" << endl
<< "init (image_type& i, const object_type& o)"
<< "{"
+ << "ODB_POTENTIALLY_UNUSED (i);"
+ << "ODB_POTENTIALLY_UNUSED (o);"
+ << endl
<< "bool grew (false);"
<< endl;
inherits (c, init_image_base_inherits_);
names (c, init_image_member_names_);
- os << "if (grew)" << endl
- << "i.version++;" << endl
+ os << "return grew;"
<< "}";
// init (object, image)
@@ -1956,6 +1980,8 @@ namespace relational
os << "void " << traits << "::" << endl
<< "init (object_type& o, const image_type& i, database& db)"
<< "{"
+ << "ODB_POTENTIALLY_UNUSED (o);"
+ << "ODB_POTENTIALLY_UNUSED (i);"
<< "ODB_POTENTIALLY_UNUSED (db);"
<< endl;
@@ -1966,21 +1992,24 @@ namespace relational
// init (id_image, id)
//
- os << "void " << traits << "::" << endl
- << "init (id_image_type& i, const id_type& id)"
- << "{";
+ if (!base_id)
+ {
+ os << "void " << traits << "::" << endl
+ << "init (id_image_type& i, const id_type& id)"
+ << "{";
- if (grow_id)
- os << "bool grew (false);";
+ if (grow_id)
+ os << "bool grew (false);";
- init_id_image_member_->traverse (id);
+ init_id_image_member_->traverse (id);
- if (grow_id)
- os << endl
- << "if (grew)" << endl
- << "i.version++;";
+ if (grow_id)
+ os << endl
+ << "if (grew)" << endl
+ << "i.version++;";
- os << "}";
+ os << "}";
+ }
// persist ()
//
@@ -1997,17 +2026,19 @@ namespace relational
<< "image_type& im (sts.image ());"
<< "binding& imb (sts.in_image_binding ());"
<< endl
- << "init (im, obj);";
+ << "if (init (im, obj))" << endl
+ << "im.version++;"
+ << endl;
if (auto_id)
{
string const& n (id.name ());
string var ("im." + n + (n[n.size () - 1] == '_' ? "" : "_"));
init_auto_id (id, var);
+ os << endl;
}
- os << endl
- << "if (im.version != sts.in_image_version () || imb.version == 0)"
+ os << "if (im.version != sts.in_image_version () || imb.version == 0)"
<< "{"
<< "bind (imb.bind, im, false);"
<< "sts.in_image_version (im.version);"
@@ -2067,7 +2098,9 @@ namespace relational
//
os << "image_type& im (sts.image ());"
<< "binding& imb (sts.in_image_binding ());"
- << "init (im, obj);"
+ << endl
+ << "if (init (im, obj))" << endl
+ << "im.version++;"
<< endl
<< "if (im.version != sts.in_image_version () || imb.version == 0)"
<< "{"
@@ -2245,7 +2278,8 @@ namespace relational
os << endl
<< "if (r == select_statement::truncated)"
<< "{"
- << "grow (im, sts.out_image_truncated ());"
+ << "if (grow (im, sts.out_image_truncated ()))" << endl
+ << "im.version++;"
<< endl
<< "if (im.version != sts.out_image_version ())"
<< "{"
diff --git a/odb/validator.cxx b/odb/validator.cxx
index 6c62ea8..998bd8b 100644
--- a/odb/validator.cxx
+++ b/odb/validator.cxx
@@ -40,29 +40,83 @@ namespace
valid_ = false;
}
+ }
+
+ bool& valid_;
+ size_t count_;
+ };
- if (m.count ("id"))
+ // Find id member.
+ //
+ struct id_member: traversal::class_
+ {
+ id_member (bool object, bool& valid, semantics::data_member*& m)
+ : object_ (object), member_ (valid, m)
+ {
+ *this >> inherits_ >> *this;
+ *this >> names_ >> member_;
+ }
+
+ virtual void
+ traverse (semantics::class_& c)
+ {
+ // Skip transient bases.
+ //
+ if (object_)
{
- if (id_ != 0)
- {
- cerr << m.file () << ":" << m.line () << ":" << m.column () << ":"
- << " error: multiple object id members" << endl;
+ if (!c.count ("object"))
+ return;
+ }
+ else
+ {
+ if (!context::comp_value (c))
+ return;
+ }
- cerr << id_->file () << ":" << id_->line () << ":" << id_->column ()
- << ": info: previous id member declared here" << endl;
+ inherits (c);
+ names (c);
+ }
- valid_ = false;
- }
+ private:
+ struct member: traversal::data_member
+ {
+ member (bool& valid, semantics::data_member*& m)
+ : valid_ (valid), m_ (m)
+ {
+ }
- id_ = &m;
+ virtual void
+ traverse (semantics::data_member& m)
+ {
+ if (m.count ("id"))
+ {
+ if (m_ != 0)
+ {
+ cerr << m.file () << ":" << m.line () << ":" << m.column () << ":"
+ << " error: multiple object id members" << endl;
+
+ cerr << m_->file () << ":" << m_->line () << ":" << m_->column ()
+ << ": info: previous id member declared here" << endl;
+
+ valid_ = false;
+ }
+ else
+ m_ = &m;
+ }
}
- }
- bool& valid_;
- size_t count_;
- semantics::data_member* id_;
+ bool& valid_;
+ semantics::data_member*& m_;
+ };
+
+ bool object_;
+ member member_;
+ traversal::names names_;
+ traversal::inherits inherits_;
};
+ //
+ //
struct class_: traversal::class_
{
class_ (bool& valid, semantics::unit& unit)
@@ -84,6 +138,8 @@ namespace
virtual void
traverse_object (type& c)
{
+ bool base (false);
+
for (type::inherits_iterator i (c.inherits_begin ());
i != c.inherits_end ();
++i)
@@ -91,13 +147,8 @@ namespace
type& b (i->base ());
if (b.count ("object"))
- {
- cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " error: object inheritance is not yet supported" << endl;
-
- valid_ = false;
- }
- else if (context::comp_value (b))
+ base = true;
+ if (context::comp_value (b))
{
// @@ Should we use hint here?
//
@@ -117,24 +168,37 @@ namespace
}
}
- member_.count_ = 0;
- member_.id_ = 0;
-
- names (c);
+ // Check id.
+ //
+ semantics::data_member* id (0);
+ {
+ id_member t (true, valid_, id);
+ t.traverse (c);
+ }
- if (member_.id_ == 0)
+ if (id == 0)
{
- cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " error: no data member designated as object id" << endl;
+ if (!context::abstract (c))
+ {
+ cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
+ << " error: no data member designated as object id" << endl;
- cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " info: use '#pragma db id' to specify object id member"
- << endl;
+ cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
+ << " info: use '#pragma db id' to specify object id member"
+ << endl;
- valid_ = false;
+ valid_ = false;
+ }
}
+ else
+ c.set ("id-member", id);
+
+ // Check members.
+ //
+ member_.count_ = 0;
+ names (c);
- if (member_.count_ == 0)
+ if (member_.count_ == 0 && !base)
{
cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
<< " error: no persistent data members in the class" << endl;
@@ -146,13 +210,17 @@ namespace
virtual void
traverse_value (type& c)
{
+ bool base (false);
+
for (type::inherits_iterator i (c.inherits_begin ());
i != c.inherits_end ();
++i)
{
type& b (i->base ());
- if (b.count ("object"))
+ if (context::comp_value (b))
+ base = true;
+ else if (b.count ("object"))
{
// @@ Should we use hint here?
//
@@ -173,21 +241,29 @@ namespace
}
}
- member_.count_ = 0;
- member_.id_ = 0;
-
- names (c);
+ // Check id.
+ //
+ semantics::data_member* id (0);
+ {
+ id_member t (false, valid_, id);
+ t.traverse (c);
+ }
- if (member_.id_ != 0)
+ if (id != 0)
{
- cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " error: value type data member cannot be designated as "
+ cerr << id->file () << ":" << id->line () << ":" << id->column ()
+ << ": error: value type data member cannot be designated as "
<< "object id" << endl;
valid_ = false;
}
- if (member_.count_ == 0)
+ // Check members.
+ //
+ member_.count_ = 0;
+ names (c);
+
+ if (member_.count_ == 0 && !base)
{
cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
<< " error: no persistent data members in the class" << endl;