From b8906e62ceb122949f5dc9f49b1174986b64d503 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 17 Oct 2025 08:57:10 -0400 Subject: [PATCH] re-document 12915 as not fully fixed The ORM side of this issue can't be fixed without rewriting .params() which will be 2.1 only, so clarify changelog References: #12915 Change-Id: I2e524d5390241aa289786f524b6a51f39bc09876 --- doc/build/changelog/unreleased_20/12915.rst | 9 +++-- test/orm/test_core_compilation.py | 43 --------------------- test/sql/test_selectable.py | 12 ++++-- 3 files changed, 14 insertions(+), 50 deletions(-) diff --git a/doc/build/changelog/unreleased_20/12915.rst b/doc/build/changelog/unreleased_20/12915.rst index 399c474715..a67c1548e0 100644 --- a/doc/build/changelog/unreleased_20/12915.rst +++ b/doc/build/changelog/unreleased_20/12915.rst @@ -2,7 +2,8 @@ :tags: bug, sql :tickets: 12915 - Fixed issue where using :meth:`_sql.Select.params` to replace bound - parameters in a query could fail for some cases where the parameters - were embedded in subqueries or CTEs when ORM classes were involved, - due to issues with internal query traversal for these cases. + Some improvements to the :meth:`_sql.ClauseElement.params` method to + replace bound parameters in a query were made, however the ultimate issue + in :ticket:`12915` involving ORM :func:`_orm.aliased` cannot be fixed fully + until 2.1, where the method is being rewritten to work without relying on + Core cloned traversal. diff --git a/test/orm/test_core_compilation.py b/test/orm/test_core_compilation.py index 57c0ae36b0..b49d4286bf 100644 --- a/test/orm/test_core_compilation.py +++ b/test/orm/test_core_compilation.py @@ -36,7 +36,6 @@ from sqlalchemy.orm import with_loader_criteria from sqlalchemy.orm import with_polymorphic from sqlalchemy.sql import and_ from sqlalchemy.sql import sqltypes -from sqlalchemy.sql import visitors from sqlalchemy.sql.selectable import Join as core_join from sqlalchemy.sql.selectable import LABEL_STYLE_DISAMBIGUATE_ONLY from sqlalchemy.sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL @@ -366,48 +365,6 @@ class SelectableTest(QueryTest, AssertsCompiledSQL): checkparams={"param_1": 6, "param_2": 5}, ) - @testing.variation("use_get_params", [True, False]) - def test_annotated_cte_params_traverse(self, use_get_params): - """test #12915 - - test that .params() applied to a statement that includes - an annotated CTE will traverse into the CTE's internal structures - to replace the bound parameters. - - """ - User = self.classes.User - - ids_param = bindparam("ids") - cte = select(User).where(User.id == ids_param).cte("cte") - - ca = cte._annotate({"foo": "bar"}) - - stmt = select(ca) - - if use_get_params: - stmt = stmt.params(ids=17) - else: - # test without using params(), in case the implementation - # for params() changes we still want to test cloned_traverse - def visit_bindparam(bind): - if bind.key == "ids": - bind.value = 17 - bind.required = False - - stmt = visitors.cloned_traverse( - stmt, - {"maintain_key": True, "detect_subquery_cols": True}, - {"bindparam": visit_bindparam}, - ) - - self.assert_compile( - stmt, - "WITH cte AS (SELECT users.id AS id, users.name AS name " - "FROM users WHERE users.id = :ids) " - "SELECT cte.id, cte.name FROM cte", - checkparams={"ids": 17}, - ) - class PropagateAttrsTest(QueryTest): __backend__ = True diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py index 3172c970d2..c4c28b4f46 100644 --- a/test/sql/test_selectable.py +++ b/test/sql/test_selectable.py @@ -3138,7 +3138,13 @@ class AnnotationsTest(fixtures.TestBase): @testing.variation("use_get_params", [True, False]) def test_annotated_cte_params_traverse(self, use_get_params): - """test #12915""" + """test #12915 + + this issue attempted to repair some traversal issues found using + params() but does not fix the full issue reported in #12915, which + is a "wontfix" in favor of #7066. + + """ user = Table("user", MetaData(), Column("id", Integer)) ids_param = bindparam("ids") @@ -3152,8 +3158,8 @@ class AnnotationsTest(fixtures.TestBase): if use_get_params: stmt = stmt.params(ids=17) else: - # test without using params(), in case the implementation - # for params() changes we still want to test cloned_traverse + # test without using params(), as the implementation + # for params() will be changing def visit_bindparam(bind): if bind.key == "ids": bind.value = 17 -- 2.47.3