aboutsummaryrefslogtreecommitdiff
path: root/odb/mysql
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-11-22 14:18:40 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-11-22 14:18:40 +0200
commit759c865ebbdf8401e58ef5df705f9d1ad3d83cc9 (patch)
tree142b8b4f0ef70774632ae6e9254b9514ccbc8d29 /odb/mysql
parent4a50c5a7e9976587569276c768f85ad481694e70 (diff)
Implement support for one-to-{one,many} inverse relationships
New pragma: inverse.
Diffstat (limited to 'odb/mysql')
-rw-r--r--odb/mysql/common.cxx36
-rw-r--r--odb/mysql/common.hxx8
-rw-r--r--odb/mysql/header.cxx6
-rw-r--r--odb/mysql/schema.cxx9
-rw-r--r--odb/mysql/source.cxx204
5 files changed, 202 insertions, 61 deletions
diff --git a/odb/mysql/common.cxx b/odb/mysql/common.cxx
index d7e6187..e33e7df 100644
--- a/odb/mysql/common.cxx
+++ b/odb/mysql/common.cxx
@@ -36,16 +36,20 @@ namespace mysql
if (comp_value (t))
{
member_info mi (m, t, var, fq_type_override_);
- pre (mi);
- traverse_composite (mi);
- post (mi);
+ if (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);
+ if (pre (mi))
+ {
+ traverse_container (mi);
+ post (mi);
+ }
}
else
{
@@ -55,17 +59,21 @@ namespace mysql
{
member_info mi (m, id_member (*c).type (), var, fq_type_override_);
mi.st = &st;
- pre (mi);
- traverse_object_pointer (mi);
- post (mi);
+ if (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);
+ if (pre (mi))
+ {
+ traverse_simple (mi);
+ post (mi);
+ }
}
}
}
@@ -475,7 +483,7 @@ namespace mysql
}
}
- void query_columns::
+ bool query_columns::
column (semantics::data_member& m, string const& col_name, bool)
{
string name (public_name (m));
@@ -509,5 +517,7 @@ namespace mysql
<< column << ");"
<< endl;
}
+
+ return true;
}
}
diff --git a/odb/mysql/common.hxx b/odb/mysql/common.hxx
index fb1f2a3..3044aa9 100644
--- a/odb/mysql/common.hxx
+++ b/odb/mysql/common.hxx
@@ -66,9 +66,13 @@ namespace mysql
}
};
- virtual void
+ // The false return value indicates that no further callbacks
+ // should be called for this member.
+ //
+ virtual bool
pre (member_info&)
{
+ return true;
}
virtual void
@@ -248,7 +252,7 @@ namespace mysql
virtual void
composite (semantics::data_member&, semantics::type&);
- virtual void
+ virtual bool
column (semantics::data_member&, string const&, bool);
private:
diff --git a/odb/mysql/header.cxx b/odb/mysql/header.cxx
index 1dc080a..4d604a4 100644
--- a/odb/mysql/header.cxx
+++ b/odb/mysql/header.cxx
@@ -29,17 +29,19 @@ namespace mysql
{
}
- virtual void
+ virtual bool
pre (member_info& mi)
{
if (container (mi.t))
- return;
+ return false;
image_type = member_image_type_.image_type (mi.m);
if (var_override_.empty ())
os << "// " << mi.m.name () << endl
<< "//" << endl;
+
+ return true;
}
virtual void
diff --git a/odb/mysql/schema.cxx b/odb/mysql/schema.cxx
index 0c004ad..0007121 100644
--- a/odb/mysql/schema.cxx
+++ b/odb/mysql/schema.cxx
@@ -23,9 +23,14 @@ namespace mysql
{
}
- virtual void
+ virtual bool
column (semantics::data_member& m, string const& name, bool first)
{
+ // Ignore inverse object pointers.
+ //
+ if (inverse (m))
+ return false;
+
if (!first)
os << "," << endl;
@@ -40,6 +45,8 @@ namespace mysql
os << " REFERENCES `" << table_name (*c) << "` (`" <<
column_name (id_member (*c)) << "`)";
}
+
+ return true;
}
private:
diff --git a/odb/mysql/source.cxx b/odb/mysql/source.cxx
index 1588e36..bdcae1b 100644
--- a/odb/mysql/source.cxx
+++ b/odb/mysql/source.cxx
@@ -18,36 +18,130 @@ namespace mysql
{
struct object_columns: object_columns_base, context
{
- object_columns (context& c, char const* suffix = "")
+ object_columns (context& c,
+ std::string const& table_name,
+ bool out,
+ char const* suffix = "")
: object_columns_base (c),
context (c),
+ table_name_ (table_name),
+ out_ (out),
first_ (true),
suffix_ (suffix)
{
}
- object_columns (context& c, bool first, char const* suffix = "")
+ object_columns (context& c,
+ std::string const& table_name,
+ bool out,
+ bool first,
+ char const* suffix = "")
: object_columns_base (c),
context (c),
+ table_name_ (table_name),
+ out_ (out),
first_ (first),
suffix_ (suffix)
{
}
- virtual void
- column (semantics::data_member&, string const& name, bool first)
+ virtual bool
+ column (semantics::data_member& m, string const& name, bool first)
{
+ semantics::data_member* im (inverse (m));
+
+ // Ignore inverse object pointers if we are generating 'in' columns.
+ //
+ if (im != 0 && !out_)
+ return false;
+
if (!first || !first_)
os << ",\"" << endl;
- os << "\"`" << name << "`" << suffix_;
+ // Inverse object pointers come from a joined table.
+ //
+ if (im != 0)
+ {
+ semantics::class_* c (object_pointer (m));
+
+ if (container (im->type ()))
+ {
+ // This container is a direct member of the class so the table
+ // prefix is just the class table name.
+ //
+ table_prefix tp (table_name (*c) + "_", 1);
+ string const& it (table_name (*im, tp));
+ string const& id (column_name (*im, "id", "object_id"));
+
+ os << "\"`" << it << "`.`" << id << "`" << suffix_;
+ }
+ else
+ {
+ os << "\"`" << table_name (*c) << "`.`" <<
+ column_name (id_member (*c)) << "`" << suffix_;
+ }
+ }
+ else
+ os << "\"`" << table_name_ << "`.`" << name << "`" << suffix_;
+
+ return true;
}
private:
+ string table_name_;
+ bool out_;
bool first_;
string suffix_;
};
+ struct object_joins: object_columns_base, context
+ {
+ object_joins (context& c, semantics::class_& scope)
+ : object_columns_base (c),
+ context (c),
+ table_ (table_name (scope)),
+ id_ (id_member (scope))
+ {
+ }
+
+ virtual bool
+ column (semantics::data_member& m, string const&, bool)
+ {
+ if (semantics::data_member* im = inverse (m))
+ {
+ semantics::class_* c (object_pointer (m));
+
+ if (container (im->type ()))
+ {
+ // This container is a direct member of the class so the table
+ // prefix is just the class table name.
+ //
+ table_prefix tp (table_name (*c) + "_", 1);
+ string const& it (table_name (*im, tp));
+ string const& val (column_name (*im, "value", "value"));
+
+ os << "\" LEFT JOIN `" << it << "` ON `" << it << "`.`" <<
+ val << "` = `" << table_ << "`.`" <<
+ column_name (id_) << "`\"" << endl;
+ }
+ else
+ {
+ string const& it (table_name (*c));
+
+ os << "\" LEFT JOIN `" << it << "` ON `" << it << "`.`" <<
+ column_name (*im) << "` = `" << table_ << "`.`" <<
+ column_name (id_) << "`\"" << endl;
+ }
+ }
+
+ return true;
+ }
+
+ private:
+ string table_;
+ semantics::data_member& id_;
+ };
+
const char* integer_buffer_types[] =
{
"MYSQL_TYPE_TINY",
@@ -111,11 +205,11 @@ namespace mysql
{
}
- virtual void
+ virtual bool
pre (member_info& mi)
{
if (container (mi.t))
- return;
+ return false;
ostringstream ostr;
ostr << "b[n]";
@@ -124,16 +218,21 @@ namespace mysql
arg = arg_override_.empty () ? string ("i") : arg_override_;
if (var_override_.empty ())
+ {
os << "// " << mi.m.name () << endl
<< "//" << endl;
+
+ if (inverse (mi.m, key_prefix_))
+ os << "if (out)"
+ << "{";
+ }
+
+ return true;
}
virtual void
post (member_info& mi)
{
- if (container (mi.t))
- return;
-
if (var_override_.empty ())
{
if (semantics::class_* c = comp_value (mi.t))
@@ -141,7 +240,10 @@ namespace mysql
else
os << "n++;";
- os << endl;
+ if (inverse (mi.m, key_prefix_))
+ os << "}";
+ else
+ os << endl;
}
}
@@ -314,11 +416,11 @@ namespace mysql
{
}
- virtual void
+ virtual bool
pre (member_info& mi)
{
if (container (mi.t))
- return;
+ return false;
ostringstream ostr;
ostr << "e[" << index_ << "UL]";
@@ -327,14 +429,14 @@ namespace mysql
if (var_override_.empty ())
os << "// " << mi.m.name () << endl
<< "//" << endl;
+
+ return true;
}
virtual void
post (member_info& mi)
{
- if (container (mi.t))
- return;
- else if (semantics::class_* c = comp_value (mi.t))
+ if (semantics::class_* c = comp_value (mi.t))
index_ += in_column_count (*c);
else
index_++;
@@ -496,11 +598,14 @@ namespace mysql
{
}
- virtual void
+ virtual bool
pre (member_info& mi)
{
- if (container (mi.t))
- return;
+ // Ignore containers (they get their own table) and inverse
+ // object pointers (they are not present in the 'in' binding).
+ //
+ if (container (mi.t) || inverse (mi.m, key_prefix_))
+ return false;
if (!member_override_.empty ())
member = member_override_;
@@ -555,14 +660,13 @@ namespace mysql
+ image_type + ",\n "
+ db_type + " >";
}
+
+ return true;
}
virtual void
post (member_info& mi)
{
- if (container (mi.t))
- return;
-
if (!comp_value (mi.t))
{
if (object_pointer (mi.m, key_prefix_))
@@ -757,11 +861,11 @@ namespace mysql
{
}
- virtual void
+ virtual bool
pre (member_info& mi)
{
if (container (mi.t))
- return;
+ return false;
if (!member_override_.empty ())
member = member_override_;
@@ -812,14 +916,13 @@ namespace mysql
+ image_type + ",\n "
+ db_type + " >";
}
+
+ return true;
}
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 ()
@@ -1060,7 +1163,7 @@ namespace mysql
{
if (comp_value (*kt))
{
- object_columns t (*this, false);
+ object_columns t (*this, table, false, false);
t.traverse_composite (m, *kt, "key", "key");
}
else
@@ -1079,7 +1182,7 @@ namespace mysql
if (comp_value (vt))
{
- object_columns t (*this, false);
+ object_columns t (*this, table, false, false);
t.traverse_composite (m, vt, "value", "value");
}
else
@@ -1116,7 +1219,7 @@ namespace mysql
{
if (comp_value (*kt))
{
- object_columns t (*this, false);
+ object_columns t (*this, table, false, false);
t.traverse_composite (m, *kt, "key", "key");
}
else
@@ -1135,7 +1238,7 @@ namespace mysql
if (comp_value (vt))
{
- object_columns t (*this, false);
+ object_columns t (*this, table, false, false);
t.traverse_composite (m, vt, "value", "value");
}
else
@@ -2008,13 +2111,15 @@ namespace mysql
t.traverse (c);
}
+ string const& table (table_name (c));
+
// persist_statement
//
os << "const char* const " << traits << "::persist_statement =" << endl
- << "\"INSERT INTO `" << table_name (c) << "` (\"" << endl;
+ << "\"INSERT INTO `" << table << "` (\"" << endl;
{
- object_columns t (*this);
+ object_columns t (*this, table, false);
t.traverse (c);
}
@@ -2033,34 +2138,40 @@ namespace mysql
<< "\"SELECT \"" << endl;
{
- object_columns t (*this);
+ object_columns t (*this, table, true);
t.traverse (c);
}
os << "\"" << endl
- << "\" FROM `" << table_name (c) << "` WHERE `" <<
- column_name (id) << "` = ?\";"
+ << "\" FROM `" << table << "`\"" << endl;
+
+ {
+ object_joins t (*this, c);
+ t.traverse (c);
+ }
+
+ os << "\" WHERE `" << table << "`.`" << column_name (id) << "` = ?\";"
<< endl;
// update_statement
//
os << "const char* const " << traits << "::update_statement =" << endl
- << "\"UPDATE `" << table_name (c) << "` SET \"" << endl;
+ << "\"UPDATE `" << table << "` SET \"" << endl;
{
- object_columns t (*this, " = ?");
+ object_columns t (*this, table, false, " = ?");
t.traverse (c);
}
os << "\"" << endl
- << "\" WHERE `" << column_name (id) << "` = ?\";"
+ << "\" WHERE `" << table << "`.`" << column_name (id) << "` = ?\";"
<< endl;
// erase_statement
//
os << "const char* const " << traits << "::erase_statement =" << endl
- << "\"DELETE FROM `" << table_name (c) << "`\"" << endl
- << "\" WHERE `" << column_name (id) << "` = ?\";"
+ << "\"DELETE FROM `" << table << "`\"" << endl
+ << "\" WHERE `" << table << "`.`" << column_name (id) << "` = ?\";"
<< endl;
// query_clause
@@ -2071,12 +2182,19 @@ namespace mysql
<< "\"SELECT \"" << endl;
{
- object_columns t (*this);
+ object_columns t (*this, table, true);
t.traverse (c);
}
os << "\"" << endl
- << "\" FROM `" << table_name (c) << "` \";"
+ << "\" FROM `" << table << "`\"" << endl;
+
+ {
+ object_joins t (*this, c);
+ t.traverse (c);
+ }
+
+ os << "\" \";"
<< endl;
}