diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2018-08-04 13:45:07 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2018-08-04 13:46:19 -0400 |
commit | abeea1d82db34232bbef01e98fa4d1de0f583eb6 (patch) | |
tree | fa5fa3576e8248975bbbd47c3fc21e31822529e9 /lib/sqlalchemy/sql/compiler.py | |
parent | e9e869f4d557a2a4e9a57f74862b4db7493b657e (diff) | |
download | sqlalchemy-abeea1d82db34232bbef01e98fa4d1de0f583eb6.tar.gz |
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
Diffstat (limited to 'lib/sqlalchemy/sql/compiler.py')
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index ae1dd2c7c..529e28ba6 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -2180,11 +2180,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) @@ -2194,8 +2189,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 " @@ -2289,14 +2291,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: @@ -2401,9 +2404,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) |