From d7662d2cc72668eee0a21737edfcc1bbe41c229b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 25 Apr 2011 12:30:04 +0200 Subject: Reuse container traits from composite values --- odb/common.cxx | 30 ++-- odb/common.hxx | 19 ++- odb/relational/header.hxx | 85 ++++++++--- odb/relational/source.hxx | 365 ++++++++++++++++++++++++++-------------------- 4 files changed, 301 insertions(+), 198 deletions(-) (limited to 'odb') diff --git a/odb/common.cxx b/odb/common.cxx index bf163d4..20fd354 100644 --- a/odb/common.cxx +++ b/odb/common.cxx @@ -17,21 +17,28 @@ simple (semantics::data_member&) } void object_members_base:: -composite (semantics::data_member&, semantics::class_& c) +container (semantics::data_member&) +{ +} + +void object_members_base:: +composite (semantics::data_member*, semantics::class_& c) { inherits (c); names (c); } void object_members_base:: -container (semantics::data_member&) +object (semantics::class_& c) { + inherits (c); + names (c); } void object_members_base:: traverse_composite (semantics::data_member& m, semantics::class_& c) { - composite (m, c); + composite (&m, c); } void object_members_base:: @@ -47,8 +54,8 @@ traverse (semantics::class_& c) semantics::class_* prev; if (obj) { - prev = object; - object = &c; + prev = context::object; + context::object = &c; } if (obj && build_table_prefix_) @@ -65,8 +72,7 @@ traverse (semantics::class_& c) tb = true; } - inherits (c); - names (c); + object (c); if (tb) { @@ -76,12 +82,14 @@ traverse (semantics::class_& c) } else { - inherits (c); - names (c); + if (obj) + object (c); + else + composite (0, c); } if (obj) - object = prev; + context::object = prev; } void object_members_base::member:: @@ -134,7 +142,7 @@ traverse (semantics::data_member& m) om_.table_prefix_.level++; } - om_.composite (m, *comp); + om_.composite (&m, *comp); if (om_.build_table_prefix_) { diff --git a/odb/common.hxx b/odb/common.hxx index 2d220b8..548e2a2 100644 --- a/odb/common.hxx +++ b/odb/common.hxx @@ -18,16 +18,23 @@ struct object_members_base: traversal::class_, virtual context virtual void simple (semantics::data_member&); - // If you override this function, call the base if you want the composite - // to be recursively traversed. The second argument is the actual composite - // type, which is not necessarily the same as m.type() in case of - // traverse_composite(). + virtual void + container (semantics::data_member&); + + // 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 - container (semantics::data_member&); + object (semantics::class_&); public: object_members_base () diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 9e258ea..5ad7d2e 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -181,20 +181,47 @@ namespace relational { typedef container_traits base; - container_traits (semantics::class_& obj) - : object_members_base (true, false), object_ (obj) + container_traits (semantics::class_& c) + : object_members_base (true, false), c_ (c) { } virtual void + composite (semantics::data_member* m, semantics::class_& c) + { + if (c_.count ("object")) + object_members_base::composite (m, c); + else + { + // If we are generating traits for a composite value type, then + // we don't want to go into its bases or it composite members. + // + if (m == 0 && &c == &c_) + names (c); + } + } + + virtual void container (semantics::data_member& m) { using semantics::type; using semantics::class_; - // Figure out if this member is from a base object. + // Figure out if this member is from a base object or composite + // value and whether it is abstract. // - bool base (context::object != &object_); + bool base, abst; + + if (c_.count ("object")) + { + base = context::object != &c_ || !m.scope ().count ("object"); + abst = abstract (c_); + } + else + { + base = false; // We don't go into bases. + abst = true; // Always abstract. + } type& t (m.type ()); container_kind_type ck (container_kind (t)); @@ -303,25 +330,36 @@ namespace relational << "struct " << name; if (base) - os << ": access::object_traits< " << context::object->fq_name () << - " >::" << name; + { + semantics::class_& b (dynamic_cast (m.scope ())); + + if (b.count ("object")) + os << ": access::object_traits< " << b.fq_name () << " >::" << + name; + else + os << ": access::composite_value_traits< " << b.fq_name () << + " >::" << public_name (m) << "_traits"; // No prefix_. + } os << "{"; - // column_count - // - os << "static const std::size_t cond_column_count = " << - cond_columns << "UL;" - << "static const std::size_t data_column_count = " << - data_columns << "UL;" - << endl; + if (!abst) + { + // column_count + // + os << "static const std::size_t cond_column_count = " << + cond_columns << "UL;" + << "static const std::size_t data_column_count = " << + data_columns << "UL;" + << endl; - // Statements. - // - os << "static const char* const insert_one_statement;" - << "static const char* const select_all_statement;" - << "static const char* const delete_all_statement;" - << endl; + // Statements. + // + os << "static const char* const insert_one_statement;" + << "static const char* const select_all_statement;" + << "static const char* const delete_all_statement;" + << endl; + } if (base) { @@ -659,7 +697,7 @@ namespace relational } private: - semantics::class_& object_; + semantics::class_& c_; }; // @@ -952,6 +990,13 @@ namespace relational // image_type_->traverse (c); + // Containers. + // + { + instance t (c); + t->traverse (c); + } + // grow () // os << "static bool" << endl diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 844dc11..5b2ec8d 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -560,12 +560,13 @@ namespace relational { typedef container_traits base; - container_traits (semantics::class_& obj) // @@ context::object - : object_members_base (true, true), - object_ (obj), - id_member_ (id_member (obj)) + container_traits (semantics::class_& c) + : object_members_base (true, true), c_ (c) { - obj_scope_ = "access::object_traits< " + obj.fq_name () + " >"; + if (c.count ("object")) + scope_ = "access::object_traits< " + c.fq_name () + " >"; + else + scope_ = "access::composite_value_traits< " + c.fq_name () + " >"; } // Unless the database system can execute several interleaving @@ -578,13 +579,40 @@ namespace relational } virtual void + composite (semantics::data_member* m, semantics::class_& c) + { + if (c_.count ("object")) + object_members_base::composite (m, c); + else + { + // If we are generating traits for a composite value type, then + // we don't want to go into its bases or it composite members. + // + if (m == 0 && &c == &c_) + names (c); + } + } + + virtual void container (semantics::data_member& m) { using semantics::type; - // Figure out if this member is from a base object. + // Figure out if this member is from a base object or composite + // value and whether it is abstract. // - bool base (context::object != &object_); + bool base, abst; + + if (c_.count ("object")) + { + base = context::object != &c_ || !m.scope ().count ("object"); + abst = abstract (c_); + } + else + { + base = false; // We don't go into bases. + abst = true; // Always abstract. + } type& t (m.type ()); container_kind_type ck (container_kind (t)); @@ -631,7 +659,7 @@ namespace relational has_a (vt, test_eager_pointer)); string name (prefix_ + public_name (m) + "_traits"); - string scope (obj_scope_ + "::" + name); + string scope (scope_ + "::" + name); os << "// " << m.name () << endl << "//" << endl @@ -640,196 +668,199 @@ namespace relational // // Statements. // - string table (table_qname (m, table_prefix_)); - - // select_all_statement - // - os << "const char* const " << scope << - "::select_all_statement =" << endl; - - if (inverse) + if (!abst) { - semantics::class_* c (object_pointer (vt)); + string table (table_qname (m, table_prefix_)); - string inv_table; // Other table name. - string inv_id; // Other id column. - string inv_fid; // Other foreign id column (ref to us). + // select_all_statement + // + os << "const char* const " << scope << + "::select_all_statement =" << endl; - if (context::container (im->type ())) + if (inverse) { - // many(i)-to-many - // + semantics::class_* c (object_pointer (vt)); - // This other container is a direct member of the class so the - // table prefix is just the class table name. - // - table_prefix tp (table_name (*c) + "_", 1); - inv_table = table_qname (*im, tp); - inv_id = column_qname (*im, "id", "object_id"); - inv_fid = column_qname (*im, "value", "value"); + string inv_table; // Other table name. + string inv_id; // Other id column. + string inv_fid; // Other foreign id column (ref to us). + + if (context::container (im->type ())) + { + // many(i)-to-many + // + + // This other container is a direct member of the class so the + // table prefix is just the class table name. + // + table_prefix tp (table_name (*c) + "_", 1); + inv_table = table_qname (*im, tp); + inv_id = column_qname (*im, "id", "object_id"); + inv_fid = column_qname (*im, "value", "value"); + } + else + { + // many(i)-to-one + // + inv_table = table_qname (*c); + inv_id = column_qname (id_member (*c)); + inv_fid = column_qname (*im); + } + + os << strlit ("SELECT ") << endl + << strlit ("_." + inv_fid + ',') << endl + << strlit ("_." + inv_id) << endl + << strlit (" FROM " + inv_table + " AS _" + " WHERE _." + inv_fid + " = ?"); } else { - // many(i)-to-one - // - inv_table = table_qname (*c); - inv_id = column_qname (id_member (*c)); - inv_fid = column_qname (*im); - } + string const& id_col (column_qname (m, "id", "object_id")); - os << strlit ("SELECT ") << endl - << 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 ("_." + id_col + ',') << endl; + os << strlit ("SELECT ") << endl + << strlit ("_." + id_col + ',') << endl; - switch (ck) - { - case ck_ordered: + switch (ck) { - if (ordered) + case ck_ordered: { - instance t (table, false, false); - string const& col (column_qname (m, "index", "index")); - t->column (m, "index", table, col); - t->flush (); + if (ordered) + { + instance t (table, false, false); + string const& col (column_qname (m, "index", "index")); + t->column (m, "index", table, col); + t->flush (); + } + break; } - break; - } - case ck_map: - case ck_multimap: - { - instance t (table, false, false); + case ck_map: + case ck_multimap: + { + instance t (table, false, false); - if (semantics::class_* ckt = comp_value (*kt)) - t->traverse_composite (m, *ckt, "key", "key"); - else + if (semantics::class_* ckt = comp_value (*kt)) + t->traverse_composite (m, *ckt, "key", "key"); + else + { + string const& col (column_qname (m, "key", "key")); + t->column (m, "key", table, col); + t->flush (); + } + break; + } + case ck_set: + case ck_multiset: { - string const& col (column_qname (m, "key", "key")); - t->column (m, "key", table, col); - t->flush (); + break; } - break; - } - case ck_set: - case ck_multiset: - { - break; } - } - instance t (table, false); + instance t (table, false); - if (semantics::class_* cvt = comp_value (vt)) - t->traverse_composite (m, *cvt, "value", "value"); - else - { - string const& col (column_qname (m, "value", "value")); - t->column (m, "value", table, col); - t->flush (); - } + if (semantics::class_* cvt = comp_value (vt)) + t->traverse_composite (m, *cvt, "value", "value"); + else + { + string const& col (column_qname (m, "value", "value")); + t->column (m, "value", table, col); + t->flush (); + } - os << strlit (" FROM " + table + " AS _" - " WHERE _." + id_col + " = ?"); + os << strlit (" FROM " + table + " AS _" + " WHERE _." + id_col + " = ?"); - if (ordered) - { - string const& col (column_qname (m, "index", "index")); + if (ordered) + { + string const& col (column_qname (m, "index", "index")); - os << endl - << strlit (" ORDER BY _." + col) << endl; + os << endl + << strlit (" ORDER BY _." + col) << endl; + } } - } - - os << ";" - << endl; - - // insert_one_statement - // - os << "const char* const " << scope << - "::insert_one_statement =" << endl; - if (inverse) - os << strlit ("") << ";" + os << ";" << endl; - else - { - os << strlit ("INSERT INTO " + table + " (") << endl - << strlit (column_qname (m, "id", "object_id") + ',') << endl; - switch (ck) + // insert_one_statement + // + os << "const char* const " << scope << + "::insert_one_statement =" << endl; + + if (inverse) + os << strlit ("") << ";" + << endl; + else { - case ck_ordered: + os << strlit ("INSERT INTO " + table + " (") << endl + << strlit (column_qname (m, "id", "object_id") + ',') << endl; + + switch (ck) { - if (ordered) + case ck_ordered: { - instance t (false, false); - t->column (m, "index", "", column_qname (m, "index", "index")); - t->flush (); + if (ordered) + { + instance t (false, false); + t->column (m, "index", "", column_qname (m, "index", "index")); + t->flush (); + } + break; } - break; - } - case ck_map: - case ck_multimap: - { - instance t (false, false); + case ck_map: + case ck_multimap: + { + instance t (false, false); - if (semantics::class_* ckt = comp_value (*kt)) - t->traverse_composite (m, *ckt, "key", "key"); - else + if (semantics::class_* ckt = comp_value (*kt)) + t->traverse_composite (m, *ckt, "key", "key"); + else + { + t->column (m, "key", "", column_qname (m, "key", "key")); + t->flush (); + } + break; + } + case ck_set: + case ck_multiset: { - t->column (m, "key", "", column_qname (m, "key", "key")); - t->flush (); + break; } - break; } - case ck_set: - case ck_multiset: + + instance t (false); + + if (semantics::class_* cvt = comp_value (vt)) + t->traverse_composite (m, *cvt, "value", "value"); + else { - break; + t->column (m, "value", "", column_qname (m, "value", "value")); + t->flush (); } + + string values; + for (size_t i (0), n (m.get ("data-column-count")); + i < n; ++i) + values += i != 0 ? ",?" : "?"; + + os << strlit (") VALUES (" + values + ")") << ";" + << endl; } - instance t (false); + // delete_all_statement + // + os << "const char* const " << scope << + "::delete_all_statement =" << endl; - if (semantics::class_* cvt = comp_value (vt)) - t->traverse_composite (m, *cvt, "value", "value"); + if (inverse) + os << strlit ("") << ";" + << endl; else { - t->column (m, "value", "", column_qname (m, "value", "value")); - t->flush (); + os << strlit ("DELETE FROM " + table) << endl + << strlit (" WHERE " + column_qname (m, "id", "object_id") + + " = ?") << ";" + << endl; } - - string values; - for (size_t i (0), n (m.get ("data-column-count")); - i < n; ++i) - values += i != 0 ? ",?" : "?"; - - os << strlit (") VALUES (" + values + ")") << ";" - << endl; - } - - // delete_all_statement - // - os << "const char* const " << scope << - "::delete_all_statement =" << endl; - - if (inverse) - os << strlit ("") << ";" - << endl; - else - { - os << strlit ("DELETE FROM " + table) << endl - << strlit (" WHERE " + column_qname (m, "id", "object_id") + - " = ?") << ";" - << endl; } if (base) @@ -1546,9 +1577,8 @@ namespace relational } protected: - string obj_scope_; - semantics::class_& object_; - semantics::data_member& id_member_; + string scope_; + semantics::class_& c_; }; // Container statement cache members. @@ -1620,10 +1650,16 @@ namespace relational } virtual void - composite (semantics::data_member& m, semantics::class_& c) + composite (semantics::data_member* m, semantics::class_& c) { + if (m == 0) + { + object_members_base::composite (m, c); + return; + } + string old (obj_prefix_); - obj_prefix_ += m.name (); + obj_prefix_ += m->name (); obj_prefix_ += '.'; object_members_base::composite (m, c); obj_prefix_ = old; @@ -2431,6 +2467,13 @@ namespace relational << "//" << endl << endl; + // Containers. + // + { + instance t (c); + t->traverse (c); + } + // grow () // os << "bool " << traits << "::" << endl -- cgit v1.1