From: Mike Bayer Date: Mon, 31 Jul 2023 21:47:07 +0000 (-0400) Subject: expand out all columns for _all_column_expressions X-Git-Tag: rel_2_0_20~25^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=244a94957b50e4a6dcdb1ffbcf4ce1a76a18f0b2;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git expand out all columns for _all_column_expressions 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 --- diff --git a/doc/build/changelog/unreleased_20/10169.rst b/doc/build/changelog/unreleased_20/10169.rst new file mode 100644 index 0000000000..d9f579ef1e --- /dev/null +++ b/doc/build/changelog/unreleased_20/10169.rst @@ -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. + diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index dcf464896b..e78830e5bf 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -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=()): diff --git a/test/orm/inheritance/test_relationship.py b/test/orm/inheritance/test_relationship.py index 4ed2a453d3..b86e9f9f79 100644 --- a/test/orm/inheritance/test_relationship.py +++ b/test/orm/inheritance/test_relationship.py @@ -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", ) diff --git a/test/orm/test_core_compilation.py b/test/orm/test_core_compilation.py index fe47bcd856..34ab5d9a7c 100644 --- a/test/orm/test_core_compilation.py +++ b/test/orm/test_core_compilation.py @@ -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 diff --git a/test/orm/test_eager_relations.py b/test/orm/test_eager_relations.py index 261269dec1..b1b6e86b79 100644 --- a/test/orm/test_eager_relations.py +++ b/test/orm/test_eager_relations.py @@ -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 "