From 0efbd383bf4b9d6c1a884ff0249412567b329fce Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 13 Jun 2013 18:25:00 +0200 Subject: Add support for native views that call stored procedures --- odb/context.hxx | 3 ++- odb/relational/processor.cxx | 29 +++++++++++++++++++++-------- odb/relational/source.cxx | 40 +++++++++++++++++++++++++++++++++------- odb/relational/source.hxx | 3 ++- 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/odb/context.hxx b/odb/context.hxx index fe9b533..50d47f2 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -178,7 +178,8 @@ struct view_query enum kind_type { runtime, - complete, + complete_select, // SELECT query. + complete_execute, // Stored procedure call. condition }; diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx index 5ac97f5..0c27971 100644 --- a/odb/relational/processor.cxx +++ b/odb/relational/processor.cxx @@ -1234,22 +1234,35 @@ namespace relational if (!vq.literal.empty ()) { string q (upcase (vq.literal)); - vq.kind = (q.compare (0, 7, "SELECT ") == 0) - ? view_query::complete - : view_query::condition; + + if (q.compare (0, 7, "SELECT ") == 0) + vq.kind = view_query::complete_select; + else if (q.compare (0, 5, "EXEC ") == 0 || + q.compare (0, 5, "CALL ") == 0 || + q.compare (0, 8, "EXECUTE ") == 0) + vq.kind = view_query::complete_execute; + else + vq.kind = view_query::condition; } else if (!vq.expr.empty ()) { // If the first token in the expression is a string and - // it starts with "SELECT " or is equal to "SELECT", then - // we have a complete query. + // it starts with "SELECT " or is equal to "SELECT" or + // one of the stored procedure call keywords, then we + // have a complete query. // if (vq.expr.front ().type == CPP_STRING) { string q (upcase (vq.expr.front ().literal)); - vq.kind = (q.compare (0, 7, "SELECT ") == 0 || q == "SELECT") - ? view_query::complete - : view_query::condition; + + if (q.compare (0, 7, "SELECT ") == 0 || q == "SELECT") + vq.kind = view_query::complete_select; + else if (q.compare (0, 5, "EXEC ") == 0 || q == "EXEC" || + q.compare (0, 5, "CALL ") == 0 || q == "CALL" || + q.compare (0, 8, "EXECUTE ") == 0 || q == "EXECUTE") + vq.kind = view_query::complete_execute; + else + vq.kind = view_query::condition; } else vq.kind = view_query::condition; diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index 210d04b..b1d2a3d 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -3079,11 +3079,13 @@ traverse_view (type& c) << "query_statement (const query_base_type& q)" << "{"; - if (vq.kind == view_query::complete) + if (vq.kind == view_query::complete_select || + vq.kind == view_query::complete_execute) { os << "query_base_type r (" << endl; bool ph (false); + bool pred (vq.kind == view_query::complete_select); if (!vq.literal.empty ()) { @@ -3099,9 +3101,21 @@ traverse_view (type& c) if (p != string::npos) { ph = true; - os << strlit (string (vq.literal, 0, p + 1)) << " +" << endl - << "(q.empty () ? query_base_type::true_expr : q) +" << endl - << strlit (string (vq.literal, p + 2)); + // For the SELECT query we keep the parenthesis in (?) and + // also handle the case where the query expression is empty. + // + if (pred) + os << strlit (string (vq.literal, 0, p + 1)) << " +" << endl + << "(q.empty () ? query_base_type::true_expr : q) +" << endl + << strlit (string (vq.literal, p + 2)); + else + { + os << strlit (string (vq.literal, 0, p)) << " + q"; + + p += 3; + if (p != vq.literal.size ()) + os << strlit (string (vq.literal, p)); + } } else os << strlit (vq.literal); @@ -3115,7 +3129,7 @@ traverse_view (type& c) // os << "// From " << location_string (vq.loc, true) << endl << translate_expression ( - c, vq.expr, scope, vq.loc, "query", &ph).value; + c, vq.expr, scope, vq.loc, "query", &ph, pred).value; } os << ");"; @@ -4237,7 +4251,8 @@ namespace relational semantics::scope& scope, location_t loc, string const& prag, - bool* placeholder) + bool* placeholder, + bool predicate) { // This code is similar to translate() from context.cxx. // @@ -4432,8 +4447,19 @@ namespace relational if (tt == CPP_CLOSE_PAREN) { - r += "q.empty () ? query_base_type::true_expr : q"; *placeholder = true; + + // Predicate is true if this is a SELECT statement clause. + // Otherwise it is a stored procedure parameters. + // + if (predicate) + r += "q.empty () ? query_base_type::true_expr : q"; + else + { + r.resize (r.size () - 1); // Remove opening paren. + r += "q"; + break; // Skip the closing paren as well. + } } else { diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 0b50788..37328c8 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -3873,7 +3873,8 @@ namespace relational semantics::scope& start_scope, location_t loc, string const& prag, - bool* placeholder = 0); + bool* placeholder = 0, + bool predicate = true); // // composite // -- cgit v1.1