aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-04-25 12:30:04 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-04-25 12:30:04 +0200
commitd7662d2cc72668eee0a21737edfcc1bbe41c229b (patch)
tree7a7c61af162e1bdb870a701cb54a747f6bafa0eb
parent82d1a3918899958cb26ed77119fbf908beb94dbc (diff)
Reuse container traits from composite values
-rw-r--r--odb/common.cxx30
-rw-r--r--odb/common.hxx19
-rw-r--r--odb/relational/header.hxx85
-rw-r--r--odb/relational/source.hxx365
4 files changed, 301 insertions, 198 deletions
diff --git a/odb/common.cxx b/odb/common.cxx
index bf163d4..20fd354 100644
--- a/odb/common.cxx
+++ b/odb/common.cxx
@@ -17,21 +17,28 @@ simple (semantics::data_member&)
}
void object_members_base::
-composite (semantics::data_member&, semantics::class_& c)
+container (semantics::data_member&)
+{
+}
+
+void object_members_base::
+composite (semantics::data_member*, semantics::class_& c)
{
inherits (c);
names (c);
}
void object_members_base::
-container (semantics::data_member&)
+object (semantics::class_& c)
{
+ inherits (c);
+ names (c);
}
void object_members_base::
traverse_composite (semantics::data_member& m, semantics::class_& c)
{
- composite (m, c);
+ composite (&m, c);
}
void object_members_base::
@@ -47,8 +54,8 @@ traverse (semantics::class_& c)
semantics::class_* prev;
if (obj)
{
- prev = object;
- object = &c;
+ prev = context::object;
+ context::object = &c;
}
if (obj && build_table_prefix_)
@@ -65,8 +72,7 @@ traverse (semantics::class_& c)
tb = true;
}
- inherits (c);
- names (c);
+ object (c);
if (tb)
{
@@ -76,12 +82,14 @@ traverse (semantics::class_& c)
}
else
{
- inherits (c);
- names (c);
+ if (obj)
+ object (c);
+ else
+ composite (0, c);
}
if (obj)
- object = prev;
+ context::object = prev;
}
void object_members_base::member::
@@ -134,7 +142,7 @@ traverse (semantics::data_member& m)
om_.table_prefix_.level++;
}
- om_.composite (m, *comp);
+ om_.composite (&m, *comp);
if (om_.build_table_prefix_)
{
diff --git a/odb/common.hxx b/odb/common.hxx
index 2d220b8..548e2a2 100644
--- a/odb/common.hxx
+++ b/odb/common.hxx
@@ -18,16 +18,23 @@ struct object_members_base: traversal::class_, virtual context
virtual void
simple (semantics::data_member&);
- // If you override this function, call the base if you want the composite
- // to be recursively traversed. The second argument is the actual composite
- // type, which is not necessarily the same as m.type() in case of
- // traverse_composite().
+ virtual void
+ container (semantics::data_member&);
+
+ // If you override this function, you can call the base to traverse
+ // bases and members. The first argument is the data member and can
+ // be NULL if we are traversing the root type or a base. The second
+ // argument is the actual composite type, which is not necessarily
+ // the same as m.type ().
//
virtual void
- composite (semantics::data_member&, semantics::class_&);
+ composite (semantics::data_member*, semantics::class_&);
+ // If you override this function, you can call the base to traverse
+ // bases and members.
+ //
virtual void
- container (semantics::data_member&);
+ object (semantics::class_&);
public:
object_members_base ()
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 9e258ea..5ad7d2e 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -181,20 +181,47 @@ namespace relational
{
typedef container_traits base;
- container_traits (semantics::class_& obj)
- : object_members_base (true, false), object_ (obj)
+ container_traits (semantics::class_& c)
+ : object_members_base (true, false), c_ (c)
{
}
virtual void
+ composite (semantics::data_member* m, semantics::class_& c)
+ {
+ if (c_.count ("object"))
+ object_members_base::composite (m, c);
+ else
+ {
+ // If we are generating traits for a composite value type, then
+ // we don't want to go into its bases or it composite members.
+ //
+ if (m == 0 && &c == &c_)
+ names (c);
+ }
+ }
+
+ virtual void
container (semantics::data_member& m)
{
using semantics::type;
using semantics::class_;
- // Figure out if this member is from a base object.
+ // Figure out if this member is from a base object or composite
+ // value and whether it is abstract.
//
- bool base (context::object != &object_);
+ bool base, abst;
+
+ if (c_.count ("object"))
+ {
+ base = context::object != &c_ || !m.scope ().count ("object");
+ abst = abstract (c_);
+ }
+ else
+ {
+ base = false; // We don't go into bases.
+ abst = true; // Always abstract.
+ }
type& t (m.type ());
container_kind_type ck (container_kind (t));
@@ -303,25 +330,36 @@ namespace relational
<< "struct " << name;
if (base)
- os << ": access::object_traits< " << context::object->fq_name () <<
- " >::" << name;
+ {
+ semantics::class_& b (dynamic_cast<semantics::class_&> (m.scope ()));
+
+ if (b.count ("object"))
+ os << ": access::object_traits< " << b.fq_name () << " >::" <<
+ name;
+ else
+ os << ": access::composite_value_traits< " << b.fq_name () <<
+ " >::" << public_name (m) << "_traits"; // No prefix_.
+ }
os << "{";
- // column_count
- //
- os << "static const std::size_t cond_column_count = " <<
- cond_columns << "UL;"
- << "static const std::size_t data_column_count = " <<
- data_columns << "UL;"
- << endl;
+ if (!abst)
+ {
+ // column_count
+ //
+ os << "static const std::size_t cond_column_count = " <<
+ cond_columns << "UL;"
+ << "static const std::size_t data_column_count = " <<
+ data_columns << "UL;"
+ << endl;
- // Statements.
- //
- os << "static const char* const insert_one_statement;"
- << "static const char* const select_all_statement;"
- << "static const char* const delete_all_statement;"
- << endl;
+ // Statements.
+ //
+ os << "static const char* const insert_one_statement;"
+ << "static const char* const select_all_statement;"
+ << "static const char* const delete_all_statement;"
+ << endl;
+ }
if (base)
{
@@ -659,7 +697,7 @@ namespace relational
}
private:
- semantics::class_& object_;
+ semantics::class_& c_;
};
//
@@ -952,6 +990,13 @@ namespace relational
//
image_type_->traverse (c);
+ // Containers.
+ //
+ {
+ instance<container_traits> t (c);
+ t->traverse (c);
+ }
+
// grow ()
//
os << "static bool" << endl
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 844dc11..5b2ec8d 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -560,12 +560,13 @@ namespace relational
{
typedef container_traits base;
- container_traits (semantics::class_& obj) // @@ context::object
- : object_members_base (true, true),
- object_ (obj),
- id_member_ (id_member (obj))
+ container_traits (semantics::class_& c)
+ : object_members_base (true, true), c_ (c)
{
- obj_scope_ = "access::object_traits< " + obj.fq_name () + " >";
+ if (c.count ("object"))
+ scope_ = "access::object_traits< " + c.fq_name () + " >";
+ else
+ scope_ = "access::composite_value_traits< " + c.fq_name () + " >";
}
// Unless the database system can execute several interleaving
@@ -578,13 +579,40 @@ namespace relational
}
virtual void
+ composite (semantics::data_member* m, semantics::class_& c)
+ {
+ if (c_.count ("object"))
+ object_members_base::composite (m, c);
+ else
+ {
+ // If we are generating traits for a composite value type, then
+ // we don't want to go into its bases or it composite members.
+ //
+ if (m == 0 && &c == &c_)
+ names (c);
+ }
+ }
+
+ virtual void
container (semantics::data_member& m)
{
using semantics::type;
- // Figure out if this member is from a base object.
+ // Figure out if this member is from a base object or composite
+ // value and whether it is abstract.
//
- bool base (context::object != &object_);
+ bool base, abst;
+
+ if (c_.count ("object"))
+ {
+ base = context::object != &c_ || !m.scope ().count ("object");
+ abst = abstract (c_);
+ }
+ else
+ {
+ base = false; // We don't go into bases.
+ abst = true; // Always abstract.
+ }
type& t (m.type ());
container_kind_type ck (container_kind (t));
@@ -631,7 +659,7 @@ namespace relational
has_a (vt, test_eager_pointer));
string name (prefix_ + public_name (m) + "_traits");
- string scope (obj_scope_ + "::" + name);
+ string scope (scope_ + "::" + name);
os << "// " << m.name () << endl
<< "//" << endl
@@ -640,196 +668,199 @@ namespace relational
//
// Statements.
//
- string table (table_qname (m, table_prefix_));
-
- // select_all_statement
- //
- os << "const char* const " << scope <<
- "::select_all_statement =" << endl;
-
- if (inverse)
+ if (!abst)
{
- semantics::class_* c (object_pointer (vt));
+ string table (table_qname (m, table_prefix_));
- string inv_table; // Other table name.
- string inv_id; // Other id column.
- string inv_fid; // Other foreign id column (ref to us).
+ // select_all_statement
+ //
+ os << "const char* const " << scope <<
+ "::select_all_statement =" << endl;
- if (context::container (im->type ()))
+ if (inverse)
{
- // many(i)-to-many
- //
+ semantics::class_* c (object_pointer (vt));
- // This other 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);
- inv_table = table_qname (*im, tp);
- inv_id = column_qname (*im, "id", "object_id");
- inv_fid = column_qname (*im, "value", "value");
+ string inv_table; // Other table name.
+ string inv_id; // Other id column.
+ string inv_fid; // Other foreign id column (ref to us).
+
+ if (context::container (im->type ()))
+ {
+ // many(i)-to-many
+ //
+
+ // This other 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);
+ inv_table = table_qname (*im, tp);
+ inv_id = column_qname (*im, "id", "object_id");
+ inv_fid = column_qname (*im, "value", "value");
+ }
+ else
+ {
+ // many(i)-to-one
+ //
+ inv_table = table_qname (*c);
+ inv_id = column_qname (id_member (*c));
+ inv_fid = column_qname (*im);
+ }
+
+ os << strlit ("SELECT ") << endl
+ << strlit ("_." + inv_fid + ',') << endl
+ << strlit ("_." + inv_id) << endl
+ << strlit (" FROM " + inv_table + " AS _"
+ " WHERE _." + inv_fid + " = ?");
}
else
{
- // many(i)-to-one
- //
- inv_table = table_qname (*c);
- inv_id = column_qname (id_member (*c));
- inv_fid = column_qname (*im);
- }
+ string const& id_col (column_qname (m, "id", "object_id"));
- os << strlit ("SELECT ") << endl
- << strlit ("_." + inv_fid + ',') << endl
- << strlit ("_." + inv_id) << endl
- << strlit (" FROM " + inv_table + " AS _"
- " WHERE _." + inv_fid + " = ?");
- }
- else
- {
- string const& id_col (column_qname (m, "id", "object_id"));
-
- os << strlit ("SELECT ") << endl
- << strlit ("_." + id_col + ',') << endl;
+ os << strlit ("SELECT ") << endl
+ << strlit ("_." + id_col + ',') << endl;
- switch (ck)
- {
- case ck_ordered:
+ switch (ck)
{
- if (ordered)
+ case ck_ordered:
{
- instance<object_columns> t (table, false, false);
- string const& col (column_qname (m, "index", "index"));
- t->column (m, "index", table, col);
- t->flush ();
+ if (ordered)
+ {
+ instance<object_columns> t (table, false, false);
+ string const& col (column_qname (m, "index", "index"));
+ t->column (m, "index", table, col);
+ t->flush ();
+ }
+ break;
}
- break;
- }
- case ck_map:
- case ck_multimap:
- {
- instance<object_columns> t (table, false, false);
+ case ck_map:
+ case ck_multimap:
+ {
+ instance<object_columns> t (table, false, false);
- if (semantics::class_* ckt = comp_value (*kt))
- t->traverse_composite (m, *ckt, "key", "key");
- else
+ if (semantics::class_* ckt = comp_value (*kt))
+ t->traverse_composite (m, *ckt, "key", "key");
+ else
+ {
+ string const& col (column_qname (m, "key", "key"));
+ t->column (m, "key", table, col);
+ t->flush ();
+ }
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
{
- string const& col (column_qname (m, "key", "key"));
- t->column (m, "key", table, col);
- t->flush ();
+ break;
}
- break;
- }
- case ck_set:
- case ck_multiset:
- {
- break;
}
- }
- instance<object_columns> t (table, false);
+ instance<object_columns> t (table, false);
- if (semantics::class_* cvt = comp_value (vt))
- t->traverse_composite (m, *cvt, "value", "value");
- else
- {
- string const& col (column_qname (m, "value", "value"));
- t->column (m, "value", table, col);
- t->flush ();
- }
+ if (semantics::class_* cvt = comp_value (vt))
+ t->traverse_composite (m, *cvt, "value", "value");
+ else
+ {
+ string const& col (column_qname (m, "value", "value"));
+ t->column (m, "value", table, col);
+ t->flush ();
+ }
- os << strlit (" FROM " + table + " AS _"
- " WHERE _." + id_col + " = ?");
+ os << strlit (" FROM " + table + " AS _"
+ " WHERE _." + id_col + " = ?");
- if (ordered)
- {
- string const& col (column_qname (m, "index", "index"));
+ if (ordered)
+ {
+ string const& col (column_qname (m, "index", "index"));
- os << endl
- << strlit (" ORDER BY _." + col) << endl;
+ os << endl
+ << strlit (" ORDER BY _." + col) << endl;
+ }
}
- }
-
- os << ";"
- << endl;
-
- // insert_one_statement
- //
- os << "const char* const " << scope <<
- "::insert_one_statement =" << endl;
- if (inverse)
- os << strlit ("") << ";"
+ os << ";"
<< endl;
- else
- {
- os << strlit ("INSERT INTO " + table + " (") << endl
- << strlit (column_qname (m, "id", "object_id") + ',') << endl;
- switch (ck)
+ // insert_one_statement
+ //
+ os << "const char* const " << scope <<
+ "::insert_one_statement =" << endl;
+
+ if (inverse)
+ os << strlit ("") << ";"
+ << endl;
+ else
{
- case ck_ordered:
+ os << strlit ("INSERT INTO " + table + " (") << endl
+ << strlit (column_qname (m, "id", "object_id") + ',') << endl;
+
+ switch (ck)
{
- if (ordered)
+ case ck_ordered:
{
- instance<object_columns> t (false, false);
- t->column (m, "index", "", column_qname (m, "index", "index"));
- t->flush ();
+ if (ordered)
+ {
+ instance<object_columns> t (false, false);
+ t->column (m, "index", "", column_qname (m, "index", "index"));
+ t->flush ();
+ }
+ break;
}
- break;
- }
- case ck_map:
- case ck_multimap:
- {
- instance<object_columns> t (false, false);
+ case ck_map:
+ case ck_multimap:
+ {
+ instance<object_columns> t (false, false);
- if (semantics::class_* ckt = comp_value (*kt))
- t->traverse_composite (m, *ckt, "key", "key");
- else
+ if (semantics::class_* ckt = comp_value (*kt))
+ t->traverse_composite (m, *ckt, "key", "key");
+ else
+ {
+ t->column (m, "key", "", column_qname (m, "key", "key"));
+ t->flush ();
+ }
+ break;
+ }
+ case ck_set:
+ case ck_multiset:
{
- t->column (m, "key", "", column_qname (m, "key", "key"));
- t->flush ();
+ break;
}
- break;
}
- case ck_set:
- case ck_multiset:
+
+ instance<object_columns> t (false);
+
+ if (semantics::class_* cvt = comp_value (vt))
+ t->traverse_composite (m, *cvt, "value", "value");
+ else
{
- break;
+ t->column (m, "value", "", column_qname (m, "value", "value"));
+ t->flush ();
}
+
+ string values;
+ for (size_t i (0), n (m.get<size_t> ("data-column-count"));
+ i < n; ++i)
+ values += i != 0 ? ",?" : "?";
+
+ os << strlit (") VALUES (" + values + ")") << ";"
+ << endl;
}
- instance<object_columns> t (false);
+ // delete_all_statement
+ //
+ os << "const char* const " << scope <<
+ "::delete_all_statement =" << endl;
- if (semantics::class_* cvt = comp_value (vt))
- t->traverse_composite (m, *cvt, "value", "value");
+ if (inverse)
+ os << strlit ("") << ";"
+ << endl;
else
{
- t->column (m, "value", "", column_qname (m, "value", "value"));
- t->flush ();
+ os << strlit ("DELETE FROM " + table) << endl
+ << strlit (" WHERE " + column_qname (m, "id", "object_id") +
+ " = ?") << ";"
+ << endl;
}
-
- string values;
- for (size_t i (0), n (m.get<size_t> ("data-column-count"));
- i < n; ++i)
- values += i != 0 ? ",?" : "?";
-
- os << strlit (") VALUES (" + values + ")") << ";"
- << endl;
- }
-
- // delete_all_statement
- //
- os << "const char* const " << scope <<
- "::delete_all_statement =" << endl;
-
- if (inverse)
- os << strlit ("") << ";"
- << endl;
- else
- {
- os << strlit ("DELETE FROM " + table) << endl
- << strlit (" WHERE " + column_qname (m, "id", "object_id") +
- " = ?") << ";"
- << endl;
}
if (base)
@@ -1546,9 +1577,8 @@ namespace relational
}
protected:
- string obj_scope_;
- semantics::class_& object_;
- semantics::data_member& id_member_;
+ string scope_;
+ semantics::class_& c_;
};
// Container statement cache members.
@@ -1620,10 +1650,16 @@ namespace relational
}
virtual void
- composite (semantics::data_member& m, semantics::class_& c)
+ composite (semantics::data_member* m, semantics::class_& c)
{
+ if (m == 0)
+ {
+ object_members_base::composite (m, c);
+ return;
+ }
+
string old (obj_prefix_);
- obj_prefix_ += m.name ();
+ obj_prefix_ += m->name ();
obj_prefix_ += '.';
object_members_base::composite (m, c);
obj_prefix_ = old;
@@ -2431,6 +2467,13 @@ namespace relational
<< "//" << endl
<< endl;
+ // Containers.
+ //
+ {
+ instance<container_traits> t (c);
+ t->traverse (c);
+ }
+
// grow ()
//
os << "bool " << traits << "::" << endl