summaryrefslogtreecommitdiff
path: root/odb/mysql/source.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-11-06 18:05:19 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-11-06 18:05:19 +0200
commitce696c26d2c9dd5a5813fd865082ab19ac49bcfa (patch)
treec44331b2a6e6fa1d9d518ddff63e711ce5d308c4 /odb/mysql/source.cxx
parent727a83dc82fa094aa91630d165d230a9a2dabe60 (diff)
Add support for container persistence
Diffstat (limited to 'odb/mysql/source.cxx')
-rw-r--r--odb/mysql/source.cxx1558
1 files changed, 1311 insertions, 247 deletions
diff --git a/odb/mysql/source.cxx b/odb/mysql/source.cxx
index d572560..29495df 100644
--- a/odb/mysql/source.cxx
+++ b/odb/mysql/source.cxx
@@ -18,21 +18,33 @@ namespace mysql
{
struct object_columns: object_columns_base, context
{
- object_columns (context& c, string const& suffix = "")
- : object_columns_base (c), context (c), suffix_ (suffix)
+ object_columns (context& c, char const* suffix = "")
+ : object_columns_base (c),
+ context (c),
+ first_ (true),
+ suffix_ (suffix)
+ {
+ }
+
+ object_columns (context& c, bool first, char const* suffix = "")
+ : object_columns_base (c),
+ context (c),
+ first_ (first),
+ suffix_ (suffix)
{
}
virtual void
column (semantics::data_member&, string const& name, bool first)
{
- if (!first)
+ if (!first || !first_)
os << ",\"" << endl;
os << "\"`" << name << "`" << suffix_;
}
private:
+ bool first_;
string suffix_;
};
@@ -82,43 +94,66 @@ namespace mysql
struct bind_member: member_base
{
- bind_member (context& c, size_t& index, bool id)
- : member_base (c, id), index_ (index)
+ bind_member (context& c,
+ size_t& index,
+ string const& var = string (),
+ string const& arg = string ())
+ : member_base (c, var), index_ (index), arg_override_ (arg)
+ {
+ }
+
+ bind_member (context& c,
+ size_t& index,
+ string const& var,
+ string const& arg,
+ semantics::type& t,
+ string const& fq_type,
+ string const& key_prefix)
+ : member_base (c, var, t, fq_type, key_prefix),
+ index_ (index),
+ arg_override_ (arg)
{
}
virtual void
- pre (type& m)
+ pre (member_info& mi)
{
+ if (container (mi.t))
+ return;
+
ostringstream ostr;
ostr << "b[" << index_ << "UL]";
b = ostr.str ();
- if (!id_)
- os << "// " << m.name () << endl
+ arg = arg_override_.empty () ? string ("i") : arg_override_;
+
+ if (var_override_.empty ())
+ os << "// " << mi.m.name () << endl
<< "//" << endl;
}
virtual void
- post (type& m)
+ post (member_info& mi)
{
- if (semantics::class_* c = comp_value (m.type ()))
+ if (container (mi.t))
+ return;
+ else if (semantics::class_* c = comp_value (mi.t))
index_ += column_count (*c);
else
index_++;
}
virtual void
- traverse_composite (type& m)
+ traverse_composite (member_info& mi)
{
- os << "composite_value_traits< " << m.type ().fq_name () <<
+ os << "composite_value_traits< " << mi.fq_type () <<
" >::bind (" << endl
- << "b + " << index_ << "UL, i." << var << "value);"
+ << "b + " << index_ << "UL, " << arg << "." << mi.var << "value);"
<< endl;
}
virtual void
- traverse_integer (type&, sql_type const& t)
+ traverse_integer (member_info& mi)
{
// While the is_unsigned should indicate whether the
// buffer variable is unsigned, rather than whether the
@@ -126,51 +161,51 @@ namespace mysql
// this is the same.
//
os << b << ".buffer_type = " <<
- integer_buffer_types[t.type - sql_type::TINYINT] << ";"
- << b << ".is_unsigned = " << (t.unsign ? "1" : "0") << ";"
- << b << ".buffer = &i." << var << "value;"
- << b << ".is_null = &i." << var << "null;"
+ integer_buffer_types[mi.st->type - sql_type::TINYINT] << ";"
+ << b << ".is_unsigned = " << (mi.st->unsign ? "1" : "0") << ";"
+ << b << ".buffer = &" << arg << "." << mi.var << "value;"
+ << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
virtual void
- traverse_float (type&, sql_type const& t)
+ traverse_float (member_info& mi)
{
os << b << ".buffer_type = " <<
- float_buffer_types[t.type - sql_type::FLOAT] << ";"
- << b << ".buffer = &i." << var << "value;"
- << b << ".is_null = &i." << var << "null;"
+ float_buffer_types[mi.st->type - sql_type::FLOAT] << ";"
+ << b << ".buffer = &" << arg << "." << mi.var << "value;"
+ << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
virtual void
- traverse_decimal (type&, sql_type const&)
+ traverse_decimal (member_info& mi)
{
os << b << ".buffer_type = MYSQL_TYPE_NEWDECIMAL;"
- << b << ".buffer = i." << var << "value.data ();"
+ << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
<< b << ".buffer_length = static_cast<unsigned long> (" << endl
- << "i." << var << "value.capacity ());"
- << b << ".length = &i." << var << "size;"
- << b << ".is_null = &i." << var << "null;"
+ << "" << arg << "." << mi.var << "value.capacity ());"
+ << b << ".length = &" << arg << "." << mi.var << "size;"
+ << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
virtual void
- traverse_date_time (type&, sql_type const& t)
+ traverse_date_time (member_info& mi)
{
os << b << ".buffer_type = " <<
- date_time_buffer_types[t.type - sql_type::DATE] << ";"
- << b << ".buffer = &i." << var << "value;";
+ date_time_buffer_types[mi.st->type - sql_type::DATE] << ";"
+ << b << ".buffer = &" << arg << "." << mi.var << "value;";
- if (t.type == sql_type::YEAR)
+ if (mi.st->type == sql_type::YEAR)
os << b << ".is_unsigned = 0;";
- os << b << ".is_null = &i." << var << "null;"
+ os << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
virtual void
- traverse_short_string (type&, sql_type const& t)
+ traverse_short_string (member_info& mi)
{
// MySQL documentation is quite confusing about the use of
// buffer_length and length when it comes to input parameters.
@@ -178,73 +213,76 @@ namespace mysql
// only if length is NULL.
//
os << b << ".buffer_type = " <<
- char_bin_buffer_types[t.type - sql_type::CHAR] << ";"
- << b << ".buffer = i." << var << "value.data ();"
+ char_bin_buffer_types[mi.st->type - sql_type::CHAR] << ";"
+ << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
<< b << ".buffer_length = static_cast<unsigned long> (" << endl
- << "i." << var << "value.capacity ());"
- << b << ".length = &i." << var << "size;"
- << b << ".is_null = &i." << var << "null;"
+ << "" << arg << "." << mi.var << "value.capacity ());"
+ << b << ".length = &" << arg << "." << mi.var << "size;"
+ << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
virtual void
- traverse_long_string (type&, sql_type const& t)
+ traverse_long_string (member_info& mi)
{
os << b << ".buffer_type = " <<
- char_bin_buffer_types[t.type - sql_type::CHAR] << ";"
- << b << ".buffer = i." << var << "value.data ();"
+ char_bin_buffer_types[mi.st->type - sql_type::CHAR] << ";"
+ << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
<< b << ".buffer_length = static_cast<unsigned long> (" << endl
- << "i." << var << "value.capacity ());"
- << b << ".length = &i." << var << "size;"
- << b << ".is_null = &i." << var << "null;"
+ << "" << arg << "." << mi.var << "value.capacity ());"
+ << b << ".length = &" << arg << "." << mi.var << "size;"
+ << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
virtual void
- traverse_bit (type&, sql_type const&)
+ traverse_bit (member_info& mi)
{
// Treated as a BLOB.
//
os << b << ".buffer_type = MYSQL_TYPE_BLOB;"
- << b << ".buffer = i." << var << "value;"
+ << b << ".buffer = " << arg << "." << mi.var << "value;"
<< b << ".buffer_length = static_cast<unsigned long> (" << endl
- << "sizeof (i." << var << "value));"
- << b << ".length = &i." << var << "size;"
- << b << ".is_null = &i." << var << "null;"
+ << "sizeof (" << arg << "." << mi.var << "value));"
+ << b << ".length = &" << arg << "." << mi.var << "size;"
+ << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
virtual void
- traverse_enum (type&, sql_type const&)
+ traverse_enum (member_info& mi)
{
// Represented as a string.
//
os << b << ".buffer_type = MYSQL_TYPE_STRING;"
- << b << ".buffer = i." << var << "value.data ();"
+ << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
<< b << ".buffer_length = static_cast<unsigned long> (" << endl
- << "i." << var << "value.capacity ());"
- << b << ".length = &i." << var << "size;"
- << b << ".is_null = &i." << var << "null;"
+ << "" << arg << "." << mi.var << "value.capacity ());"
+ << b << ".length = &" << arg << "." << mi.var << "size;"
+ << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
virtual void
- traverse_set (type&, sql_type const&)
+ traverse_set (member_info& mi)
{
// Represented as a string.
//
os << b << ".buffer_type = MYSQL_TYPE_STRING;"
- << b << ".buffer = i." << var << "value.data ();"
+ << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
<< b << ".buffer_length = static_cast<unsigned long> (" << endl
- << "i." << var << "value.capacity ());"
- << b << ".length = &i." << var << "size;"
- << b << ".is_null = &i." << var << "null;"
+ << "" << arg << "." << mi.var << "value.capacity ());"
+ << b << ".length = &" << arg << "." << mi.var << "size;"
+ << b << ".is_null = &" << arg << "." << mi.var << "null;"
<< endl;
}
private:
- string b;
size_t& index_;
+
+ string b;
+ string arg;
+ string arg_override_;
};
struct bind_base: traversal::class_, context
@@ -277,123 +315,139 @@ namespace mysql
struct grow_member: member_base
{
grow_member (context& c, size_t& index)
- : member_base (c, false), index_ (index)
+ : member_base (c), index_ (index)
+ {
+ }
+
+ grow_member (context& c,
+ size_t& index,
+ string const& var,
+ semantics::type& t,
+ string const& fq_type,
+ string const& key_prefix)
+ : member_base (c, var, t, fq_type, key_prefix), index_ (index)
{
}
virtual void
- pre (type& m)
+ pre (member_info& mi)
{
+ if (container (mi.t))
+ return;
+
ostringstream ostr;
ostr << "e[" << index_ << "UL]";
e = ostr.str ();
- os << "// " << m.name () << endl
- << "//" << endl;
+ if (var_override_.empty ())
+ os << "// " << mi.m.name () << endl
+ << "//" << endl;
}
virtual void
- post (type& m)
+ post (member_info& mi)
{
- if (semantics::class_* c = comp_value (m.type ()))
+ if (container (mi.t))
+ return;
+ else if (semantics::class_* c = comp_value (mi.t))
index_ += column_count (*c);
else
index_++;
}
virtual void
- traverse_composite (type& m)
+ traverse_composite (member_info& mi)
{
- os << "if (composite_value_traits< " << m.type ().fq_name () <<
+ os << "if (composite_value_traits< " << mi.fq_type () <<
" >::grow (" << endl
- << "i." << var << "value, e + " << index_ << "UL))"
+ << "i." << mi.var << "value, e + " << index_ << "UL))"
<< "{"
<< "r = true;"
<< "}";
}
virtual void
- traverse_integer (type&, sql_type const&)
+ traverse_integer (member_info&)
{
os << e << " = 0;"
<< endl;
}
virtual void
- traverse_float (type&, sql_type const&)
+ traverse_float (member_info&)
{
os << e << " = 0;"
<< endl;
}
virtual void
- traverse_decimal (type&, sql_type const&)
+ traverse_decimal (member_info& mi)
{
// @@ Optimization disabled.
//
os << "if (" << e << ")" << endl
<< "{"
- << "i." << var << "value.capacity (i." << var << "size);"
+ << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
<< "r = true;"
<< "}";
}
virtual void
- traverse_date_time (type&, sql_type const&)
+ traverse_date_time (member_info&)
{
os << e << " = 0;"
<< endl;
}
virtual void
- traverse_short_string (type&, sql_type const&)
+ traverse_short_string (member_info& mi)
{
// @@ Optimization disabled.
//
os << "if (" << e << ")" << endl
<< "{"
- << "i." << var << "value.capacity (i." << var << "size);"
+ << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
<< "r = true;"
<< "}";
}
virtual void
- traverse_long_string (type&, sql_type const&)
+ traverse_long_string (member_info& mi)
{
os << "if (" << e << ")" << endl
<< "{"
- << "i." << var << "value.capacity (i." << var << "size);"
+ << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
<< "r = true;"
<< "}";
}
virtual void
- traverse_bit (type&, sql_type const&)
+ traverse_bit (member_info&)
{
os << e << " = 0;"
<< endl;
}
virtual void
- traverse_enum (type&, sql_type const&)
+ traverse_enum (member_info& mi)
{
// Represented as a string.
//
os << "if (" << e << ")" << endl
<< "{"
- << "i." << var << "value.capacity (i." << var << "size);"
+ << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
<< "r = true;"
<< "}";
}
virtual void
- traverse_set (type&, sql_type const&)
+ traverse_set (member_info& mi)
{
// Represented as a string.
//
os << "if (" << e << ")" << endl
<< "{"
- << "i." << var << "value.capacity (i." << var << "size);"
+ << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
<< "r = true;"
<< "}";
}
@@ -434,25 +488,41 @@ namespace mysql
struct init_image_member: member_base
{
- init_image_member (context& c, bool id)
- : member_base (c, id),
- member_image_type_ (c, id),
- member_database_type_ (c)
+ init_image_member (context& c,
+ string const& var = string (),
+ string const& member = string ())
+ : member_base (c, var),
+ member_image_type_ (c),
+ member_database_type_ (c),
+ member_override_ (member)
{
}
- virtual void
- pre (type& m)
+ init_image_member (context& c,
+ string const& var,
+ string const& member,
+ semantics::type& t,
+ string const& fq_type,
+ string const& key_prefix)
+ : member_base (c, var, t, fq_type, key_prefix),
+ member_image_type_ (c, t, fq_type, key_prefix),
+ member_database_type_ (c, t, fq_type, key_prefix),
+ member_override_ (member)
{
- semantics::type& t (m.type ());
+ }
- if (comp_value (t))
- traits = "composite_value_traits< " + t.fq_name () + " >";
+ virtual void
+ pre (member_info& mi)
+ {
+ if (container (mi.t))
+ return;
+ else if (comp_value (mi.t))
+ traits = "composite_value_traits< " + mi.fq_type () + " >";
else
{
- type = t.fq_name (m.belongs ().hint ());
- image_type = member_image_type_.image_type (m);
- db_type = member_database_type_.database_type (m);
+ 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 + ", "
@@ -460,11 +530,11 @@ namespace mysql
+ db_type + " >";
}
- if (id_)
- member = "id";
+ if (!member_override_.empty ())
+ member = member_override_;
else
{
- string const& name (m.name ());
+ string const& name (mi.m.name ());
member = "o." + name;
os << "// " << name << endl
@@ -473,9 +543,9 @@ namespace mysql
}
virtual void
- traverse_composite (type&)
+ traverse_composite (member_info& mi)
{
- os << "if (" << traits << "::init (i." << var << "value, " <<
+ os << "if (" << traits << "::init (i." << mi.var << "value, " <<
member << "))"
<< "{"
<< "grew = true;"
@@ -483,98 +553,98 @@ namespace mysql
}
virtual void
- traverse_integer (type&, sql_type const&)
+ traverse_integer (member_info& mi)
{
os << "{"
<< "bool is_null;"
<< traits << "::set_image (" << endl
- << "i." << var << "value, is_null, " << member << ");"
- << "i." << var << "null = is_null;"
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "null = is_null;"
<< "}";
}
virtual void
- traverse_float (type&, sql_type const&)
+ traverse_float (member_info& mi)
{
os << "{"
<< "bool is_null;"
<< traits << "::set_image (" << endl
- << "i." << var << "value, is_null, " << member << ");"
- << "i." << var << "null = is_null;"
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "null = is_null;"
<< "}";
}
virtual void
- traverse_decimal (type&, sql_type const&)
+ traverse_decimal (member_info& mi)
{
// @@ Optimization: can remove growth check if buffer is fixed.
//
os << "{"
<< "bool is_null;"
<< "std::size_t size;"
- << "std::size_t cap (i." << var << "value.capacity ());"
+ << "std::size_t cap (i." << mi.var << "value.capacity ());"
<< traits << "::set_image (" << endl
- << "i." << var << "value," << endl
+ << "i." << mi.var << "value," << endl
<< "size," << endl
<< "is_null," << endl
<< member << ");"
- << "i." << var << "size = static_cast<unsigned long> (size);"
- << "i." << var << "null = is_null;"
- << "grew = grew || (cap != i." << var << "value.capacity ());"
+ << "i." << mi.var << "size = static_cast<unsigned long> (size);"
+ << "i." << mi.var << "null = is_null;"
+ << "grew = grew || (cap != i." << mi.var << "value.capacity ());"
<< "}";
}
virtual void
- traverse_date_time (type&, sql_type const&)
+ traverse_date_time (member_info& mi)
{
os << "{"
<< "bool is_null;"
<< traits << "::set_image (" << endl
- << "i." << var << "value, is_null, " << member << ");"
- << "i." << var << "null = is_null;"
+ << "i." << mi.var << "value, is_null, " << member << ");"
+ << "i." << mi.var << "null = is_null;"
<< "}";
}
virtual void
- traverse_short_string (type&, sql_type const&)
+ traverse_short_string (member_info& mi)
{
// @@ Optimization: can remove growth check if buffer is fixed.
//
os << "{"
<< "bool is_null;"
<< "std::size_t size;"
- << "std::size_t cap (i." << var << "value.capacity ());"
+ << "std::size_t cap (i." << mi.var << "value.capacity ());"
<< traits << "::set_image (" << endl
- << "i." << var << "value," << endl
+ << "i." << mi.var << "value," << endl
<< "size," << endl
<< "is_null," << endl
<< member << ");"
- << "i." << var << "size = static_cast<unsigned long> (size);"
- << "i." << var << "null = is_null;"
- << "grew = grew || (cap != i." << var << "value.capacity ());"
+ << "i." << mi.var << "size = static_cast<unsigned long> (size);"
+ << "i." << mi.var << "null = is_null;"
+ << "grew = grew || (cap != i." << mi.var << "value.capacity ());"
<< "}";
}
virtual void
- traverse_long_string (type&, sql_type const&)
+ traverse_long_string (member_info& mi)
{
os << "{"
<< "bool is_null;"
<< "std::size_t size;"
- << "std::size_t cap (i." << var << "value.capacity ());"
+ << "std::size_t cap (i." << mi.var << "value.capacity ());"
<< traits << "::set_image (" << endl
- << "i." << var << "value," << endl
+ << "i." << mi.var << "value," << endl
<< "size," << endl
<< "is_null," << endl
<< member << ");"
- << "i." << var << "size = static_cast<unsigned long> (size);"
- << "i." << var << "null = is_null;"
- << "grew = grew || (cap != i." << var << "value.capacity ());"
+ << "i." << mi.var << "size = static_cast<unsigned long> (size);"
+ << "i." << mi.var << "null = is_null;"
+ << "grew = grew || (cap != i." << mi.var << "value.capacity ());"
<< "}";
}
virtual void
- traverse_bit (type&, sql_type const&)
+ traverse_bit (member_info& mi)
{
// Represented as a BLOB.
//
@@ -582,53 +652,53 @@ namespace mysql
<< "bool is_null;"
<< "std::size_t size;"
<< traits << "::set_image (" << endl
- << "i." << var << "value," << endl
- << "sizeof (i." << var << "value)," << endl
+ << "i." << mi.var << "value," << endl
+ << "sizeof (i." << mi.var << "value)," << endl
<< "size," << endl
<< "is_null," << endl
<< member << ");"
- << "i." << var << "size = static_cast<unsigned long> (size);"
- << "i." << var << "null = is_null;"
+ << "i." << mi.var << "size = static_cast<unsigned long> (size);"
+ << "i." << mi.var << "null = is_null;"
<< "}";
}
virtual void
- traverse_enum (type&, sql_type const&)
+ traverse_enum (member_info& mi)
{
// Represented as a string.
//
os << "{"
<< "bool is_null;"
<< "std::size_t size;"
- << "std::size_t cap (i." << var << "value.capacity ());"
+ << "std::size_t cap (i." << mi.var << "value.capacity ());"
<< traits << "::set_image (" << endl
- << "i." << var << "value," << endl
+ << "i." << mi.var << "value," << endl
<< "size," << endl
<< "is_null," << endl
<< member << ");"
- << "i." << var << "size = static_cast<unsigned long> (size);"
- << "i." << var << "null = is_null;"
- << "grew = grew || (cap != i." << var << "value.capacity ());"
+ << "i." << mi.var << "size = static_cast<unsigned long> (size);"
+ << "i." << mi.var << "null = is_null;"
+ << "grew = grew || (cap != i." << mi.var << "value.capacity ());"
<< "}";
}
virtual void
- traverse_set (type&, sql_type const&)
+ traverse_set (member_info& mi)
{
// Represented as a string.
//
os << "{"
<< "bool is_null;"
<< "std::size_t size;"
- << "std::size_t cap (i." << var << "value.capacity ());"
+ << "std::size_t cap (i." << mi.var << "value.capacity ());"
<< traits << "::set_image (" << endl
- << "i." << var << "value," << endl
+ << "i." << mi.var << "value," << endl
<< "size," << endl
<< "is_null," << endl
<< member << ");"
- << "i." << var << "size = static_cast<unsigned long> (size);"
- << "i." << var << "null = is_null;"
- << "grew = grew || (cap != i." << var << "value.capacity ());"
+ << "i." << mi.var << "size = static_cast<unsigned long> (size);"
+ << "i." << mi.var << "null = is_null;"
+ << "grew = grew || (cap != i." << mi.var << "value.capacity ());"
<< "}";
}
@@ -641,6 +711,8 @@ namespace mysql
member_image_type member_image_type_;
member_database_type member_database_type_;
+
+ string member_override_;
};
struct init_image_base: traversal::class_, context
@@ -670,24 +742,37 @@ namespace mysql
struct init_value_member: member_base
{
init_value_member (context& c)
- : member_base (c, false),
- member_image_type_ (c, false),
+ : member_base (c),
+ member_image_type_ (c),
member_database_type_ (c)
{
}
- virtual void
- pre (type& m)
+ init_value_member (context& c,
+ string const& var,
+ string const& member,
+ semantics::type& t,
+ string const& fq_type,
+ string const& key_prefix)
+ : member_base (c, var, t, fq_type, key_prefix),
+ member_image_type_ (c, t, fq_type, key_prefix),
+ member_database_type_ (c, t, fq_type, key_prefix),
+ member_override_ (member)
{
- semantics::type& t (m.type ());
+ }
- if (comp_value (t))
- traits = "composite_value_traits< " + t.fq_name () + " >";
+ virtual void
+ pre (member_info& mi)
+ {
+ if (container (mi.t))
+ return;
+ else if (comp_value (mi.t))
+ traits = "composite_value_traits< " + mi.fq_type () + " >";
else
{
- type = m.type ().fq_name (m.belongs ().hint ());
- image_type = member_image_type_.image_type (m);
- db_type = member_database_type_.database_type (m);
+ 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 + ", "
@@ -695,113 +780,122 @@ namespace mysql
+ db_type + " >";
}
- os << "// " << m.name () << endl
- << "//" << endl;
+ if (!member_override_.empty ())
+ member = member_override_;
+ else
+ {
+ string const& name (mi.m.name ());
+ member = "o." + name;
+
+ os << "// " << name << endl
+ << "//" << endl;
+ }
}
virtual void
- traverse_composite (type& m)
+ traverse_composite (member_info& mi)
{
- os << traits << "::init (o." << m.name () << ", i." << var << "value);"
+ os << traits << "::init (" << member << ", i." <<
+ mi.var << "value);"
<< endl;
}
virtual void
- traverse_integer (type& m, sql_type const&)
+ traverse_integer (member_info& mi)
{
os << traits << "::set_value (" << endl
- << "o." << m.name () << ", i." << var << "value, " <<
- "i." << var << "null);"
+ << member << ", i." << mi.var << "value, " <<
+ "i." << mi.var << "null);"
<< endl;
}
virtual void
- traverse_float (type& m, sql_type const&)
+ traverse_float (member_info& mi)
{
os << traits << "::set_value (" << endl
- << "o." << m.name () << ", i." << var << "value, " <<
- "i." << var << "null);"
+ << member << ", i." << mi.var << "value, " <<
+ "i." << mi.var << "null);"
<< endl;
}
virtual void
- traverse_decimal (type& m, sql_type const&)
+ traverse_decimal (member_info& mi)
{
os << traits << "::set_value (" << endl
- << "o." << m.name () << "," << endl
- << "i." << var << "value," << endl
- << "i." << var << "size," << endl
- << "i." << var << "null);"
+ << member << "," << endl
+ << "i." << mi.var << "value," << endl
+ << "i." << mi.var << "size," << endl
+ << "i." << mi.var << "null);"
<< endl;
}
virtual void
- traverse_date_time (type& m, sql_type const&)
+ traverse_date_time (member_info& mi)
{
os << traits << "::set_value (" << endl
- << "o." << m.name () << ", i." << var << "value, " <<
- "i." << var << "null);"
+ << member << ", i." << mi.var << "value, " <<
+ "i." << mi.var << "null);"
<< endl;
}
virtual void
- traverse_short_string (type& m, sql_type const&)
+ traverse_short_string (member_info& mi)
{
os << traits << "::set_value (" << endl
- << "o." << m.name () << "," << endl
- << "i." << var << "value," << endl
- << "i." << var << "size," << endl
- << "i." << var << "null);"
+ << member << "," << endl
+ << "i." << mi.var << "value," << endl
+ << "i." << mi.var << "size," << endl
+ << "i." << mi.var << "null);"
<< endl;
}
virtual void
- traverse_long_string (type& m, sql_type const&)
+ traverse_long_string (member_info& mi)
{
os << traits << "::set_value (" << endl
- << "o." << m.name () << "," << endl
- << "i." << var << "value," << endl
- << "i." << var << "size," << endl
- << "i." << var << "null);"
+ << member << "," << endl
+ << "i." << mi.var << "value," << endl
+ << "i." << mi.var << "size," << endl
+ << "i." << mi.var << "null);"
<< endl;
}
virtual void
- traverse_bit (type& m, sql_type const&)
+ traverse_bit (member_info& mi)
{
// Represented as a BLOB.
//
os << traits << "::set_value (" << endl
- << "o." << m.name () << "," << endl
- << "i." << var << "value," << endl
- << "i." << var << "size," << endl
- << "i." << var << "null);"
+ << member << "," << endl
+ << "i." << mi.var << "value," << endl
+ << "i." << mi.var << "size," << endl
+ << "i." << mi.var << "null);"
<< endl;
}
virtual void
- traverse_enum (type& m, sql_type const&)
+ traverse_enum (member_info& mi)
{
// Represented as a string.
//
os << traits << "::set_value (" << endl
- << "o." << m.name () << "," << endl
- << "i." << var << "value," << endl
- << "i." << var << "size," << endl
- << "i." << var << "null);"
+ << member << "," << endl
+ << "i." << mi.var << "value," << endl
+ << "i." << mi.var << "size," << endl
+ << "i." << mi.var << "null);"
<< endl;
}
virtual void
- traverse_set (type& m, sql_type const&)
+ traverse_set (member_info& mi)
{
// Represented as a string.
//
os << traits << "::set_value (" << endl
- << "o." << m.name () << "," << endl
- << "i." << var << "value," << endl
- << "i." << var << "size," << endl
- << "i." << var << "null);"
+ << member << "," << endl
+ << "i." << mi.var << "value," << endl
+ << "i." << mi.var << "size," << endl
+ << "i." << mi.var << "null);"
<< endl;
}
@@ -810,9 +904,12 @@ namespace mysql
string db_type;
string image_type;
string traits;
+ string member;
member_image_type member_image_type_;
member_database_type member_database_type_;
+
+ string member_override_;
};
struct init_value_base: traversal::class_, context
@@ -832,6 +929,872 @@ namespace mysql
}
};
+ // Member-specific traits types for container members.
+ //
+ struct container_traits: object_members_base, context
+ {
+ container_traits (context& c, semantics::class_& obj)
+ : object_members_base (c, true, true),
+ context (c),
+ object_ (obj),
+ id_member_ (id_member (obj))
+ {
+ obj_scope_ = "access::object_traits< " + obj.fq_name () + " >";
+ }
+
+ virtual void
+ container (semantics::data_member& m)
+ {
+ using semantics::type;
+
+ type& t (m.type ());
+ container_kind_type ck (container_kind (t));
+
+ type& vt (container_vt (t));
+ type* it (0);
+ type* kt (0);
+
+ bool grow (false);
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ it = &container_it (t);
+ grow = grow || context::grow (m, *it, "index");
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ kt = &container_kt (t);
+ grow = grow || context::grow (m, *kt, "key");
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+
+ grow = grow || context::grow (m, vt, "value");
+
+ string name (prefix_ + public_name (m) + "_traits");
+ string scope (obj_scope_ + "::" + name);
+
+ os << "// " << m.name () << endl
+ << "//" << endl
+ << endl;
+
+ //
+ // Statements.
+ //
+ string table (table_name (m, table_prefix_));
+
+ // insert_one_statement
+ //
+ os << "const char* const " << scope << "::insert_one_statement =" << endl
+ << "\"INSERT INTO `" << table << "` (\"" << endl
+ << "\"`" << column_name (m, "id", "object_id") << "`";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << ",\"" << endl
+ << "\"`" << column_name (m, "index", "index") << "`";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ if (comp_value (*kt))
+ {
+ object_columns t (*this, false);
+ t.traverse_composite (m, *kt, "key", "key");
+ }
+ else
+ {
+ os << ",\"" << endl
+ << "\"`" << column_name (m, "key", "key") << "`";
+ }
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+
+ if (comp_value (vt))
+ {
+ object_columns t (*this, false);
+ t.traverse_composite (m, vt, "value", "value");
+ }
+ else
+ {
+ os << ",\"" << endl
+ << "\"`" << column_name (m, "value", "value") << "`";
+ }
+
+ os << "\"" << endl
+ << "\") VALUES (";
+
+ for (size_t i (0), n (m.get<size_t> ("data-column-count")); i < n; ++i)
+ os << (i != 0 ? "," : "") << '?';
+
+ os << ")\";"
+ << endl;
+
+ // select_all_statement
+ //
+ os << "const char* const " << scope << "::select_all_statement =" << endl
+ << "\"SELECT \"" << endl
+ << "\"`" << column_name (m, "id", "object_id") << "`";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << ",\"" << endl
+ << "\"`" << column_name (m, "index", "index") << "`";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ if (comp_value (*kt))
+ {
+ object_columns t (*this, false);
+ t.traverse_composite (m, *kt, "key", "key");
+ }
+ else
+ {
+ os << ",\"" << endl
+ << "\"`" << column_name (m, "key", "key") << "`";
+ }
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+
+ if (comp_value (vt))
+ {
+ object_columns t (*this, false);
+ t.traverse_composite (m, vt, "value", "value");
+ }
+ else
+ {
+ os << ",\"" << endl
+ << "\"`" << column_name (m, "value", "value") << "`";
+ }
+
+ os << "\"" << endl
+ << "\" FROM `" << table << "` WHERE `" <<
+ column_name (m, "id", "object_id") << "` = ?\"" << endl;
+
+ if (ck == ck_ordered)
+ os << "\" ORDER BY `" << column_name (m, "index", "index") << "`\"";
+
+ os << ";"
+ << endl;
+
+ // delete_all_statement
+ //
+ os << "const char* const " << scope << "::delete_all_statement =" << endl
+ << "\"DELETE FROM `" << table << "`\"" << endl
+ << "\" WHERE `" << column_name (m, "id", "object_id") << "` = ?\";"
+ << endl;
+
+ //
+ // Functions.
+ //
+
+ // bind()
+ //
+ {
+ size_t index;
+ bind_member bind_id (*this, index, "id_", "id");
+
+ // bind (cond_image_type)
+ //
+ os << "void " << scope << "::" << endl
+ << "bind (MYSQL_BIND* b, id_image_type* p, cond_image_type& c)"
+ << "{";
+
+ index = 0;
+
+ os << "// object_id" << endl
+ << "//" << endl
+ << "if (p != 0)"
+ << "{"
+ << "id_image_type& id (*p);";
+ bind_id.traverse (id_member_);
+ os << "}";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "// index" << endl
+ << "//" << endl;
+ bind_member bm (
+ *this, index, "index_", "c", *it, "index_type", "index");
+ bm.traverse (m);
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "// key" << endl
+ << "//" << endl;
+ bind_member bm (
+ *this, index, "key_", "c", *kt, "key_type", "key");
+ bm.traverse (m);
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "// value" << endl
+ << "//" << endl;
+ bind_member bm (
+ *this, index, "value_", "c", vt, "value_type", "value");
+ bm.traverse (m);
+ break;
+ }
+ }
+
+ os << "}";
+
+ // bind (data_image_type)
+ //
+ os << "void " << scope << "::" << endl
+ << "bind (MYSQL_BIND* b, id_image_type* p, data_image_type& d)"
+ << "{";
+
+ index = 0;
+
+ os << "// object_id" << endl
+ << "//" << endl
+ << "if (p != 0)"
+ << "{"
+ << "id_image_type& id (*p);";
+ bind_id.traverse (id_member_);
+ os << "}";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "// index" << endl
+ << "//" << endl;
+ bind_member bm (
+ *this, index, "index_", "d", *it, "index_type", "index");
+ bm.traverse (m);
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "// key" << endl
+ << "//" << endl;
+ bind_member bm (
+ *this, index, "key_", "d", *kt, "key_type", "key");
+ bm.traverse (m);
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+
+ os << "// value" << endl
+ << "//" << endl;
+ bind_member bm (
+ *this, index, "value_", "d", vt, "value_type", "value");
+ bm.traverse (m);
+
+ os << "}";
+ }
+
+ // grow ()
+ //
+ {
+ size_t index (0);
+
+ os << "bool " << scope << "::" << endl
+ << "grow (data_image_type&" << (grow ? " i" : "") << ", my_bool* e)"
+ << "{"
+ << "bool r (false);"
+ << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "// index" << endl
+ << "//" << endl;
+ grow_member gm (
+ *this, index, "index_", *it, "index_type", "index");
+ gm.traverse (m);
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "// key" << endl
+ << "//" << endl;
+ grow_member gm (*this, index, "key_", *kt, "key_type", "key");
+ gm.traverse (m);
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ break;
+ }
+ }
+
+ os << "// value" << endl
+ << "//" << endl;
+ grow_member gm (*this, index, "value_", vt, "value_type", "value");
+ gm.traverse (m);
+
+ os << "return r;"
+ << "}";
+ }
+
+ // init (data_image)
+ //
+ os << "bool " << scope << "::" << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "init (data_image_type& i, index_type j, const value_type& v)"
+ << "{"
+ << "bool grew (false);"
+ << endl
+ << "// index" << endl
+ << "//" << endl;
+
+ init_image_member im (
+ *this, "index_", "j", *it, "index_type", "index");
+ im.traverse (m);
+
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "init (data_image_type& i, const key_type& k, " <<
+ "const value_type& v)"
+ << "{"
+ << "bool grew (false);"
+ << endl
+ << "// key" << endl
+ << "//" << endl;
+
+ init_image_member im (*this, "key_", "k", *kt, "key_type", "key");
+ im.traverse (m);
+
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "init (data_image_type& i, const value_type& v)"
+ << "{"
+ << "bool grew (false);"
+ << endl;
+ break;
+ }
+ }
+
+ os << "// value" << endl
+ << "//" << endl;
+ {
+ init_image_member im (
+ *this, "value_", "v", vt, "value_type", "value");
+ im.traverse (m);
+ }
+ os << "return grew;"
+ << "}";
+
+ // init (data)
+ //
+ os << "void " << scope << "::" << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "init (index_type& j, value_type& v, const data_image_type& i)"
+ << "{"
+ << "// index" << endl
+ << "//" << endl;
+
+ init_value_member im (
+ *this, "index_", "j", *it, "index_type", "index");
+ im.traverse (m);
+
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "init (key_type& k, value_type& v, const data_image_type& i)"
+ << "{"
+ << "// key" << endl
+ << "//" << endl;
+
+ init_value_member im (*this, "key_", "k", *kt, "key_type", "key");
+ im.traverse (m);
+
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "init (value_type& v, const data_image_type& i)"
+ << "{";
+ break;
+ }
+ }
+
+ os << "// value" << endl
+ << "//" << endl;
+ {
+ init_value_member im (
+ *this, "value_", "v", vt, "value_type", "value");
+ im.traverse (m);
+ }
+ os << "}";
+
+ // insert_one
+ //
+ os << "void " << scope << "::" << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "insert_one (index_type i, const value_type& v, void* d)";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "insert_one (const key_type& k, const value_type& v, void* d)";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "insert_one (const value_type& v, void* d)";
+ break;
+ }
+ }
+
+ os << "{"
+ << "using namespace mysql;"
+ << endl
+ << "typedef container_statements< " << name << " > statements;"
+ << "statements& sts (*static_cast< statements* > (d));"
+ << "binding& b (sts.data_image_binding ());"
+ << "data_image_type& di (sts.data_image ());"
+ << endl
+ << "if (";
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "init (di, i, v)";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "init (di, k, v)";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "init (di, v)";
+ break;
+ }
+ }
+
+ os << " || b.version == 0)"
+ << "{"
+ << "bind (b.bind, 0, di);"
+ << "b.version++;"
+ << "}"
+ << "if (!sts.insert_one_statement ().execute ())" << endl
+ << "throw object_already_persistent ();"
+ << "}";
+
+
+ // load_all
+ //
+ os << "bool " << scope << "::" << endl;
+
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "load_all (index_type& i, value_type& v, void* d)";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "load_all (key_type& k, value_type& v, void* d)";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "load_all (value_type& v, void* d)";
+ break;
+ }
+ }
+
+ os << "{"
+ << "using namespace mysql;"
+ << endl
+ << "typedef container_statements< " << name << " > statements;"
+ << "statements& sts (*static_cast< statements* > (d));"
+ << "data_image_type& di (sts.data_image ());";
+
+ // Extract current element.
+ //
+ switch (ck)
+ {
+ case ck_ordered:
+ {
+ os << "init (i, v, di);";
+ break;
+ }
+ case ck_map:
+ case ck_multimap:
+ {
+ os << "init (k, v, di);";
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
+ {
+ os << "init (v, di);";
+ break;
+ }
+ }
+
+ // Fetch next.
+ //
+ os << endl
+ << "select_statement& st (sts.select_all_statement ());"
+ << "select_statement::result r (st.fetch ());";
+
+ if (grow)
+ os << endl
+ << "if (r == select_statement::truncated)"
+ << "{"
+ << "if (grow (di, sts.data_image_error ()))"
+ << "{"
+ << "binding& db (sts.data_image_binding ());"
+ << "bind (db.bind, 0, di);"
+ << "db.version++;"
+ << "st.refetch ();"
+ << "}"
+ << "}";
+
+ os << "if (r == select_statement::no_data)"
+ << "{"
+ << "st.free_result ();"
+ << "return false;"
+ << "}"
+ << "return true;"
+ << "}";
+
+ // delete_all
+ //
+ os << "void " << scope << "::" << endl
+ << "delete_all (void* d)"
+ << "{"
+ << "using namespace mysql;"
+ << endl
+ << "typedef container_statements< " << name << " > statements;"
+ << "statements& sts (*static_cast< statements* > (d));"
+ << "sts.delete_all_statement ().execute ();"
+ << "}";
+
+ // persist
+ //
+ os << "void " << scope << "::" << endl
+ << "persist (const container_type& c," << endl
+ << "id_image_type& id," << endl
+ << "bool rebind," << endl
+ << "statements_type& sts)"
+ << "{"
+ << "using namespace mysql;"
+ << endl
+ << "binding& b (sts.data_image_binding ());"
+ << "if (rebind || b.version == 0)"
+ << "{"
+ << "bind (b.bind, &id, sts.data_image ());"
+ << "b.version++;"
+ << "}"
+ << "if (rebind)" // We don't need it, just don't miss the event.
+ << "{"
+ << "binding& cb (sts.cond_image_binding ());"
+ << "bind (cb.bind, &id, sts.cond_image ());"
+ << "cb.version++;"
+ << "}"
+ << "container_traits::persist (c, sts.functions ());"
+ << "}";
+
+ // load
+ //
+ os << "void " << scope << "::" << endl
+ << "load (container_type& c," << endl
+ << "id_image_type& id," << endl
+ << "bool rebind," << endl
+ << "statements_type& sts)"
+ << "{"
+ << "using namespace mysql;"
+ << endl
+ << "binding& db (sts.data_image_binding ());"
+ << "if (rebind || db.version == 0)"
+ << "{"
+ << "bind (db.bind, &id, sts.data_image ());"
+ << "db.version++;"
+ << "}"
+ << "binding& cb (sts.cond_image_binding ());"
+ << "if (rebind || cb.version == 0)"
+ << "{"
+ << "bind (cb.bind, &id, sts.cond_image ());"
+ << "cb.version++;"
+ << "}"
+ << "select_statement& st (sts.select_all_statement ());"
+ << "st.execute ();"
+ << "select_statement::result r (st.fetch ());";
+
+ if (grow)
+ os << endl
+ << "if (r == select_statement::truncated)"
+ << "{"
+ << "if (grow (sts.data_image (), sts.data_image_error ()))"
+ << "{"
+ << "bind (db.bind, 0, sts.data_image ());"
+ << "db.version++;"
+ << "st.refetch ();"
+ << "}"
+ << "}";
+
+ os << "bool more (r != select_statement::no_data);"
+ << endl
+ << "if (!more)" << endl
+ << "st.free_result ();"
+ << endl
+ << "container_traits::load (c, more, sts.functions ());"
+ << "}";
+
+ // update
+ //
+ os << "void " << scope << "::" << endl
+ << "update (const container_type& c," << endl
+ << "id_image_type& id," << endl
+ << "bool rebind," << endl
+ << "statements_type& sts)"
+ << "{"
+ << "using namespace mysql;"
+ << endl
+ << "binding& db (sts.data_image_binding ());"
+ << "if (rebind || db.version == 0)"
+ << "{"
+ << "bind (db.bind, &id, sts.data_image ());"
+ << "db.version++;"
+ << "}"
+ << "binding& cb (sts.cond_image_binding ());"
+ << "if (rebind || cb.version == 0)" // We may need it (delete_all).
+ << "{"
+ << "bind (cb.bind, &id, sts.cond_image ());"
+ << "cb.version++;"
+ << "}"
+ << "container_traits::update (c, sts.functions ());"
+ << "}";
+
+ // erase
+ //
+ os << "void " << scope << "::" << endl
+ << "erase (id_image_type& id, bool rebind, statements_type& sts)"
+ << "{"
+ << "using namespace mysql;"
+ << endl
+ << "binding& b (sts.cond_image_binding ());"
+ << "if (rebind || b.version == 0)"
+ << "{"
+ << "bind (b.bind, &id, sts.cond_image ());"
+ << "b.version++;"
+ << "}"
+ << "if (rebind)"
+ << "{"
+ << "binding& db (sts.data_image_binding ());"
+ << "bind (db.bind, &id, sts.data_image ());"
+ << "db.version++;"
+ << "}"
+ << "container_traits::erase (sts.functions ());"
+ << "}";
+ }
+
+ private:
+ string obj_scope_;
+ semantics::class_& object_;
+ semantics::data_member& id_member_;
+ };
+
+ // Container statement cache members.
+ //
+ struct container_cache_members: object_members_base, context
+ {
+ container_cache_members (context& c)
+ : object_members_base (c, true, false),
+ context (c),
+ containers_ (false)
+ {
+ }
+
+ bool
+ containers () const
+ {
+ return containers_;
+ }
+
+ virtual void
+ container (semantics::data_member& m)
+ {
+ string traits (prefix_ + public_name (m) + "_traits");
+ os << "mysql::container_statements< " << traits << " > " <<
+ prefix_ << m.name () << ";";
+
+ containers_ = true;
+ }
+
+ private:
+ bool containers_;
+ };
+
+ struct container_cache_init_members: object_members_base, context
+ {
+ container_cache_init_members (context& c)
+ : object_members_base (c, true, false), context (c), first_ (true)
+ {
+ }
+
+ virtual void
+ container (semantics::data_member& m)
+ {
+ if (first_)
+ {
+ os << endl
+ << ": ";
+ first_ = false;
+ }
+ else
+ os << "," << endl
+ << " ";
+
+ os << prefix_ << m.name () << " (c)";
+ }
+
+ private:
+ bool first_;
+ };
+
+ // Calls for container members.
+ //
+ struct container_calls: object_members_base, context
+ {
+ enum call_type
+ {
+ persist_call,
+ load_call,
+ update_call,
+ erase_call
+ };
+
+ container_calls (context& c, call_type call)
+ : object_members_base (c, true, false), context (c), call_ (call)
+ {
+ }
+
+ virtual void
+ composite (semantics::data_member& m, semantics::type& t)
+ {
+ string old (obj_prefix_);
+ obj_prefix_ += m.name ();
+ obj_prefix_ += '.';
+ object_members_base::composite (m, t);
+ obj_prefix_ = old;
+ }
+
+ virtual void
+ container (semantics::data_member& m)
+ {
+ using semantics::type;
+
+ string const& name (m.name ());
+ string obj_name (obj_prefix_ + name);
+ string sts_name (prefix_ + name);
+ string traits (prefix_ + public_name (m) + "_traits");
+
+ switch (call_)
+ {
+ case persist_call:
+ {
+ os << traits << "::persist (obj." << obj_name << ", i, grew, " <<
+ "sts.container_statment_cache ()." << sts_name << ");";
+ break;
+ }
+ case load_call:
+ {
+ os << traits << "::load (obj." << obj_name << ", i, grew, " <<
+ "sts.container_statment_cache ()." << sts_name << ");";
+ break;
+ }
+ case update_call:
+ {
+ os << traits << "::update (obj." << obj_name << ", i, grew, " <<
+ "sts.container_statment_cache ()." << sts_name << ");";
+ break;
+ }
+ case erase_call:
+ {
+ os << traits << "::erase (i, grew, " <<
+ "sts.container_statment_cache ()." << sts_name << ");";
+ break;
+ }
+ }
+ }
+
+ private:
+ call_type call_;
+ string obj_prefix_;
+ };
+
//
//
struct class_: traversal::class_, context
@@ -841,11 +1804,11 @@ namespace mysql
grow_base_ (c, index_),
grow_member_ (c, index_),
bind_base_ (c, index_),
- bind_member_ (c, index_, false),
- bind_id_member_ (c, index_, true),
+ bind_member_ (c, index_),
+ bind_id_member_ (c, index_, "id_"),
init_image_base_ (c),
- init_image_member_ (c, false),
- init_id_image_member_ (c, true),
+ init_image_member_ (c),
+ init_id_image_member_ (c, "id_", "id"),
init_value_base_ (c),
init_value_member_ (c)
{
@@ -854,13 +1817,10 @@ namespace mysql
bind_base_inherits_ >> bind_base_;
bind_member_names_ >> bind_member_;
- bind_id_member_names_ >> bind_id_member_;
init_image_base_inherits_ >> init_image_base_;
init_image_member_names_ >> init_image_member_;
- init_id_image_member_names_ >> init_id_image_member_;
-
init_value_base_inherits_ >> init_value_base_;
init_value_member_names_ >> init_value_member_;
}
@@ -886,14 +1846,48 @@ namespace mysql
bool grow (context::grow (c));
bool def_ctor (TYPE_HAS_DEFAULT_CONSTRUCTOR (c.tree_node ()));
- id_member_.traverse (c);
- semantics::data_member& id (*id_member_.member ());
+ semantics::data_member& id (id_member (c));
bool auto_id (id.count ("auto"));
os << "// " << c.name () << endl
<< "//" << endl
<< endl;
+ //
+ // Containers.
+ //
+
+ // Statement cache (definition).
+ //
+ bool containers;
+ {
+ os << "struct " << traits << "::container_statement_cache_type"
+ << "{";
+
+ container_cache_members cm (*this);
+ cm.traverse (c);
+ containers = cm.containers ();
+
+ os << (containers ? "\n" : "")
+ << "container_statement_cache_type (mysql::connection&" <<
+ (containers ? " c" : "") << ")";
+
+ container_cache_init_members im (*this);
+ im.traverse (c);
+
+ os << "{"
+ << "}"
+ << "};";
+ }
+
+ // Traits types.
+ //
+ if (containers)
+ {
+ container_traits t (*this, c);
+ t.traverse (c);
+ }
+
// query columns
//
if (options.generate_query ())
@@ -1008,7 +2002,7 @@ namespace mysql
<< "{";
index_ = 0;
- names (c, bind_id_member_names_);
+ bind_id_member_.traverse (id);
os << "}";
@@ -1060,11 +2054,36 @@ namespace mysql
<< "bind (b.bind, sts.image ());"
<< "b.version++;"
<< "}"
- << "mysql::persist_statement& st (sts.persist_statement ());"
- << "st.execute ();";
+ << "insert_statement& st (sts.persist_statement ());"
+ << "if (!st.execute ())" << endl
+ << "throw object_already_persistent ();"
+ << endl;
if (auto_id)
- os << "obj." << id.name () << " = static_cast<id_type> (st.id ());";
+ os << "obj." << id.name () << " = static_cast<id_type> (st.id ());"
+ << endl;
+
+ if (containers)
+ {
+ // Initialize id_image.
+ //
+ os << "{"
+ << "bool grew (false);"
+ << "const id_type& id (obj." << id.name () << ");"
+ << "id_image_type& i (sts.id_image ());";
+ init_id_image_member_.traverse (id);
+ os << "binding& idb (sts.id_image_binding ());"
+ << "if (grew && idb.version != 0)"
+ << "{"
+ << "bind (idb.bind, i);"
+ << "idb.version++;"
+ << "}";
+
+ container_calls t (*this, container_calls::persist_call);
+ t.traverse (c);
+
+ os << "}";
+ }
os << "}";
@@ -1082,7 +2101,7 @@ namespace mysql
<< "bool grew (false);"
<< "const id_type& id (object_traits::id (obj));"
<< "id_image_type& i (sts.id_image ());";
- names (c, init_id_image_member_names_);
+ init_id_image_member_.traverse (id);
os << "binding& idb (sts.id_image_binding ());"
<< "if (grew || idb.version == 0)"
<< "{"
@@ -1095,8 +2114,16 @@ namespace mysql
<< "bind (imb.bind, sts.image ());"
<< "imb.version++;"
<< "}"
- << "sts.update_statement ().execute ();"
- << "}";
+ << "sts.update_statement ().execute ();";
+
+ if (containers)
+ {
+ os << endl;
+ container_calls t (*this, container_calls::update_call);
+ t.traverse (c);
+ }
+
+ os << "}";
// erase ()
//
@@ -1111,19 +2138,29 @@ namespace mysql
<< endl
<< "bool grew (false);"
<< "id_image_type& i (sts.id_image ());";
- names (c, init_id_image_member_names_);
+ init_id_image_member_.traverse (id);
os << "binding& idb (sts.id_image_binding ());"
<< "if (grew || idb.version == 0)"
<< "{"
<< "bind (idb.bind, i);"
<< "idb.version++;"
<< "}"
- << "sts.erase_statement ().execute ();"
- << "}";
+ << "if (sts.erase_statement ().execute () != 1)" << endl
+ << "throw object_not_persistent ();";
+
+ if (containers)
+ {
+ os << endl;
+ container_calls t (*this, container_calls::erase_call);
+ t.traverse (c);
+ }
+
+ os << "}";
// find ()
//
if (def_ctor)
+ {
os << traits << "::pointer_type" << endl
<< traits << "::" << endl
<< "find (database&, const id_type& id)"
@@ -1134,18 +2171,30 @@ namespace mysql
<< "object_statements<object_type>& sts (" << endl
<< "conn.statement_cache ().find<object_type> ());"
<< endl
- << "if (find (sts, id))"
+ << "bool grew (false);"
+ << "if (find (sts, id, grew))"
<< "{"
<< "pointer_type p (access::object_factory< " << type <<
" >::create ());"
<< "pointer_traits< pointer_type >::guard g (p);"
- << "init (pointer_traits< pointer_type >::get_ref (p), " <<
- "sts.image ());"
- << "g.release ();"
+ << "object_type& obj (pointer_traits< pointer_type >::get_ref (p));"
+ << "init (obj, sts.image ());";
+
+ if (containers)
+ {
+ os << endl
+ << "id_image_type& i (sts.id_image ());";
+ container_calls t (*this, container_calls::load_call);
+ t.traverse (c);
+ os << endl;
+ }
+
+ os << "g.release ();"
<< "return p;"
<< "}"
<< "return pointer_type ();"
<< "}";
+ }
os << "bool " << traits << "::" << endl
<< "find (database&, const id_type& id, object_type& obj)"
@@ -1156,23 +2205,34 @@ namespace mysql
<< "object_statements<object_type>& sts (" << endl
<< "conn.statement_cache ().find<object_type> ());"
<< endl
- << "if (find (sts, id))"
+ << "bool grew (false);"
+ << "if (find (sts, id, grew))"
<< "{"
- << "init (obj, sts.image ());"
- << "return true;"
+ << "init (obj, sts.image ());";
+
+ if (containers)
+ {
+ os << endl
+ << "id_image_type& i (sts.id_image ());";
+ container_calls t (*this, container_calls::load_call);
+ t.traverse (c);
+ os << endl;
+ }
+
+ os << "return true;"
<< "}"
<< "return false;"
<< "}";
os << "bool " << traits << "::" << endl
- << "find (mysql::object_statements<object_type>& sts, " <<
- "const id_type& id)"
+ << "find (mysql::object_statements<object_type>& sts," << endl
+ << "const id_type& id," << endl
+ << "bool& grew)"
<< "{"
<< "using namespace mysql;"
<< endl
- << "bool grew (false);"
<< "id_image_type& i (sts.id_image ());";
- names (c, init_id_image_member_names_);
+ init_id_image_member_.traverse (id);
os << "binding& idb (sts.id_image_binding ());"
<< "if (grew || idb.version == 0)"
<< "{"
@@ -1185,15 +2245,13 @@ namespace mysql
<< "bind (imb.bind, sts.image ());"
<< "imb.version++;"
<< "}"
- << "mysql::find_statement& st (sts.find_statement ());"
- << "mysql::find_statement::result r (st.execute ());"
- << endl
- << "if (r == mysql::find_statement::no_data)" << endl
- << "return false;"
- << endl;
+ << "select_statement& st (sts.find_statement ());"
+ << "st.execute ();"
+ << "select_statement::result r (st.fetch ());";
if (grow)
- os << "if (r == mysql::find_statement::truncated)"
+ os << endl
+ << "if (r == select_statement::truncated)"
<< "{"
<< "if (grow (sts.image (), sts.image_error ()))"
<< "{"
@@ -1204,7 +2262,7 @@ namespace mysql
<< "}";
os << "st.free_result ();"
- << "return true;"
+ << "return r != select_statement::no_data;"
<< "}";
// query ()
@@ -1227,11 +2285,11 @@ namespace mysql
<< "bind (imb.bind, sts.image ());"
<< "imb.version++;"
<< "}"
- << "details::shared_ptr<query_statement> st (" << endl
- << "new (details::shared) query_statement (conn," << endl
+ << "details::shared_ptr<select_statement> st (" << endl
+ << "new (details::shared) select_statement (conn," << endl
<< "query_clause + q.clause ()," << endl
- << "imb," << endl
- << "q.parameters ()));"
+ << "q.parameters ()," << endl
+ << "imb));"
<< "st->execute ();"
<< endl
<< "details::shared_ptr<odb::result_impl<object_type> > r (" << endl
@@ -1244,6 +2302,9 @@ namespace mysql
virtual void
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 + " >");
@@ -1254,7 +2315,8 @@ namespace mysql
// grow ()
//
os << "bool " << traits << "::" << endl
- << "grow (image_type&" << (grow (c) ? " i" : "") << ", my_bool* e)"
+ << "grow (image_type&" << (grow ? " i" : "") << ", " <<
+ "my_bool*" << (columns ? " e" : "") << ")"
<< "{"
<< "bool r (false);"
<< endl;
@@ -1269,7 +2331,8 @@ namespace mysql
// bind (image_type)
//
os << "void " << traits << "::" << endl
- << "bind (MYSQL_BIND* b, image_type& i)"
+ << "bind (MYSQL_BIND*" << (columns ? " b" : "") << ", " <<
+ "image_type&" << (columns ? " i" : "") << ")"
<< "{";
index_ = 0;
@@ -1281,7 +2344,8 @@ namespace mysql
// init (image, object)
//
os << "bool " << traits << "::" << endl
- << "init (image_type& i, const value_type& o)"
+ << "init (image_type&" << (columns ? " i" : "") << ", " <<
+ "const value_type&" << (columns ? " o" : "") << ")"
<< "{"
<< "bool grew (false);"
<< endl;
@@ -1295,7 +2359,8 @@ namespace mysql
// init (object, image)
//
os << "void " << traits << "::" << endl
- << "init (value_type& o, const image_type& i)"
+ << "init (value_type&" << (columns ? " o" : "") << ", " <<
+ "const image_type&" << (columns ? " i" : "") << ")"
<< "{";
inherits (c, init_value_base_inherits_);
@@ -1305,8 +2370,6 @@ namespace mysql
}
private:
- id_member id_member_;
-
bool id_;
size_t index_;
@@ -1320,7 +2383,6 @@ namespace mysql
bind_member bind_member_;
traversal::names bind_member_names_;
bind_member bind_id_member_;
- traversal::names bind_id_member_names_;
init_image_base init_image_base_;
traversal::inherits init_image_base_inherits_;
@@ -1328,7 +2390,6 @@ namespace mysql
traversal::names init_image_member_names_;
init_image_member init_id_image_member_;
- traversal::names init_id_image_member_names_;
init_value_base init_value_base_;
traversal::inherits init_value_base_inherits_;
@@ -1359,6 +2420,9 @@ namespace mysql
<< "#include <odb/mysql/transaction.hxx>" << endl
<< "#include <odb/mysql/connection.hxx>" << endl
<< "#include <odb/mysql/statement.hxx>" << endl
+ << "#include <odb/mysql/statement-cache.hxx>" << endl
+ << "#include <odb/mysql/object-statements.hxx>" << endl
+ << "#include <odb/mysql/container-statements.hxx>" << endl
<< "#include <odb/mysql/exceptions.hxx>" << endl;
if (ctx.options.generate_query ())