From b069af3f557dd3ce94d2d665fa5759279aa3780f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 14 Jan 2013 18:02:32 +0200 Subject: Fix bug in handling polymorphic derived classes without any value members --- odb/relational/source.cxx | 78 +++++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 27 deletions(-) (limited to 'odb/relational/source.cxx') diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index 0ec7cc4..58e40e7 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -525,6 +525,13 @@ traverse_object (type& c) << endl; } + // Index of the first empty SELECT statement in poly-derived + // statement list. All subsequent statements are also empty. + // The first statement can never be empty (contains id and + // type_id). + // + size_t empty_depth (0); + if (id != 0) { instance id_cols; @@ -551,38 +558,43 @@ traverse_object (type& c) find_column_counts[poly_depth - d] = sc.size (); } - os << strlit ("SELECT ") << endl; - - for (statement_columns::const_iterator i (sc.begin ()), - e (sc.end ()); i != e;) + if (sc.size () != 0) { - string const& c (i->column); - os << strlit (c + (++i != e ? "," : "")) << endl; - } + os << strlit ("SELECT ") << endl; - os << strlit (" FROM " + qtable) << endl; + for (statement_columns::const_iterator i (sc.begin ()), + e (sc.end ()); i != e;) + { + string const& c (i->column); + os << strlit (c + (++i != e ? "," : "")) << endl; + } - if (poly_derived) - { - instance j (c, d); - j->traverse (c); - } + os << strlit (" FROM " + qtable) << endl; - bool f (false); // @@ (im)perfect forwarding - instance j (c, f, d); // @@ (im)perfect forwarding - j->traverse (c); + if (poly_derived) + { + instance j (c, d); + j->traverse (c); + } - instance qp (table); - for (object_columns_list::iterator b (id_cols->begin ()), i (b); - i != id_cols->end (); ++i) - { - if (i != b) - os << endl; + bool f (false); // @@ (im)perfect forwarding + instance j (c, f, d); // @@ (im)perfect forwarding + j->traverse (c); - os << strlit ((i == b ? " WHERE " : " AND ") + - qtable + "." + quote_id (i->name) + "=" + - convert_to (qp->next (), i->type, *i->member)); + instance qp (table); + for (object_columns_list::iterator b (id_cols->begin ()), i (b); + i != id_cols->end (); ++i) + { + if (i != b) + os << endl; + + os << strlit ((i == b ? " WHERE " : " AND ") + + qtable + "." + quote_id (i->name) + "=" + + convert_to (qp->next (), i->type, *i->member)); + } } + else + os << strlit (""); // Empty SELECT statement. if (abst) break; @@ -605,11 +617,14 @@ traverse_object (type& c) os << "const std::size_t " << traits << "::find_column_counts[] =" << "{"; - for (std::vector::iterator i (find_column_counts.begin ()), - e (find_column_counts.end ()); i != e;) + for (std::vector::iterator b (find_column_counts.begin ()), + i (b), e (find_column_counts.end ()); i != e;) { os << *i << "UL"; + if (*i == 0 && empty_depth == 0) + empty_depth = i - b; + if (++i != e) os << ',' << endl; } @@ -2397,6 +2412,12 @@ traverse_object (type& c) << "d = depth - d;" // Convert to distance from derived. << endl; + // Avoid trying to execute an empty SELECT statement. + // + if (empty_depth != 0) + os << "if (d > " << (poly_depth - empty_depth) << "UL)" + << "{"; + os << "if (!find_ (sts, 0, d))" << endl << "throw object_not_persistent ();" // Database inconsistency. << endl; @@ -2415,6 +2436,9 @@ traverse_object (type& c) if (delay_freeing_statement_result) os << "ar.free ();"; + if (empty_depth != 0) + os << "}"; + os << "load_ (sts, obj, d);" << "}"; } -- cgit v1.1