From 428558c89850fe8c79b9c89a943bd996912d12f5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 5 Sep 2011 10:36:33 +0200 Subject: Support for views; native part --- odb/common.cxx | 81 +++++++----- odb/common.hxx | 12 ++ odb/context.cxx | 17 ++- odb/context.hxx | 29 ++++- odb/include.cxx | 4 +- odb/pragma.cxx | 90 +++++++------ odb/relational/header.hxx | 145 ++++++++++++++++++++- odb/relational/inline.hxx | 55 ++++++-- odb/relational/mysql/context.cxx | 7 +- odb/relational/pgsql/source.cxx | 4 +- odb/relational/source.hxx | 257 +++++++++++++++++++++++++++++++------- odb/relational/type-processor.cxx | 8 +- odb/validator.cxx | 134 ++++++++++++++++---- 13 files changed, 674 insertions(+), 169 deletions(-) diff --git a/odb/common.cxx b/odb/common.cxx index 81f8155..036b491 100644 --- a/odb/common.cxx +++ b/odb/common.cxx @@ -44,6 +44,14 @@ traverse_object (semantics::class_& c) } void object_members_base:: +traverse_view (semantics::class_& c) +{ + // A view has no bases. + // + names (c); +} + +void object_members_base:: traverse (semantics::data_member& m, semantics::class_& c) { traverse_composite_wrapper (&m, c, 0); @@ -52,24 +60,28 @@ traverse (semantics::data_member& m, semantics::class_& c) void object_members_base:: traverse (semantics::class_& c) { - bool obj (object (c)); + class_kind_type k (class_kind (c)); - // Ignore transient bases. - // - if (!(obj || context::composite (c))) + if (k == class_other) + { + // Ignore transient bases. + // + assert (context::top_object != 0); return; - - semantics::class_* prev; - if (obj) + } + else if (k == class_composite) { - prev = context::cur_object; - context::cur_object = &c; - - if (context::top_object == 0) - context::top_object = &c; + traverse_composite_wrapper (0, c, 0); + return; } - if (obj && build_table_prefix_) + semantics::class_* prev (context::cur_object); + context::cur_object = &c; + + if (context::top_object == 0) + context::top_object = &c; + + if (build_table_prefix_) { // Don't reset the table prefix if we are traversing a base. // @@ -83,7 +95,10 @@ traverse (semantics::class_& c) tb = true; } - traverse_object (c); + if (k == class_object) + traverse_object (c); + else + traverse_view (c); if (tb) { @@ -93,19 +108,16 @@ traverse (semantics::class_& c) } else { - if (obj) + if (k == class_object) traverse_object (c); else - traverse_composite_wrapper (0, c, 0); + traverse_view (c); } - if (obj) - { - if (prev == 0) - context::top_object = 0; + if (prev == 0) + context::top_object = 0; - context::cur_object = prev; - } + context::cur_object = prev; } void object_members_base::member:: @@ -206,6 +218,14 @@ traverse_object (semantics::class_& c) } void object_columns_base:: +traverse_view (semantics::class_& c) +{ + // A view has no bases. + // + names (c); +} + +void object_columns_base:: traverse (semantics::data_member& m, semantics::class_& c, string const& key_prefix, @@ -236,12 +256,15 @@ traverse (semantics::data_member& m, void object_columns_base:: traverse (semantics::class_& c) { - bool obj (object (c)); + class_kind_type k (class_kind (c)); // Ignore transient bases. // - if (!(obj || context::composite (c))) + if (k == class_other) + { + assert (context::top_object != 0); return; + } bool f (top_level_); @@ -249,7 +272,7 @@ traverse (semantics::class_& c) top_level_ = false; semantics::class_* prev; - if (obj) + if (k == class_object || k == class_view) { prev = context::cur_object; context::cur_object = &c; @@ -258,12 +281,14 @@ traverse (semantics::class_& c) context::top_object = &c; } - if (obj) + if (k == class_object) traverse_object (c); - else + else if (k == class_view) + traverse_view (c); + else if (k == class_composite) traverse_composite (0, c); - if (obj) + if (k == class_object || k == class_view) { if (prev == 0) context::top_object = 0; diff --git a/odb/common.hxx b/odb/common.hxx index 9e48771..60f5e3b 100644 --- a/odb/common.hxx +++ b/odb/common.hxx @@ -50,6 +50,12 @@ struct object_members_base: traversal::class_, virtual context virtual void traverse_object (semantics::class_&); + // If you override this function, you can call the base to traverse + // members. + // + virtual void + traverse_view (semantics::class_&); + public: object_members_base () : member_ (*this) @@ -144,6 +150,12 @@ struct object_columns_base: traversal::class_, virtual context virtual void traverse_object (semantics::class_&); + // If you override this function, you can call the base to traverse + // members. + // + virtual void + traverse_view (semantics::class_&); + // Called after the last column, provided at least one column hasn't // been ignored. // diff --git a/odb/context.cxx b/odb/context.cxx index 33d9e08..56b9ab0 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -279,6 +279,19 @@ null (semantics::data_member& m, string const& kp) } } +context::class_kind_type context:: +class_kind (semantics::class_& c) +{ + if (object (c)) + return class_object; + else if (view (c)) + return class_view; + else if (composite (c)) + return class_composite; + else + return class_other; +} + string context:: upcase (string const& s) { @@ -1006,10 +1019,10 @@ is_a (semantics::data_member& m, } bool context:: -has_a (semantics::type& t, unsigned short flags) +has_a (semantics::class_& c, unsigned short flags) { has_a_impl impl (flags); - impl.dispatch (t); + impl.dispatch (c); return impl.result (); } diff --git a/odb/context.hxx b/odb/context.hxx index 75becef..e00ec4e 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -57,6 +57,16 @@ enum container_kind ck_multimap }; +// The same as class_kind in libodb/odb/traits.hxx. +// +enum class_kind +{ + class_object, + class_view, + class_composite, + class_other +}; + class context { public: @@ -84,6 +94,12 @@ public: } static bool + view (semantics::type& t) + { + return t.count ("view"); + } + + static bool transient (semantics::data_member& m) { return m.count ("transient"); @@ -177,6 +193,11 @@ public: bool null (semantics::data_member&, string const& key_prefix); + typedef ::class_kind class_kind_type; + + static class_kind_type + class_kind (semantics::class_&); + // Database names and types. // public: @@ -377,7 +398,7 @@ public: string const& key_prefix); bool - has_a (semantics::type&, unsigned short flags); + has_a (semantics::class_&, unsigned short flags); public: // Process include path by adding the prefix, putting it through @@ -480,12 +501,12 @@ public: bool embedded_schema; - // Outermost object currently being traversed. + // Outermost object or view 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. + // Object or view currently being traversed. It can be the same as + // top_object or it can a base of top_object. // semantics::class_*& cur_object; diff --git a/odb/include.cxx b/odb/include.cxx index 08e785f..16842c8 100644 --- a/odb/include.cxx +++ b/odb/include.cxx @@ -79,7 +79,9 @@ namespace if (c.file () == unit.file ()) return; - // We only generate things for objects and composite value types. + // We only generate things for objects and composite value types. In + // particular, we don't care about views since they cannot be used in + // definitions of other views, objects, or composite values. // if (!(object (c) || composite (c))) return; diff --git a/odb/pragma.cxx b/odb/pragma.cxx index 23d3fd3..ec3fb8d 100644 --- a/odb/pragma.cxx +++ b/odb/pragma.cxx @@ -126,9 +126,11 @@ check_decl_type (tree d, string const& name, string const& p, location_t l) } } else if (p == "object" || + p == "view" || p == "pointer" || p == "abstract" || - p == "callback") + p == "callback" || + p == "query") { if (tc != RECORD_TYPE) { @@ -140,7 +142,7 @@ check_decl_type (tree d, string const& name, string const& p, location_t l) else if (p == "table") { // Table can be used for both members (container) and types (container - // or object). + // object, or view). // if (tc != FIELD_DECL && !TYPE_P (d)) { @@ -442,6 +444,40 @@ handle_pragma (cpp_reader* reader, tt = pragma_lex (&t); } + else if (p == "query") + { + // query ("statement") + // + + // Make sure we've got the correct declaration type. + // + if (decl != 0 && !check_decl_type (decl, decl_name, p, loc)) + return; + + if (pragma_lex (&t) != CPP_OPEN_PAREN) + { + error () << "'(' expected after db pragma '" << p << "'" << endl; + return; + } + + tt = pragma_lex (&t); + + if (tt != CPP_STRING) + { + error () << "query statement expected in db pragma '" << p << "'" << endl; + return; + } + + val = TREE_STRING_POINTER (t); + + if (pragma_lex (&t) != CPP_CLOSE_PAREN) + { + error () << "')' expected at the end of db pragma '" << p << "'" << endl; + return; + } + + tt = pragma_lex (&t); + } else if (p == "id") { // id @@ -839,47 +875,12 @@ handle_pragma_qualifier (cpp_reader* reader, string const& p) // Pragma qualifiers. // - if (p == "object") + if (p == "object" || + p == "view" || + p == "value") { // object [()] - // - - tt = pragma_lex (&t); - - if (tt == CPP_OPEN_PAREN) - { - tt = pragma_lex (&t); - - if (tt == CPP_NAME || tt == CPP_SCOPE) - { - decl = parse_scoped_name (t, tt, decl_name, true, p); - - if (decl == 0) - return; - - // Make sure we've got the correct declaration type. - // - if (!check_decl_type (decl, decl_name, p, loc)) - return; - - if (tt != CPP_CLOSE_PAREN) - { - error () << "')' expected at the end of db pragma '" << p << "'" - << endl; - return; - } - - tt = pragma_lex (&t); - } - else - { - error () << "type name expected in db pragma '" << p << "'" << endl; - return; - } - } - } - else if (p == "value") - { + // view [()] // value [()] // @@ -1029,6 +1030,12 @@ handle_pragma_db_object (cpp_reader* r) } extern "C" void +handle_pragma_db_view (cpp_reader* r) +{ + handle_pragma_qualifier (r, "view"); +} + +extern "C" void handle_pragma_db_value (cpp_reader* r) { handle_pragma_qualifier (r, "value"); @@ -1229,6 +1236,7 @@ register_odb_pragmas (void*, void*) /* c_register_pragma_with_expansion ("db", "object", handle_pragma_db_object); + c_register_pragma_with_expansion ("db", "view", handle_pragma_db_view); c_register_pragma_with_expansion ("db", "value", handle_pragma_db_value); c_register_pragma_with_expansion ("db", "member", handle_pragma_db_member); c_register_pragma_with_expansion ("db", "id", handle_pragma_db_id); diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 69f7977..f7e1058 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -46,7 +46,7 @@ namespace relational { bool obj (object (c)); - // Ignore transient bases. + // Ignore transient bases. Not used for views. // if (!(obj || composite (c))) return; @@ -92,6 +92,7 @@ namespace relational { os << "struct image_type"; + if (!view (c)) { instance b; traversal::inherits i (*b); @@ -126,7 +127,7 @@ namespace relational virtual void traverse (type& c) { - // Ignore transient bases. + // Ignore transient bases. Not used for views. // if (!object (c)) return; @@ -224,7 +225,7 @@ namespace relational if (object (c_)) { - base = cur_object != &c_ || + base = cur_object != &c_ || !object (dynamic_cast (m.scope ())); abst = abstract (c_); } @@ -754,6 +755,8 @@ namespace relational if (object (c)) traverse_object (c); + else if (view (c)) + traverse_view (c); else if (composite (c)) traverse_composite (c); } @@ -782,6 +785,12 @@ namespace relational << "//" << endl; os << "template <>" << endl + << "struct class_traits< " << type << " >" + << "{" + << "static const class_kind kind = class_object;" + << "};"; + + os << "template <>" << endl << "class access::object_traits< " << type << " >" << "{" << "public:" << endl; @@ -1073,6 +1082,124 @@ namespace relational } virtual void + view_public_extra_pre (type&) + { + } + + virtual void + view_public_extra_post (type&) + { + } + + virtual void + traverse_view (type& c) + { + string const& type (c.fq_name ()); + + os << "// " << c.name () << endl + << "//" << endl; + + os << "template <>" << endl + << "struct class_traits< " << type << " >" + << "{" + << "static const class_kind kind = class_view;" + << "};"; + + os << "template <>" << endl + << "class access::view_traits< " << type << " >" + << "{" + << "public:" << endl; + + view_public_extra_pre (c); + + // view_type & pointer_type + // + os << "typedef " << type << " view_type;" + << "typedef " << c.get ("object-pointer") << " pointer_type;" + << endl; + + // image_type + // + image_type_->traverse (c); + + // + // Query. + // + + // query_base_type + // + os << "typedef " << db << "::query query_base_type;" + << endl; + + // query_type + // + os << "typedef query_base_type query_type;" + << endl; + + /* + os << "struct query_type: query_base_type, query_columns" + << "{" + << "query_type ();" + << "query_type (const std::string&);" + << "query_type (const query_base_type&);" + << "};"; + */ + + // + // Functions. + // + + // grow () + // + os << "static bool" << endl + << "grow (image_type&, " << truncated_vector << ");" + << endl; + + // bind (image_type) + // + os << "static void" << endl + << "bind (" << bind_vector << ", image_type&);" + << endl; + + // init (view, image) + // + os << "static void" << endl + << "init (view_type&, const image_type&);" + << endl; + + // column_count + // + os << "static const std::size_t column_count = " << + out_column_count (c) << "UL;" + << endl; + + // Statements. + // + os << "static const char* const query_statement;" + << endl; + + // + // Functions. + // + + // callback () + // + os << "static void" << endl + << "callback (database&, view_type&, callback_event);" + << endl; + + // query () + // + os << "static result" << endl + << "query (database&, const query_type&);" + << endl; + + view_public_extra_post (c); + + os << "};"; + } + + virtual void traverse_composite (type& c) { string const& type (c.fq_name ()); @@ -1081,11 +1208,17 @@ namespace relational << "//" << endl; os << "template <>" << endl + << "struct class_traits< " << type << " >" + << "{" + << "static const class_kind kind = class_composite;" + << "};"; + + os << "template <>" << endl << "class access::composite_value_traits< " << type << " >" << "{" << "public:" << endl; - // object_type + // value_type // os << "typedef " << type << " value_type;" << endl; @@ -1113,13 +1246,13 @@ namespace relational << "bind (" << bind_vector << ", image_type&);" << endl; - // init (image, object) + // init (image, value) // os << "static bool" << endl << "init (image_type&, const value_type&);" << endl; - // init (object, image) + // init (value, image) // os << "static void" << endl << "init (value_type&, const image_type&, database&);" diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx index 311640e..1134df6 100644 --- a/odb/relational/inline.hxx +++ b/odb/relational/inline.hxx @@ -41,29 +41,31 @@ namespace relational virtual void traverse (type& c) { + bool obj (object (c)); + // Ignore transient bases. // - if (!object (c)) + if (!(obj || view (c))) return; if (c.count ("callback")) { string name (c.get ("callback")); - // In case of the const object, we only generate the call if + // In case of the const instance, we only generate the call if // there is a const callback. // if (const_) { if (c.count ("callback-const")) - os << "static_cast< const " << c.fq_name () << "& > (obj)." << + os << "static_cast< const " << c.fq_name () << "& > (x)." << name << " (e, db);"; } else - os << "static_cast< " << c.fq_name () << "& > (obj)." << + os << "static_cast< " << c.fq_name () << "& > (x)." << name << " (e, db);"; } - else + else if (obj) inherits (c); } @@ -86,6 +88,8 @@ namespace relational if (object (c)) traverse_object (c); + if (view (c)) + traverse_view (c); else if (composite (c)) traverse_composite (c); } @@ -178,11 +182,11 @@ namespace relational // os << "inline" << endl << "void " << traits << "::" << endl - << "callback (database& db, object_type& obj, callback_event e)" + << "callback (database& db, object_type& x, callback_event e)" << endl << "{" << "ODB_POTENTIALLY_UNUSED (db);" - << "ODB_POTENTIALLY_UNUSED (obj);" + << "ODB_POTENTIALLY_UNUSED (x);" << "ODB_POTENTIALLY_UNUSED (e);" << endl; callback_calls_->traverse (c, false); @@ -190,11 +194,10 @@ namespace relational os << "inline" << endl << "void " << traits << "::" << endl - << "callback (database& db, const object_type& obj, " << - "callback_event e)" + << "callback (database& db, const object_type& x, callback_event e)" << "{" << "ODB_POTENTIALLY_UNUSED (db);" - << "ODB_POTENTIALLY_UNUSED (obj);" + << "ODB_POTENTIALLY_UNUSED (x);" << "ODB_POTENTIALLY_UNUSED (e);" << endl; callback_calls_->traverse (c, true); @@ -239,6 +242,38 @@ namespace relational } virtual void + view_extra (type&) + { + } + + virtual void + traverse_view (type& c) + { + string const& type (c.fq_name ()); + string traits ("access::view_traits< " + type + " >"); + + os << "// " << c.name () << endl + << "//" << endl + << endl; + + view_extra (c); + + // callback () + // + os << "inline" << endl + << "void " << traits << "::" << endl + << "callback (database& db, view_type& x, callback_event e)" + << endl + << "{" + << "ODB_POTENTIALLY_UNUSED (db);" + << "ODB_POTENTIALLY_UNUSED (x);" + << "ODB_POTENTIALLY_UNUSED (e);" + << endl; + callback_calls_->traverse (c, false); + os << "}"; + } + + virtual void traverse_composite (type&) { /* diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx index ccd1861..59b93ba 100644 --- a/odb/relational/mysql/context.cxx +++ b/odb/relational/mysql/context.cxx @@ -122,9 +122,11 @@ namespace relational virtual void traverse (type& c) { + bool view (context::view (c)); + // Ignore transient bases. // - if (!(context::object (c) || context::composite (c))) + if (!(context::object (c) || view || context::composite (c))) return; if (c.count ("mysql-grow")) @@ -133,7 +135,8 @@ namespace relational { // r_ should be false. // - inherits (c); + if (!view) + inherits (c); if (!r_) names (c); diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index b869520..da9d0d7 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -969,7 +969,7 @@ namespace relational } virtual void - query_statement_ctor_args (type&) + object_query_statement_ctor_args (type&) { os << "sts.connection ()," << endl << "query_statement_name," << endl @@ -981,7 +981,7 @@ namespace relational } virtual void - erase_query_statement_ctor_args (type&) + object_erase_query_statement_ctor_args (type&) { os << "conn," << endl << "erase_query_statement_name," << endl diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index d9cf66f..a3ef5de 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -404,7 +404,7 @@ namespace relational { bool obj (object (c)); - // Ignore transient bases. + // Ignore transient bases. Not used for views. // if (!(obj || composite (c))) return; @@ -461,7 +461,7 @@ namespace relational { bool obj (object (c)); - // Ignore transient bases. + // Ignore transient bases. Not used for views. // if (!(obj || composite (c))) return; @@ -519,7 +519,7 @@ namespace relational { bool obj (object (c)); - // Ignore transient bases. + // Ignore transient bases. Not used for views. // if (!(obj || composite (c))) return; @@ -570,7 +570,7 @@ namespace relational { bool obj (object (c)); - // Ignore transient bases. + // Ignore transient bases. Not used for views. // if (!(obj || composite (c))) return; @@ -689,8 +689,13 @@ namespace relational grow = grow || context::grow (m, vt, "value"); - bool eager_ptr (is_a (m, test_eager_pointer, vt, "value") || - has_a (vt, test_eager_pointer)); + bool eager_ptr (is_a (m, test_eager_pointer, vt, "value")); + + if (!eager_ptr) + { + if (semantics::class_* cvt = composite_wrapper (vt)) + eager_ptr = has_a (*cvt, test_eager_pointer); + } string name (prefix_ + public_name (m) + "_traits"); string scope (scope_ + "::" + name); @@ -1902,17 +1907,32 @@ namespace relational if (object (c)) traverse_object (c); + else if (view (c)) + traverse_view (c); else if (composite (c)) traverse_composite (c); } + // + // common + // + + virtual void + post_query_ (type&) + { + } + + // + // object + // + virtual void object_extra (type&) { } virtual void - query_statement_ctor_args (type&) + object_query_statement_ctor_args (type&) { os << "sts.connection ()," << endl << "query_clause + q.clause (table_name)," << endl @@ -1921,7 +1941,7 @@ namespace relational } virtual void - erase_query_statement_ctor_args (type&) + object_erase_query_statement_ctor_args (type&) { os << "conn," << endl << "erase_query_clause + q.clause (table_name)," << endl @@ -1929,11 +1949,6 @@ namespace relational } virtual void - post_query_ (type&) - { - } - - virtual void traverse_object (type& c) { bool abst (abstract (c)); @@ -2249,10 +2264,10 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << db << "::connection& conn (" << db << - "::transaction::current ().connection ());" + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find ());" + << "conn.statement_cache ().find_object ());" << "image_type& im (sts.image ());" << "binding& imb (sts.in_image_binding ());" << endl @@ -2311,10 +2326,10 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << db << "::connection& conn (" << db << - "::transaction::current ().connection ());" + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find ());" + << "conn.statement_cache ().find_object ());" << endl; // Initialize id image. @@ -2363,10 +2378,10 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << db << "::connection& conn (" << db << - "::transaction::current ().connection ());" + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find ());" + << "conn.statement_cache ().find_object ());" << endl; // Initialize id image. @@ -2410,10 +2425,10 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << db << "::connection& conn (" << db << - "::transaction::current ().connection ());" + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find ());" + << "conn.statement_cache ().find_object ());" << "object_statements< object_type >::auto_lock l (sts);" << endl << "if (l.locked ())" @@ -2452,10 +2467,10 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << db << "::connection& conn (" << db << - "::transaction::current ().connection ());" + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find ());" + << "conn.statement_cache ().find_object ());" << "object_statements< object_type >::auto_lock l (sts);" << endl << "if (l.locked ())" @@ -2568,19 +2583,24 @@ namespace relational << "const query_type& q)" << "{" << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" << endl - << db << "::connection& conn (" << db << - "::transaction::current ().connection ());" + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" << endl << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find ());" - << "odb::details::shared_ptr st;" + << "conn.statement_cache ().find_object ());" + << "shared_ptr st;" << endl << "query_ (db, q, sts, st);" << endl - << "odb::details::shared_ptr > r (" << endl - << "new (odb::details::shared) " << db << - "::result_impl (q, st, sts));" + << "shared_ptr > r (" << endl + << "new (shared) " << db << + "::result_impl (" << endl + << "q, st, sts));" + << endl << "return result (r);" << "}"; @@ -2592,19 +2612,24 @@ namespace relational << "const query_type& q)" << "{" << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" << endl - << db << "::connection& conn (" << db << - "::transaction::current ().connection ());" + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" << endl << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find ());" - << "odb::details::shared_ptr st;" + << "conn.statement_cache ().find_object ());" + << "shared_ptr st;" << endl << "query_ (db, q, sts, st);" << endl - << "odb::details::shared_ptr > r (" << endl - << "new (odb::details::shared) " << db << - "::result_impl (q, st, sts));" + << "shared_ptr > r (" << endl + << "new (shared) " << db << + "::result_impl (" << endl + << "q, st, sts));" + << endl << "return result (r);" << "}"; @@ -2628,7 +2653,7 @@ namespace relational << "st.reset (new (odb::details::shared) select_statement (" << endl; - query_statement_ctor_args (c); + object_query_statement_ctor_args (c); os << "));" << endl << "st->execute ();"; @@ -2644,12 +2669,12 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << db << "::connection& conn (" << db << - "::transaction::current ().connection ());" + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" << endl << "delete_statement st (" << endl; - erase_query_statement_ctor_args (c); + object_erase_query_statement_ctor_args (c); os << ");" << endl @@ -2811,6 +2836,142 @@ namespace relational << endl; } + // + // view + // + + virtual void + view_extra (type&) + { + } + + virtual void + view_query_statement_ctor_args (type&) + { + os << "sts.connection ()," << endl + << "query_statement + q.clause (\"\")," << endl + << "q.parameters_binding ()," << endl + << "imb"; + } + + virtual void + traverse_view (type& c) + { + string const& type (c.fq_name ()); + string traits ("access::view_traits< " + type + " >"); + + os << "// " << c.name () << endl + << "//" << endl + << endl; + + view_extra (c); + + // + // Functions. + // + + // grow () + // + os << "bool " << traits << "::" << endl + << "grow (image_type& i, " << truncated_vector << " t)" + << "{" + << "ODB_POTENTIALLY_UNUSED (i);" + << "ODB_POTENTIALLY_UNUSED (t);" + << endl + << "bool grew (false);" + << endl; + + index_ = 0; + names (c, grow_member_names_); + + os << "return grew;" + << "}"; + + // bind (image_type) + // + os << "void " << traits << "::" << endl + << "bind (" << bind_vector << " b, image_type& i)" + << "{" + << "bool out (true);" //@@ Try to get rid of this. + << "ODB_POTENTIALLY_UNUSED (out);" + << endl + << "std::size_t n (0);" + << endl; + + names (c, bind_member_names_); + + os << "}"; + + // init (view, image) + // + os << "void " << traits << "::" << endl + << "init (view_type& o, const image_type& i)" + << "{" + << "ODB_POTENTIALLY_UNUSED (o);" + << "ODB_POTENTIALLY_UNUSED (i);" + << endl; + + names (c, init_value_member_names_); + + os << "}"; + + // query_statement + // + os << "const char* const " << traits << "::query_statement =" << endl + << strlit (c.get ("query")) << endl + << strlit (" ") << ";" << endl + << endl; + + // query () + // + os << "result< " << traits << "::view_type >" << endl + << traits << "::" << endl + << "query (database&, const query_type& q)" + << "{" + << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" + << endl + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" + << endl + << "view_statements< view_type >& sts (" << endl + << "conn.statement_cache ().find_view ());" + << endl + << "image_type& im (sts.image ());" + << "binding& imb (sts.image_binding ());" + << endl + << "if (im.version != sts.image_version () || imb.version == 0)" + << "{" + << "bind (imb.bind, im);" + << "sts.image_version (im.version);" + << "imb.version++;" + << "}" + << "shared_ptr st (" << endl + << "new (shared) select_statement (" << endl; + + view_query_statement_ctor_args (c); + + os << "));" << endl + << "st->execute ();"; + + post_query_ (c); + + os << endl + << "shared_ptr > r (" << endl + << "new (shared) " << db << + "::result_impl (" << endl + << "q, st, sts));" + << endl + << "return result (r);" + << "}"; + } + + // + // composite + // + virtual void traverse_composite (type& c) { @@ -2863,7 +3024,7 @@ namespace relational os << "}"; - // init (image, object) + // init (image, value) // os << "bool " << traits << "::" << endl << "init (image_type& i, const value_type& o)" @@ -2880,7 +3041,7 @@ namespace relational os << "return grew;" << "}"; - // init (object, image) + // init (value, image) // os << "void " << traits << "::" << endl << "init (value_type& o, const image_type& i, database& db)" diff --git a/odb/relational/type-processor.cxx b/odb/relational/type-processor.cxx index 12d2b52..362fab3 100644 --- a/odb/relational/type-processor.cxx +++ b/odb/relational/type-processor.cxx @@ -1087,16 +1087,16 @@ namespace relational virtual void traverse (type& c) { - bool obj (object (c)); + bool ov (object (c) || view (c)); - if (!(obj || composite (c))) + if (!(ov || composite (c))) return; names (c); - // Assign object pointer. + // Assign pointer. // - if (obj) + if (ov) assign_pointer (c); } diff --git a/odb/validator.cxx b/odb/validator.cxx index 435d480..0494741 100644 --- a/odb/validator.cxx +++ b/odb/validator.cxx @@ -80,10 +80,12 @@ namespace // struct id_member: traversal::class_ { - id_member (bool object, bool& valid, semantics::data_member*& m) - : object_ (object), member_ (valid, m) + id_member (class_kind kind, bool& valid, semantics::data_member*& m) + : kind_ (kind), member_ (valid, m) { - *this >> inherits_ >> *this; + if (kind != class_view) + *this >> inherits_ >> *this; + *this >> names_ >> member_; } @@ -92,18 +94,36 @@ namespace { // Skip transient bases. // - if (object_) + switch (kind_) { - if (!context::object (c)) - return; - } - else - { - if (!context::composite (c)) - return; + case class_object: + { + if (!context::object (c)) + return; + break; + } + case class_view: + { + break; + } + case class_composite: + { + if (!context::composite (c)) + return; + break; + } + case class_other: + { + assert (false); + break; + } } - inherits (c); + // Views don't have bases. + // + if (kind_ != class_view) + inherits (c); + names (c); } @@ -139,7 +159,7 @@ namespace semantics::data_member*& m_; }; - bool object_; + class_kind kind_; member member_; traversal::names names_; traversal::inherits inherits_; @@ -178,6 +198,8 @@ namespace { if (context::object (c)) traverse_object (c); + else if (context::view (c)) + traverse_view (c); else { if (context::composite (c)) @@ -241,18 +263,20 @@ namespace if (context::object (b)) base = true; - if (context::composite (b)) + else if (context::view (b) || context::composite (b)) { // @@ Should we use hint here? // string name (b.fq_name ()); cerr << c.file () << ":" << c.line () << ":" << c.column () << ":" - << " error: base class '" << name << "' is a value type" + << " error: base class '" << name << "' is a view or value type" << endl; cerr << c.file () << ":" << c.line () << ":" << c.column () << ":" - << " info: object types cannot derive from value types" << endl; + << " info: object types cannot derive from view or value " + << "types" + << endl; cerr << b.file () << ":" << b.line () << ":" << b.column () << ":" << " info: class '" << name << "' is defined here" << endl; @@ -265,7 +289,7 @@ namespace // semantics::data_member* id (0); { - id_member t (true, valid_, id); + id_member t (class_object, valid_, id); t.traverse (c); } @@ -328,6 +352,73 @@ namespace } virtual void + traverse_view (type& c) + { + // Check bases. + // + for (type::inherits_iterator i (c.inherits_begin ()); + i != c.inherits_end (); + ++i) + { + type& b (i->base ()); + + if (context::object (b) || + context::view (b) || + context::composite (b)) + { + // @@ Should we use hint here? + // + string name (b.fq_name ()); + + cerr << c.file () << ":" << c.line () << ":" << c.column () << ":" + << " error: base class '" << name << "' is an object, " + << "view, or value type" + << endl; + + cerr << c.file () << ":" << c.line () << ":" << c.column () << ":" + << " info: view types cannot derive from view, object or " + << "value types" + << endl; + + cerr << b.file () << ":" << b.line () << ":" << b.column () << ":" + << " info: class '" << name << "' is defined here" << endl; + + valid_ = false; + } + } + + // Check id. + // + semantics::data_member* id (0); + { + id_member t (class_view, valid_, id); + t.traverse (c); + } + + if (id != 0) + { + cerr << id->file () << ":" << id->line () << ":" << id->column () + << ": error: view type data member cannot be designated as " + << "object id" << endl; + + valid_ = false; + } + + // Check members. + // + member_.count_ = 0; + names (c); + + if (member_.count_ == 0) + { + cerr << c.file () << ":" << c.line () << ":" << c.column () << ":" + << " error: no persistent data members in the class" << endl; + + valid_ = false; + } + } + + virtual void traverse_composite (type& c) { bool base (false); @@ -340,19 +431,20 @@ namespace if (context::composite (b)) base = true; - else if (context::object (b)) + else if (context::object (b) || context::view (b)) { // @@ Should we use hint here? // string name (b.fq_name ()); cerr << c.file () << ":" << c.line () << ":" << c.column () << ":" - << " error: base class '" << name << "' is an object type" + << " error: base class '" << name << "' is a view or object " + << "type" << endl; cerr << c.file () << ":" << c.line () << ":" << c.column () << ":" << " info: composite value types cannot derive from object " - << "types" << endl; + << "or view types" << endl; cerr << b.file () << ":" << b.line () << ":" << b.column () << ":" << " info: class '" << name << "' is defined here" << endl; @@ -365,7 +457,7 @@ namespace // semantics::data_member* id (0); { - id_member t (false, valid_, id); + id_member t (class_composite, valid_, id); t.traverse (c); } -- cgit v1.1