From 4aff711b791751368a5f1612c9e711470dfde023 Mon Sep 17 00:00:00 2001 From: StdCarrot Date: Fri, 4 Dec 2020 15:15:42 +0900 Subject: [PATCH 1/2] Fix #319 - Fixed problem: typemap doesn't exist error when trying to use sub-column of CompositeType in select query(equivalent as get Comparator of sub-column) - Solving by: Get sub-column's type correctly. --- sqlalchemy_utils/types/pg_composite.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sqlalchemy_utils/types/pg_composite.py b/sqlalchemy_utils/types/pg_composite.py index a1b244b9..5b0b28bb 100644 --- a/sqlalchemy_utils/types/pg_composite.py +++ b/sqlalchemy_utils/types/pg_composite.py @@ -183,7 +183,10 @@ class CompositeType(UserDefinedType, SchemaType): class comparator_factory(UserDefinedType.Comparator): def __getattr__(self, key): try: - type_ = self.type.typemap[key] + if key in self.type.column_map: + type_ = self.type.column_map[key].type + else: + type_ = self.type.typemap[key] except KeyError: raise KeyError( "Type '%s' doesn't have an attribute: '%s'" % ( @@ -201,6 +204,7 @@ def __init__(self, name, columns): SchemaType.__init__(self) self.name = name self.columns = columns + self.column_map = {col.name: col for col in columns} if name in registered_composites: self.type_cls = registered_composites[name].type_cls else: From d7e0dc992179fa13c915915357164247a6f0dcc9 Mon Sep 17 00:00:00 2001 From: yhbu Date: Thu, 14 Apr 2022 18:29:53 +0900 Subject: [PATCH 2/2] Unit test for fix #319 --- tests/types/test_composite.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/types/test_composite.py b/tests/types/test_composite.py index 1698dcff..f07f6e38 100644 --- a/tests/types/test_composite.py +++ b/tests/types/test_composite.py @@ -99,6 +99,18 @@ def test_incomplete_dict(self, session, Account): assert account.balance.currency is None assert account.balance.amount == 15 + def test_composite_attribute_query(self, session, Account): + account_query = session \ + .query(Account) \ + .filter(Account.balance.amount == 15) + + raw_query = str( + account_query.statement + .compile(compile_kwargs={"literal_binds": True}) + ) + assert '(account.balance).amount = 15' in raw_query + + @pytest.mark.skipif('i18n.babel is None') @pytest.mark.usefixtures('postgresql_dsn')