From 8d2d412d2afd4d3ce8a24876b86bdb56d1abc508 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 4 Aug 2018 13:45:07 -0400 Subject: Include UPDATE/DELETE extra_froms in correlation Fixed bug where the multi-table support for UPDATE and DELETE statements did not consider the additional FROM elements as targets for correlation, when a correlated SELECT were also combined with the statement. This change now includes that a SELECT statement in the WHERE clause for such a statement will try to auto-correlate back to these additional tables in the parent UPDATE/DELETE or unconditionally correlate if :meth:`.Select.correlate` is used. Note that auto-correlation raises an error if the SELECT statement would have no FROM clauses as a result, which can now occur if the parent UPDATE/DELETE specifies the same tables in its additional set of tables ; specify :meth:`.Select.correlate` explicitly to resolve. Change-Id: Ie11eaad7e49af3f59df11691b104d6359341bdae Fixes: #4313 (cherry picked from commit abeea1d82db34232bbef01e98fa4d1de0f583eb6) --- lib/sqlalchemy/sql/compiler.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'lib/sqlalchemy/sql/compiler.py') diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 75827b34e..80df2fcb5 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -2177,11 +2177,6 @@ class SQLCompiler(Compiled): def visit_update(self, update_stmt, asfrom=False, **kw): toplevel = not self.stack - self.stack.append( - {'correlate_froms': {update_stmt.table}, - "asfrom_froms": {update_stmt.table}, - "selectable": update_stmt}) - extra_froms = update_stmt._extra_froms is_multitable = bool(extra_froms) @@ -2191,8 +2186,15 @@ class SQLCompiler(Compiled): render_extra_froms = [ f for f in extra_froms if f not in main_froms ] + correlate_froms = main_froms.union(extra_froms) else: render_extra_froms = [] + correlate_froms = {update_stmt.table} + + self.stack.append( + {'correlate_froms': correlate_froms, + "asfrom_froms": correlate_froms, + "selectable": update_stmt}) text = "UPDATE " @@ -2286,14 +2288,15 @@ class SQLCompiler(Compiled): def visit_delete(self, delete_stmt, asfrom=False, **kw): toplevel = not self.stack - self.stack.append({'correlate_froms': {delete_stmt.table}, - "asfrom_froms": {delete_stmt.table}, - "selectable": delete_stmt}) - crud._setup_crud_params(self, delete_stmt, crud.ISDELETE, **kw) extra_froms = delete_stmt._extra_froms + correlate_froms = {delete_stmt.table}.union(extra_froms) + self.stack.append({'correlate_froms': correlate_froms, + "asfrom_froms": correlate_froms, + "selectable": delete_stmt}) + text = "DELETE " if delete_stmt._prefixes: @@ -2398,9 +2401,9 @@ class StrSQLCompiler(SQLCompiler): for t in extra_froms) def delete_extra_from_clause(self, update_stmt, - from_table, extra_froms, - from_hints, - **kw): + from_table, extra_froms, + from_hints, + **kw): return ', ' + ', '.join( t._compiler_dispatch(self, asfrom=True, fromhints=from_hints, **kw) -- cgit v1.2.1