]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
pass along independent CTE attributes in ORM context
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 31 Jul 2023 15:17:20 +0000 (11:17 -0400)
committermike bayer <mike_mp@zzzcomputing.com>
Mon, 31 Jul 2023 21:01:06 +0000 (21:01 +0000)
Fixed issue where an ORM-enabled :func:`_sql.select` construct would not
render any CTEs added only via the :meth:`_sql.Select.add_cte` method that
were not otherwise referenced in the statement.

Fixes: #10167
Change-Id: Ib13f478607628b02742e6026e94bce54b089627d

doc/build/changelog/unreleased_20/10167.rst [new file with mode: 0644]
lib/sqlalchemy/orm/context.py
test/orm/test_core_compilation.py

diff --git a/doc/build/changelog/unreleased_20/10167.rst b/doc/build/changelog/unreleased_20/10167.rst
new file mode 100644 (file)
index 0000000..ac05401
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: bug, orm
+    :tickets: 10167
+
+    Fixed issue where an ORM-enabled :func:`_sql.select` construct would not
+    render any CTEs added only via the :meth:`_sql.Select.add_cte` method that
+    were not otherwise referenced in the statement.
index dfb7b3ef629a7105b9d816e439a29cc029bd7359..e961e59347eb7a16e05073da7d8915e3f984ae2e 100644 (file)
@@ -1604,6 +1604,8 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
         prefixes,
         suffixes,
         group_by,
+        independent_ctes,
+        independent_ctes_opts,
     ):
         statement = Select._create_raw_select(
             _raw_columns=raw_columns,
@@ -1631,6 +1633,8 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
         statement._offset_clause = offset_clause
         statement._fetch_clause = fetch_clause
         statement._fetch_clause_options = fetch_clause_options
+        statement._independent_ctes = independent_ctes
+        statement._independent_ctes_opts = independent_ctes_opts
 
         if prefixes:
             statement._prefixes = prefixes
@@ -2296,6 +2300,10 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
             "fetch_clause_options": (
                 self.select_statement._fetch_clause_options
             ),
+            "independent_ctes": self.select_statement._independent_ctes,
+            "independent_ctes_opts": (
+                self.select_statement._independent_ctes_opts
+            ),
         }
 
     @property
index fe47bcd856902debecaeba76a2a0c9e34748de2f..328460fe39deb8f126277937aa9e72fc7a6a774f 100644 (file)
@@ -519,6 +519,33 @@ class DMLTest(QueryTest, AssertsCompiledSQL):
         else:
             stmt_type.fail()
 
+    @testing.variation("stmt_type", ["core", "orm"])
+    def test_add_cte(self, stmt_type: testing.Variation):
+        """test #10167"""
+
+        if stmt_type.orm:
+            User = self.classes.User
+            cte_select = select(User.name).limit(1).cte()
+            cte_insert = insert(User).from_select(["name"], cte_select).cte()
+        elif stmt_type.core:
+            user_table = self.tables.users
+            cte_select = select(user_table.c.name).limit(1).cte()
+            cte_insert = (
+                insert(user_table).from_select(["name"], cte_select).cte()
+            )
+        else:
+            stmt_type.fail()
+
+        select_stmt = select(cte_select).add_cte(cte_insert)
+
+        self.assert_compile(
+            select_stmt,
+            "WITH anon_2 AS (SELECT users.name AS name FROM users LIMIT "
+            ":param_1), anon_1 AS (INSERT INTO users (name) "
+            "SELECT anon_2.name AS name FROM anon_2) "
+            "SELECT anon_2.name FROM anon_2",
+        )
+
 
 class ColumnsClauseFromsTest(QueryTest, AssertsCompiledSQL):
     __dialect__ = "default"