summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2009-01-05 19:23:56 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2009-01-05 19:23:56 +0000
commit182badb266ef1ebae5f5acb3a87fb7cb99569799 (patch)
tree8eb3168dd1db0a362aa08df51dcfbd97783db3b4 /lib/sqlalchemy
parentb5e0d613faf826f6824e6dfc5814eb9d7a3af76a (diff)
downloadsqlalchemy-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.py13
-rw-r--r--lib/sqlalchemy/orm/properties.py25
-rw-r--r--lib/sqlalchemy/orm/query.py15
-rw-r--r--lib/sqlalchemy/orm/util.py2
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)