on_conflict_do_update assumes the compiler statement is the insert
from sqlalchemy import table, column, select, literal_column
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.dialects import postgresql
foo = table("foo", column("foo_id"), column("foo_data"))
refreshed_foo = table("refreshed_foo", column("foo_id"), column("foo_data"))
new_data = table("new_data", column("foo_id"), column("foo_data"))
select_query = select([new_data])
ins = insert(foo).from_select(select_query.columns.keys(), select_query)
upsert = ins.on_conflict_do_update(
index_elements=[foo.c.foo_id],
set_={"foo_data": ins.excluded.foo_data}
).returning(literal_column('1').label('x')).cte("perform_inserts")
stmt = select([upsert.c.x])
print stmt.compile(dialect=postgresql.dialect())
output:
#!
File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/sql/compiler.py", line 1412, in visit_cte
self, asfrom=True, **kwargs
File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
return meth(self, **kw)
File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/sql/compiler.py", line 2104, in visit_insert
insert_stmt._post_values_clause, **kw)
File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/sql/compiler.py", line 242, in process
return obj._compiler_dispatch(self, **kwargs)
File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
return meth(self, **kw)
File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/dialects/postgresql/base.py", line 1535, in visit_on_conflict_do_update
cols = insert_statement.table.c
AttributeError: 'Select' object has no attribute 'table'
patch:
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index b56ac5b10..821752870 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1529,7 +1529,9 @@ class PGCompiler(compiler.SQLCompiler):
set_parameters = dict(clause.update_values_to_set)
# create a list of column assignment clauses as tuples
- cols = self.statement.table.c
+
+ insert_statement = self.stack[-1]['selectable']
+ cols = insert_statement.table.c
for c in cols:
col_key = c.key
if col_key in set_parameters:
Comments (3)
-
reporter -
reporter - changed status to resolved
use the stack to get the insert statement in on conflict
Fixed bug in Postgresql :meth:
.postgresql.dml.Insert.on_conflict_do_update
which would prevent the insert statement from being used as a CTE, e.g. via :meth:.Insert.cte
, within another statement.Change-Id: Ie20972a05e194290bc9d92819750845872949ecc Fixes:
#4074→ <<cset 70516536107a>>
-
reporter use the stack to get the insert statement in on conflict
Fixed bug in Postgresql :meth:
.postgresql.dml.Insert.on_conflict_do_update
which would prevent the insert statement from being used as a CTE, e.g. via :meth:.Insert.cte
, within another statement.Change-Id: Ie20972a05e194290bc9d92819750845872949ecc Fixes:
#4074(cherry picked from commit 70516536107a44230762206342c51239c5d85417)→ <<cset a14e5c42ca78>>
- Log in to comment
https://gerrit.sqlalchemy.org/#/q/Ie20972a05e194290bc9d92819750845872949ecc