From: Mike Bayer Date: Wed, 1 Feb 2023 23:16:39 +0000 (-0500) Subject: Fixed regression when using from_statement in orm context. X-Git-Tag: rel_2_0_2~15^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d995af71980b1f887f2f374580d1341d72cc3442;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git 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 --- 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