]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
expand out all columns for _all_column_expressions
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 31 Jul 2023 21:47:07 +0000 (17:47 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 1 Aug 2023 03:00:10 +0000 (23:00 -0400)
Fixed issue where the ORM's generation of a SELECT from a joined
inheritance model with same-named columns in superclass and subclass would
somehow not send the correct list of column names to the :class:`.CTE`
construct, when the RECURSIVE column list were generated.

Fixes: #10169
Change-Id: I531d9bb469443c077ee34cbc1eeb097ada46f20f

doc/build/changelog/unreleased_20/10169.rst [new file with mode: 0644]
lib/sqlalchemy/orm/mapper.py
test/orm/inheritance/test_relationship.py
test/orm/test_core_compilation.py
test/orm/test_eager_relations.py

diff --git a/doc/build/changelog/unreleased_20/10169.rst b/doc/build/changelog/unreleased_20/10169.rst
new file mode 100644 (file)
index 0000000..d9f579e
--- /dev/null
@@ -0,0 +1,9 @@
+.. change::
+    :tags: bug, orm
+    :tickets: 10169
+
+    Fixed issue where the ORM's generation of a SELECT from a joined
+    inheritance model with same-named columns in superclass and subclass would
+    somehow not send the correct list of column names to the :class:`.CTE`
+    construct, when the RECURSIVE column list were generated.
+
index dcf464896b0c1a0100bd8fc7565a4eb5bc925ebe..e78830e5bf281bb734069e2f2e64c0ea6b4bfe25 100644 (file)
@@ -2931,10 +2931,11 @@ class Mapper(
         adapter = self._polymorphic_adapter
 
         return [
-            adapter.columns[prop.columns[0]] if adapter else prop.columns[0]
+            adapter.columns[c] if adapter else c
             for prop in poly_properties
             if isinstance(prop, properties.ColumnProperty)
             and prop._renders_in_subqueries
+            for c in prop.columns
         ]
 
     def _columns_plus_keys(self, polymorphic_mappers=()):
index 4ed2a453d3ec0cc1b2b4ca412359628984a3ddd6..b86e9f9f798868b2128312229b0292ddc890f195 100644 (file)
@@ -1822,6 +1822,7 @@ class SubClassToSubClassMultiTest(AssertsCompiledSQL, fixtures.MappedTest):
         # I3abfb45dd6e50f84f29d39434caa0b550ce27864,
         # this query is coming out instead which is equivalent, but not
         # totally sure where this happens
+        # update: changed slightly in #10169
 
         stmt = select(Sub2)
 
@@ -1839,6 +1840,7 @@ class SubClassToSubClassMultiTest(AssertsCompiledSQL, fixtures.MappedTest):
         self.assert_compile(
             stmt,
             "SELECT anon_1.sub2_id AS anon_1_sub2_id, "
+            "anon_1.base2_id AS anon_1_base2_id, "
             "anon_1.base2_base1_id AS anon_1_base2_base1_id, "
             "anon_1.base2_data AS anon_1_base2_data, "
             "anon_1.sub2_subdata AS anon_1_sub2_subdata "
@@ -1846,8 +1848,8 @@ class SubClassToSubClassMultiTest(AssertsCompiledSQL, fixtures.MappedTest):
             "base2.base1_id AS base2_base1_id, base2.data AS base2_data, "
             "sub2.subdata AS sub2_subdata "
             "FROM base2 JOIN sub2 ON base2.id = sub2.id) AS anon_1 "
-            "JOIN ep1 ON anon_1.sub2_id = ep1.base2_id "
-            "JOIN ep2 ON anon_1.sub2_id = ep2.base2_id",
+            "JOIN ep1 ON anon_1.base2_id = ep1.base2_id "
+            "JOIN ep2 ON anon_1.base2_id = ep2.base2_id",
         )
 
     def test_seven(self):
@@ -1882,10 +1884,12 @@ class SubClassToSubClassMultiTest(AssertsCompiledSQL, fixtures.MappedTest):
             # adding Sub2 to the entities list helps it,
             # otherwise the joins for Sub2.ep1/ep2 don't have columns
             # to latch onto.   Can't really make it better than this
+            # update: changed slightly in #10169
             stmt,
             "SELECT anon_1.parent_id AS anon_1_parent_id, "
             "anon_1.parent_data AS anon_1_parent_data, "
             "anon_1.sub2_id AS anon_1_sub2_id, "
+            "anon_1.base2_id AS anon_1_base2_id, "
             "anon_1.base2_base1_id AS anon_1_base2_base1_id, "
             "anon_1.base2_data AS anon_1_base2_data, "
             "anon_1.sub2_subdata AS anon_1_sub2_subdata "
@@ -1899,8 +1903,8 @@ class SubClassToSubClassMultiTest(AssertsCompiledSQL, fixtures.MappedTest):
             "ON parent.id = sub1.parent_id JOIN "
             "(base2 JOIN sub2 ON base2.id = sub2.id) "
             "ON base1.id = base2.base1_id) AS anon_1 "
-            "JOIN ep1 ON anon_1.sub2_id = ep1.base2_id "
-            "JOIN ep2 ON anon_1.sub2_id = ep2.base2_id",
+            "JOIN ep1 ON anon_1.base2_id = ep1.base2_id "
+            "JOIN ep2 ON anon_1.base2_id = ep2.base2_id",
         )
 
 
index fe47bcd856902debecaeba76a2a0c9e34748de2f..34ab5d9a7c3d09fd283ea0a6387761726cc55c40 100644 (file)
@@ -2516,6 +2516,28 @@ class JoinedInhTest(
             "ON companies.company_id = people.company_id",
         )
 
+    def test_cte_recursive_handles_dupe_columns(self):
+        """test #10169"""
+        Engineer = self.classes.Engineer
+
+        my_cte = select(Engineer).cte(recursive=True)
+
+        self.assert_compile(
+            select(my_cte),
+            "WITH RECURSIVE anon_1(person_id, person_id_1, company_id, name, "
+            "type, status, "
+            "engineer_name, primary_language) AS (SELECT engineers.person_id "
+            "AS person_id, people.person_id AS person_id_1, people.company_id "
+            "AS company_id, people.name AS name, people.type AS type, "
+            "engineers.status AS status, engineers.engineer_name AS "
+            "engineer_name, engineers.primary_language AS primary_language "
+            "FROM people JOIN engineers ON people.person_id = "
+            "engineers.person_id) SELECT anon_1.person_id, "
+            "anon_1.person_id_1, anon_1.company_id, "
+            "anon_1.name, anon_1.type, anon_1.status, anon_1.engineer_name, "
+            "anon_1.primary_language FROM anon_1",
+        )
+
 
 class RawSelectTest(QueryTest, AssertsCompiledSQL):
     """older tests from test_query.   Here, they are converted to use
index 261269dec1a07a7d77e15ca51a5f6887b4b08f1a..b1b6e86b79479a63188e0f5d919a91c684a640ec 100644 (file)
@@ -5774,11 +5774,14 @@ class LoadFromJoinedInhWUnion(
         self.assert_compile(
             q,
             "SELECT anon_1.anon_2_sample_id AS anon_1_anon_2_sample_id, "
+            "anon_1.anon_2_base_data_file_id AS "
+            "anon_1_anon_2_base_data_file_id, "
             "anon_1.anon_2_base_data_file_type "
             "AS anon_1_anon_2_base_data_file_type, "
             "tags_1.id AS tags_1_id, tags_1.name AS tags_1_name, "
             "tags_1.sample_id AS tags_1_sample_id FROM "
             "(SELECT anon_2.sample_id AS anon_2_sample_id, "
+            "anon_2.base_data_file_id AS anon_2_base_data_file_id, "
             "anon_2.base_data_file_type AS anon_2_base_data_file_type "
             "FROM (SELECT sample.id AS sample_id, "
             "base_data_file.id AS base_data_file_id, "
@@ -5807,6 +5810,7 @@ class LoadFromJoinedInhWUnion(
         self.assert_compile(
             q,
             "SELECT anon_1.sample_id AS anon_1_sample_id, "
+            "anon_1.base_data_file_id AS anon_1_base_data_file_id, "
             "anon_1.base_data_file_type AS anon_1_base_data_file_type, "
             "tags_1.id AS tags_1_id, tags_1.name AS tags_1_name, "
             "tags_1.sample_id AS tags_1_sample_id "