diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-10-18 17:34:52 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-10-18 17:34:52 +0000 |
| commit | 1127b10b278440247f18d1859e1f70a4aafaa9fb (patch) | |
| tree | d1b149d4bf92b1a01235000490438bfd91391a0e /lib/sqlalchemy/orm | |
| parent | 654794cdcf89eb7842ddf06bd9316bd860bca9e7 (diff) | |
| download | sqlalchemy-1127b10b278440247f18d1859e1f70a4aafaa9fb.tar.gz | |
- "not equals" comparisons of simple many-to-one relation
to an instance will not drop into an EXISTS clause
and will compare foreign key columns instead.
- removed not-really-working use cases of comparing
a collection to an iterable. Use contains() to test
for collection membership.
- Further simplified SELECT compilation and its relationship
to result row processing.
- Direct execution of a union() construct will properly set up
result-row processing. [ticket:1194]
Diffstat (limited to 'lib/sqlalchemy/orm')
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 40 |
1 files changed, 17 insertions, 23 deletions
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index d2f5dae0c..40bca8a11 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -347,18 +347,7 @@ class PropertyLoader(StrategizedProperty): else: return self.prop._optimized_compare(None) elif self.prop.uselist: - if not hasattr(other, '__iter__'): - raise sa_exc.InvalidRequestError("Can only compare a collection to an iterable object. Use contains().") - else: - j = self.prop.primaryjoin - if self.prop.secondaryjoin: - j = j & self.prop.secondaryjoin - clauses = [] - for o in other: - clauses.append( - sql.exists([1], j & sql.and_(*[x==y for (x, y) in zip(self.prop.mapper.primary_key, self.prop.mapper.primary_key_from_instance(o))])) - ) - return sql.and_(*clauses) + raise sa_exc.InvalidRequestError("Can't compare a collection to an object or collection; use contains() to test for membership.") else: return self.prop._optimized_compare(other) @@ -418,25 +407,30 @@ class PropertyLoader(StrategizedProperty): return clause def __negated_contains_or_equals(self, other): + if self.prop.direction == MANYTOONE: + state = attributes.instance_state(other) + strategy = self.prop._get_strategy(strategies.LazyLoader) + if strategy.use_get: + return sql.and_(*[ + sql.or_( + x != + self.prop.mapper._get_committed_state_attr_by_column(state, y), + x == None) + for (x, y) in self.prop.local_remote_pairs]) + criterion = sql.and_(*[x==y for (x, y) in zip(self.prop.mapper.primary_key, self.prop.mapper.primary_key_from_instance(other))]) return ~self._criterion_exists(criterion) def __ne__(self, other): - # TODO: simplify MANYTOONE comparsion when - # the 'use_get' flag is enabled - if other is None: if self.prop.direction == MANYTOONE: return sql.or_(*[x!=None for x in self.prop._foreign_keys]) - elif self.prop.uselist: - return self.any() else: - return self.has() - - if self.prop.uselist and not hasattr(other, '__iter__'): - raise sa_exc.InvalidRequestError("Can only compare a collection to an iterable object") - - return self.__negated_contains_or_equals(other) + return self._criterion_exists() + elif self.prop.uselist: + raise sa_exc.InvalidRequestError("Can't compare a collection to an object or collection; use contains() to test for membership.") + else: + return self.__negated_contains_or_equals(other) def compare(self, op, value, value_is_parent=False): if op == operators.eq: |
