]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
pop the stack that we pushed
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 8 Mar 2022 18:40:12 +0000 (13:40 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 8 Mar 2022 18:40:12 +0000 (13:40 -0500)
Fixed regression caused by :ticket:`7760` where the new capabilities of
:class:`.TextualSelect` were not fully implemented within the compiler
properly, leading to issues with composed INSERT constructs such as "INSERT
FROM SELECT" and "INSERT...ON CONFLICT" when combined with CTE and textual
statements.

Fixes: #7798
Change-Id: Ia2ce92507e574dd36fd26dd38ec9dd2713584467

doc/build/changelog/unreleased_14/7798.rst [new file with mode: 0644]
lib/sqlalchemy/sql/compiler.py
test/dialect/postgresql/test_compiler.py
test/sql/test_cte.py

diff --git a/doc/build/changelog/unreleased_14/7798.rst b/doc/build/changelog/unreleased_14/7798.rst
new file mode 100644 (file)
index 0000000..31a5bb2
--- /dev/null
@@ -0,0 +1,9 @@
+.. change::
+    :tags: bug, sql, regression
+    :tickets: 7798
+
+    Fixed regression caused by :ticket:`7760` where the new capabilities of
+    :class:`.TextualSelect` were not fully implemented within the compiler
+    properly, leading to issues with composed INSERT constructs such as "INSERT
+    FROM SELECT" and "INSERT...ON CONFLICT" when combined with CTE and textual
+    statements.
index 712d31462402664b17fda31014daaec39a7920b6..09e38a5ab96ca81218550ffe1cfb7666d61576b1 100644 (file)
@@ -1721,6 +1721,8 @@ class SQLCompiler(Compiled):
             nesting_level = len(self.stack) if not toplevel else None
             text = self._render_cte_clause(nesting_level=nesting_level) + text
 
+        self.stack.pop(-1)
+
         return text
 
     def visit_null(self, expr, **kw):
index 98b974ea538b4c795f53ec0bebe3abdd5e29965d..2221fd30a84490bee29d221779d2cdbdc37e6d61 100644 (file)
@@ -2321,6 +2321,28 @@ class InsertOnConflictTest(fixtures.TestBase, AssertsCompiledSQL):
                 ):
                     meth()
 
+    def test_on_conflict_cte_plus_textual(self):
+        """test #7798"""
+
+        bar = table("bar", column("id"), column("attr"), column("foo_id"))
+        s1 = text("SELECT bar.id, bar.attr FROM bar").columns(
+            bar.c.id, bar.c.attr
+        )
+        s2 = (
+            insert(bar)
+            .from_select(list(s1.selected_columns), s1)
+            .on_conflict_do_update(
+                index_elements=[s1.selected_columns.id],
+                set_={"attr": s1.selected_columns.attr},
+            )
+        )
+
+        self.assert_compile(
+            s2,
+            "INSERT INTO bar (id, attr) SELECT bar.id, bar.attr "
+            "FROM bar ON CONFLICT (id) DO UPDATE SET attr = bar.attr",
+        )
+
     def test_do_nothing_no_target(self):
 
         i = (
index 2ee6fa9f312c6aabc49fcbb15a6dd7f75567e64a..686d4928d6fa1f1fbf74df886896e5b5320edacc 100644 (file)
@@ -1649,6 +1649,27 @@ class CTETest(fixtures.TestBase, AssertsCompiledSQL):
             "(SELECT id FROM baz)",
         )
 
+    def test_textual_select_stack_correction(self):
+        """test #7798 , regression from #7760"""
+
+        foo = table("foo", column("id"))
+        bar = table("bar", column("id"), column("attr"), column("foo_id"))
+
+        s1 = text("SELECT id FROM foo").columns(foo.c.id)
+        s2 = text(
+            "SELECT bar.id, bar.attr FROM bar WHERE br.id IN "
+            "(SELECT id FROM baz)"
+        ).columns(bar.c.id, bar.c.attr)
+        s3 = bar.insert().from_select(list(s2.selected_columns), s2)
+        s4 = s3.add_cte(s1.cte(name="baz"))
+
+        self.assert_compile(
+            s4,
+            "WITH baz AS (SELECT id FROM foo) INSERT INTO bar (id, attr) "
+            "SELECT bar.id, bar.attr FROM bar WHERE br.id IN "
+            "(SELECT id FROM baz)",
+        )
+
     def test_insert_uses_independent_cte(self):
         products = table("products", column("id"), column("price"))