aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-08-30 06:06:26 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-08-30 06:06:26 +0200
commitf3f682c074117fda84bf51a4ce9a378d950a04de (patch)
tree464e5db1a9843a1edf814bb0c0143767219ccc0c
parentc1f534db5d6bc29f9be0e7498e4971c7132d013a (diff)
Statement processing/optimization base work
-rw-r--r--odb/context.cxx6
-rw-r--r--odb/context.hxx2
-rw-r--r--odb/header.cxx6
-rw-r--r--odb/relational/header.cxx7
-rw-r--r--odb/relational/header.hxx10
-rw-r--r--odb/relational/mssql/header.cxx6
-rw-r--r--odb/relational/mssql/source.cxx54
-rw-r--r--odb/relational/oracle/source.cxx27
-rw-r--r--odb/relational/pgsql/source.cxx42
-rw-r--r--odb/relational/source.cxx441
-rw-r--r--odb/relational/source.hxx288
11 files changed, 547 insertions, 342 deletions
diff --git a/odb/context.cxx b/odb/context.cxx
index 35433c9..5fc14d4 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -630,12 +630,17 @@ context (ostream& os_,
ops.schema_format ()[db].count (schema_format::separate)),
multi_static (ops.multi_database () == multi_database::static_),
multi_dynamic (ops.multi_database () == multi_database::dynamic),
+ force_versioned (false),
top_object (data_->top_object_),
cur_object (data_->cur_object_)
{
assert (current_ == 0);
current_ = this;
+ // Write boolean values as true/false.
+ //
+ os.setf (ios_base::boolalpha);
+
// Export control.
//
if (!ops.export_symbol ()[db].empty ())
@@ -731,6 +736,7 @@ context ()
separate_schema (current ().separate_schema),
multi_static (current ().multi_static),
multi_dynamic (current ().multi_dynamic),
+ force_versioned (current ().force_versioned),
top_object (current ().top_object),
cur_object (current ().cur_object)
{
diff --git a/odb/context.hxx b/odb/context.hxx
index be612f7..df32cdd 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -1460,6 +1460,8 @@ public:
bool multi_static;
bool multi_dynamic;
+ bool force_versioned; // Force statement processing for debugging.
+
// Outermost object or view currently being traversed.
//
semantics::class_*& top_object;
diff --git a/odb/header.cxx b/odb/header.cxx
index f09c1e8..4c58774 100644
--- a/odb/header.cxx
+++ b/odb/header.cxx
@@ -91,7 +91,7 @@ traverse_object (type& c)
// polymorphic, root_type, base_type, etc.
//
- os << "static const bool polymorphic = " << (poly ? "true" : "false") << ";"
+ os << "static const bool polymorphic = " << poly << ";"
<< endl;
if (poly)
@@ -176,7 +176,7 @@ traverse_object (type& c)
}
os << endl
- << "static const bool auto_id = " << (auto_id ? "true;" : "false;");
+ << "static const bool auto_id = " << auto_id << ";";
}
os << endl;
@@ -193,7 +193,7 @@ traverse_object (type& c)
// abstract
//
- os << "static const bool abstract = " << (abst ? "true" : "false") << ";"
+ os << "static const bool abstract = " << abst << ";"
<< endl;
// id ()
diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx
index da7f80c..9bf6f5e 100644
--- a/odb/relational/header.cxx
+++ b/odb/relational/header.cxx
@@ -27,7 +27,6 @@ traverse_object (type& c)
bool reuse_abst (abst && !poly);
string const& type (class_fq_name (c));
- column_count_type const& cc (column_count (c));
// Sections.
//
@@ -325,6 +324,9 @@ traverse_object (type& c)
return;
}
+ column_count_type const& cc (column_count (c));
+ bool versioned (force_versioned);
+
// Statements typedefs.
//
if (poly)
@@ -403,6 +405,9 @@ traverse_object (type& c)
cc.separate_update << "UL;"
<< endl;
+ os << "static const bool versioned = " << versioned << ";"
+ << endl;
+
// Statements.
//
os << "static const char persist_statement[];";
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 4616543..0620a98 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -242,6 +242,7 @@ namespace relational
// Figure out column counts.
//
size_t id_columns, value_columns, data_columns, cond_columns;
+ bool versioned;
if (!reuse_abst)
{
@@ -323,6 +324,8 @@ namespace relational
data_columns += value_columns;
}
+ versioned = force_versioned;
+
// Store column counts for the source generator.
//
m.set ("id-column-count", id_columns);
@@ -369,6 +372,9 @@ namespace relational
data_columns << "UL;"
<< endl;
+ os << "static const bool versioned = " << versioned << ";"
+ << endl;
+
// Statements.
//
os << "static const char insert_statement[];"
@@ -986,6 +992,7 @@ namespace relational
// column_count
//
column_count_type const& cc (column_count (poly ? *poly_root : c_));
+ bool versioned (force_versioned);
// Generate load and update column counts even when they are zero so
// that we can instantiate section_statements.
@@ -1003,6 +1010,9 @@ namespace relational
(update ? s.total - s.inverse - s.readonly : 0) << "UL;"
<< endl;
+ os << "static const bool versioned = " << versioned << ";"
+ << endl;
+
// Statements.
//
if (load || load_opt)
diff --git a/odb/relational/mssql/header.cxx b/odb/relational/mssql/header.cxx
index 5601755..f943a8a 100644
--- a/odb/relational/mssql/header.cxx
+++ b/odb/relational/mssql/header.cxx
@@ -40,8 +40,7 @@ namespace relational
rv = (t.type == sql_type::ROWVERSION);
}
- os << "static const bool rowversion = " <<
- (rv ? "true" : "false") << ";"
+ os << "static const bool rowversion = " << rv << ";"
<< endl;
}
};
@@ -66,8 +65,7 @@ namespace relational
rv = (t.type == sql_type::ROWVERSION);
}
- os << "static const bool rowversion = " <<
- (rv ? "true" : "false") << ";"
+ os << "static const bool rowversion = " << rv << ";"
<< endl;
}
};
diff --git a/odb/relational/mssql/source.cxx b/odb/relational/mssql/source.cxx
index 837313a..ffc5897 100644
--- a/odb/relational/mssql/source.cxx
+++ b/odb/relational/mssql/source.cxx
@@ -873,22 +873,25 @@ namespace relational
: "sts.update_statement ().version ()";
}
- virtual void
+ virtual string
update_statement_extra (user_section&)
{
+ string r;
+
semantics::data_member* ver (optimistic (c_));
if (ver == 0 ||
parse_sql_type (column_type (*ver), *ver).type !=
sql_type::ROWVERSION)
- return;
+ return r;
// Long data & SQL Server 2005 incompatibility is detected
// in persist_statement_extra.
//
- os << strlit (
- " OUTPUT INSERTED." + convert_from (
- column_qname (*ver, column_prefix ()), *ver)) << endl;
+ r = "OUTPUT INSERTED." +
+ convert_from (column_qname (*ver, column_prefix ()), *ver);
+
+ return r;
}
};
entry<section_traits> section_traits_;
@@ -930,11 +933,13 @@ namespace relational
os << "st.stream_result ();";
}
- virtual void
+ virtual string
persist_statement_extra (type& c,
relational::query_parameters&,
persist_position p)
{
+ string r;
+
type* poly_root (polymorphic (c));
bool poly_derived (poly_root != 0 && poly_root != &c);
@@ -942,7 +947,7 @@ namespace relational
// auto id/version are handled by the root.
//
if (poly_derived)
- return;
+ return r;
// See if we have auto id or ROWVERSION version.
//
@@ -960,7 +965,7 @@ namespace relational
}
if (id == 0 && ver == 0)
- return;
+ return r;
// SQL Server 2005 has a bug that causes it to fail on an
// INSERT statement with the OUTPUT clause if data for one
@@ -996,23 +1001,21 @@ namespace relational
throw operation_failed ();
}
- os << endl
- << strlit ("; SELECT " +
- convert_from ("SCOPE_IDENTITY()", *id));
+ r = "; SELECT " + convert_from ("SCOPE_IDENTITY()", *id);
}
- return;
+ return r;
}
}
if (p == persist_after_columns)
{
- string s (" OUTPUT ");
+ r = "OUTPUT ";
// Top-level auto id column.
//
if (id != 0)
- s += "INSERTED." + convert_from (
+ r += "INSERTED." + convert_from (
column_qname (*id, column_prefix ()), *id);
// Top-level version column.
@@ -1020,19 +1023,21 @@ namespace relational
if (ver != 0)
{
if (id != 0)
- s += ',';
+ r += ',';
- s += "INSERTED." + convert_from (
+ r += "INSERTED." + convert_from (
column_qname (*ver, column_prefix ()), *ver);
}
-
- os << strlit (s) << endl;
}
+
+ return r;
}
- virtual void
+ virtual string
update_statement_extra (type& c)
{
+ string r;
+
type* poly_root (polymorphic (c));
bool poly_derived (poly_root != 0 && poly_root != &c);
@@ -1040,21 +1045,22 @@ namespace relational
// version is handled by the root.
//
if (poly_derived)
- return;
+ return r;
semantics::data_member* ver (optimistic (c));
if (ver == 0 ||
parse_sql_type (column_type (*ver), *ver).type !=
sql_type::ROWVERSION)
- return;
+ return r;
// Long data & SQL Server 2005 incompatibility is detected
// in persist_statement_extra.
//
- os << strlit (
- " OUTPUT INSERTED." + convert_from (
- column_qname (*ver, column_prefix ()), *ver)) << endl;
+ r = "OUTPUT INSERTED." +
+ convert_from (column_qname (*ver, column_prefix ()), *ver);
+
+ return r;
}
virtual void
diff --git a/odb/relational/oracle/source.cxx b/odb/relational/oracle/source.cxx
index 2fc2ad2..3a6b46a 100644
--- a/odb/relational/oracle/source.cxx
+++ b/odb/relational/oracle/source.cxx
@@ -595,30 +595,29 @@ namespace relational
os << "st.stream_result ();";
}
- virtual void
+ virtual string
persist_statement_extra (type& c,
relational::query_parameters& qp,
persist_position p)
{
- if (p != persist_after_values)
- return;
+ string r;
- semantics::data_member* id (id_member (c));
+ if (p == persist_after_values)
+ {
+ semantics::data_member* id (id_member (c));
- type* poly_root (polymorphic (c));
- bool poly_derived (poly_root != 0 && poly_root != &c);
+ type* poly_root (polymorphic (c));
+ bool poly_derived (poly_root != 0 && poly_root != &c);
- if (id != 0 && !poly_derived && id->count ("auto"))
- {
// Top-level auto id.
//
- os << endl
- << strlit (" RETURNING " +
- convert_from (column_qname (*id, column_prefix ()),
- *id) +
- " INTO " +
- qp.next ());
+ if (id != 0 && !poly_derived && id->count ("auto"))
+ r = "RETURNING " +
+ convert_from (column_qname (*id, column_prefix ()), *id) +
+ " INTO " + qp.next ();
}
+
+ return r;
}
};
entry<class_> class_entry_;
diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx
index d5fe8fd..7c5f2f6 100644
--- a/odb/relational/pgsql/source.cxx
+++ b/odb/relational/pgsql/source.cxx
@@ -631,28 +631,28 @@ namespace relational
{
class_ (base const& x): base (x) {}
- virtual void
+ virtual string
persist_statement_extra (type& c,
relational::query_parameters&,
persist_position p)
{
- if (p != persist_after_values)
- return;
+ string r;
- semantics::data_member* id (id_member (c));
+ if (p == persist_after_values)
+ {
+ semantics::data_member* id (id_member (c));
- type* poly_root (polymorphic (c));
- bool poly_derived (poly_root != 0 && poly_root != &c);
+ type* poly_root (polymorphic (c));
+ bool poly_derived (poly_root != 0 && poly_root != &c);
- if (id != 0 && !poly_derived && id->count ("auto"))
- {
// Top-level auto id.
//
- os << endl
- << strlit (" RETURNING " +
- convert_from (column_qname (*id, column_prefix ()),
- *id));
+ if (id != 0 && !poly_derived && id->count ("auto"))
+ r = "RETURNING " +
+ convert_from (column_qname (*id, column_prefix ()), *id);
}
+
+ return r;
}
virtual void
@@ -847,7 +847,10 @@ namespace relational
}
virtual void
- object_query_statement_ctor_args (type&, string const& q, bool prep)
+ object_query_statement_ctor_args (type&,
+ string const& q,
+ bool process,
+ bool prep)
{
os << "sts.connection ()," << endl;
@@ -856,7 +859,9 @@ namespace relational
else
os << "query_statement_name," << endl;
- os << "query_statement + " << q << ".clause ()," << endl
+ os << "text," << endl
+ << process << "," << endl // Process.
+ << "true," << endl // Optimize.
<< q << ".parameter_types ()," << endl
<< q << ".parameter_count ()," << endl
<< q << ".parameters_binding ()," << endl
@@ -868,14 +873,17 @@ namespace relational
{
os << "conn," << endl
<< "erase_query_statement_name," << endl
- << "erase_query_statement + q.clause ()," << endl
+ << "text," << endl
<< "q.parameter_types ()," << endl
<< "q.parameter_count ()," << endl
<< "q.parameters_binding ()";
}
virtual void
- view_query_statement_ctor_args (type&, string const& q, bool prep)
+ view_query_statement_ctor_args (type&,
+ string const& q,
+ bool process,
+ bool prep)
{
os << "sts.connection ()," << endl;
@@ -885,6 +893,8 @@ namespace relational
os << "query_statement_name," << endl;
os << q << ".clause ()," << endl
+ << process << "," << endl // Process.
+ << "true," << endl // Optimize.
<< q << ".parameter_types ()," << endl
<< q << ".parameter_count ()," << endl
<< q << ".parameters_binding ()," << endl
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx
index df804d2..3805be2 100644
--- a/odb/relational/source.cxx
+++ b/odb/relational/source.cxx
@@ -477,6 +477,8 @@ traverse_object (type& c)
if (reuse_abst)
return;
+ bool versioned (force_versioned);
+
//
// Containers (concrete).
//
@@ -613,6 +615,8 @@ traverse_object (type& c)
// persist_statement
//
{
+ string sep (versioned ? "\n" : " ");
+
statement_columns sc;
{
statement_kind sk (statement_insert); // Imperfect forwarding.
@@ -624,30 +628,52 @@ traverse_object (type& c)
bool dv (sc.empty ()); // The DEFAULT VALUES syntax.
os << "const char " << traits << "::persist_statement[] =" << endl
- << strlit ("INSERT INTO " + qtable + (dv ? "" : " (")) << endl;
+ << strlit ("INSERT INTO " + qtable + sep) << endl;
- for (statement_columns::const_iterator i (sc.begin ()),
+ for (statement_columns::const_iterator b (sc.begin ()), i (b),
e (sc.end ()); i != e;)
{
- string const& c (i->column);
- os << strlit (c + (++i != e ? "," : ")")) << endl;
+ string s;
+
+ if (i == b)
+ s += '(';
+ s += i->column;
+ s += (++i != e ? ',' : ')');
+ s += sep;
+
+ os << strlit (s) << endl;
}
instance<query_parameters> qp (table);
- persist_statement_extra (c, *qp, persist_after_columns);
+ string extra (persist_statement_extra (c, *qp, persist_after_columns));
+
+ if (!extra.empty ())
+ os << strlit (extra + sep) << endl;
+ string values;
if (!dv)
{
- string values;
- instance<persist_statement_params> pt (values, *qp);
+ os << strlit ("VALUES" + sep) << endl;
+
+ values += '(';
+ instance<persist_statement_params> pt (values, *qp, sep);
pt->traverse (c);
- os << strlit (" VALUES (" + values + ")");
+ values += ')';
}
else
- os << strlit (" DEFAULT VALUES");
+ values = "DEFAULT VALUES";
+
+ extra = persist_statement_extra (c, *qp, persist_after_values);
- persist_statement_extra (c, *qp, persist_after_values);
+ if (!extra.empty ())
+ values += sep;
+
+ os << strlit (values);
+
+ if (!extra.empty ())
+ os << endl
+ << strlit (extra);
os << ";"
<< endl;
@@ -662,6 +688,8 @@ traverse_object (type& c)
if (id != 0)
{
+ string sep (versioned ? "\n" : " ");
+
instance<object_columns_list> id_cols;
id_cols->traverse (*id);
@@ -689,22 +717,26 @@ traverse_object (type& c)
if (sc.size () != 0)
{
- os << strlit ("SELECT ") << endl;
+ os << strlit ("SELECT" + sep) << endl;
for (statement_columns::const_iterator i (sc.begin ()),
e (sc.end ()); i != e;)
{
string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
+ os << strlit (c + (++i != e ? "," : "") + sep) << endl;
}
- os << strlit (" FROM " + qtable) << endl;
+ os << strlit ("FROM " + qtable + sep) << endl;
if (d != 1)
{
+ bool f (false); // @@ (im)perfect forwarding
size_t d1 (d - 1); //@@ (im)perfect forward.
- instance<polymorphic_object_joins> j (c, d1);
+ instance<polymorphic_object_joins> j (c, f, d1);
j->traverse (polymorphic_base (c));
+
+ for (strings::const_iterator i (j->begin ()); i != j->end (); ++i)
+ os << strlit (*i + sep) << endl;
}
{
@@ -714,19 +746,24 @@ traverse_object (type& c)
object_section* s (&main_section); // @@ (im)perfect forwarding
instance<object_joins> j (c, f, d, s);
j->traverse (c);
+
+ for (strings::const_iterator i (j->begin ()); i != j->end (); ++i)
+ os << strlit (*i + sep) << endl;
}
+ string where ("WHERE ");
instance<query_parameters> qp (table);
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
if (i != b)
- os << endl;
+ where += " AND ";
- os << strlit ((i == b ? " WHERE " : " AND ") +
- qtable + "." + quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ where += qtable + "." + quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
+
+ os << strlit (where);
}
else
os << strlit (""); // Empty SELECT statement.
@@ -791,24 +828,24 @@ traverse_object (type& c)
e (sc.end ()); i != e;)
{
string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
+ os << strlit (c + (++i != e ? ", " : " ")) << endl;
}
- os << strlit (" FROM " + qtable) << endl;
+ os << strlit ("FROM " + qtable + " ") << endl;
+ string where ("WHERE ");
instance<query_parameters> qp (table);
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
if (i != b)
- os << endl;
+ where += " AND ";
- os << strlit ((i == b ? " WHERE " : " AND ") +
- qtable + "." + quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ where += qtable + "." + quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
- os << ";"
+ os << strlit (where) << ";"
<< endl;
}
@@ -816,6 +853,8 @@ traverse_object (type& c)
//
if (update_columns != 0)
{
+ string sep (versioned ? "\n" : " ");
+
instance<query_parameters> qp (table);
statement_columns sc;
@@ -829,13 +868,14 @@ traverse_object (type& c)
}
os << "const char " << traits << "::update_statement[] =" << endl
- << strlit ("UPDATE " + qtable + " SET ") << endl;
+ << strlit ("UPDATE " + qtable + sep) << endl
+ << strlit ("SET" + sep) << endl;
for (statement_columns::const_iterator i (sc.begin ()),
e (sc.end ()); i != e;)
{
string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
+ os << strlit (c + (++i != e ? "," : "") + sep) << endl;
}
// This didn't work out: cannot change the identity column.
@@ -850,29 +890,31 @@ traverse_object (type& c)
// os << strlit (c + "=" + c) << endl;
//}
- update_statement_extra (c);
+ string extra (update_statement_extra (c));
+
+ if (!extra.empty ())
+ os << strlit (extra + sep) << endl;
+ string where ("WHERE ");
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
if (i != b)
- os << endl;
+ where += " AND ";
- os << strlit ((i == b ? " WHERE " : " AND ") +
- quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ where += quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
+ // Top-level version column.
+ //
if (opt != 0 && !poly_derived)
{
- // Top-level version column.
- //
- os << endl
- << strlit (" AND " + column_qname (*opt, column_prefix ()) + "=" +
- convert_to (qp->next (), *opt));
+ where += " AND " + column_qname (*opt, column_prefix ()) + "=" +
+ convert_to (qp->next (), *opt);
}
- os << ";"
+ os << strlit (where) << ";"
<< endl;
}
@@ -881,19 +923,20 @@ traverse_object (type& c)
{
instance<query_parameters> qp (table);
os << "const char " << traits << "::erase_statement[] =" << endl
- << strlit ("DELETE FROM " + qtable);
+ << strlit ("DELETE FROM " + qtable + " ") << endl;
+ string where ("WHERE ");
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
+ if (i != b)
+ where += " AND ";
- os << endl
- << strlit ((i == b ? " WHERE " : " AND ") +
- quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ where += quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
- os << ";"
+ os << strlit (where) << ";"
<< endl;
}
@@ -903,26 +946,32 @@ traverse_object (type& c)
os << "const char " << traits << "::optimistic_erase_statement[] " <<
"=" << endl
- << strlit ("DELETE FROM " + qtable);
+ << strlit ("DELETE FROM " + qtable + " ") << endl;
+ string where ("WHERE ");
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
- os << endl
- << strlit ((i == b ? " WHERE " : " AND ") +
- quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ if (i != b)
+ where += " AND ";
+
+ where += quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
// Top-level version column.
//
- os << endl
- << strlit (" AND " + column_qname (*opt, column_prefix ()) + "=" +
- convert_to (qp->next (), *opt)) << ";"
+ where += " AND " + column_qname (*opt, column_prefix ()) + "=" +
+ convert_to (qp->next (), *opt);
+
+ os << strlit (where) << ";"
<< endl;
}
}
+ // query_statement
+ //
+ bool query_optimize (false);
if (options.generate_query ())
{
// query_statement
@@ -936,23 +985,14 @@ traverse_object (type& c)
process_statement_columns (sc, statement_select);
}
- os << "const char " << traits << "::query_statement[] =" << endl
- << strlit ("SELECT ") << endl;
-
- for (statement_columns::const_iterator i (sc.begin ()),
- e (sc.end ()); i != e;)
- {
- string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
- }
-
- os << strlit (" FROM " + qtable) << endl;
-
+ strings joins;
if (poly_depth != 1)
{
+ bool t (true); //@@ (im)perfect forwarding
size_t d (poly_depth - 1); //@@ (im)perfect forward.
- instance<polymorphic_object_joins> j (c, d);
+ instance<polymorphic_object_joins> j (c, t, d);
j->traverse (polymorphic_base (c));
+ joins = j->joins;
}
if (id != 0)
@@ -961,27 +1001,40 @@ traverse_object (type& c)
// can be used in the WHERE clause.
//
bool t (true); //@@ (im)perfect forwarding
- instance<object_joins> oj (c, t, poly_depth);
- oj->traverse (c);
+ instance<object_joins> j (c, t, poly_depth);
+ j->traverse (c);
+ joins.insert (joins.end (), j->begin (), j->end ());
+ }
+
+ query_optimize = !joins.empty ();
+
+ string sep (versioned || query_optimize ? "\n" : " ");
+
+ os << "const char " << traits << "::query_statement[] =" << endl
+ << strlit ("SELECT" + sep) << endl;
+
+ for (statement_columns::const_iterator i (sc.begin ()),
+ e (sc.end ()); i != e;)
+ {
+ string const& c (i->column);
+ os << strlit (c + (++i != e ? "," : "") + sep) << endl;
}
- os << strlit (" ") << ";"
+ string prev ("FROM " + qtable);
+
+ for (strings::const_iterator i (joins.begin ()); i != joins.end (); ++i)
+ {
+ os << strlit (prev + sep) << endl;
+ prev = *i;
+ }
+
+ os << strlit (prev) << ";"
<< endl;
// erase_query_statement
//
os << "const char " << traits << "::erase_query_statement[] =" << endl
- << strlit ("DELETE FROM " + qtable) << endl;
-
- // DELETE JOIN:
- //
- // MySQL:
- // << strlit ("DELETE FROM " + qtable + " USING " + qtable) << endl;
- // << strlit ("DELETE " + qtable + " FROM " + qtable) << endl;
- // oj->write ();
- //
-
- os << strlit (" ") << ";"
+ << strlit ("DELETE FROM " + qtable) << ";"
<< endl;
// table_name
@@ -1822,7 +1875,7 @@ traverse_object (type& c)
base = true; // We have a readonly optimistic root.
}
- os << ", " << (base ? "true" : "false");
+ os << ", " << base;
}
os << ");";
@@ -3444,6 +3497,8 @@ traverse_object (type& c)
else
result_type = "no_id_object_result_impl<object_type>";
+ string sep (versioned || query_optimize ? "\n" : " ");
+
// Unprepared.
//
if (!options.omit_unprepared ())
@@ -3494,10 +3549,18 @@ traverse_object (type& c)
<< "}";
}
+ os << "std::string text (query_statement);"
+ << "if (!q.empty ())"
+ << "{"
+ << "text += " << strlit (sep) << ";"
+ << "text += q.clause ();"
+ << "}";
+
os << "q.init_parameters ();"
<< "shared_ptr<select_statement> st (" << endl
<< "new (shared) select_statement (" << endl;
- object_query_statement_ctor_args (c, "q", false);
+ object_query_statement_ctor_args (
+ c, "q", versioned || query_optimize, false);
os << "));" << endl
<< "st->execute ();";
@@ -3532,6 +3595,12 @@ traverse_object (type& c)
<< db << "::connection& conn (" << endl
<< db << "::transaction::current ().connection ());"
<< endl
+ << "std::string text (erase_query_statement);"
+ << "if (!q.empty ())"
+ << "{"
+ << "text += ' ';"
+ << "text += q.clause ();"
+ << "}"
<< "q.init_parameters ();"
<< "delete_statement st (" << endl;
object_erase_query_statement_ctor_args (c);
@@ -3601,6 +3670,13 @@ traverse_object (type& c)
<< "}";
}
+ os << "std::string text (query_statement);"
+ << "if (!q.empty ())"
+ << "{"
+ << "text += " << strlit (sep) << ";"
+ << "text += q.clause ();"
+ << "}";
+
os << "shared_ptr<" << db << "::prepared_query_impl> r (" << endl
<< "new (shared) " << db << "::prepared_query_impl (conn));"
<< "r->name = n;"
@@ -3608,7 +3684,8 @@ traverse_object (type& c)
<< "r->query = q;"
<< "r->stmt.reset (" << endl
<< "new (shared) select_statement (" << endl;
- object_query_statement_ctor_args (c, "r->query", true);
+ object_query_statement_ctor_args (
+ c, "r->query", versioned || query_optimize, true);
os << "));"
<< endl
<< "return r;"
@@ -3790,6 +3867,18 @@ traverse_object (type& c)
void relational::source::class_::
traverse_view (type& c)
{
+ view_query& vq (c.get<view_query> ("query"));
+
+ // Only process the view query if it is versioned since the query text
+ // (e.g., in the native view) must be structured. Also, we probably
+ // shouldn't try to optimize JOINs since the objects are JOINed
+ // explicitly by the user, unless we are adding poly-bases/derived.
+ //
+ // When versioning is forced, don't do it for native views.
+ //
+ bool versioned (force_versioned && vq.kind == view_query::condition);
+ bool query_optimize (false);
+
string const& type (class_fq_name (c));
string traits ("access::view_traits_impl< " + type + ", id_" +
db.string () + " >");
@@ -3862,8 +3951,6 @@ traverse_view (type& c)
// query_statement()
//
- view_query& vq (c.get<view_query> ("query"));
-
if (vq.kind != view_query::runtime)
{
os << traits << "::query_base_type" << endl
@@ -3930,8 +4017,13 @@ traverse_view (type& c)
// at the end.
//
if (!ph)
- os << "r += q.clause_prefix ();"
- << "r += q;";
+ os << endl
+ << "if (!q.empty ())"
+ << "{"
+ << "r += " << strlit (versioned ? "\n" : " ") << ";"
+ << "r += q.clause_prefix ();"
+ << "r += q;"
+ << "}";
}
else // vq.kind == view_query::condition
{
@@ -3942,21 +4034,9 @@ traverse_view (type& c)
process_statement_columns (sc, statement_select);
}
- os << "query_base_type r (" << endl
- << strlit ("SELECT ") << endl;
-
- for (statement_columns::const_iterator i (sc.begin ()),
- e (sc.end ()); i != e;)
- {
- string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
- }
-
- os << ");"
- << endl;
-
- // Generate from-list.
+ // Generate the from-list.
//
+ strings from;
view_objects const& objs (c.get<view_objects> ("objects"));
for (view_objects::const_iterator i (objs.begin ());
@@ -3980,9 +4060,7 @@ traverse_view (type& c)
if (!i->alias.empty ())
l += (need_alias_as ? " AS " : " ") + quote_id (i->alias);
- os << "r += " << strlit (l) << ";"
- << endl;
-
+ from.push_back (l);
continue;
}
@@ -4001,21 +4079,18 @@ traverse_view (type& c)
if (e.kind != expression::literal)
{
- error (i->loc)
- << "invalid join condition in db pragma table" << endl;
-
+ error (i->loc) << "invalid join condition in db pragma " <<
+ "table" << endl;
throw operation_failed ();
}
l += " ON";
- // Output the pragma location for easier error tracking.
+ // Add the pragma location for easier error tracking.
//
- os << "r += " << strlit (l) << ";"
- << "// From " << location_string (i->loc, true) << endl
- << "r += " << e.value << ";"
- << endl;
-
+ from.push_back (l);
+ from.push_back ("// From " + location_string (i->loc, true));
+ from.push_back (e.value);
continue;
}
@@ -4044,18 +4119,18 @@ traverse_view (type& c)
if (!alias.empty ())
l += (need_alias_as ? " AS " : " ") + quote_id (alias);
- os << "r += " << strlit (l) << ";";
+ from.push_back (l);
if (poly_depth != 1)
{
+ bool t (true); //@@ (im)perfect forwarding
size_t d (poly_depth - 1); //@@ (im)perfect forward.
- instance<polymorphic_object_joins> j (
- o, d, i->alias, "r += ", ";");
+ instance<polymorphic_object_joins> j (o, t, d, i->alias);
j->traverse (polymorphic_base (o));
- }
-
- os << endl;
+ from.insert (from.end (), j->begin (), j->end ());
+ query_optimize = query_optimize || !j->joins.empty ();
+ }
continue;
}
@@ -4078,22 +4153,22 @@ traverse_view (type& c)
l += " ON";
- // Output the pragma location for easier error tracking.
+ // Add the pragma location for easier error tracking.
//
- os << "r += " << strlit (l) << ";"
- << "// From " << location_string (i->loc, true) << endl
- << "r += " << e.value << ";";
+ from.push_back (l);
+ from.push_back ("// From " + location_string (i->loc, true));
+ from.push_back (e.value);
if (poly_depth != 1)
{
+ bool t (true); //@@ (im)perfect forwarding
size_t d (poly_depth - 1); //@@ (im)perfect forward.
- instance<polymorphic_object_joins> j (
- o, d, i->alias, "r += ", ";");
+ instance<polymorphic_object_joins> j (o, t, d, i->alias);
j->traverse (polymorphic_base (o));
- }
-
- os << endl;
+ from.insert (from.end (), j->begin (), j->end ());
+ query_optimize = query_optimize || !j->joins.empty ();
+ }
continue;
}
@@ -4147,39 +4222,28 @@ traverse_view (type& c)
//
if (!ambig)
{
- error (i->loc)
- << "pointed-to object '" << class_name (*c) << "' is "
- << "ambiguous" << endl;
-
- info (i->loc)
- << "candidates are:" << endl;
-
- info (vo->loc)
- << " '" << vo->name () << "'" << endl;
-
+ error (i->loc) << "pointed-to object '" << class_name (*c) <<
+ "' is ambiguous" << endl;
+ info (i->loc) << "candidates are:" << endl;
+ info (vo->loc) << " '" << vo->name () << "'" << endl;
ambig = true;
}
- info (j->loc)
- << " '" << j->name () << "'" << endl;
+ info (j->loc) << " '" << j->name () << "'" << endl;
}
if (ambig)
{
- info (i->loc)
- << "use the full join condition clause in db pragma "
- << "object to resolve this ambiguity" << endl;
-
+ info (i->loc) << "use the full join condition clause in db " <<
+ "pragma object to resolve this ambiguity" << endl;
throw operation_failed ();
}
if (vo == 0)
{
- error (i->loc)
- << "pointed-to object '" << class_name (*c) << "' "
- << "specified in the join condition has not been "
- << "previously associated with this view" << endl;
-
+ error (i->loc) << "pointed-to object '" << class_name (*c) <<
+ "' specified in the join condition has not been " <<
+ "previously associated with this view" << endl;
throw operation_failed ();
}
}
@@ -4253,7 +4317,7 @@ traverse_view (type& c)
l = "LEFT JOIN ";
l += ct;
l += " ON";
- os << "r += " << strlit (l) << ";";
+ from.push_back (l);
// If we are the pointed-to object, then we have to turn
// things around. This is necessary to have the proper
@@ -4330,7 +4394,7 @@ traverse_view (type& c)
l += '.';
l += quote_id (j->name);
- os << "r += " << strlit (l) << ";";
+ from.push_back (strlit (l));
}
}
@@ -4341,7 +4405,7 @@ traverse_view (type& c)
l += (need_alias_as ? " AS " : " ") + quote_id (alias);
l += " ON";
- os << "r += " << strlit (l) << ";";
+ from.push_back (l);
if (cont != 0)
{
@@ -4413,7 +4477,7 @@ traverse_view (type& c)
l += '.';
l += quote_id (j->name);
- os << "r += " << strlit (l) << ";";
+ from.push_back (strlit (l));
}
}
else
@@ -4457,27 +4521,60 @@ traverse_view (type& c)
l += '.';
l += quote_id (j->name);
- os << "r += " << strlit (l) << ";";
+ from.push_back (strlit (l));
}
}
if (poly_depth != 1)
{
+ bool t (true); //@@ (im)perfect forwarding
size_t d (poly_depth - 1); //@@ (im)perfect forward.
- instance<polymorphic_object_joins> j (
- o, d, i->alias, "r += ", ";");
+ instance<polymorphic_object_joins> j (o, t, d, i->alias);
j->traverse (polymorphic_base (o));
+
+ from.insert (from.end (), j->begin (), j->end ());
+ query_optimize = query_optimize || !j->joins.empty ();
}
+ } // End JOIN-generating for-loop.
- os << endl;
+ string sep (versioned || query_optimize ? "\n" : " ");
- } // End JOIN-generating for-loop.
+ os << "query_base_type r (" << endl
+ << strlit ("SELECT" + sep);
+
+ for (statement_columns::const_iterator i (sc.begin ()),
+ e (sc.end ()); i != e;)
+ {
+ string const& c (i->column);
+ os << endl
+ << strlit (c + (++i != e ? "," : "") + sep);
+ }
+
+ os << ");"
+ << endl;
+
+ // It is much easier to add the separator at the beginning of the
+ // next line since the JOIN condition may not be a string literal.
+ //
+ for (strings::const_iterator i (from.begin ()); i != from.end (); ++i)
+ {
+ if (i->compare (0, 5, "FROM ") == 0)
+ os << "r += " << strlit (*i) << ";";
+ else if (i->compare (0, 5, "LEFT ") == 0)
+ os << endl
+ << "r += " << strlit (sep + *i) << ";";
+ else if (i->compare (0, 3, "// ") == 0)
+ os << *i << endl;
+ else
+ os << "r += " << *i << ";"; // Already a string literal.
+ }
// Generate the query condition.
//
if (!vq.literal.empty () || !vq.expr.empty ())
{
- os << "query_base_type c (" << endl;
+ os << endl
+ << "query_base_type c (" << endl;
bool ph (false);
@@ -4521,21 +4618,31 @@ traverse_view (type& c)
// rid of useless clauses like WHERE TRUE.
//
if (ph)
- os << "c.optimize ();";
+ os << endl
+ << "c.optimize ();";
}
if (!ph)
- os << "c += q;";
+ os << endl
+ << "c += q;";
- os << "r += c.clause_prefix ();"
+ os << endl
+ << "if (!c.empty ())"
+ << "{"
+ << "r += " << strlit (sep) << ";"
+ << "r += c.clause_prefix ();"
<< "r += c;"
- << endl;
+ << "}";
}
else
{
- os << "r += q.clause_prefix ();"
+ os << endl
+ << "if (!q.empty ())"
+ << "{"
+ << "r += " << strlit (sep) << ";"
+ << "r += q.clause_prefix ();"
<< "r += q;"
- << endl;
+ << "}";
}
}
@@ -4579,7 +4686,8 @@ traverse_view (type& c)
os << "qs.init_parameters ();"
<< "shared_ptr<select_statement> st (" << endl
<< "new (shared) select_statement (" << endl;
- view_query_statement_ctor_args (c, "qs", false);
+ view_query_statement_ctor_args (
+ c, "qs", versioned || query_optimize, false);
os << "));" << endl
<< "st->execute ();";
@@ -4651,7 +4759,8 @@ traverse_view (type& c)
os << "r->stmt.reset (" << endl
<< "new (shared) select_statement (" << endl;
- view_query_statement_ctor_args (c, "r->query", true);
+ view_query_statement_ctor_args (
+ c, "r->query", versioned || query_optimize, true);
os << "));"
<< endl
<< "return r;"
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 3bf7c95..aae34da 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -490,35 +490,16 @@ namespace relational
typedef polymorphic_object_joins base;
polymorphic_object_joins (semantics::class_& obj,
+ bool query,
size_t depth,
string const& alias = "",
- string const prefix = "",
- string const& suffix = "\n")
- : object_columns_base (true, true),
- obj_ (obj),
- depth_ (depth),
- section_ (0),
- alias_ (alias),
- prefix_ (prefix),
- suffix_ (suffix)
- {
- init ();
- }
-
- polymorphic_object_joins (semantics::class_& obj,
- size_t depth,
- user_section& section)
+ user_section* section = 0)
: object_columns_base (true, true),
obj_ (obj),
+ query_ (query),
depth_ (depth),
- section_ (&section),
- suffix_ ("\n")
- {
- init ();
- }
-
- void
- init ()
+ section_ (section),
+ alias_ (alias)
{
// Get the table and id columns.
//
@@ -553,6 +534,14 @@ namespace relational
stop = true; // Stop at this base if there are no more overrides.
}
}
+ // Skip intermediates that don't add any data members.
+ //
+ else if (!query_)
+ {
+ column_count_type const& cc (column_count (c));
+ if (cc.total == cc.id + cc.separate_load)
+ skip = true;
+ }
if (!skip)
{
@@ -574,27 +563,35 @@ namespace relational
cond << alias << '.' << qn << '=' << table_ << '.' << qn;
}
- string line (" LEFT JOIN " + quote_id (table));
+ string line ("LEFT JOIN " + quote_id (table));
if (!alias_.empty ())
line += (need_alias_as ? " AS " : " ") + alias;
line += " ON " + cond.str ();
- os << prefix_ << strlit (line) << suffix_;
+ joins.push_back (line);
}
if (!stop && --depth_ != 0)
inherits (c);
}
+ public:
+ strings joins;
+
+ strings::const_iterator
+ begin () const {return joins.begin ();}
+
+ strings::const_iterator
+ end () const {return joins.end ();}
+
private:
semantics::class_& obj_;
+ bool query_;
size_t depth_;
user_section* section_;
string alias_;
- string prefix_;
- string suffix_;
string table_;
instance<object_columns_list> cols_;
};
@@ -823,7 +820,7 @@ namespace relational
if (!t.empty ())
{
- string line (" LEFT JOIN ");
+ string line ("LEFT JOIN ");
line += t;
if (!a.empty ())
@@ -832,7 +829,7 @@ namespace relational
line += " ON ";
line += cond.str ();
- os << strlit (line) << endl;
+ joins.push_back (line);
}
// Add dependent join (i.e., an object table join via the
@@ -840,7 +837,7 @@ namespace relational
//
if (!dt.empty ())
{
- string line (" LEFT JOIN ");
+ string line ("LEFT JOIN ");
line += dt;
if (!da.empty ())
@@ -849,12 +846,12 @@ namespace relational
line += " ON ";
line += dcond.str ();
- os << strlit (line) << endl;
+ joins.push_back (line);
}
// If we joined the object that is part of a polymorphic type
// hierarchy, then we may need join its bases as well as its
- // derived types.
+ // derived types. This is only done for queries.
//
if (joined_obj != 0 && poly)
{
@@ -864,22 +861,35 @@ namespace relational
//
if (joined_obj != &c)
{
+ bool t (true); //@@ (im)perfect forward.
size_t d (polymorphic_depth (c) - depth); //@@ (im)perfect forward.
- instance<polymorphic_object_joins> t (*joined_obj, d, alias);
- t->traverse (c);
+ instance<polymorphic_object_joins> j (*joined_obj, t, d, alias);
+ j->traverse (c);
+ joins.insert (joins.end (), j->joins.begin (), j->joins.end ());
}
// Join "down" (base).
//
if (joined_obj != poly_root)
{
+ bool t (true); //@@ (im)perfect forward.
size_t d (depth - 1); //@@ (im)perfect forward.
- instance<polymorphic_object_joins> t (*joined_obj, d, alias);
- t->traverse (polymorphic_base (*joined_obj));
+ instance<polymorphic_object_joins> j (*joined_obj, t, d, alias);
+ j->traverse (polymorphic_base (*joined_obj));
+ joins.insert (joins.end (), j->joins.begin (), j->joins.end ());
}
}
}
+ public:
+ strings joins;
+
+ strings::const_iterator
+ begin () const {return joins.begin ();}
+
+ strings::const_iterator
+ end () const {return joins.end ();}
+
private:
bool query_;
size_t depth_;
@@ -1454,8 +1464,7 @@ namespace relational
// Indicate to the value_traits whether this column can be NULL.
//
- os << "bool is_null (" <<
- (null (mi.m, key_prefix_) ? "true" : "false") << ");";
+ os << "bool is_null (" << null (mi.m, key_prefix_) << ");";
}
if (comp)
@@ -2074,6 +2083,9 @@ namespace relational
//
if (!reuse_abst)
{
+ bool versioned (force_versioned);
+ string sep (versioned ? "\n" : " ");
+
semantics::type& idt (container_idt (m));
qname table (table_name (m, table_prefix_));
@@ -2181,26 +2193,29 @@ namespace relational
process_statement_columns (sc, statement_select);
- os << strlit ("SELECT ") << endl;
+ os << strlit ("SELECT" + sep) << endl;
for (statement_columns::const_iterator i (sc.begin ()),
e (sc.end ()); i != e;)
{
string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
+ os << strlit (c + (++i != e ? "," : "") + sep) << endl;
}
instance<query_parameters> qp (inv_table);
- os << strlit (" FROM " + inv_qtable);
+ os << strlit ("FROM " + inv_qtable + sep) << endl;
+ string where ("WHERE ");
for (object_columns_list::iterator b (inv_fid_cols->begin ()),
i (b); i != inv_fid_cols->end (); ++i)
{
- os << endl
- << strlit ((i == b ? " WHERE " : " AND ") +
- inv_qtable + "." + quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ if (i != b)
+ where += " AND ";
+
+ where += inv_qtable + "." + quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
+ os << strlit (where);
}
else
{
@@ -2235,25 +2250,27 @@ namespace relational
process_statement_columns (sc, statement_select);
- os << strlit ("SELECT ") << endl;
+ os << strlit ("SELECT" + sep) << endl;
for (statement_columns::const_iterator i (sc.begin ()),
e (sc.end ()); i != e;)
{
string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
+ os << strlit (c + (++i != e ? "," : "") + sep) << endl;
}
instance<query_parameters> qp (table);
- os << strlit (" FROM " + qtable);
+ os << strlit ("FROM " + qtable + sep) << endl;
+ string where ("WHERE ");
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
- os << endl
- << strlit ((i == b ? " WHERE " : " AND ") +
- qtable + "." + quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ if (i != b)
+ where += " AND ";
+
+ where += qtable + "." + quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
if (ordered)
@@ -2263,9 +2280,10 @@ namespace relational
string const& col (
column_qname (m, "index", "index", column_prefix ()));
- os << endl
- << strlit (" ORDER BY " + qtable + "." + col);
+ where += " ORDER BY " + qtable + "." + col;
}
+
+ os << strlit (where);
}
os << ";"
@@ -2312,27 +2330,40 @@ namespace relational
process_statement_columns (sc, statement_insert);
- os << strlit ("INSERT INTO " + qtable + " (") << endl;
+ os << strlit ("INSERT INTO " + qtable + sep) << endl;
- for (statement_columns::const_iterator i (sc.begin ()),
+ for (statement_columns::const_iterator b (sc.begin ()), i (b),
e (sc.end ()); i != e;)
{
- string const& c (i->column);
- os << strlit (c + (++i != e ? "," : ")")) << endl;
+ string s;
+
+ if (i == b)
+ s += '(';
+ s += i->column;
+ s += (++i != e ? ',' : ')');
+ s += sep;
+
+ os << strlit (s) << endl;
}
- string values;
+ os << strlit ("VALUES" + sep) << endl;
+
+ string values ("(");
instance<query_parameters> qp (table);
for (statement_columns::const_iterator b (sc.begin ()), i (b),
e (sc.end ()); i != e; ++i)
{
if (i != b)
+ {
values += ',';
+ values += sep;
+ }
values += convert_to (qp->next (), i->type, *i->member);
}
+ values += ')';
- os << strlit (" VALUES (" + values + ")") << ";"
+ os << strlit (values) << ";"
<< endl;
}
@@ -2342,7 +2373,8 @@ namespace relational
{
os << "const char " << scope << "::" << endl
<< "update_statement[] =" << endl
- << strlit ("UPDATE " + qtable + " SET ");
+ << strlit ("UPDATE " + qtable + sep) << endl
+ << strlit ("SET" + sep) << endl;
instance<query_parameters> qp (table);
statement_columns sc;
@@ -2358,28 +2390,28 @@ namespace relational
e (sc.end ()); i != e;)
{
string const& c (i->column);
- os << endl
- << strlit (c + (++i != e ? "," : ""));
+ os << strlit (c + (++i != e ? "," : "") + sep) << endl;
}
+ string where ("WHERE ");
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
- os << endl
- << strlit ((i == b ? " WHERE " : " AND ") +
- quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ if (i != b)
+ where += " AND ";
+
+ where += quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
for (object_columns_list::iterator b (ik_cols->begin ()), i (b);
i != ik_cols->end (); ++i)
{
- os << endl
- << strlit (" AND " + quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ where += " AND " + quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
- os << ";"
+ os << strlit (where) << ";"
<< endl;
}
@@ -2395,15 +2427,17 @@ namespace relational
{
instance<query_parameters> qp (table);
- os << strlit ("DELETE FROM " + qtable);
+ os << strlit ("DELETE FROM " + qtable + " ") << endl;
+ string where ("WHERE ");
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
- os << endl
- << strlit ((i == b ? " WHERE " : " AND ") +
- quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ if (i != b)
+ where += " AND ";
+
+ where += quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
if (smart)
@@ -2411,14 +2445,13 @@ namespace relational
for (object_columns_list::iterator b (ik_cols->begin ()), i (b);
i != ik_cols->end (); ++i)
{
- os << endl
- << strlit (" AND " + quote_id (i->name) +
- (ck == ck_ordered ? ">=" : "=") +
- convert_to (qp->next (), i->type, *i->member));
+ where += " AND " + quote_id (i->name) +
+ (ck == ck_ordered ? ">=" : "=") +
+ convert_to (qp->next (), i->type, *i->member);
}
}
- os << ";"
+ os << strlit (where) << ";"
<< endl;
}
}
@@ -3257,7 +3290,7 @@ namespace relational
<< "functions_type& fs (sts.functions ());";
if (!smart && ck == ck_ordered)
- os << "fs.ordered_ = " << (ordered ? "true" : "false") << ";";
+ os << "fs.ordered_ = " << ordered << ";";
os << "container_traits_type::persist (c, fs);"
<< "}";
@@ -3314,7 +3347,7 @@ namespace relational
<< "functions_type& fs (sts.functions ());";
if (!smart && ck == ck_ordered)
- os << "fs.ordered_ = " << (ordered ? "true" : "false") << ";";
+ os << "fs.ordered_ = " << ordered << ";";
os << "container_traits_type::load (c, more, fs);"
<< "}";
@@ -3338,7 +3371,7 @@ namespace relational
<< "functions_type& fs (sts.functions ());";
if (!smart && ck == ck_ordered)
- os << "fs.ordered_ = " << (ordered ? "true" : "false") << ";";
+ os << "fs.ordered_ = " << ordered << ";";
os << "container_traits_type::update (c, fs);"
<< "}";
@@ -3361,7 +3394,7 @@ namespace relational
<< "functions_type& fs (sts.functions ());";
if (!smart && ck == ck_ordered)
- os << "fs.ordered_ = " << (ordered ? "true" : "false") << ";";
+ os << "fs.ordered_ = " << ordered << ";";
os << "container_traits_type::erase (" << (smart ? "c, " : "") << "fs);"
<< "}";
@@ -3840,9 +3873,10 @@ namespace relational
return "1";
}
- virtual void
+ virtual string
update_statement_extra (user_section&)
{
+ return "";
}
virtual void
@@ -4215,6 +4249,9 @@ namespace relational
return;
}
+ bool versioned (force_versioned);
+ string sep (versioned ? "\n" : " ");
+
// Statements.
//
qname table (table_name (c_));
@@ -4240,25 +4277,28 @@ namespace relational
os << "const char " << scope << "::" << endl
<< "select_statement[] =" << endl
- << strlit ("SELECT ") << endl;
+ << strlit ("SELECT" + sep) << endl;
for (statement_columns::const_iterator i (sc.begin ()),
e (sc.end ()); i != e;)
{
string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
+ os << strlit (c + (++i != e ? "," : "") + sep) << endl;
}
- os << strlit (" FROM " + qtable) << endl;
+ os << strlit ("FROM " + qtable + sep) << endl;
// Join polymorphic bases.
//
if (depth != 1 && s.base != 0)
{
+ bool f (false); //@@ (im)perfect forwarding
size_t d (depth - 1); //@@ (im)perfect forward.
- user_section& bs (*s.base); //@@ (im)perfect forward.
- instance<polymorphic_object_joins> j (c_, d, bs);
+ instance<polymorphic_object_joins> j (c_, f, d, "", s.base);
j->traverse (*poly_base);
+
+ for (strings::const_iterator i (j->begin ()); i != j->end (); ++i)
+ os << strlit (*i + sep) << endl;
}
// Join tables of inverse members belonging to this section.
@@ -4268,21 +4308,24 @@ namespace relational
object_section* ps (&s); // @@ (im)perfect forwarding
instance<object_joins> j (c_, f, depth, ps);
j->traverse (c_);
+
+ for (strings::const_iterator i (j->begin ()); i != j->end (); ++i)
+ os << strlit (*i + sep) << endl;
}
+ string where ("WHERE ");
instance<query_parameters> qp (table);
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
if (i != b)
- os << endl;
+ where += " AND ";
- os << strlit ((i == b ? " WHERE " : " AND ") +
- qtable + "." + quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ where += qtable + "." + quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
- os << ";"
+ os << strlit (where) << ";"
<< endl;
}
@@ -4304,13 +4347,14 @@ namespace relational
os << "const char " << scope << "::" << endl
<< "update_statement[] =" << endl
- << strlit ("UPDATE " + qtable + " SET ") << endl;
+ << strlit ("UPDATE " + qtable + sep) << endl
+ << strlit ("SET" + sep) << endl;
for (statement_columns::const_iterator i (sc.begin ()),
e (sc.end ()); i != e;)
{
string const& c (i->column);
- os << strlit (c + (++i != e ? "," : "")) << endl;
+ os << strlit (c + (++i != e ? "," : "") + sep) << endl;
}
// This didn't work out: cannot change the identity column.
@@ -4325,27 +4369,29 @@ namespace relational
// os << strlit (c + "=" + c) << endl;
//}
- update_statement_extra (s);
+ string extra (update_statement_extra (s));
+ if (!extra.empty ())
+ os << strlit (extra + sep) << endl;
+
+ string where ("WHERE ");
for (object_columns_list::iterator b (id_cols->begin ()), i (b);
i != id_cols->end (); ++i)
{
if (i != b)
- os << endl;
+ where += " AND ";
- os << strlit ((i == b ? " WHERE " : " AND ") +
- quote_id (i->name) + "=" +
- convert_to (qp->next (), i->type, *i->member));
+ where += quote_id (i->name) + "=" +
+ convert_to (qp->next (), i->type, *i->member);
}
if (s.optimistic ()) // Note: not update_opt.
{
- os << endl
- << strlit (" AND " + column_qname (*opt, column_prefix ()) +
- "=" + convert_to (qp->next (), *opt));
+ where += " AND " + column_qname (*opt, column_prefix ()) + "=" +
+ convert_to (qp->next (), *opt);
}
- os << ";"
+ os << strlit (where) << ";"
<< endl;
}
@@ -4745,8 +4791,10 @@ namespace relational
{
typedef persist_statement_params base;
- persist_statement_params (string& params, query_parameters& qp)
- : params_ (params), qp_ (qp)
+ persist_statement_params (string& params,
+ query_parameters& qp,
+ const string& sep)
+ : params_ (params), qp_ (qp), sep_ (sep)
{
}
@@ -4772,7 +4820,10 @@ namespace relational
if (!p.empty ())
{
if (!first)
+ {
params_ += ',';
+ params_ += sep_;
+ }
params_ += (p != "DEFAULT" ? convert_to (p, column_type (), m) : p);
}
@@ -4789,6 +4840,7 @@ namespace relational
private:
string& params_;
query_parameters& qp_;
+ const string& sep_;
};
//
@@ -4908,14 +4960,16 @@ namespace relational
persist_after_values
};
- virtual void
+ virtual string
persist_statement_extra (type&, query_parameters&, persist_position)
{
+ return "";
}
- virtual void
+ virtual string
update_statement_extra (type&)
{
+ return "";
}
//
@@ -4946,10 +5000,13 @@ namespace relational
virtual void
object_query_statement_ctor_args (type&,
std::string const& q,
+ bool process,
bool /*prepared*/)
{
os << "conn," << endl
- << "query_statement + " << q << ".clause ()," << endl
+ << "text," << endl
+ << process << "," << endl // Process.
+ << "true," << endl // Optimize.
<< q << ".parameters_binding ()," << endl
<< "imb";
}
@@ -4958,7 +5015,7 @@ namespace relational
object_erase_query_statement_ctor_args (type&)
{
os << "conn," << endl
- << "erase_query_statement + q.clause ()," << endl
+ << "text," << endl
<< "q.parameters_binding ()";
}
@@ -4991,10 +5048,13 @@ namespace relational
virtual void
view_query_statement_ctor_args (type&,
string const& q,
+ bool process,
bool /*prepared*/)
{
os << "conn," << endl
<< q << ".clause ()," << endl
+ << process << "," << endl // Process.
+ << "true," << endl // Optimize.
<< q << ".parameters_binding ()," << endl
<< "imb";
}