diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2009-01-05 19:23:56 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2009-01-05 19:23:56 +0000 |
| commit | 182badb266ef1ebae5f5acb3a87fb7cb99569799 (patch) | |
| tree | 8eb3168dd1db0a362aa08df51dcfbd97783db3b4 /lib/sqlalchemy | |
| parent | b5e0d613faf826f6824e6dfc5814eb9d7a3af76a (diff) | |
| download | sqlalchemy-182badb266ef1ebae5f5acb3a87fb7cb99569799.tar.gz | |
- property.of_type() is now recognized on a single-table
inheriting target, when used in the context of
prop.of_type(..).any()/has(), as well as
query.join(prop.of_type(...)).
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 13 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 25 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 15 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/util.py | 2 |
4 files changed, 38 insertions, 17 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 5c0629daf..316617835 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -839,6 +839,19 @@ class Mapper(object): return from_obj + @property + def _single_table_criterion(self): + if self.single and \ + self.inherits and \ + self.polymorphic_on and \ + self.polymorphic_identity is not None: + return self.polymorphic_on.in_( + m.polymorphic_identity + for m in self.polymorphic_iterator()) + else: + return None + + @util.memoized_property def _with_polymorphic_mappers(self): if not self.with_polymorphic: diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 675b505e7..343b73f42 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -386,6 +386,13 @@ class RelationProperty(StrategizedProperty): to_selectable = target_mapper._with_polymorphic_selectable if self.prop._is_self_referential(): to_selectable = to_selectable.alias() + + single_crit = target_mapper._single_table_criterion + if single_crit: + if criterion is not None: + criterion = single_crit & criterion + else: + criterion = single_crit else: to_selectable = None @@ -393,6 +400,7 @@ class RelationProperty(StrategizedProperty): source_selectable = self.__clause_element__() else: source_selectable = None + pj, sj, source, dest, secondary, target_adapter = \ self.prop._create_joins(dest_polymorphic=True, dest_selectable=to_selectable, source_selectable=source_selectable) @@ -863,8 +871,8 @@ class RelationProperty(StrategizedProperty): def _is_self_referential(self): return self.mapper.common_parent(self.parent) - def _create_joins(self, source_polymorphic=False, source_selectable=None, dest_polymorphic=False, dest_selectable=None): - key = util.WeakCompositeKey(source_polymorphic, source_selectable, dest_polymorphic, dest_selectable) + def _create_joins(self, source_polymorphic=False, source_selectable=None, dest_polymorphic=False, dest_selectable=None, of_type=None): + key = util.WeakCompositeKey(source_polymorphic, source_selectable, dest_polymorphic, dest_selectable, of_type) try: return self.__join_cache[key] except KeyError: @@ -896,14 +904,15 @@ class RelationProperty(StrategizedProperty): # in the case that the join is to a subclass # this is analgous to the "_adjust_for_single_table_inheritance()" # method in Query. - if self.mapper.single and self.mapper.inherits and self.mapper.polymorphic_on and self.mapper.polymorphic_identity is not None: - crit = self.mapper.polymorphic_on.in_( - m.polymorphic_identity - for m in self.mapper.polymorphic_iterator()) + + dest_mapper = of_type or self.mapper + + single_crit = dest_mapper._single_table_criterion + if single_crit: if secondaryjoin: - secondaryjoin = secondaryjoin & crit + secondaryjoin = secondaryjoin & single_crit else: - primaryjoin = primaryjoin & crit + primaryjoin = primaryjoin & single_crit if aliased: diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index e733cc024..7a5721761 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -887,7 +887,8 @@ class Query(object): self.__currenttables.add(prop.secondary) self.__currenttables.add(prop.table) - right_entity = prop.mapper + if not right_entity: + right_entity = prop.mapper if alias_criterion: right_adapter = ORMAdapter(right_entity, @@ -1618,14 +1619,12 @@ class Query(object): """ for entity, (mapper, adapter, s, i, w) in self._mapper_adapter_map.iteritems(): - if mapper.single and mapper.inherits and mapper.polymorphic_on and mapper.polymorphic_identity is not None: - crit = mapper.polymorphic_on.in_( - m.polymorphic_identity - for m in mapper.polymorphic_iterator()) + single_crit = mapper._single_table_criterion + if single_crit: if adapter: - crit = adapter.traverse(crit) - crit = self._adapt_clause(crit, False, False) - context.whereclause = sql.and_(context.whereclause, crit) + single_crit = adapter.traverse(single_crit) + single_crit = self._adapt_clause(single_crit, False, False) + context.whereclause = sql.and_(context.whereclause, single_crit) def __str__(self): return str(self._compile_context().statement) diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index 411c827c6..4f99586da 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -386,7 +386,7 @@ class _ORMJoin(expression.Join): prop = None if prop: - pj, sj, source, dest, secondary, target_adapter = prop._create_joins(source_selectable=adapt_from, dest_selectable=adapt_to, source_polymorphic=True, dest_polymorphic=True) + pj, sj, source, dest, secondary, target_adapter = prop._create_joins(source_selectable=adapt_from, dest_selectable=adapt_to, source_polymorphic=True, dest_polymorphic=True, of_type=right_mapper) if sj: left = sql.join(left, secondary, pj, isouter) |
