From 2fe7a723c0b98d23531a76d9c1a451e3a57bf0c5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 17 Nov 2010 18:05:06 +0200 Subject: Add support for unidirectional object relationships New test: common/relationship. --- odb/mysql/common.cxx | 227 +++++++++++++++++++----------------- odb/mysql/common.hxx | 17 ++- odb/mysql/context.cxx | 41 ++++--- odb/mysql/context.hxx | 3 +- odb/mysql/header.cxx | 13 ++- odb/mysql/schema.cxx | 24 +++- odb/mysql/source.cxx | 315 ++++++++++++++++++++++++++++++++------------------ 7 files changed, 393 insertions(+), 247 deletions(-) (limited to 'odb/mysql') diff --git a/odb/mysql/common.cxx b/odb/mysql/common.cxx index 17cae9e..d7e6187 100644 --- a/odb/mysql/common.cxx +++ b/odb/mysql/common.cxx @@ -33,130 +33,149 @@ namespace mysql semantics::type& t (type_override_ != 0 ? *type_override_ : m.type ()); - member_info mi (m, t, var, fq_type_override_); - if (comp_value (t)) { + member_info mi (m, t, var, fq_type_override_); pre (mi); traverse_composite (mi); + post (mi); } else if (container (t)) { + member_info mi (m, t, var, fq_type_override_); pre (mi); traverse_container (mi); + post (mi); } else { sql_type const& st (db_type (m, key_prefix_)); - mi.st = &st; - pre (mi); - switch (st.type) + if (semantics::class_* c = object_pointer (m, key_prefix_)) { - // Integral types. - // - case sql_type::TINYINT: - case sql_type::SMALLINT: - case sql_type::MEDIUMINT: - case sql_type::INT: - case sql_type::BIGINT: - { - traverse_integer (mi); - break; - } - - // Float types. - // - case sql_type::FLOAT: - case sql_type::DOUBLE: - { - traverse_float (mi); - break; - } - case sql_type::DECIMAL: - { - traverse_decimal (mi); - break; - } - - // Data-time types. + member_info mi (m, id_member (*c).type (), var, fq_type_override_); + mi.st = &st; + pre (mi); + traverse_object_pointer (mi); + post (mi); + } + else + { + member_info mi (m, t, var, fq_type_override_); + mi.st = &st; + pre (mi); + traverse_simple (mi); + post (mi); + } + } + } + + void member_base:: + traverse_simple (member_info& mi) + { + switch (mi.st->type) + { + // Integral types. + // + case sql_type::TINYINT: + case sql_type::SMALLINT: + case sql_type::MEDIUMINT: + case sql_type::INT: + case sql_type::BIGINT: + { + traverse_integer (mi); + break; + } + + // Float types. + // + case sql_type::FLOAT: + case sql_type::DOUBLE: + { + traverse_float (mi); + break; + } + case sql_type::DECIMAL: + { + traverse_decimal (mi); + break; + } + + // Data-time types. + // + case sql_type::DATE: + case sql_type::TIME: + case sql_type::DATETIME: + case sql_type::TIMESTAMP: + case sql_type::YEAR: + { + traverse_date_time (mi); + break; + } + + // String and binary types. + // + case sql_type::CHAR: + case sql_type::VARCHAR: + case sql_type::TINYTEXT: + case sql_type::TEXT: + case sql_type::MEDIUMTEXT: + case sql_type::LONGTEXT: + { + // For string types the limit is in characters rather + // than in bytes. The fixed-length pre-allocated buffer + // optimization can only be used for 1-byte encodings. + // To support this we will need the character encoding + // in sql_type. // - case sql_type::DATE: - case sql_type::TIME: - case sql_type::DATETIME: - case sql_type::TIMESTAMP: - case sql_type::YEAR: - { - traverse_date_time (mi); - break; - } - - // String and binary types. + traverse_long_string (mi); + break; + } + case sql_type::BINARY: + case sql_type::TINYBLOB: + { + // BINARY's range is always 255 or less from MySQL 5.0.3. + // TINYBLOB can only store up to 255 bytes. // - case sql_type::CHAR: - case sql_type::VARCHAR: - case sql_type::TINYTEXT: - case sql_type::TEXT: - case sql_type::MEDIUMTEXT: - case sql_type::LONGTEXT: - { - // For string types the limit is in characters rather - // than in bytes. The fixed-length pre-allocated buffer - // optimization can only be used for 1-byte encodings. - // To support this we will need the character encoding - // in sql_type. - // - traverse_long_string (mi); - break; - } - case sql_type::BINARY: - case sql_type::TINYBLOB: - { - // BINARY's range is always 255 or less from MySQL 5.0.3. - // TINYBLOB can only store up to 255 bytes. - // + traverse_short_string (mi); + break; + } + case sql_type::VARBINARY: + case sql_type::BLOB: + case sql_type::MEDIUMBLOB: + case sql_type::LONGBLOB: + { + if (mi.st->range && mi.st->range_value <= 255) traverse_short_string (mi); - break; - } - case sql_type::VARBINARY: - case sql_type::BLOB: - case sql_type::MEDIUMBLOB: - case sql_type::LONGBLOB: - { - if (st.range && st.range_value <= 255) - traverse_short_string (mi); - else - traverse_long_string (mi); - - break; - } - - // Other types. - // - case sql_type::BIT: - { - traverse_bit (mi); - break; - } - case sql_type::ENUM: - { - traverse_enum (mi); - break; - } - case sql_type::SET: - { - traverse_set (mi); - break; - } - case sql_type::invalid: - { - assert (false); - break; - } + else + traverse_long_string (mi); + + break; } - } - post (mi); + // Other types. + // + case sql_type::BIT: + { + traverse_bit (mi); + break; + } + case sql_type::ENUM: + { + traverse_enum (mi); + break; + } + case sql_type::SET: + { + traverse_set (mi); + break; + } + case sql_type::invalid: + { + assert (false); + break; + } + } } // diff --git a/odb/mysql/common.hxx b/odb/mysql/common.hxx index 31c6962..fb1f2a3 100644 --- a/odb/mysql/common.hxx +++ b/odb/mysql/common.hxx @@ -46,7 +46,13 @@ namespace mysql string fq_type () const { - return fq_type_.empty () ? t.fq_name (m.belongs ().hint ()) : fq_type_; + // Use the original type from 'm' instead of 't' since the hint + // may be invalid for a different type. Plus, if a type is + // overriden, then the fq_type must be as well. + // + return fq_type_.empty () + ? m.type ().fq_name (m.belongs ().hint ()) + : fq_type_; } string const& fq_type_; @@ -81,6 +87,15 @@ namespace mysql } virtual void + traverse_object_pointer (member_info& mi) + { + traverse_simple (mi); + } + + virtual void + traverse_simple (member_info&); + + virtual void traverse_integer (member_info&) { } diff --git a/odb/mysql/context.cxx b/odb/mysql/context.cxx index 4803da2..de3eed0 100644 --- a/odb/mysql/context.cxx +++ b/odb/mysql/context.cxx @@ -26,28 +26,28 @@ namespace mysql type_map_entry type_map[] = { - {"bool", "TINYINT(1) NOT NULL", 0}, + {"bool", "TINYINT(1)", 0}, - {"char", "TINYINT NOT NULL", 0}, - {"signed char", "TINYINT NOT NULL", 0}, - {"unsigned char", "TINYINT UNSIGNED NOT NULL", 0}, + {"char", "TINYINT", 0}, + {"signed char", "TINYINT", 0}, + {"unsigned char", "TINYINT UNSIGNED", 0}, - {"short int", "SMALLINT NOT NULL", 0}, - {"short unsigned int", "SMALLINT UNSIGNED NOT NULL", 0}, + {"short int", "SMALLINT", 0}, + {"short unsigned int", "SMALLINT UNSIGNED", 0}, - {"int", "INT NOT NULL", 0}, - {"unsigned int", "INT UNSIGNED NOT NULL", 0}, + {"int", "INT", 0}, + {"unsigned int", "INT UNSIGNED", 0}, - {"long int", "BIGINT NOT NULL", 0}, - {"long unsigned int", "BIGINT UNSIGNED NOT NULL", 0}, + {"long int", "BIGINT", 0}, + {"long unsigned int", "BIGINT UNSIGNED", 0}, - {"long long int", "BIGINT NOT NULL", 0}, - {"long long unsigned int", "BIGINT UNSIGNED NOT NULL", 0}, + {"long long int", "BIGINT", 0}, + {"long long unsigned int", "BIGINT UNSIGNED", 0}, - {"float", "FLOAT NOT NULL", 0}, - {"double", "DOUBLE NOT NULL", 0}, + {"float", "FLOAT", 0}, + {"double", "DOUBLE", 0}, - {"::std::string", "TEXT NOT NULL", "VARCHAR(255) NOT NULL"} + {"::std::string", "TEXT", "VARCHAR (255)"} }; } @@ -145,8 +145,10 @@ namespace mysql virtual void traverse_composite (member_info& mi) { + // Reset any overrides. + // if (!hg_.r_) - hg_.r_ = hg_.dispatch (dynamic_cast (mi.t)); + hg_.r_ = context::grow (dynamic_cast (mi.t)); } virtual void @@ -216,11 +218,12 @@ namespace mysql string context::data:: column_type_impl (semantics::type& t, string const& type, - semantics::context* ctx) const + semantics::context& ctx, + column_type_flags f) const { - string r (::context::data::column_type_impl (t, type, ctx)); + string r (::context::data::column_type_impl (t, type, ctx, f)); - if (!r.empty () && ctx != 0 && ctx->count ("auto")) + if (!r.empty () && ctx.count ("auto") && (f & ctf_object_id_ref) == 0) r += " AUTO_INCREMENT"; return r; diff --git a/odb/mysql/context.hxx b/odb/mysql/context.hxx index 9a6beec..4ac36ca 100644 --- a/odb/mysql/context.hxx +++ b/odb/mysql/context.hxx @@ -105,7 +105,8 @@ namespace mysql virtual string column_type_impl (semantics::type&, string const& type, - semantics::context*) const; + semantics::context&, + column_type_flags) const; }; private: diff --git a/odb/mysql/header.cxx b/odb/mysql/header.cxx index 79b8d67..130a2ba 100644 --- a/odb/mysql/header.cxx +++ b/odb/mysql/header.cxx @@ -525,24 +525,25 @@ namespace mysql { case ck_ordered: { - os << "init (index_type&, value_type&, const data_image_type&);"; + os << "init (index_type&, value_type&, "; break; } case ck_map: case ck_multimap: { - os << "init (key_type&, value_type&, const data_image_type&);"; + os << "init (key_type&, value_type&, "; break; } case ck_set: case ck_multiset: { - os << "init (value_type&, const data_image_type&);"; + os << "init (value_type&, "; break; } } - os << endl; + os << "const data_image_type&, database&);" + << endl; // insert_one // @@ -801,7 +802,7 @@ namespace mysql // init (object, image) // os << "static void" << endl - << "init (object_type&, const image_type&);" + << "init (object_type&, const image_type&, database&);" << endl; // persist () @@ -895,7 +896,7 @@ namespace mysql // init (object, image) // os << "static void" << endl - << "init (value_type&, const image_type&);" + << "init (value_type&, const image_type&, database&);" << endl; os << "};"; diff --git a/odb/mysql/schema.cxx b/odb/mysql/schema.cxx index 1dfeb1f..0c004ad 100644 --- a/odb/mysql/schema.cxx +++ b/odb/mysql/schema.cxx @@ -18,8 +18,8 @@ namespace mysql struct object_columns: object_columns_base, context { - object_columns (context& c) - : object_columns_base (c), context (c) + object_columns (context& c, string const& prefix = string ()) + : object_columns_base (c), context (c), prefix_ (prefix) { } @@ -29,11 +29,21 @@ namespace mysql if (!first) os << "," << endl; - os << " `" << name << "` " << column_type (m); + os << " `" << name << "` " << column_type (m, prefix_); if (m.count ("id")) os << " PRIMARY KEY"; + + using semantics::class_; + if (class_* c = object_pointer (m, prefix_)) + { + os << " REFERENCES `" << table_name (*c) << "` (`" << + column_name (id_member (*c)) << "`)"; + } } + + private: + string prefix_; }; struct member_create: object_members_base, context @@ -67,7 +77,7 @@ namespace mysql // object_id (simple value) // string id_name (column_name (m, "id", "object_id")); - os << " `" << id_name << "` " << column_type (id_member_); + os << " `" << id_name << "` " << column_type (id_member_, "ref"); // index (simple value) // @@ -95,8 +105,9 @@ namespace mysql } else { + object_columns oc (*this, "key"); string const& name (column_name (m, "key", "key")); - os << " `" << name << "` " << column_type (m, "key"); + oc.column (m, name, true); } } @@ -112,8 +123,9 @@ namespace mysql } else { + object_columns oc (*this, "value"); string const& name (column_name (m, "value", "value")); - os << " `" << name << "` " << column_type (m, "value"); + oc.column (m, name, true); } } diff --git a/odb/mysql/source.cxx b/odb/mysql/source.cxx index 2f65de6..8351ad5 100644 --- a/odb/mysql/source.cxx +++ b/odb/mysql/source.cxx @@ -516,19 +516,6 @@ namespace mysql { if (container (mi.t)) return; - else if (comp_value (mi.t)) - traits = "composite_value_traits< " + mi.fq_type () + " >"; - else - { - type = mi.fq_type (); - image_type = member_image_type_.image_type (mi.m); - db_type = member_database_type_.database_type (mi.m); - - traits = "mysql::value_traits< " - + type + ", " - + image_type + ", " - + db_type + " >"; - } if (!member_override_.empty ()) member = member_override_; @@ -540,6 +527,65 @@ namespace mysql os << "// " << name << endl << "//" << endl; } + + if (comp_value (mi.t)) + traits = "composite_value_traits< " + mi.fq_type () + " >"; + else + { + if (semantics::class_* c = object_pointer (mi.m, key_prefix_)) + { + type = "obj_traits::id_type"; + image_type = member_image_type_.image_type (mi.m); + db_type = member_database_type_.database_type (mi.m); + + // Handle NULL pointers and extract the id. + // + os << "{" + << "typedef object_traits< " << c->fq_name () << + " > obj_traits;" + << "typedef pointer_traits< " << mi.fq_type () << + " > ptr_traits;" + << endl + << "bool is_null (ptr_traits::null_ptr (" << member << "));" + << "if (!is_null)" + << "{" + << "const " << type << "& id (" << endl + << "obj_traits::id (ptr_traits::get_ref (" << member << ")));" + << endl; + + member = "id"; + } + else + { + type = mi.fq_type (); + image_type = member_image_type_.image_type (mi.m); + db_type = member_database_type_.database_type (mi.m); + + os << "{" + << "bool is_null;"; + } + + traits = "mysql::value_traits<\n " + + type + ",\n " + + image_type + ",\n " + + db_type + " >"; + } + } + + virtual void + post (member_info& mi) + { + if (container (mi.t)) + return; + + if (!comp_value (mi.t)) + { + if (object_pointer (mi.m, key_prefix_)) + os << "}"; + + os << "i." << mi.var << "null = is_null;" + << "}"; + } } virtual void @@ -555,23 +601,15 @@ namespace mysql virtual void traverse_integer (member_info& mi) { - os << "{" - << "bool is_null;" - << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "null = is_null;" - << "}"; + os << traits << "::set_image (" << endl + << "i." << mi.var << "value, is_null, " << member << ");"; } virtual void traverse_float (member_info& mi) { - os << "{" - << "bool is_null;" - << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "null = is_null;" - << "}"; + os << traits << "::set_image (" << endl + << "i." << mi.var << "value, is_null, " << member << ");"; } virtual void @@ -579,9 +617,7 @@ namespace mysql { // @@ Optimization: can remove growth check if buffer is fixed. // - os << "{" - << "bool is_null;" - << "std::size_t size;" + os << "std::size_t size;" << "std::size_t cap (i." << mi.var << "value.capacity ());" << traits << "::set_image (" << endl << "i." << mi.var << "value," << endl @@ -589,20 +625,14 @@ namespace mysql << "is_null," << endl << member << ");" << "i." << mi.var << "size = static_cast (size);" - << "i." << mi.var << "null = is_null;" - << "grew = grew || (cap != i." << mi.var << "value.capacity ());" - << "}"; + << "grew = grew || (cap != i." << mi.var << "value.capacity ());"; } virtual void traverse_date_time (member_info& mi) { - os << "{" - << "bool is_null;" - << traits << "::set_image (" << endl - << "i." << mi.var << "value, is_null, " << member << ");" - << "i." << mi.var << "null = is_null;" - << "}"; + os << traits << "::set_image (" << endl + << "i." << mi.var << "value, is_null, " << member << ");"; } virtual void @@ -610,9 +640,7 @@ namespace mysql { // @@ Optimization: can remove growth check if buffer is fixed. // - os << "{" - << "bool is_null;" - << "std::size_t size;" + os << "std::size_t size;" << "std::size_t cap (i." << mi.var << "value.capacity ());" << traits << "::set_image (" << endl << "i." << mi.var << "value," << endl @@ -620,17 +648,13 @@ namespace mysql << "is_null," << endl << member << ");" << "i." << mi.var << "size = static_cast (size);" - << "i." << mi.var << "null = is_null;" - << "grew = grew || (cap != i." << mi.var << "value.capacity ());" - << "}"; + << "grew = grew || (cap != i." << mi.var << "value.capacity ());"; } virtual void traverse_long_string (member_info& mi) { - os << "{" - << "bool is_null;" - << "std::size_t size;" + os << "std::size_t size;" << "std::size_t cap (i." << mi.var << "value.capacity ());" << traits << "::set_image (" << endl << "i." << mi.var << "value," << endl @@ -638,9 +662,7 @@ namespace mysql << "is_null," << endl << member << ");" << "i." << mi.var << "size = static_cast (size);" - << "i." << mi.var << "null = is_null;" - << "grew = grew || (cap != i." << mi.var << "value.capacity ());" - << "}"; + << "grew = grew || (cap != i." << mi.var << "value.capacity ());"; } virtual void @@ -648,18 +670,14 @@ namespace mysql { // Represented as a BLOB. // - os << "{" - << "bool is_null;" - << "std::size_t size;" + os << "std::size_t size;" << traits << "::set_image (" << endl << "i." << mi.var << "value," << endl << "sizeof (i." << mi.var << "value)," << endl << "size," << endl << "is_null," << endl << member << ");" - << "i." << mi.var << "size = static_cast (size);" - << "i." << mi.var << "null = is_null;" - << "}"; + << "i." << mi.var << "size = static_cast (size);"; } virtual void @@ -667,9 +685,7 @@ namespace mysql { // Represented as a string. // - os << "{" - << "bool is_null;" - << "std::size_t size;" + os << "std::size_t size;" << "std::size_t cap (i." << mi.var << "value.capacity ());" << traits << "::set_image (" << endl << "i." << mi.var << "value," << endl @@ -677,9 +693,7 @@ namespace mysql << "is_null," << endl << member << ");" << "i." << mi.var << "size = static_cast (size);" - << "i." << mi.var << "null = is_null;" - << "grew = grew || (cap != i." << mi.var << "value.capacity ());" - << "}"; + << "grew = grew || (cap != i." << mi.var << "value.capacity ());"; } virtual void @@ -687,9 +701,7 @@ namespace mysql { // Represented as a string. // - os << "{" - << "bool is_null;" - << "std::size_t size;" + os << "std::size_t size;" << "std::size_t cap (i." << mi.var << "value.capacity ());" << traits << "::set_image (" << endl << "i." << mi.var << "value," << endl @@ -697,9 +709,7 @@ namespace mysql << "is_null," << endl << member << ");" << "i." << mi.var << "size = static_cast (size);" - << "i." << mi.var << "null = is_null;" - << "grew = grew || (cap != i." << mi.var << "value.capacity ());" - << "}"; + << "grew = grew || (cap != i." << mi.var << "value.capacity ());"; } private: @@ -766,19 +776,6 @@ namespace mysql { if (container (mi.t)) return; - else if (comp_value (mi.t)) - traits = "composite_value_traits< " + mi.fq_type () + " >"; - else - { - type = mi.fq_type (); - image_type = member_image_type_.image_type (mi.m); - db_type = member_database_type_.database_type (mi.m); - - traits = "mysql::value_traits< " - + type + ", " - + image_type + ", " - + db_type + " >"; - } if (!member_override_.empty ()) member = member_override_; @@ -790,13 +787,75 @@ namespace mysql os << "// " << name << endl << "//" << endl; } + + if (comp_value (mi.t)) + traits = "composite_value_traits< " + mi.fq_type () + " >"; + else + { + if (semantics::class_* c = object_pointer (mi.m, key_prefix_)) + { + type = "obj_traits::id_type"; + image_type = member_image_type_.image_type (mi.m); + db_type = member_database_type_.database_type (mi.m); + + // Handle NULL pointers and extract the id. + // + os << "{" + << "typedef object_traits< " << c->fq_name () << + " > obj_traits;" + << "typedef pointer_traits< " << mi.fq_type () << + " > ptr_traits;" + << endl + << "if (i." << mi.var << "null)" << endl + << member << " = ptr_traits::pointer_type ();" + << "else" + << "{" + << type << " id;"; + + member = "id"; + } + else + { + type = mi.fq_type (); + image_type = member_image_type_.image_type (mi.m); + db_type = member_database_type_.database_type (mi.m); + } + + traits = "mysql::value_traits<\n " + + type + ",\n " + + image_type + ",\n " + + db_type + " >"; + } + } + + virtual void + post (member_info& mi) + { + if (container (mi.t)) + return; + + if (!comp_value (mi.t) && object_pointer (mi.m, key_prefix_)) + { + member = member_override_.empty () + ? "o." + mi.m.name () + : member_override_; + + os << "// If a compiler error points to the line below, then" << endl + << "// it most likely means that a pointer used in a member" << endl + << "// cannot be initialized from an object pointer." << endl + << "//" << endl + << member << " = ptr_traits::pointer_type (" << endl + << "db.load< obj_traits::object_type > (id));" + << "}" + << "}"; + } } virtual void traverse_composite (member_info& mi) { os << traits << "::init (" << member << ", i." << - mi.var << "value);" + mi.var << "value, db);" << endl; } @@ -924,7 +983,8 @@ namespace mysql { os << "// " << c.name () << " base" << endl << "//" << endl - << "composite_value_traits< " << c.fq_name () << " >::init (o, i);" + << "composite_value_traits< " << c.fq_name () << + " >::init (o, i, db);" << endl; } }; @@ -1232,8 +1292,10 @@ namespace mysql size_t index (0); os << "bool " << scope << "::" << endl - << "grow (data_image_type&" << (grow ? " i" : "") << ", my_bool* e)" + << "grow (data_image_type& i, my_bool* e)" << "{" + << "ODB_POTENTIALLY_UNUSED (i);" + << endl << "bool r (false);" << endl; @@ -1339,8 +1401,11 @@ namespace mysql { case ck_ordered: { - os << "init (index_type& j, value_type& v, const data_image_type& i)" + os << "init (index_type& j, value_type& v, " << + "const data_image_type& i, database& db)" << "{" + << "ODB_POTENTIALLY_UNUSED (db);" + << endl << "// index" << endl << "//" << endl; @@ -1353,8 +1418,11 @@ namespace mysql case ck_map: case ck_multimap: { - os << "init (key_type& k, value_type& v, const data_image_type& i)" + os << "init (key_type& k, value_type& v, " << + "const data_image_type& i, database& db)" << "{" + << "ODB_POTENTIALLY_UNUSED (db);" + << endl << "// key" << endl << "//" << endl; @@ -1366,8 +1434,11 @@ namespace mysql case ck_set: case ck_multiset: { - os << "init (value_type& v, const data_image_type& i)" - << "{"; + os << "init (value_type& v, const data_image_type& i, " << + "database& db)" + << "{" + << "ODB_POTENTIALLY_UNUSED (db);" + << endl; break; } } @@ -1375,6 +1446,9 @@ namespace mysql os << "// value" << endl << "//" << endl; { + // If the value is an object pointer, pass the id type as a + // type override. + // init_value_member im ( *this, "value_", "v", vt, "value_type", "value"); im.traverse (m); @@ -1485,19 +1559,19 @@ namespace mysql { case ck_ordered: { - os << "init (i, v, di);"; + os << "init (i, v, di, sts.connection ().database ());"; break; } case ck_map: case ck_multimap: { - os << "init (k, v, di);"; + os << "init (k, v, di, sts.connection ().database ());"; break; } case ck_set: case ck_multiset: { - os << "init (v, di);"; + os << "init (v, di, sts.connection ().database ());"; break; } } @@ -1514,9 +1588,9 @@ namespace mysql << "{" << "if (grow (di, sts.data_image_error ()))" << "{" - << "binding& db (sts.data_image_binding ());" - << "bind (db.bind, 0, di);" - << "db.version++;" + << "binding& b (sts.data_image_binding ());" + << "bind (b.bind, 0, di);" + << "b.version++;" << "st.refetch ();" << "}" << "}"; @@ -1589,8 +1663,15 @@ namespace mysql << "cb.version++;" << "}" << "select_statement& st (sts.select_all_statement ());" - << "st.execute ();" - << "select_statement::result r (st.fetch ());"; + << "st.execute ();"; + + // If we are loading eager object pointers, cache the result + // since we will be loading other objects. + // + if (is_a (m, eager_pointer, vt, "value") || has_a (vt, eager_pointer)) + os << "st.cache ();"; + + os << "select_statement::result r (st.fetch ());"; if (grow) os << endl @@ -1971,8 +2052,10 @@ namespace mysql // grow () // os << "bool " << traits << "::" << endl - << "grow (image_type&" << (grow ? " i" : "") << ", my_bool* e)" + << "grow (image_type& i, my_bool* e)" << "{" + << "ODB_POTENTIALLY_UNUSED (i);" + << endl << "bool r (false);" << endl; @@ -2023,8 +2106,10 @@ namespace mysql // init (object, image) // os << "void " << traits << "::" << endl - << "init (object_type& o, const image_type& i)" - << "{"; + << "init (object_type& o, const image_type& i, database& db)" + << "{" + << "ODB_POTENTIALLY_UNUSED (db);" + << endl; inherits (c, init_value_base_inherits_); names (c, init_value_member_names_); @@ -2163,7 +2248,7 @@ namespace mysql { os << traits << "::pointer_type" << endl << traits << "::" << endl - << "find (database&, const id_type& id)" + << "find (database& db, const id_type& id)" << "{" << "using namespace mysql;" << endl @@ -2178,7 +2263,7 @@ namespace mysql "pointer_type >::create ());" << "pointer_traits< pointer_type >::guard_type g (p);" << "object_type& obj (pointer_traits< pointer_type >::get_ref (p));" - << "init (obj, sts.image ());"; + << "init (obj, sts.image (), db);"; if (containers) { @@ -2197,7 +2282,7 @@ namespace mysql } os << "bool " << traits << "::" << endl - << "find (database&, const id_type& id, object_type& obj)" + << "find (database& db, const id_type& id, object_type& obj)" << "{" << "using namespace mysql;" << endl @@ -2208,7 +2293,7 @@ namespace mysql << "bool grew (false);" << "if (find (sts, id, grew))" << "{" - << "init (obj, sts.image ());"; + << "init (obj, sts.image (), db);"; if (containers) { @@ -2303,7 +2388,6 @@ namespace mysql traverse_value (type& c) { bool columns (column_count (c) != 0); - bool grow (columns && context::grow (c)); string const& type (c.fq_name ()); string traits ("access::composite_value_traits< " + type + " >"); @@ -2315,9 +2399,10 @@ namespace mysql // grow () // os << "bool " << traits << "::" << endl - << "grow (image_type&" << (grow ? " i" : "") << ", " << - "my_bool*" << (columns ? " e" : "") << ")" + << "grow (image_type& i, my_bool*" << (columns ? " e" : "") << ")" << "{" + << "ODB_POTENTIALLY_UNUSED (i);" + << endl << "bool r (false);" << endl; @@ -2360,8 +2445,11 @@ namespace mysql // os << "void " << traits << "::" << endl << "init (value_type&" << (columns ? " o" : "") << ", " << - "const image_type&" << (columns ? " i" : "") << ")" - << "{"; + "const image_type&" << (columns ? " i" : "") << ", " << + "database& db)" + << "{" + << "ODB_POTENTIALLY_UNUSED (db);" + << endl; inherits (c, init_value_base_inherits_); names (c, init_value_member_names_); @@ -2426,9 +2514,16 @@ namespace mysql << "#include " << endl; if (ctx.options.generate_query ()) - ctx.os << "#include " << endl - << endl - << "#include " << endl; + ctx.os << "#include " << endl; + + ctx.os << endl; + + // Details includes. + // + ctx.os << "#include " << endl; + + if (ctx.options.generate_query ()) + ctx.os << "#include " << endl; ctx.os << endl; -- cgit v1.1