diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-06-10 13:45:19 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-06-10 13:45:19 -0400 |
| commit | b614a24c5ddf4c7c7aa45e1eaeb3f82e36737729 (patch) | |
| tree | 95c31f73e46603c154124f7c69d2a2cb7943157a /lib/sqlalchemy | |
| parent | 1652491cc6ef44c803e58c0d842818ab7310f498 (diff) | |
| download | sqlalchemy-b614a24c5ddf4c7c7aa45e1eaeb3f82e36737729.tar.gz | |
Fixed the interaction between composite attributes and
the :func:`.aliased` function. Previously, composite attributes
wouldn't work correctly in comparison operations when aliasing
was applied. Also in 0.8.2. [ticket:2755]
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/descriptor_props.py | 38 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/util.py | 1 |
2 files changed, 24 insertions, 15 deletions
diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py index 86b445bb6..c565cb715 100644 --- a/lib/sqlalchemy/orm/descriptor_props.py +++ b/lib/sqlalchemy/orm/descriptor_props.py @@ -298,7 +298,7 @@ class CompositeProperty(DescriptorProperty): ) def _comparator_factory(self, mapper): - return self.comparator_factory(self) + return self.comparator_factory(self, mapper) class Comparator(PropComparator): """Produce boolean, comparison, and other operators for @@ -318,29 +318,39 @@ class CompositeProperty(DescriptorProperty): :attr:`.TypeEngine.comparator_factory` """ - def __init__(self, prop, adapter=None): - self.prop = self.property = prop - self.adapter = adapter def __clause_element__(self): - if self.adapter: - # TODO: test coverage for adapted composite comparison - return expression.ClauseList( - *[self.adapter(x) for x in self.prop._comparable_elements]) - else: - return expression.ClauseList(*self.prop._comparable_elements) + return expression.ClauseList(*self._comparable_elements) __hash__ = None + @util.memoized_property + def _comparable_elements(self): + if self.adapter: + # we need to do a little fudging here because + # the adapter function we're given only accepts + # ColumnElements, but our prop._comparable_elements is returning + # InstrumentedAttribute, because we support the use case + # of composites that refer to relationships. The better + # solution here is to open up how AliasedClass interacts + # with PropComparators so more context is available. + return [self.adapter(x.__clause_element__()) + for x in self.prop._comparable_elements] + else: + return self.prop._comparable_elements + def __eq__(self, other): if other is None: values = [None] * len(self.prop._comparable_elements) else: values = other.__composite_values__() - return sql.and_( - *[a == b - for a, b in zip(self.prop._comparable_elements, values)] - ) + comparisons = [ + a == b + for a, b in zip(self.prop._comparable_elements, values) + ] + if self.adapter: + comparisons = [self.adapter(x) for x in comparisons] + return sql.and_(*comparisons) def __ne__(self, other): return sql.not_(self.__eq__(other)) diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index 38cf58792..ef9de760e 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -575,7 +575,6 @@ class AliasedClass(object): def __adapt_prop(self, existing, key): comparator = existing.comparator.adapted(self.__adapt_element) - queryattr = attributes.QueryableAttribute( self, key, impl=existing.impl, |
