From 587db8c7ca28d5cd1722307073aa31aed5b89d0a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 22 Apr 2011 14:07:32 +0200 Subject: Initial support for non-polymorphic inheritance Every class gets a separate table. New test: common/inheritance. --- odb/relational/common.cxx | 53 ++++++++++-- odb/relational/common.hxx | 6 +- odb/relational/header.hxx | 138 ++++++++++++++++++++++++------- odb/relational/inline.hxx | 54 +++++++++++- odb/relational/mysql/source.cxx | 4 +- odb/relational/source.hxx | 176 ++++++++++++++++++++++++---------------- 6 files changed, 318 insertions(+), 113 deletions(-) (limited to 'odb/relational') 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 b; + traversal::inherits i (*b); + inherits (c, i); + } + + os << "{"; + + { + instance 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 ("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 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_; + instance query_type_; instance 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 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 ())" << "{" -- cgit v1.1