summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2023-04-30 13:56:33 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2023-04-30 14:53:08 -0400
commit56443acb89e531b3695de669c76297e4a5568fc1 (patch)
tree83a9307f7d051de9a03c8a5a83c3735639f80af9 /test
parent39c8e95b1f50190ff30a836b2bcf13ba2cacc052 (diff)
downloadsqlalchemy-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.py51
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"