summaryrefslogtreecommitdiff
path: root/odb/mysql/source.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-10-27 17:36:59 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-10-27 17:36:59 +0200
commit7f6c64f2211d37db76a97fbc79a4b5492302ef2f (patch)
treef2e386644fcaab5c51e3f5ad0ac737ea5b4d5bd2 /odb/mysql/source.cxx
parent5259b98c75f3754a0f713bcee4bddd0ed7ce35ef (diff)
Implement support for composite value types
New test: common/composite.
Diffstat (limited to 'odb/mysql/source.cxx')
-rw-r--r--odb/mysql/source.cxx527
1 files changed, 393 insertions, 134 deletions
diff --git a/odb/mysql/source.cxx b/odb/mysql/source.cxx
index c0ce773..d572560 100644
--- a/odb/mysql/source.cxx
+++ b/odb/mysql/source.cxx
@@ -16,30 +16,24 @@ namespace mysql
{
namespace
{
- struct member_column: traversal::data_member, context
+ struct object_columns: object_columns_base, context
{
- member_column (context& c, string const& suffix = "")
- : context (c), suffix_ (suffix), first_ (true)
+ object_columns (context& c, string const& suffix = "")
+ : object_columns_base (c), context (c), suffix_ (suffix)
{
}
virtual void
- traverse (type& m)
+ column (semantics::data_member&, string const& name, bool first)
{
- if (m.count ("transient"))
- return;
-
- if (first_)
- first_ = false;
- else
+ if (!first)
os << ",\"" << endl;
- os << "\"`" << column_name (m) << "`" << suffix_;
+ os << "\"`" << name << "`" << suffix_;
}
private:
string suffix_;
- bool first_;
};
const char* integer_buffer_types[] =
@@ -82,10 +76,14 @@ namespace mysql
"MYSQL_TYPE_BLOB" // LONGBLOB
};
+ //
+ // bind
+ //
+
struct bind_member: member_base
{
- bind_member (context& c, bool id)
- : member_base (c, id), index_ (0)
+ bind_member (context& c, size_t& index, bool id)
+ : member_base (c, id), index_ (index)
{
}
@@ -93,7 +91,7 @@ namespace mysql
pre (type& m)
{
ostringstream ostr;
- ostr << "b.bind[" << index_ << "UL]";
+ ostr << "b[" << index_ << "UL]";
b = ostr.str ();
if (!id_)
@@ -102,9 +100,21 @@ namespace mysql
}
virtual void
- post (type&)
+ post (type& m)
{
- index_++;
+ if (semantics::class_* c = comp_value (m.type ()))
+ index_ += column_count (*c);
+ else
+ index_++;
+ }
+
+ virtual void
+ traverse_composite (type& m)
+ {
+ os << "composite_value_traits< " << m.type ().fq_name () <<
+ " >::bind (" << endl
+ << "b + " << index_ << "UL, i." << var << "value);"
+ << endl;
}
virtual void
@@ -234,13 +244,40 @@ namespace mysql
private:
string b;
- size_t index_;
+ size_t& index_;
+ };
+
+ struct bind_base: traversal::class_, context
+ {
+ bind_base (context& c, size_t& index)
+ : context (c), index_ (index)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ os << "// " << c.name () << " base" << endl
+ << "//" << endl
+ << "composite_value_traits< " << c.fq_name () <<
+ " >::bind (b + " << index_ << "UL, i);"
+ << endl;
+
+ index_ += column_count (c);
+ }
+
+ private:
+ size_t& index_;
};
+ //
+ // grow
+ //
+
struct grow_member: member_base
{
- grow_member (context& c)
- : member_base (c, false), index_ (0)
+ grow_member (context& c, size_t& index)
+ : member_base (c, false), index_ (index)
{
}
@@ -256,9 +293,23 @@ namespace mysql
}
virtual void
- post (type&)
+ post (type& m)
{
- index_++;
+ if (semantics::class_* c = comp_value (m.type ()))
+ index_ += column_count (*c);
+ else
+ index_++;
+ }
+
+ virtual void
+ traverse_composite (type& m)
+ {
+ os << "if (composite_value_traits< " << m.type ().fq_name () <<
+ " >::grow (" << endl
+ << "i." << var << "value, e + " << index_ << "UL))"
+ << "{"
+ << "r = true;"
+ << "}";
}
virtual void
@@ -349,11 +400,38 @@ namespace mysql
private:
string e;
- size_t index_;
+ size_t& index_;
+ };
+
+ struct grow_base: traversal::class_, context
+ {
+ grow_base (context& c, size_t& index)
+ : context (c), index_ (index)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ os << "// " << c.name () << " base" << endl
+ << "//" << endl
+ << "if (composite_value_traits< " << c.fq_name () <<
+ " >::grow (i, e + " << index_ << "UL))"
+ << "{"
+ << "r = true;"
+ << "}";
+
+ index_ += column_count (c);
+ }
+
+ private:
+ size_t& index_;
};
//
+ // init image
//
+
struct init_image_member: member_base
{
init_image_member (context& c, bool id)
@@ -366,14 +444,21 @@ namespace mysql
virtual void
pre (type& m)
{
- type = m.type ().fq_name (m.belongs ().hint ());
- image_type = member_image_type_.image_type (m);
- db_type = member_database_type_.database_type (m);
+ semantics::type& t (m.type ());
- traits = "mysql::value_traits< "
- + type + ", "
- + image_type + ", "
- + db_type + " >";
+ if (comp_value (t))
+ traits = "composite_value_traits< " + t.fq_name () + " >";
+ else
+ {
+ type = t.fq_name (m.belongs ().hint ());
+ image_type = member_image_type_.image_type (m);
+ db_type = member_database_type_.database_type (m);
+
+ traits = "mysql::value_traits< "
+ + type + ", "
+ + image_type + ", "
+ + db_type + " >";
+ }
if (id_)
member = "id";
@@ -388,21 +473,35 @@ namespace mysql
}
virtual void
+ traverse_composite (type&)
+ {
+ os << "if (" << traits << "::init (i." << var << "value, " <<
+ member << "))"
+ << "{"
+ << "grew = true;"
+ << "}";
+ }
+
+ virtual void
traverse_integer (type&, sql_type const&)
{
- os << traits << "::set_image (" << endl
+ os << "{"
+ << "bool is_null;"
+ << traits << "::set_image (" << endl
<< "i." << var << "value, is_null, " << member << ");"
<< "i." << var << "null = is_null;"
- << endl;
+ << "}";
}
virtual void
traverse_float (type&, sql_type const&)
{
- os << traits << "::set_image (" << endl
+ os << "{"
+ << "bool is_null;"
+ << traits << "::set_image (" << endl
<< "i." << var << "value, is_null, " << member << ");"
<< "i." << var << "null = is_null;"
- << endl;
+ << "}";
}
virtual void
@@ -411,6 +510,7 @@ namespace mysql
// @@ 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 ());"
<< traits << "::set_image (" << endl
@@ -427,10 +527,12 @@ namespace mysql
virtual void
traverse_date_time (type&, sql_type const&)
{
- os << traits << "::set_image (" << endl
+ os << "{"
+ << "bool is_null;"
+ << traits << "::set_image (" << endl
<< "i." << var << "value, is_null, " << member << ");"
<< "i." << var << "null = is_null;"
- << endl;
+ << "}";
}
virtual void
@@ -439,6 +541,7 @@ namespace mysql
// @@ 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 ());"
<< traits << "::set_image (" << endl
@@ -456,6 +559,7 @@ namespace mysql
traverse_long_string (type&, sql_type const&)
{
os << "{"
+ << "bool is_null;"
<< "std::size_t size;"
<< "std::size_t cap (i." << var << "value.capacity ());"
<< traits << "::set_image (" << endl
@@ -475,6 +579,7 @@ namespace mysql
// Represented as a BLOB.
//
os << "{"
+ << "bool is_null;"
<< "std::size_t size;"
<< traits << "::set_image (" << endl
<< "i." << var << "value," << endl
@@ -493,6 +598,7 @@ namespace mysql
// Represented as a string.
//
os << "{"
+ << "bool is_null;"
<< "std::size_t size;"
<< "std::size_t cap (i." << var << "value.capacity ());"
<< traits << "::set_image (" << endl
@@ -512,6 +618,7 @@ namespace mysql
// Represented as a string.
//
os << "{"
+ << "bool is_null;"
<< "std::size_t size;"
<< "std::size_t cap (i." << var << "value.capacity ());"
<< traits << "::set_image (" << endl
@@ -536,8 +643,30 @@ namespace mysql
member_database_type member_database_type_;
};
+ struct init_image_base: traversal::class_, context
+ {
+ init_image_base (context& c)
+ : context (c)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ os << "// " << c.name () << " base" << endl
+ << "//" << endl
+ << "if (composite_value_traits< " << c.fq_name () <<
+ " >::init (i, o))"
+ << "{"
+ << "grew = true;"
+ << "}";
+ }
+ };
+
//
+ // init value
//
+
struct init_value_member: member_base
{
init_value_member (context& c)
@@ -550,20 +679,34 @@ namespace mysql
virtual void
pre (type& m)
{
- type = m.type ().fq_name (m.belongs ().hint ());
- image_type = member_image_type_.image_type (m);
- db_type = member_database_type_.database_type (m);
+ semantics::type& t (m.type ());
- traits = "mysql::value_traits< "
- + type + ", "
- + image_type + ", "
- + db_type + " >";
+ if (comp_value (t))
+ traits = "composite_value_traits< " + t.fq_name () + " >";
+ 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);
+
+ traits = "mysql::value_traits< "
+ + type + ", "
+ + image_type + ", "
+ + db_type + " >";
+ }
os << "// " << m.name () << endl
<< "//" << endl;
}
virtual void
+ traverse_composite (type& m)
+ {
+ os << traits << "::init (o." << m.name () << ", i." << var << "value);"
+ << endl;
+ }
+
+ virtual void
traverse_integer (type& m, sql_type const&)
{
os << traits << "::set_value (" << endl
@@ -672,19 +815,54 @@ namespace mysql
member_database_type member_database_type_;
};
+ struct init_value_base: traversal::class_, context
+ {
+ init_value_base (context& c)
+ : context (c)
+ {
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ os << "// " << c.name () << " base" << endl
+ << "//" << endl
+ << "composite_value_traits< " << c.fq_name () << " >::init (o, i);"
+ << endl;
+ }
+ };
+
//
//
struct class_: traversal::class_, context
{
class_ (context& c)
: context (c),
+ grow_base_ (c, index_),
+ grow_member_ (c, index_),
+ bind_base_ (c, index_),
+ bind_member_ (c, index_, false),
+ bind_id_member_ (c, index_, true),
+ init_image_base_ (c),
init_image_member_ (c, false),
init_id_image_member_ (c, true),
+ init_value_base_ (c),
init_value_member_ (c)
{
- *this >> init_image_member_names_ >> init_image_member_;
- *this >> init_id_image_member_names_ >> init_id_image_member_;
- *this >> init_value_member_names_ >> init_value_member_;
+ grow_base_inherits_ >> grow_base_;
+ grow_member_names_ >> grow_member_;
+
+ 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_;
}
virtual void
@@ -693,28 +871,25 @@ namespace mysql
if (c.file () != unit.file ())
return;
- if (!c.count ("object"))
- return;
+ if (c.count ("object"))
+ traverse_object (c);
+ else if (comp_value (c))
+ traverse_value (c);
+ }
+ virtual void
+ traverse_object (type& c)
+ {
string const& type (c.fq_name ());
string traits ("access::object_traits< " + type + " >");
+
+ 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 ());
bool auto_id (id.count ("auto"));
- member_count_.traverse (c);
- size_t column_count (member_count_.count ());
-
- bool has_grow;
- {
- has_grow_member m (*this);
- traversal::names n (m);
- names (c, n);
- has_grow = m.result ();
- }
-
os << "// " << c.name () << endl
<< "//" << endl
<< endl;
@@ -723,9 +898,8 @@ namespace mysql
//
if (options.generate_query ())
{
- query_column t (*this, c);
- traversal::names n (t);
- names (c, n);
+ query_columns t (*this, c);
+ t.traverse (c);
}
// persist_statement
@@ -734,15 +908,14 @@ namespace mysql
<< "\"INSERT INTO `" << table_name (c) << "` (\"" << endl;
{
- member_column m (*this);
- traversal::names n (m);
- names (c, n);
+ object_columns t (*this);
+ t.traverse (c);
}
os << "\"" << endl
<< "\") VALUES (";
- for (size_t i (0); i < column_count; ++i)
+ for (size_t i (0), n (column_count (c)); i < n; ++i)
os << (i != 0 ? "," : "") << '?';
os << ")\";"
@@ -754,9 +927,8 @@ namespace mysql
<< "\"SELECT \"" << endl;
{
- member_column m (*this);
- traversal::names n (m);
- names (c, n);
+ object_columns t (*this);
+ t.traverse (c);
}
os << "\"" << endl
@@ -770,9 +942,8 @@ namespace mysql
<< "\"UPDATE `" << table_name (c) << "` SET \"" << endl;
{
- member_column m (*this, " = ?");
- traversal::names n (m);
- names (c, n);
+ object_columns t (*this, " = ?");
+ t.traverse (c);
}
os << "\"" << endl
@@ -794,9 +965,8 @@ namespace mysql
<< "\"SELECT \"" << endl;
{
- member_column m (*this);
- traversal::names n (m);
- names (c, n);
+ object_columns t (*this);
+ t.traverse (c);
}
os << "\"" << endl
@@ -806,53 +976,41 @@ namespace mysql
// grow ()
//
- if (has_grow)
- {
- os << "bool " << traits << "::" << endl
- << "grow (image_type& i, my_bool* e)"
- << "{"
- << "bool r (false);"
- << endl;
+ os << "bool " << traits << "::" << endl
+ << "grow (image_type&" << (grow ? " i" : "") << ", my_bool* e)"
+ << "{"
+ << "bool r (false);"
+ << endl;
- {
- grow_member m (*this);
- traversal::names n (m);
- names (c, n);
- }
+ index_ = 0;
+ inherits (c, grow_base_inherits_);
+ names (c, grow_member_names_);
- os << "return r;"
- << "}";
- }
+ os << "return r;"
+ << "}";
// bind (image_type)
//
os << "void " << traits << "::" << endl
- << "bind (mysql::binding& b, image_type& i)"
+ << "bind (MYSQL_BIND* b, image_type& i)"
<< "{";
- {
- bind_member m (*this, false);
- traversal::names n (m);
- names (c, n);
- }
+ index_ = 0;
+ inherits (c, bind_base_inherits_);
+ names (c, bind_member_names_);
- os << "b.version++;"
- << "}";
+ os << "}";
// bind (id_image_type)
//
os << "void " << traits << "::" << endl
- << "bind (mysql::binding& b, id_image_type& i)"
+ << "bind (MYSQL_BIND* b, id_image_type& i)"
<< "{";
- {
- bind_member m (*this, true);
- traversal::names n (m);
- names (c, n);
- }
+ index_ = 0;
+ names (c, bind_id_member_names_);
- os << "b.version++;"
- << "}";
+ os << "}";
// init (image, object)
//
@@ -860,9 +1018,11 @@ namespace mysql
<< "init (image_type& i, const object_type& o)"
<< "{"
<< "bool grew (false);"
- << "bool is_null;"
<< endl;
+
+ inherits (c, init_image_base_inherits_);
names (c, init_image_member_names_);
+
os << "return grew;"
<< "}";
@@ -871,7 +1031,10 @@ namespace mysql
os << "void " << traits << "::" << endl
<< "init (object_type& o, const image_type& i)"
<< "{";
+
+ inherits (c, init_value_base_inherits_);
names (c, init_value_member_names_);
+
os << "}";
// persist ()
@@ -892,9 +1055,11 @@ namespace mysql
os << "obj." << id.name () << " = 0;"
<< endl;
- os << "if (init (sts.image (), obj) || b.version == 0)" << endl
- << "bind (b, sts.image ());"
- << endl
+ os << "if (init (sts.image (), obj) || b.version == 0)"
+ << "{"
+ << "bind (b.bind, sts.image ());"
+ << "b.version++;"
+ << "}"
<< "mysql::persist_statement& st (sts.persist_statement ());"
<< "st.execute ();";
@@ -914,18 +1079,22 @@ namespace mysql
<< "object_statements<object_type>& sts (" << endl
<< "conn.statement_cache ().find<object_type> ());"
<< endl
- << "bool is_null, grew (false);"
+ << "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_);
os << "binding& idb (sts.id_image_binding ());"
- << "if (grew || idb.version == 0)" << endl
- << "bind (idb, i);"
- << endl
+ << "if (grew || idb.version == 0)"
+ << "{"
+ << "bind (idb.bind, i);"
+ << "idb.version++;"
+ << "}"
<< "binding& imb (sts.image_binding ());"
- << "if (init (sts.image (), obj) || imb.version == 0)" << endl
- << "bind (imb, sts.image ());"
- << endl
+ << "if (init (sts.image (), obj) || imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, sts.image ());"
+ << "imb.version++;"
+ << "}"
<< "sts.update_statement ().execute ();"
<< "}";
@@ -940,13 +1109,15 @@ namespace mysql
<< "object_statements<object_type>& sts (" << endl
<< "conn.statement_cache ().find<object_type> ());"
<< endl
- << "bool is_null, grew (false);"
+ << "bool grew (false);"
<< "id_image_type& i (sts.id_image ());";
names (c, init_id_image_member_names_);
os << "binding& idb (sts.id_image_binding ());"
- << "if (grew || idb.version == 0)" << endl
- << "bind (idb, i);"
- << endl
+ << "if (grew || idb.version == 0)"
+ << "{"
+ << "bind (idb.bind, i);"
+ << "idb.version++;"
+ << "}"
<< "sts.erase_statement ().execute ();"
<< "}";
@@ -999,17 +1170,21 @@ namespace mysql
<< "{"
<< "using namespace mysql;"
<< endl
- << "bool is_null, grew (false);"
+ << "bool grew (false);"
<< "id_image_type& i (sts.id_image ());";
names (c, init_id_image_member_names_);
os << "binding& idb (sts.id_image_binding ());"
- << "if (grew || idb.version == 0)" << endl
- << "bind (idb, i);"
- << endl
+ << "if (grew || idb.version == 0)"
+ << "{"
+ << "bind (idb.bind, i);"
+ << "idb.version++;"
+ << "}"
<< "binding& imb (sts.image_binding ());"
- << "if (imb.version == 0)" << endl
- << "bind (imb, sts.image ());"
- << endl
+ << "if (imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, sts.image ());"
+ << "imb.version++;"
+ << "}"
<< "mysql::find_statement& st (sts.find_statement ());"
<< "mysql::find_statement::result r (st.execute ());"
<< endl
@@ -1017,12 +1192,13 @@ namespace mysql
<< "return false;"
<< endl;
- if (has_grow)
+ if (grow)
os << "if (r == mysql::find_statement::truncated)"
<< "{"
<< "if (grow (sts.image (), sts.image_error ()))"
<< "{"
- << "bind (imb, sts.image ());"
+ << "bind (imb.bind, sts.image ());"
+ << "imb.version++;"
<< "st.refetch ();"
<< "}"
<< "}";
@@ -1046,9 +1222,11 @@ namespace mysql
<< "conn.statement_cache ().find<object_type> ());"
<< endl
<< "binding& imb (sts.image_binding ());"
- << "if (imb.version == 0)" << endl
- << "bind (imb, sts.image ());"
- << endl
+ << "if (imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, sts.image ());"
+ << "imb.version++;"
+ << "}"
<< "details::shared_ptr<query_statement> st (" << endl
<< "new (details::shared) query_statement (conn," << endl
<< "query_clause + q.clause ()," << endl
@@ -1063,16 +1241,97 @@ namespace mysql
}
}
+ virtual void
+ traverse_value (type& c)
+ {
+ string const& type (c.fq_name ());
+ string traits ("access::composite_value_traits< " + type + " >");
+
+ os << "// " << c.name () << endl
+ << "//" << endl
+ << endl;
+
+ // grow ()
+ //
+ os << "bool " << traits << "::" << endl
+ << "grow (image_type&" << (grow (c) ? " i" : "") << ", my_bool* e)"
+ << "{"
+ << "bool r (false);"
+ << endl;
+
+ index_ = 0;
+ inherits (c, grow_base_inherits_);
+ names (c, grow_member_names_);
+
+ os << "return r;"
+ << "}";
+
+ // bind (image_type)
+ //
+ os << "void " << traits << "::" << endl
+ << "bind (MYSQL_BIND* b, image_type& i)"
+ << "{";
+
+ index_ = 0;
+ inherits (c, bind_base_inherits_);
+ names (c, bind_member_names_);
+
+ os << "}";
+
+ // init (image, object)
+ //
+ os << "bool " << traits << "::" << endl
+ << "init (image_type& i, const value_type& o)"
+ << "{"
+ << "bool grew (false);"
+ << endl;
+
+ inherits (c, init_image_base_inherits_);
+ names (c, init_image_member_names_);
+
+ os << "return grew;"
+ << "}";
+
+ // init (object, image)
+ //
+ os << "void " << traits << "::" << endl
+ << "init (value_type& o, const image_type& i)"
+ << "{";
+
+ inherits (c, init_value_base_inherits_);
+ names (c, init_value_member_names_);
+
+ os << "}";
+ }
+
private:
id_member id_member_;
- member_count member_count_;
+ bool id_;
+ size_t index_;
+
+ grow_base grow_base_;
+ traversal::inherits grow_base_inherits_;
+ grow_member grow_member_;
+ traversal::names grow_member_names_;
+
+ bind_base bind_base_;
+ traversal::inherits bind_base_inherits_;
+ 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_;
init_image_member init_image_member_;
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_;
init_value_member init_value_member_;
traversal::names init_value_member_names_;
};