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 14:39:18 -0400 |
| commit | 8d2d412d2afd4d3ce8a24876b86bdb56d1abc508 (patch) | |
| tree | 4d72e0ee4e82535ea31e00380bfa7ad495a6555a /lib/sqlalchemy/sql/compiler.py | |
| parent | 108d331e8932833ae9f81c79ccc6a522717a75f4 (diff) | |
| download | sqlalchemy-8d2d412d2afd4d3ce8a24876b86bdb56d1abc508.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
(cherry picked from commit abeea1d82db34232bbef01e98fa4d1de0f583eb6)
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 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) |
