]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
set within_columns_clause=False for all sub-elements of select()
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 9 Nov 2021 20:02:44 +0000 (15:02 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 9 Nov 2021 20:25:38 +0000 (15:25 -0500)
Fixed issue where using the feature of using a string label for ordering or
grouping described at :ref:`tutorial_order_by_label` would fail to function
correctly if used on a :class:`.CTE` construct, when the CTE were embedded
inside of an enclosing :class:`_sql.Select` statement that itself was set
up as a scalar subquery.

Fixes: #7269
Change-Id: Ied6048a1c9a622374a418230c8cfedafa8d3f87e

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

diff --git a/doc/build/changelog/unreleased_14/7269.rst b/doc/build/changelog/unreleased_14/7269.rst
new file mode 100644 (file)
index 0000000..6bbd126
--- /dev/null
@@ -0,0 +1,11 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 7269
+
+    Fixed issue where using the feature of using a string label for ordering or
+    grouping described at :ref:`tutorial_order_by_label` would fail to function
+    correctly if used on a :class:`.CTE` construct, when the CTE were embedded
+    inside of an enclosing :class:`_sql.Select` statement that itself was set
+    up as a scalar subquery.
+
+
index 646b49f22e3c75c759f68ffd6ed41d42ae6e4427..a2c4f951252318ac1f1d04266b2ddfba75b7129f 100644 (file)
@@ -3216,6 +3216,9 @@ class SQLCompiler(Compiled):
         # passed in.  for ORM use this will convert from an ORM-state
         # SELECT to a regular "Core" SELECT.  other composed operations
         # such as computation of joins will be performed.
+
+        kwargs["within_columns_clause"] = False
+
         compile_state = select_stmt._compile_state_factory(
             select_stmt, self, **kwargs
         )
index 2c8ef83a0ca64db0aa604987ca4ff4f53ff3ee18..4a34a5b04dbebcf828efff16740cb1b170875a25 100644 (file)
@@ -551,6 +551,54 @@ class CTETest(fixtures.TestBase, AssertsCompiledSQL):
             "SELECT cte.id, cte.manager_id, cte.id_1 FROM cte",
         )
 
+    @testing.combinations(True, False, argnames="use_object")
+    @testing.combinations("order_by", "group_by", argnames="order_by")
+    def test_order_by_group_by_label_w_scalar_subquery(
+        self, use_object, order_by
+    ):
+        """test issue #7269"""
+        t = table("test", column("a"))
+
+        b = t.c.a.label("b")
+
+        if use_object:
+            arg = b
+        else:
+            arg = "b"
+
+        if order_by == "order_by":
+            cte = select(b).order_by(arg).cte()
+        elif order_by == "group_by":
+            cte = select(b).group_by(arg).cte()
+        else:
+            assert False
+
+        stmt = select(select(cte.c.b).label("c"))
+
+        if use_object and order_by == "group_by":
+            # group_by(b) is de-references the label, due a difference in
+            # handling between coercions.GroupByImpl and coercions.OrderByImpl.
+            # "order by" makes use of the ClauseElement._order_by_label_element
+            # feature but group_by() doesn't.  it's not clear if group_by()
+            # could do the same thing order_by() does.
+            self.assert_compile(
+                stmt,
+                "WITH anon_1 AS "
+                "(SELECT test.a AS b FROM test GROUP BY test.a) "
+                "SELECT (SELECT anon_1.b FROM anon_1) AS c",
+            )
+        else:
+            self.assert_compile(
+                stmt,
+                "WITH anon_1 AS (SELECT test.a AS b FROM test %s b) "
+                "SELECT (SELECT anon_1.b FROM anon_1) AS c"
+                % ("ORDER BY" if order_by == "order_by" else "GROUP BY")
+                # prior to the fix, the use_object version came out as:
+                # "WITH anon_1 AS (SELECT test.a AS b FROM test "
+                # "ORDER BY test.a) "
+                # "SELECT (SELECT anon_1.b FROM anon_1) AS c"
+            )
+
     def test_wrecur_dupe_col_names_w_grouping(self):
         """test #6710