From d995af71980b1f887f2f374580d1341d72cc3442 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 1 Feb 2023 18:16:39 -0500 Subject: [PATCH] Fixed regression when using from_statement in orm context. Fixed regression when using :meth:`_sql.Select.from_statement` in an ORM context, where matching of columns to SQL labels based on name alone was disabled for ORM-statements that weren't fully textual. This would prevent arbitrary SQL expressions with column-name labels from matching up to the entity to be loaded, which previously would work within the 1.4 and previous series, so the previous behavior has been restored. Fixes: #9217 Change-Id: I5f7ab9710a96a98241388883365e56d308b4daf2 --- doc/build/changelog/unreleased_20/9217.rst | 10 ++++++++++ lib/sqlalchemy/orm/context.py | 12 +++--------- test/orm/test_froms.py | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 doc/build/changelog/unreleased_20/9217.rst diff --git a/doc/build/changelog/unreleased_20/9217.rst b/doc/build/changelog/unreleased_20/9217.rst new file mode 100644 index 0000000000..5768357480 --- /dev/null +++ b/doc/build/changelog/unreleased_20/9217.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: bug, orm, regression + :tickets: 9217 + + Fixed regression when using :meth:`_sql.Select.from_statement` in an ORM + context, where matching of columns to SQL labels based on name alone was + disabled for ORM-statements that weren't fully textual. This would prevent + arbitrary SQL expressions with column-name labels from matching up to the + entity to be loaded, which previously would work within the 1.4 + and previous series, so the previous behavior has been restored. diff --git a/lib/sqlalchemy/orm/context.py b/lib/sqlalchemy/orm/context.py index 890f3382b9..0e631e66f7 100644 --- a/lib/sqlalchemy/orm/context.py +++ b/lib/sqlalchemy/orm/context.py @@ -731,19 +731,13 @@ class ORMFromStatementCompileState(ORMCompileState): # those columns completely, don't interfere with the compiler # at all; just in ORM land, use an adapter to convert from # our ORM columns to whatever columns are in the statement, - # before we look in the result row. If the inner statement is - # not ORM enabled, assume looser col matching based on name - statement_is_orm = ( - self.statement._propagate_attrs.get( - "compile_state_plugin", None - ) - == "orm" - ) + # before we look in the result row. Always adapt on names + # to accept cases such as issue #9217. self._from_obj_alias = ORMStatementAdapter( _TraceAdaptRole.ADAPT_FROM_STATEMENT, self.statement, - adapt_on_names=not statement_is_orm, + adapt_on_names=True, ) return self diff --git a/test/orm/test_froms.py b/test/orm/test_froms.py index 85c950876b..e24062469f 100644 --- a/test/orm/test_froms.py +++ b/test/orm/test_froms.py @@ -36,6 +36,7 @@ from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures +from sqlalchemy.testing import in_ from sqlalchemy.testing import is_ from sqlalchemy.testing.fixtures import fixture_session from sqlalchemy.testing.schema import Column @@ -2726,6 +2727,21 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL): eq_(q.all(), expected) + def test_unrelated_column(self): + """Test for 9217""" + + User = self.classes.User + + q = select(User.id, func.lower("SANDY").label("name")).where( + User.id == 7 + ) + + s = select(User).from_statement(q) + sess = fixture_session() + res = sess.scalars(s).one() + in_("name", res.__dict__) + eq_(res.name, "sandy") + def test_expression_selectable_matches_mzero(self): User, Address = self.classes.User, self.classes.Address -- 2.47.3