From 2ca4828d303fdd27c573429910f7a25fd1e3727c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 5 Feb 2015 14:17:07 +0200 Subject: Implement result modifiers in view query condition --- odb/relational/mssql/source.cxx | 11 +++++++++++ odb/relational/oracle/source.cxx | 15 +++++++++++++++ odb/relational/processor.cxx | 14 +++++++++++++- odb/relational/source.cxx | 13 ++++++++++++- odb/relational/source.hxx | 9 +++++++++ odb/relational/sqlite/source.cxx | 9 +++++++++ 6 files changed, 69 insertions(+), 2 deletions(-) (limited to 'odb/relational') diff --git a/odb/relational/mssql/source.cxx b/odb/relational/mssql/source.cxx index ca36dfb..71bc40e 100644 --- a/odb/relational/mssql/source.cxx +++ b/odb/relational/mssql/source.cxx @@ -1179,6 +1179,17 @@ namespace relational } } + virtual string + from_trailer (type& c) + { + return c.get ("query").for_update + ? " WITH (UPDLOCK)" + : ""; + } + + virtual string + select_trailer (type&) {return "";} + private: // Go via the dynamic creation to get access to the constructor. // diff --git a/odb/relational/oracle/source.cxx b/odb/relational/oracle/source.cxx index ea4a14b..71b032e 100644 --- a/odb/relational/oracle/source.cxx +++ b/odb/relational/oracle/source.cxx @@ -619,6 +619,21 @@ namespace relational return r; } + + virtual string + select_trailer (type& c) + { + view_query const& vq (c.get ("query")); + + if (vq.for_update && vq.distinct) + { + error (vq.loc) + << "Oracle does not support FOR UPDATE with DISTINCT" << endl; + throw operation_failed (); + } + + return base::select_trailer (c); + } }; entry class_entry_; } diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx index 7658725..16904b6 100644 --- a/odb/relational/processor.cxx +++ b/odb/relational/processor.cxx @@ -1298,11 +1298,23 @@ namespace relational vq.kind = view_query::condition; } else - vq.kind = view_query::runtime; + vq.kind = (vq.distinct || vq.for_update) + ? view_query::condition // The query(distinct) case. + : view_query::runtime; } else vq.kind = has_o ? view_query::condition : view_query::runtime; + if ((vq.distinct || vq.for_update) && vq.kind != view_query::condition) + { + error (vq.loc) + << "result modifier specified for " + << (vq.kind == view_query::runtime ? "runtime" : "native") + << " query" << endl; + + throw operation_failed (); + } + // We cannot have an incomplete query if there are not objects // to derive the rest from. // diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index 39a210e..dc083bb 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -4770,6 +4770,8 @@ traverse_view (type& c) if (!i->alias.empty ()) l += (need_alias_as ? " AS " : " ") + quote_id (i->alias); + l += from_trailer (c); + from.push_back (l); continue; } @@ -4829,6 +4831,8 @@ traverse_view (type& c) if (!alias.empty ()) l += (need_alias_as ? " AS " : " ") + quote_id (alias); + l += from_trailer (c); + from.push_back (l); if (poly_depth != 1) @@ -5539,7 +5543,7 @@ traverse_view (type& c) string sep (versioned || query_optimize ? "\n" : " "); os << "query_base_type r (" << endl - << strlit ("SELECT" + sep); + << strlit ((vq.distinct ? "SELECT DISTINCT" : "SELECT") + sep); for (statement_columns::const_iterator i (sc.begin ()), e (sc.end ()); i != e;) @@ -5632,6 +5636,13 @@ traverse_view (type& c) << "r += c.clause_prefix ();" << "r += c;" << "}"; + + string st (select_trailer (c)); + if (!st.empty ()) + { + os << "r += " << strlit (sep) << ";" + << "r += " << strlit (st) << ";"; + } } else { diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index a725b6a..48d0e1d 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -6677,6 +6677,15 @@ namespace relational << "imb"; } + virtual string + from_trailer (type&) { return "";} + + virtual string + select_trailer (type& c) + { + return c.get ("query").for_update ? "FOR UPDATE" : ""; + } + virtual void traverse_view (type& c); diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx index 3dfaae2..0824eb2 100644 --- a/odb/relational/sqlite/source.cxx +++ b/odb/relational/sqlite/source.cxx @@ -246,6 +246,15 @@ namespace relational { os << im << "null = true;"; } + + virtual string + select_trailer (type&) + { + // SQLite has not support for FOR UPDATE and since this is an + // optimization, we simply ignore it. + // + return ""; + } }; entry class_entry_; } -- cgit v1.1