diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2023-04-30 13:56:33 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2023-04-30 14:53:08 -0400 |
| commit | 56443acb89e531b3695de669c76297e4a5568fc1 (patch) | |
| tree | 83a9307f7d051de9a03c8a5a83c3735639f80af9 /test | |
| parent | 39c8e95b1f50190ff30a836b2bcf13ba2cacc052 (diff) | |
| download | sqlalchemy-56443acb89e531b3695de669c76297e4a5568fc1.tar.gz | |
do not allow non-cache-key entity objects in annotations
Fixed critical caching issue where combination of :func:`_orm.aliased()`
:func:`_sql.case` and :func:`_hybrid.hybrid_property` expressions would
cause a cache key mismatch, leading to cache keys that held onto the actual
:func:`_orm.aliased` object while also not matching each other, filling up
the cache.
Fixes: #9728
Change-Id: I700645b5629a81a0104cf923db72a7421fa43ff4
Diffstat (limited to 'test')
| -rw-r--r-- | test/orm/test_cache_key.py | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/test/orm/test_cache_key.py b/test/orm/test_cache_key.py index f1c3e6a54..884baed62 100644 --- a/test/orm/test_cache_key.py +++ b/test/orm/test_cache_key.py @@ -2,6 +2,7 @@ import random import sqlalchemy as sa from sqlalchemy import Column +from sqlalchemy import column from sqlalchemy import func from sqlalchemy import inspect from sqlalchemy import Integer @@ -16,6 +17,7 @@ from sqlalchemy import true from sqlalchemy import update from sqlalchemy import util from sqlalchemy.ext.declarative import ConcreteBase +from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import aliased from sqlalchemy.orm import Bundle from sqlalchemy.orm import defaultload @@ -785,6 +787,55 @@ class PolyCacheKeyTest(fixtures.CacheKeyFixture, _poly_fixtures._Polymorphic): compare_values=True, ) + @testing.variation( + "exprtype", ["plain_column", "self_standing_case", "case_w_columns"] + ) + def test_hybrid_w_case_ac(self, decl_base, exprtype): + """test #9728""" + + class Employees(decl_base): + __tablename__ = "employees" + id = Column(String(128), primary_key=True) + first_name = Column(String(length=64)) + + @hybrid_property + def name(self): + return self.first_name + + @name.expression + def name( + cls, + ): + if exprtype.plain_column: + return cls.first_name + elif exprtype.self_standing_case: + return case( + (column("x") == 1, column("q")), + else_=column("q"), + ) + elif exprtype.case_w_columns: + return case( + (column("x") == 1, column("q")), + else_=cls.first_name, + ) + else: + exprtype.fail() + + def go1(): + employees_2 = aliased(Employees, name="employees_2") + stmt = select(employees_2.name) + return stmt + + def go2(): + employees_2 = aliased(Employees, name="employees_2") + stmt = select(employees_2) + return stmt + + self._run_cache_key_fixture( + lambda: stmt_20(go1(), go2()), + compare_values=True, + ) + class RoundTripTest(QueryTest, AssertsCompiledSQL): __dialect__ = "default" |
