summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/compiler.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2020-08-08 13:03:17 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2020-08-08 13:34:27 -0400
commitc0685e5f419e203acd5e46f25c90e851e30e6f03 (patch)
tree42b73a6205a8b03e2ba232c21e43d5affb8657d2 /lib/sqlalchemy/sql/compiler.py
parent302e8dee82718df6c3a46de4c5283bdae51a650a (diff)
downloadsqlalchemy-c0685e5f419e203acd5e46f25c90e851e30e6f03.tar.gz
render INSERT/UPDATE column expressions up front; pass state
Fixes related to rendering of complex UPDATE DML which was not correctly preserving positional parameter order in conjunction with DML features that are only known to work on the PostgreSQL database. Both pg8000 and asyncpg use positional parameters which is why these issues are suddenly apparent. crud.py now takes on the task of rendering the column expressions for SET or VALUES so that for the very unusual case that the column expression is a compound expression that includes a bound parameter (namely an array index), the bound parameter order is preserved. Additionally, crud.py passes through the positional_names keyword argument into bindparam_string() which is necessary when CTEs are being rendered, as PG supports complex CTE / INSERT / UPDATE scenarios. Change-Id: I7f03920500e19b721636b84594de78a5bfdcbc82
Diffstat (limited to 'lib/sqlalchemy/sql/compiler.py')
-rw-r--r--lib/sqlalchemy/sql/compiler.py19
1 files changed, 7 insertions, 12 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 8e273f67c..542bf58ac 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -3286,7 +3286,7 @@ class SQLCompiler(Compiled):
if crud_params_single or not supports_default_values:
text += " (%s)" % ", ".join(
- [preparer.format_column(c[0]) for c in crud_params_single]
+ [expr for c, expr, value in crud_params_single]
)
if self.returning or insert_stmt._returning:
@@ -3311,12 +3311,15 @@ class SQLCompiler(Compiled):
elif compile_state._has_multi_parameters:
text += " VALUES %s" % (
", ".join(
- "(%s)" % (", ".join(c[1] for c in crud_param_set))
+ "(%s)"
+ % (", ".join(value for c, expr, value in crud_param_set))
for crud_param_set in crud_params
)
)
else:
- insert_single_values_expr = ", ".join([c[1] for c in crud_params])
+ insert_single_values_expr = ", ".join(
+ [value for c, expr, value in crud_params]
+ )
text += " VALUES (%s)" % insert_single_values_expr
if toplevel:
self.insert_single_values_expr = insert_single_values_expr
@@ -3424,15 +3427,7 @@ class SQLCompiler(Compiled):
text += table_text
text += " SET "
- include_table = (
- is_multitable and self.render_table_with_column_in_update_from
- )
- text += ", ".join(
- c[0]._compiler_dispatch(self, include_table=include_table)
- + "="
- + c[1]
- for c in crud_params
- )
+ text += ", ".join(expr + "=" + value for c, expr, value in crud_params)
if self.returning or update_stmt._returning:
if self.returning_precedes_values: