diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-10-15 11:33:40 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-10-21 19:25:06 +0200 |
commit | 6508eb18a20a2f0bc48374f3f0a352f1195cc95b (patch) | |
tree | 0aaf5a65d82b7d58721b0020c17885d16f178b3e /odb/relational | |
parent | b2f0cd834b8f5651985357f8acbe82edd7d11c63 (diff) |
Add support for readonly members
New pragma: readonly. New test: readonly.
Diffstat (limited to 'odb/relational')
-rw-r--r-- | odb/relational/header.hxx | 17 | ||||
-rw-r--r-- | odb/relational/mysql/source.cxx | 74 | ||||
-rw-r--r-- | odb/relational/oracle/source.cxx | 65 | ||||
-rw-r--r-- | odb/relational/pgsql/source.cxx | 77 | ||||
-rw-r--r-- | odb/relational/processor.cxx | 2 | ||||
-rw-r--r-- | odb/relational/source.hxx | 251 | ||||
-rw-r--r-- | odb/relational/sqlite/source.cxx | 74 |
7 files changed, 398 insertions, 162 deletions
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 4351db9..7190e49 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -538,19 +538,19 @@ namespace relational os << " container_type;"; os << "typedef odb::access::container_traits< container_type > " << - "container_traits;"; + "container_traits_type;"; switch (ck) { case ck_ordered: { - os << "typedef container_traits::index_type index_type;"; + os << "typedef container_traits_type::index_type index_type;"; break; } case ck_map: case ck_multimap: { - os << "typedef container_traits::key_type key_type;"; + os << "typedef container_traits_type::key_type key_type;"; } case ck_set: case ck_multiset: @@ -559,7 +559,7 @@ namespace relational } } - os << "typedef container_traits::value_type value_type;" + os << "typedef container_traits_type::value_type value_type;" << endl; // functions_type @@ -844,7 +844,7 @@ namespace relational // update // - if (!inverse) + if (!(inverse || readonly (member_path_, member_scope_))) os << "static void" << endl << "update (const container_type&," << endl << "const " << db << "::binding& id," << endl @@ -1169,9 +1169,10 @@ namespace relational // update () // - os << "static void" << endl - << "update (database&, const object_type&);" - << endl; + if (!readonly (c)) + os << "static void" << endl + << "update (database&, const object_type&);" + << endl; // erase () // diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx index 103c301..25fac41 100644 --- a/odb/relational/mysql/source.cxx +++ b/odb/relational/mysql/source.cxx @@ -200,9 +200,19 @@ namespace relational if (inverse (mi.m, key_prefix_)) os << "if (sk == statement_select)" << "{"; - else if (id (mi.m) || readonly (mi.m)) - os << "if (sk != statement_update)" - << "{"; + // If the whole class is readonly, then we will never be + // called with sk == statement_update. + // + else if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + os << "if (sk != statement_update)" + << "{"; + } } return true; @@ -213,8 +223,11 @@ namespace relational { if (var_override_.empty ()) { - if (semantics::class_* c = composite (mi.t)) + semantics::class_* c; + + if ((c = composite (mi.t))) { + bool ro (readonly (*c)); column_count_type const& cc (column_count (*c)); os << "n += " << cc.total << "UL"; @@ -223,7 +236,7 @@ namespace relational // insert = total - inverse // update = total - inverse - readonly // - if (cc.inverse != 0 || cc.readonly != 0) + if (cc.inverse != 0 || (!ro && cc.readonly != 0)) { os << " - (" << endl << "sk == statement_select ? 0 : "; @@ -231,7 +244,7 @@ namespace relational if (cc.inverse != 0) os << cc.inverse << "UL" << endl; - if (cc.readonly != 0) + if (!ro && cc.readonly != 0) { if (cc.inverse != 0) os << " + "; @@ -249,7 +262,23 @@ namespace relational else os << "n++;"; - if (inverse (mi.m, key_prefix_) || id (mi.m) || readonly (mi.m)) + bool block (false); + + // The same logic as in pre(). + // + if (inverse (mi.m, key_prefix_)) + block = true; + else if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + block = true; + } + + if (block) os << "}"; else os << endl; @@ -564,10 +593,18 @@ namespace relational os << "// " << name << endl << "//" << endl; - if (id (mi.m) || readonly (mi.m)) - // The block scope is added later, if necessary. - // - os << "if (sk == statement_insert)"; + // If the whole class is readonly, then we will never be + // called with sk == statement_update. + // + if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + os << "if (sk == statement_insert)"; + } } // If this is a wrapped composite value, then we need to @@ -583,7 +620,10 @@ namespace relational } if (composite (mi.t)) + { + os << "{"; traits = "composite_value_traits< " + mi.fq_type () + " >"; + } else { // When handling a pointer, mi.t is the id type of the referenced @@ -655,7 +695,9 @@ namespace relational virtual void post (member_info& mi) { - if (!composite (mi.t)) + if (composite (mi.t)) + os << "}"; + else { // When handling a pointer, mi.t is the id type of the referenced // object. @@ -677,15 +719,11 @@ namespace relational virtual void traverse_composite (member_info& mi) { - // Should be a single statement or a block. - // os << "if (" << traits << "::init (" << endl << "i." << mi.var << "value," << endl << member << "," << endl - << "sk))" - << "{" - << "grew = true;" - << "}"; + << "sk))" << endl + << "grew = true;"; } virtual void diff --git a/odb/relational/oracle/source.cxx b/odb/relational/oracle/source.cxx index dd3fe8b..ad58bb0 100644 --- a/odb/relational/oracle/source.cxx +++ b/odb/relational/oracle/source.cxx @@ -93,9 +93,19 @@ namespace relational if (inverse (mi.m, key_prefix_)) os << "if (sk == statement_select)" << "{"; - else if (id (mi.m) || readonly (mi.m)) - os << "if (sk != statement_update)" - << "{"; + // If the whole class is readonly, then we will never be + // called with sk == statement_update. + // + else if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + os << "if (sk != statement_update)" + << "{"; + } } return true; @@ -106,9 +116,11 @@ namespace relational { if (var_override_.empty ()) { - if (semantics::class_* c = composite (mi.t)) + semantics::class_* c; + if ((c = composite (mi.t))) { + bool ro (readonly (*c)); column_count_type const& cc (column_count (*c)); os << "n += " << cc.total << "UL"; @@ -117,7 +129,7 @@ namespace relational // insert = total - inverse // update = total - inverse - readonly // - if (cc.inverse != 0 || cc.readonly != 0) + if (cc.inverse != 0 || (!ro && cc.readonly != 0)) { os << " - (" << endl << "sk == statement_select ? 0 : "; @@ -125,7 +137,7 @@ namespace relational if (cc.inverse != 0) os << cc.inverse << "UL" << endl; - if (cc.readonly != 0) + if (!ro && cc.readonly != 0) { if (cc.inverse != 0) os << " + "; @@ -143,7 +155,23 @@ namespace relational else os << "n++;"; - if (inverse (mi.m, key_prefix_) || id (mi.m) || readonly (mi.m)) + bool block (false); + + // The same logic as in pre(). + // + if (inverse (mi.m, key_prefix_)) + block = true; + else if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + block = true; + } + + if (block) os << "}"; else os << endl; @@ -313,10 +341,18 @@ namespace relational os << "// " << name << endl << "//" << endl; - if (id (mi.m) || readonly (mi.m)) - // The block scope is added later, if necessary. - // - os << "if (sk == statement_insert)"; + // If the whole class is readonly, then we will never be + // called with sk == statement_update. + // + if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + os << "if (sk == statement_insert)"; + } } // If this is a wrapped composite value, then we need to @@ -332,7 +368,10 @@ namespace relational } if (composite (mi.t)) + { + os << "{"; traits = "composite_value_traits< " + mi.fq_type () + " >"; + } else { // When handling a pointer, mi.t is the id type of the referenced @@ -404,7 +443,9 @@ namespace relational virtual void post (member_info& mi) { - if (!composite (mi.t)) + if (composite (mi.t)) + os << "}"; + else { // When handling a pointer, mi.t is the id type of the referenced // object. diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index c5df9bd..8547df3 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -118,7 +118,8 @@ namespace relational if (inverse (m) && sk_ != statement_select) return false; - if ((id (m) || readonly (m)) && sk_ == statement_update) + if ((id (m) || readonly (member_path_, member_scope_)) && + sk_ == statement_update) return false; if (!first) @@ -166,9 +167,19 @@ namespace relational if (inverse (mi.m, key_prefix_)) os << "if (sk == statement_select)" << "{"; - else if (id (mi.m) || readonly (mi.m)) - os << "if (sk != statement_update)" - << "{"; + // If the whole class is readonly, then we will never be + // called with sk == statement_update. + // + else if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + os << "if (sk != statement_update)" + << "{"; + } } return true; @@ -179,8 +190,11 @@ namespace relational { if (var_override_.empty ()) { - if (semantics::class_* c = composite (mi.t)) + semantics::class_* c; + + if ((c = composite (mi.t))) { + bool ro (readonly (*c)); column_count_type const& cc (column_count (*c)); os << "n += " << cc.total << "UL"; @@ -189,7 +203,7 @@ namespace relational // insert = total - inverse // update = total - inverse - readonly // - if (cc.inverse != 0 || cc.readonly != 0) + if (cc.inverse != 0 || (!ro && cc.readonly != 0)) { os << " - (" << endl << "sk == statement_select ? 0 : "; @@ -197,7 +211,7 @@ namespace relational if (cc.inverse != 0) os << cc.inverse << "UL" << endl; - if (cc.readonly != 0) + if (!ro && cc.readonly != 0) { if (cc.inverse != 0) os << " + "; @@ -215,7 +229,23 @@ namespace relational else os << "n++;"; - if (inverse (mi.m, key_prefix_) || id (mi.m) || readonly (mi.m)) + bool block (false); + + // The same logic as in pre(). + // + if (inverse (mi.m, key_prefix_)) + block = true; + else if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + block = true; + } + + if (block) os << "}"; else os << endl; @@ -469,10 +499,18 @@ namespace relational os << "// " << name << endl << "//" << endl; - if (id (mi.m) || readonly (mi.m)) - // The block scope is added later, if necessary. - // - os << "if (sk == statement_insert)"; + // If the whole class is readonly, then we will never be + // called with sk == statement_update. + // + if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + os << "if (sk == statement_insert)"; + } } // If this is a wrapped composite value, then we need to @@ -488,7 +526,10 @@ namespace relational } if (composite (mi.t)) + { + os << "{"; traits = "composite_value_traits< " + mi.fq_type () + " >"; + } else { // When handling a pointer, mi.t is the id type of the referenced @@ -560,7 +601,9 @@ namespace relational virtual void post (member_info& mi) { - if (!composite (mi.t)) + if (composite (mi.t)) + os << "}"; + else { // When handling a pointer, mi.t is the id type of the referenced // object. @@ -582,15 +625,11 @@ namespace relational virtual void traverse_composite (member_info& mi) { - // Should be a single statement or a block. - // os << "if (" << traits << "::init (" << endl << "i." << mi.var << "value," << endl << member << "," << endl - << "sk))" - << "{" - << "grew = true;" - << "}"; + << "sk))" << endl + << "grew = true;"; } virtual void diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx index 6571d22..d1c3cd8 100644 --- a/odb/relational/processor.cxx +++ b/odb/relational/processor.cxx @@ -122,6 +122,8 @@ namespace relational semantics::type& t (m.type ()); + // Handle wrappers. + // semantics::type* wt (0); semantics::names* wh (0); if (process_wrapper (t)) diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 55f94f5..3ce3676 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -78,7 +78,8 @@ namespace relational if (im != 0 && sk_ != statement_select) return false; - if ((id (m) || readonly (m)) && sk_ == statement_update) + if ((id (m) || readonly (member_path_, member_scope_)) && + sk_ == statement_update) return false; if (!first) @@ -546,6 +547,16 @@ namespace relational os << "// " << c.name () << " base" << endl << "//" << endl; + // If the derived class is readonly, then we will never be + // called with sk == statement_update. + // + bool ro (readonly (c)); + bool check (ro && !readonly (*context::top_object)); + + if (check) + os << "if (sk != statement_update)" + << "{"; + os << (obj ? "object" : "composite_value") << "_traits< " << c.fq_name () << " >::bind (b + n, i, sk);"; @@ -557,7 +568,7 @@ namespace relational // insert = total - inverse // update = total - inverse - id - readonly // - if (cc.inverse != 0 || cc.id != 0 || cc.readonly != 0) + if (cc.inverse != 0 || (!ro && (cc.id != 0 || cc.readonly != 0))) { os << " - (" << endl << "sk == statement_select ? 0 : "; @@ -565,7 +576,7 @@ namespace relational if (cc.inverse != 0) os << cc.inverse << "UL" << endl; - if (cc.id != 0 || cc.readonly != 0) + if (!ro && (cc.id != 0 || cc.readonly != 0)) { if (cc.inverse != 0) os << " + "; @@ -578,8 +589,12 @@ namespace relational os << ")"; } - os << ";" - << endl; + os << ";"; + + if (check) + os << "}"; + else + os << endl; } }; @@ -684,11 +699,25 @@ namespace relational return; os << "// " << c.name () << " base" << endl - << "//" << endl - << "if (" << (obj ? "object" : "composite_value") << "_traits< " << + << "//" << endl; + + // If the derived class is readonly, then we will never be + // called with sk == statement_update. + // + bool check (readonly (c) && !readonly (*context::top_object)); + + if (check) + os << "if (sk != statement_update)" + << "{"; + + os << "if (" << (obj ? "object" : "composite_value") << "_traits< " << c.fq_name () << " >::init (i, o, sk))" << endl - << "grew = true;" - << endl; + << "grew = true;"; + + if (check) + os << "}"; + else + os << endl; } }; @@ -855,8 +884,11 @@ namespace relational if (generate_grow) grow = grow || context::grow (m, vt, "value"); - bool eager_ptr (is_a (m, test_eager_pointer, vt, "value")); - + bool eager_ptr (is_a (member_path_, + member_scope_, + test_eager_pointer, + vt, + "value")); if (!eager_ptr) { if (semantics::class_* cvt = composite_wrapper (vt)) @@ -1684,7 +1716,7 @@ namespace relational if (ck == ck_ordered) os << "fs.ordered (" << (ordered ? "true" : "false") << ");"; - os << "container_traits::persist (c, fs);" + os << "container_traits_type::persist (c, fs);" << "}"; } @@ -1751,12 +1783,12 @@ namespace relational if (ck == ck_ordered) os << "fs.ordered (" << (ordered ? "true" : "false") << ");"; - os << "container_traits::load (c, more, fs);" + os << "container_traits_type::load (c, more, fs);" << "}"; // update // - if (!inverse) + if (!(inverse || readonly (member_path_, member_scope_))) { os << "void " << scope << "::" << endl << "update (const container_type& c," << endl @@ -1790,7 +1822,7 @@ namespace relational if (ck == ck_ordered) os << "fs.ordered (" << (ordered ? "true" : "false") << ");"; - os << "container_traits::update (c, fs);" + os << "container_traits_type::update (c, fs);" << "}"; } @@ -1817,7 +1849,7 @@ namespace relational if (ck == ck_ordered) os << "fs.ordered (" << (ordered ? "true" : "false") << ");"; - os << "container_traits::erase (fs);" + os << "container_traits_type::erase (fs);" << "}"; } } @@ -1982,7 +2014,7 @@ namespace relational } case update_call: { - if (!inverse) + if (!(inverse || readonly (member_path_, member_scope_))) os << traits << "::update (" << endl << obj_name << "," << endl << "idb," << endl @@ -2106,12 +2138,16 @@ namespace relational if (c.file () != unit.file ()) return; + context::top_object = context::cur_object = &c; + if (object (c)) traverse_object (c); else if (view (c)) traverse_view (c); else if (composite (c)) traverse_composite (c); + + context::top_object = context::cur_object = 0; } // @@ -2206,8 +2242,25 @@ namespace relational // // Containers (abstract and concrete). // - bool straight_containers (has_a (c, test_straight_container)); - bool containers (straight_containers || has_a (c, test_container)); + bool containers (has_a (c, test_container)); + bool straight_containers (false); + bool straight_readwrite_containers (false); + + if (containers) + { + containers = true; + size_t scn (has_a (c, test_straight_container)); + + if (scn != 0) + { + straight_containers = true; + + // Inverse containers cannot be marked readonly. + // + straight_readwrite_containers = + scn > has_a (c, test_readonly_container); + } + } if (containers) { @@ -2263,8 +2316,13 @@ namespace relational << "ODB_POTENTIALLY_UNUSED (sk);" << endl << "using namespace " << db << ";" - << endl - << "std::size_t n (0);" + << endl; + + if (readonly (c)) + os << "assert (sk != statement_update);" + << endl; + + os << "std::size_t n (0);" << endl; inherits (c, bind_base_inherits_); @@ -2295,8 +2353,13 @@ namespace relational << "ODB_POTENTIALLY_UNUSED (sk);" << endl << "using namespace " << db << ";" - << endl - << "bool grew (false);" + << endl; + + if (readonly (c)) + os << "assert (sk != statement_update);" + << endl; + + os << "bool grew (false);" << endl; inherits (c, init_image_base_inherits_); @@ -2560,72 +2623,75 @@ namespace relational // update () // - os << "void " << traits << "::" << endl - << "update (database&, const object_type& obj)" - << "{" - << "using namespace " << db << ";" - << endl - << db << "::connection& conn (" << endl - << db << "::transaction::current ().connection ());" - << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find_object<object_type> ());" - << endl; - - if (cc.total != cc.id + cc.inverse + cc.readonly) + if (!readonly (c)) { - // Initialize id image. - // - os << "id_image_type& i (sts.id_image ());" - << "init (i, obj." << id->name () << ");" + os << "void " << traits << "::" << endl + << "update (database&, const object_type& obj)" + << "{" + << "using namespace " << db << ";" + << endl + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" + << "object_statements< object_type >& sts (" << endl + << "conn.statement_cache ().find_object<object_type> ());" << endl; - os << "binding& idb (sts.id_image_binding ());" - << "if (i.version != sts.id_image_version () || idb.version == 0)" - << "{" - << "bind (idb.bind, i);" - << "sts.id_image_version (i.version);" - << "idb.version++;" - << "}"; + if (cc.total != cc.id + cc.inverse + cc.readonly) + { + // Initialize id image. + // + os << "id_image_type& i (sts.id_image ());" + << "init (i, obj." << id->name () << ");" + << endl; - // Initialize data image. - // - os << "image_type& im (sts.image ());" - << "binding& imb (sts.update_image_binding ());" - << endl - << "if (init (im, obj, statement_update))" << endl - << "im.version++;" - << endl - << "if (im.version != sts.update_image_version () || " << - "imb.version == 0)" - << "{" - << "bind (imb.bind, im, statement_update);" - << "sts.update_image_version (im.version);" - << "imb.version++;" - << "}" - << "sts.update_statement ().execute ();"; - } - else - { - // We don't have any columns to update. Note that we still have - // to make sure this object exists in the database. For that we - // will run the SELECT query using the find_() function. - // - os << "if (!find_ (sts, obj." << id->name () << "))" << endl - << "throw object_not_persistent ();"; + os << "binding& idb (sts.id_image_binding ());" + << "if (i.version != sts.id_image_version () || idb.version == 0)" + << "{" + << "bind (idb.bind, i);" + << "sts.id_image_version (i.version);" + << "idb.version++;" + << "}"; - if (straight_containers) - os << endl - << "binding& idb (sts.id_image_binding ());"; - } + // Initialize data image. + // + os << "image_type& im (sts.image ());" + << "binding& imb (sts.update_image_binding ());" + << endl + << "if (init (im, obj, statement_update))" << endl + << "im.version++;" + << endl + << "if (im.version != sts.update_image_version () || " << + "imb.version == 0)" + << "{" + << "bind (imb.bind, im, statement_update);" + << "sts.update_image_version (im.version);" + << "imb.version++;" + << "}" + << "sts.update_statement ().execute ();"; + } + else + { + // We don't have any columns to update. Note that we still have + // to make sure this object exists in the database. For that we + // will run the SELECT query using the find_() function. + // + os << "if (!find_ (sts, obj." << id->name () << "))" << endl + << "throw object_not_persistent ();"; - if (straight_containers) - { - os << endl; - instance<container_calls> t (container_calls::update_call); - t->traverse (c); - } + if (straight_readwrite_containers) + os << endl + << "binding& idb (sts.id_image_binding ());"; + } - os << "}"; + if (straight_readwrite_containers) + { + os << endl; + instance<container_calls> t (container_calls::update_call); + t->traverse (c); + } + + os << "}"; + } // erase () // @@ -3861,8 +3927,13 @@ namespace relational << "ODB_POTENTIALLY_UNUSED (sk);" << endl << "using namespace " << db << ";" - << endl - << "std::size_t n (0);" + << endl; + + if (readonly (c)) + os << "assert (sk != statement_update);" + << endl; + + os << "std::size_t n (0);" << "ODB_POTENTIALLY_UNUSED (n);" << endl; @@ -3882,8 +3953,13 @@ namespace relational << "ODB_POTENTIALLY_UNUSED (sk);" << endl << "using namespace " << db << ";" - << endl - << "bool grew (false);" + << endl; + + if (readonly (c)) + os << "assert (sk != statement_update);" + << endl; + + os << "bool grew (false);" << endl; inherits (c, init_image_base_inherits_); @@ -3950,7 +4026,8 @@ namespace relational { extra_pre (); - os << "#include <cstring> // std::memcpy" << endl + os << "#include <cassert>" << endl + << "#include <cstring> // std::memcpy" << endl << endl; os << "#include <odb/cache-traits.hxx>" << endl; diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx index 89173dd..92c0941 100644 --- a/odb/relational/sqlite/source.cxx +++ b/odb/relational/sqlite/source.cxx @@ -51,9 +51,19 @@ namespace relational if (inverse (mi.m, key_prefix_)) os << "if (sk == statement_select)" << "{"; - else if (id (mi.m) || readonly (mi.m)) - os << "if (sk != statement_update)" - << "{"; + // If the whole class is readonly, then we will never be + // called with sk == statement_update. + // + else if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + os << "if (sk != statement_update)" + << "{"; + } } return true; @@ -64,8 +74,11 @@ namespace relational { if (var_override_.empty ()) { - if (semantics::class_* c = composite (mi.t)) + semantics::class_* c; + + if ((c = composite (mi.t))) { + bool ro (readonly (*c)); column_count_type const& cc (column_count (*c)); os << "n += " << cc.total << "UL"; @@ -74,7 +87,7 @@ namespace relational // insert = total - inverse // update = total - inverse - readonly // - if (cc.inverse != 0 || cc.readonly != 0) + if (cc.inverse != 0 || (!ro && cc.readonly != 0)) { os << " - (" << endl << "sk == statement_select ? 0 : "; @@ -82,7 +95,7 @@ namespace relational if (cc.inverse != 0) os << cc.inverse << "UL" << endl; - if (cc.readonly != 0) + if (!ro && cc.readonly != 0) { if (cc.inverse != 0) os << " + "; @@ -100,7 +113,23 @@ namespace relational else os << "n++;"; - if (inverse (mi.m, key_prefix_) || id (mi.m) || readonly (mi.m)) + bool block (false); + + // The same logic as in pre(). + // + if (inverse (mi.m, key_prefix_)) + block = true; + else if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + block = true; + } + + if (block) os << "}"; else os << endl; @@ -272,10 +301,18 @@ namespace relational os << "// " << name << endl << "//" << endl; - if (id (mi.m) || readonly (mi.m)) - // The block scope is added later, if necessary. - // - os << "if (sk == statement_insert)"; + // If the whole class is readonly, then we will never be + // called with sk == statement_update. + // + if (!readonly (*context::top_object)) + { + semantics::class_* c; + + if (id (mi.m) || + readonly (mi.m) || + ((c = composite (mi.t)) && readonly (*c))) + os << "if (sk == statement_insert)"; + } } // If this is a wrapped composite value, then we need to @@ -291,7 +328,10 @@ namespace relational } if (composite (mi.t)) + { + os << "{"; traits = "composite_value_traits< " + mi.fq_type () + " >"; + } else { // When handling a pointer, mi.t is the id type of the referenced @@ -363,7 +403,9 @@ namespace relational virtual void post (member_info& mi) { - if (!composite (mi.t)) + if (composite (mi.t)) + os << "}"; + else { // When handling a pointer, mi.t is the id type of the referenced // object. @@ -384,15 +426,11 @@ namespace relational virtual void traverse_composite (member_info& mi) { - // Should be a single statement or a block. - // os << "if (" << traits << "::init (" << endl << "i." << mi.var << "value," << endl << member << "," << endl - << "sk))" - << "{" - << "grew = true;" - << "}"; + << "sk))" << endl + << "grew = true;"; } virtual void |