aboutsummaryrefslogtreecommitdiff
path: root/odb/relational
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-04-22 14:07:32 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-04-22 14:07:32 +0200
commit587db8c7ca28d5cd1722307073aa31aed5b89d0a (patch)
treeb5295accedf2cd946d5df22ed5fbfa78290e89dc /odb/relational
parent584f3602038919957f62848a03deb5b5bd9cc9ba (diff)
Initial support for non-polymorphic inheritance
Every class gets a separate table. New test: common/inheritance.
Diffstat (limited to 'odb/relational')
-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
6 files changed, 318 insertions, 113 deletions
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 ())"
<< "{"