From 1a6a0652a6ef5b319cfc8ad05a0acee6910f7560 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 25 Apr 2011 15:02:43 +0200 Subject: Add support for abstract object types --- odb/common.cxx | 16 +++ odb/context.cxx | 2 + odb/context.hxx | 26 +++- odb/pragma.cxx | 15 +- odb/relational/header.hxx | 189 +++++++++++++++---------- odb/relational/inline.hxx | 122 ++++++++-------- odb/relational/mysql/common.cxx | 2 +- odb/relational/schema.hxx | 6 +- odb/relational/source.hxx | 283 ++++++++++++++++++++------------------ odb/relational/sqlite/common.cxx | 2 +- odb/relational/type-processor.cxx | 22 ++- odb/tracer/header.cxx | 2 +- odb/tracer/inline.cxx | 2 +- odb/tracer/source.cxx | 2 +- 14 files changed, 407 insertions(+), 284 deletions(-) (limited to 'odb') diff --git a/odb/common.cxx b/odb/common.cxx index 20fd354..2c23e76 100644 --- a/odb/common.cxx +++ b/odb/common.cxx @@ -56,6 +56,9 @@ traverse (semantics::class_& c) { prev = context::object; context::object = &c; + + if (context::top_object == 0) + context::top_object = &c; } if (obj && build_table_prefix_) @@ -89,7 +92,12 @@ traverse (semantics::class_& c) } if (obj) + { + if (prev == 0) + context::top_object = 0; + context::object = prev; + } } void object_members_base::member:: @@ -234,6 +242,9 @@ traverse (semantics::class_& c) { prev = context::object; context::object = &c; + + if (context::top_object == 0) + context::top_object = &c; } if (obj) @@ -242,7 +253,12 @@ traverse (semantics::class_& c) composite (0, c); if (obj) + { + if (prev == 0) + context::top_object = 0; + context::object = prev; + } if (f && !member_.first_) flush (); diff --git a/odb/context.cxx b/odb/context.cxx index 8a85dcd..d281090 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -113,6 +113,7 @@ context (ostream& os_, keyword_set (data_->keyword_set_), embedded_schema (ops.generate_schema () && ops.schema_format ().count (schema_format::embedded)), + top_object (data_->top_object_), object (data_->object_) { assert (current_ == 0); @@ -131,6 +132,7 @@ context () db (current ().db), keyword_set (current ().keyword_set), embedded_schema (current ().embedded_schema), + top_object (current ().top_object), object (current ().object) { } diff --git a/odb/context.hxx b/odb/context.hxx index a09d040..9878bcb 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -105,7 +105,10 @@ public: static bool abstract (semantics::class_& c) { - return c.count ("abstract"); + // If a class is abstract in the C++ sense then it is also abstract in + // the database sense. + // + return c.abstract () || c.count ("abstract"); } // Database names and types. @@ -179,12 +182,12 @@ public: static size_t out_column_count (semantics::class_&); - static semantics::data_member& + static semantics::data_member* id_member (semantics::class_& c) { - // Set by the validator. + // Set by the validator. May not be there for abstract objects. // - return *c.get ("id-member"); + return c.get ("id-member", 0); } // Object pointer information. @@ -363,7 +366,14 @@ public: bool embedded_schema; - semantics::class_*& object; // Object currently being traversed. + // Outermost object currently being traversed. + // + semantics::class_*& top_object; + + // Object currently being traversed. It can be the same as top_object + // or it can a base of top_object. + // + semantics::class_*& object; struct db_type_type { @@ -416,12 +426,16 @@ protected: { virtual ~data () {} - data (std::ostream& os): os_ (os.rdbuf ()), object_ (0) {} + data (std::ostream& os) + : os_ (os.rdbuf ()), top_object_ (0), object_ (0) + { + } public: std::ostream os_; std::stack os_stack_; + semantics::class_* top_object_; semantics::class_* object_; keyword_set_type keyword_set_; diff --git a/odb/pragma.cxx b/odb/pragma.cxx index 8cfc3fa..d8f3aef 100644 --- a/odb/pragma.cxx +++ b/odb/pragma.cxx @@ -128,7 +128,8 @@ check_decl_type (tree d, string const& name, string const& p, location_t l) } } else if (p == "object" || - p == "pointer") + p == "pointer" || + p == "abstract") { if (tc != RECORD_TYPE) { @@ -365,6 +366,18 @@ handle_pragma (cpp_reader* reader, tt = pragma_lex (&t); } + else if (p == "abstract") + { + // abstract + // + + // Make sure we've got the correct declaration type. + // + if (decl != 0 && !check_decl_type (decl, decl_name, p, loc)) + return; + + tt = pragma_lex (&t); + } else if (p == "id") { // id diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 5ad7d2e..3ecc8d8 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -730,11 +730,12 @@ namespace relational virtual void traverse_object (type& c) { + bool abst (abstract (c)); string const& type (c.fq_name ()); - 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. + semantics::data_member* id (id_member (c)); + bool auto_id (id ? id->count ("auto") : false); + bool base_id (id ? &id->scope () != &c : false); // Comes from base. os << "// " << c.name () << endl << "//" << endl; @@ -751,109 +752,76 @@ namespace relational // id_type & id_image_type // - if (base_id) + if (id != 0) { - string const& base (id.scope ().fq_name ()); + if (base_id) + { + string const& base (id->scope ().fq_name ()); - 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; + 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; - 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 types // + // Query (abstract and concrete). + // + if (options.generate_query ()) { // query_columns // query_type_->traverse (c); - - // query_base_type - // - os << "typedef " << db << "::query query_base_type;" - << endl; - - // query_type - // - os << "struct query_type: query_base_type, query_columns" - << "{" - << "query_type ();" - << "query_type (const std::string&);" - << "query_type (const query_base_type&);" - << "};"; } - // column_count - // - os << "static const std::size_t in_column_count = " << - in_column_count (c) << "UL;" - << "static const std::size_t out_column_count = " << - out_column_count (c) << "UL;" - << endl; - - // Statements. - // - os << "static const char* const persist_statement;" - << "static const char* const find_statement;" - << "static const char* const update_statement;" - << "static const char* const erase_statement;"; - - if (options.generate_query ()) - os << "static const char* const query_clause;"; - - os << endl; - // - // Containers. + // Containers (abstract and concrete). // - // Traits types. - // { instance t (c); t->traverse (c); } - // Statement cache (forward declaration). - // - os << "struct container_statement_cache_type;" - << endl; - // - // Functions. + // Functions (abstract and concrete). // // id () // - os << "static id_type" << endl - << "id (const object_type&);" - << endl; - - if (options.generate_query ()) + if (id != 0) + { os << "static id_type" << endl - << "id (const image_type&);" + << "id (const object_type&);" << endl; + if (options.generate_query ()) + os << "static id_type" << endl + << "id (const image_type&);" + << endl; + } + // grow () // os << "static bool" << endl @@ -868,9 +836,12 @@ namespace relational // bind (id_image_type) // - os << "static void" << endl - << "bind (" << bind_vector << ", id_image_type&);" - << endl; + if (id != 0) + { + os << "static void" << endl + << "bind (" << bind_vector << ", id_image_type&);" + << endl; + } // init (image, object) // @@ -886,10 +857,76 @@ namespace relational // init (id_image, id) // - os << "static void" << endl - << "init (id_image_type&, const id_type&);" + if (id != 0) + { + os << "static void" << endl + << "init (id_image_type&, const id_type&);" + << endl; + } + + // + // The rest only applies to concrete objects. + // + if (abst) + { + os << "};"; + return; + } + + // + // Query (concrete). + // + + if (options.generate_query ()) + { + // query_base_type + // + os << "typedef " << db << "::query query_base_type;" + << endl; + + // query_type + // + os << "struct query_type: query_base_type, query_columns" + << "{" + << "query_type ();" + << "query_type (const std::string&);" + << "query_type (const query_base_type&);" + << "};"; + } + + // + // Containers (concrete). + // + + // Statement cache (forward declaration). + // + os << "struct container_statement_cache_type;" + << endl; + + // column_count + // + os << "static const std::size_t in_column_count = " << + in_column_count (c) << "UL;" + << "static const std::size_t out_column_count = " << + out_column_count (c) << "UL;" << endl; + // Statements. + // + os << "static const char* const persist_statement;" + << "static const char* const find_statement;" + << "static const char* const update_statement;" + << "static const char* const erase_statement;"; + + if (options.generate_query ()) + os << "static const char* const query_clause;"; + + os << endl; + + // + // Functions (concrete). + // + // persist () // os << "static void" << endl diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx index 9e76dea..73e0112 100644 --- a/odb/relational/inline.hxx +++ b/odb/relational/inline.hxx @@ -32,16 +32,80 @@ namespace relational virtual void traverse_object (type& c) { + bool abst (abstract (c)); 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. + semantics::data_member* id (id_member (c)); + bool base_id (id ? &id->scope () != &c : false); // Comes from base. os << "// " << c.name () << endl << "//" << endl << endl; + if (id != 0) + { + // id (object_type) + // + os << "inline" << endl + << traits << "::id_type" << endl + << traits << "::" << endl + << "id (const object_type& obj)" + << "{"; + + 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);" + << "}"; + } + } + + // + // The rest only applies to concrete objects. + // + if (abst) + return; + // query_type // if (options.generate_query ()) @@ -67,60 +131,6 @@ namespace relational << "}"; } - // id (object_type) - // - os << "inline" << endl - << traits << "::id_type" << endl - << traits << "::" << endl - << "id (const object_type& obj)" - << "{"; - - 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_() // if (!has_a (c, test_container)) diff --git a/odb/relational/mysql/common.cxx b/odb/relational/mysql/common.cxx index c9a33e4..5ddd27d 100644 --- a/odb/relational/mysql/common.cxx +++ b/odb/relational/mysql/common.cxx @@ -59,7 +59,7 @@ namespace relational if (semantics::class_* c = object_pointer (t)) { - member_info mi (m, id_member (*c).type (), var, fq_type_override_); + member_info mi (m, id_member (*c)->type (), var, fq_type_override_); mi.st = &st; if (pre (mi)) { diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 6c481da..9e04b77 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -136,7 +136,7 @@ namespace relational if (c.file () != unit.file ()) return; - if (!c.count ("object")) + if (!c.count ("object") || abstract (c)) return; string const& name (table_name (c)); @@ -192,7 +192,7 @@ namespace relational if (semantics::class_* c = object_pointer (member_type (m, prefix_))) { os << " REFERENCES " << quote_id (table_name (*c)) << " (" << - quote_id (column_name (id_member (*c))) << ")"; + quote_id (column_name (*id_member (*c))) << ")"; } return true; @@ -369,7 +369,7 @@ namespace relational if (c.file () != unit.file ()) return; - if (!c.count ("object")) + if (!c.count ("object") || abstract (c)) return; string const& name (table_name (c)); diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 5b2ec8d..9a23ca4 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -111,7 +111,7 @@ namespace relational } else { - semantics::data_member& id (id_member (*c)); + semantics::data_member& id (*id_member (*c)); column (id, "", table_name_.empty () ? table_name_ : table_qname (*c), column_qname (id)); @@ -172,7 +172,7 @@ namespace relational object_joins (semantics::class_& scope, bool query) : query_ (query), table_ (table_qname (scope)), - id_ (id_member (scope)) + id_ (*id_member (scope)) { } @@ -240,7 +240,7 @@ namespace relational dt = ct; string const& id (column_qname (*im, "id", "object_id")); - dcond << dt << '.' << column_qname (id_member (*c)) << " = " << + dcond << dt << '.' << column_qname (*id_member (*c)) << " = " << t << '.' << id; } } @@ -259,7 +259,7 @@ namespace relational // t = table_qname (*c); - cond << t << '.' << column_qname (id_member (*c)) << " = _." << + cond << t << '.' << column_qname (*id_member (*c)) << " = _." << quote_id (col_name); } @@ -703,7 +703,7 @@ namespace relational // many(i)-to-one // inv_table = table_qname (*c); - inv_id = column_qname (id_member (*c)); + inv_id = column_qname (*id_member (*c)); inv_fid = column_qname (*im); } @@ -873,8 +873,6 @@ namespace relational // bind() // { - instance bind_id ("id_", "id"); - // bind (cond_image_type) // os << "void " << scope << "::" << endl @@ -1795,160 +1793,57 @@ namespace relational virtual void traverse_object (type& c) { + bool abst (abstract (c)); string const& type (c.fq_name ()); string traits ("access::object_traits< " + type + " >"); bool grow (context::grow (c)); - 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. + semantics::data_member* id (id_member (c)); + bool auto_id (id ? id->count ("auto") : false); + bool grow_id (id ? context::grow (*id) : false); + bool base_id (id ? &id->scope () != &c : false); // Comes from base. os << "// " << c.name () << endl << "//" << endl << endl; // - // Containers. - // - bool straight_containers (has_a (c, test_straight_container)); - bool containers (straight_containers || has_a (c, test_container)); - - // Statement cache (definition). + // Query. // - { - os << "struct " << traits << "::container_statement_cache_type" - << "{"; - - instance cm; - cm->traverse (c); - - os << (containers ? "\n" : "") - << "container_statement_cache_type (" << db << "::connection&" << - (containers ? " c" : "") << ")"; - - instance im; - im->traverse (c); - - os << "{" - << "}" - << "};"; - } - - // Traits types. - // - if (containers) - { - instance t (c); - t->traverse (c); - } - // query columns - // if (options.generate_query ()) { instance t (c); t->traverse (c); } - string const& table (table_qname (c)); - string const& id_col (column_qname (id)); - - // persist_statement // - os << "const char* const " << traits << "::persist_statement =" << endl - << strlit ("INSERT INTO " + table + " (") << endl; - - { - instance t (false); - t->traverse (c); - } - - string values; - for (size_t i (0), n (in_column_count (c)); i < n; ++i) - values += i != 0 ? ",?" : "?"; - - os << strlit (") VALUES (" + values + ")") << ";" - << endl; - - // find_statement - // - os << "const char* const " << traits << "::find_statement =" << endl - << strlit ("SELECT ") << endl; - - { - instance t (table, true); - t->traverse (c); - } - - os << strlit (" FROM " + table + " AS _") << endl; - - { - bool f (false); - instance t (c, f); // @@ (im)perfect forwarding - t->traverse (c); - t->write (); - } - - os << strlit (" WHERE _." + id_col + " = ?") << ";" - << endl; - - // update_statement + // Containers (abstract and concrete). // - os << "const char* const " << traits << "::update_statement =" << endl - << strlit ("UPDATE " + table + " SET ") << endl; + bool straight_containers (has_a (c, test_straight_container)); + bool containers (straight_containers || has_a (c, test_container)); + if (containers) { - instance t (false, true, " = ?"); + instance t (c); t->traverse (c); } - os << strlit (" WHERE " + id_col + " = ?") << ";" - << endl; - - // erase_statement // - os << "const char* const " << traits << "::erase_statement =" << endl - << strlit ("DELETE FROM " + table) << endl - << strlit (" WHERE " + id_col + " = ?") << ";" - << endl; - - // query_clause + // Functions (abstract and concrete). // - if (options.generate_query ()) - { - bool t (true); - instance oj (c, t); //@@ (im)perfect forwarding - oj->traverse (c); - - // We only need DISTINCT if there are joins (object pointers) - // and can optimize it out otherwise. - // - os << "const char* const " << traits << "::query_clause =" << endl - << strlit (oj->count () ? "SELECT DISTINCT " : "SELECT ") << endl; - - { - instance oc (table, true); - oc->traverse (c); - } - - os << strlit (" FROM " + table + " AS _") << endl; - oj->write (); - os << strlit (" ") << ";" - << endl; - } // id (image_type) // - if (options.generate_query () && !base_id) + if (id != 0 && options.generate_query () && !base_id) { os << traits << "::id_type" << endl << traits << "::" << endl << "id (const image_type& i)" << "{" << "id_type id;"; - init_id_value_member_->traverse (id); + init_id_value_member_->traverse (*id); os << "return id;" << "}"; } @@ -1988,13 +1883,13 @@ namespace relational // bind (id_image_type) // - if (!base_id) + if (id != 0 && !base_id) { os << "void " << traits << "::" << endl << "bind (" << bind_vector << " b, id_image_type& i)" << "{" << "std::size_t n (0);"; - bind_id_member_->traverse (id); + bind_id_member_->traverse (*id); os << "}"; } @@ -2032,7 +1927,7 @@ namespace relational // init (id_image, id) // - if (!base_id) + if (id != 0 && !base_id) { os << "void " << traits << "::" << endl << "init (id_image_type& i, const id_type& id)" @@ -2041,7 +1936,7 @@ namespace relational if (grow_id) os << "bool grew (false);"; - init_id_image_member_->traverse (id); + init_id_image_member_->traverse (*id); if (grow_id) os << endl @@ -2051,6 +1946,128 @@ namespace relational os << "}"; } + // + // The rest only applies to concrete objects. + // + if (abst) + return; + + // + // Containers (concrete). + // + + // Statement cache (definition). + // + { + os << "struct " << traits << "::container_statement_cache_type" + << "{"; + + instance cm; + cm->traverse (c); + + os << (containers ? "\n" : "") + << "container_statement_cache_type (" << db << "::connection&" << + (containers ? " c" : "") << ")"; + + instance im; + im->traverse (c); + + os << "{" + << "}" + << "};"; + } + + // + // Statements. + // + + string const& table (table_qname (c)); + string const& id_col (column_qname (*id)); + + // persist_statement + // + os << "const char* const " << traits << "::persist_statement =" << endl + << strlit ("INSERT INTO " + table + " (") << endl; + + { + instance t (false); + t->traverse (c); + } + + string values; + for (size_t i (0), n (in_column_count (c)); i < n; ++i) + values += i != 0 ? ",?" : "?"; + + os << strlit (") VALUES (" + values + ")") << ";" + << endl; + + // find_statement + // + os << "const char* const " << traits << "::find_statement =" << endl + << strlit ("SELECT ") << endl; + + { + instance t (table, true); + t->traverse (c); + } + + os << strlit (" FROM " + table + " AS _") << endl; + + { + bool f (false); + instance t (c, f); // @@ (im)perfect forwarding + t->traverse (c); + t->write (); + } + + os << strlit (" WHERE _." + id_col + " = ?") << ";" + << endl; + + // update_statement + // + os << "const char* const " << traits << "::update_statement =" << endl + << strlit ("UPDATE " + table + " SET ") << endl; + + { + instance t (false, true, " = ?"); + t->traverse (c); + } + + os << strlit (" WHERE " + id_col + " = ?") << ";" + << endl; + + // erase_statement + // + os << "const char* const " << traits << "::erase_statement =" << endl + << strlit ("DELETE FROM " + table) << endl + << strlit (" WHERE " + id_col + " = ?") << ";" + << endl; + + // query_clause + // + if (options.generate_query ()) + { + bool t (true); + instance oj (c, t); //@@ (im)perfect forwarding + oj->traverse (c); + + // We only need DISTINCT if there are joins (object pointers) + // and can optimize it out otherwise. + // + os << "const char* const " << traits << "::query_clause =" << endl + << strlit (oj->count () ? "SELECT DISTINCT " : "SELECT ") << endl; + + { + instance oc (table, true); + oc->traverse (c); + } + + os << strlit (" FROM " + table + " AS _") << endl; + oj->write (); + os << strlit (" ") << ";" + << endl; + } + // persist () // os << "void " << traits << "::" << endl @@ -2072,9 +2089,9 @@ namespace relational if (auto_id) { - string const& n (id.name ()); + string const& n (id->name ()); string var ("im." + n + (n[n.size () - 1] == '_' ? "" : "_")); - init_auto_id (id, var); + init_auto_id (*id, var); os << endl; } @@ -2090,7 +2107,7 @@ namespace relational << endl; if (auto_id) - os << "obj." << id.name () << " = static_cast (st.id ());" + os << "obj." << id->name () << " = static_cast (st.id ());" << endl; if (straight_containers) @@ -2098,7 +2115,7 @@ namespace relational // Initialize id_image and binding. // os << "id_image_type& i (sts.id_image ());" - << "init (i, obj." << id.name () << ");" + << "init (i, obj." << id->name () << ");" << endl << "binding& idb (sts.id_image_binding ());" << "if (i.version != sts.id_image_version () || idb.version == 0)" @@ -2130,7 +2147,7 @@ namespace relational // Initialize id image. // os << "id_image_type& i (sts.id_image ());" - << "init (i, obj." << id.name () << ");" + << "init (i, obj." << id->name () << ");" << endl; os << "binding& idb (sts.id_image_binding ());" diff --git a/odb/relational/sqlite/common.cxx b/odb/relational/sqlite/common.cxx index ef880ed..010e267 100644 --- a/odb/relational/sqlite/common.cxx +++ b/odb/relational/sqlite/common.cxx @@ -59,7 +59,7 @@ namespace relational if (semantics::class_* c = object_pointer (t)) { - member_info mi (m, id_member (*c).type (), var, fq_type_override_); + member_info mi (m, id_member (*c)->type (), var, fq_type_override_); mi.st = &st; if (pre (mi)) { diff --git a/odb/relational/type-processor.cxx b/odb/relational/type-processor.cxx index 18d411c..5c86b10 100644 --- a/odb/relational/type-processor.cxx +++ b/odb/relational/type-processor.cxx @@ -22,7 +22,7 @@ namespace relational id_tree_type () { context& c (context::current ()); - semantics::data_member& id (context::id_member (*c.object)); + semantics::data_member& id (*context::id_member (*c.top_object)); return &id.type (); } @@ -30,7 +30,7 @@ namespace relational id_column_type () { context& c (context::current ()); - semantics::data_member& id (context::id_member (*c.object)); + semantics::data_member& id (*context::id_member (*c.top_object)); return id.get ("column-type"); } @@ -118,7 +118,7 @@ namespace relational // This is an object pointer. The column type is the pointed-to // object id type. Except by default it can be NULL. // - semantics::data_member& id (id_member (*c)); + semantics::data_member& id (*id_member (*c)); semantics::type& idt (id.type ()); if (type.empty () && id.count ("type")) @@ -203,7 +203,7 @@ namespace relational // This is an object pointer. The column type is the pointed-to // object id type. Except by default it can be NULL. // - semantics::data_member& id (id_member (*c)); + semantics::data_member& id (*id_member (*c)); semantics::type& idt (id.type ()); if (type.empty () && id.count ("type")) @@ -660,6 +660,20 @@ namespace relational throw generation_failed (); } + // Make sure the pointed-to class is not abstract. + // + if (context::abstract (*c)) + { + os << m.file () << ":" << m.line () << ":" << m.column () << ": " + << "error: pointed-to class '" << c->fq_name () << "' " + << "is abstract" << endl; + + os << c->file () << ":" << c->line () << ":" << c->column () << ": " + << "info: class '" << c->name () << "' is defined here" << endl; + + throw generation_failed (); + } + if (m.count ("not-null") && !kp.empty ()) { m.remove ("not-null"); diff --git a/odb/tracer/header.cxx b/odb/tracer/header.cxx index 6973fe4..16bee82 100644 --- a/odb/tracer/header.cxx +++ b/odb/tracer/header.cxx @@ -26,7 +26,7 @@ namespace tracer string const& type (c.fq_name ()); - semantics::data_member& id (id_member (c)); + semantics::data_member& id (*id_member (c)); bool auto_id (id.count ("auto")); os << "// " << c.name () << endl diff --git a/odb/tracer/inline.cxx b/odb/tracer/inline.cxx index 0abfb70..f4125a9 100644 --- a/odb/tracer/inline.cxx +++ b/odb/tracer/inline.cxx @@ -27,7 +27,7 @@ namespace tracer string const& type (c.fq_name ()); string traits ("access::object_traits< " + type + " >"); - semantics::data_member& id (id_member (c)); + semantics::data_member& id (*id_member (c)); os << "// " << c.name () << endl << "//" << endl diff --git a/odb/tracer/source.cxx b/odb/tracer/source.cxx index 5b26274..c25c1ee 100644 --- a/odb/tracer/source.cxx +++ b/odb/tracer/source.cxx @@ -27,7 +27,7 @@ namespace tracer string const& type (c.fq_name ()); string traits ("access::object_traits< " + type + " >"); - semantics::data_member& id (id_member (c)); + semantics::data_member& id (*id_member (c)); bool auto_id (id.count ("auto")); os << "// " << c.name () << endl -- cgit v1.1