summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/util.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-11-24 18:49:32 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2014-11-24 18:49:32 -0500
commitde11f9498258182cbb6668b72067ec3f43a90415 (patch)
treed5d8aba789516b02391fa38d14085709ef86aca3 /lib/sqlalchemy/orm/util.py
parentba926a09b493b37c88e7b435aaccc6b399574057 (diff)
downloadsqlalchemy-de11f9498258182cbb6668b72067ec3f43a90415.tar.gz
- The :meth:`.PropComparator.of_type` modifier has been
improved in conjunction with loader directives such as :func:`.joinedload` and :func:`.contains_eager` such that if two :meth:`.PropComparator.of_type` modifiers of the same base type/path are encountered, they will be joined together into a single "polymorphic" entity, rather than replacing the entity of type A with the one of type B. E.g. a joinedload of ``A.b.of_type(BSub1)->BSub1.c`` combined with joinedload of ``A.b.of_type(BSub2)->BSub2.c`` will create a single joinedload of ``A.b.of_type((BSub1, BSub2)) -> BSub1.c, BSub2.c``, without the need for the ``with_polymorphic`` to be explicit in the query. fixes #3256
Diffstat (limited to 'lib/sqlalchemy/orm/util.py')
-rw-r--r--lib/sqlalchemy/orm/util.py22
1 files changed, 19 insertions, 3 deletions
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index ad610a4ac..4be8d19ff 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -543,8 +543,13 @@ class AliasedInsp(InspectionAttr):
mapper, self)
def __repr__(self):
- return '<AliasedInsp at 0x%x; %s>' % (
- id(self), self.class_.__name__)
+ if self.with_polymorphic_mappers:
+ with_poly = "(%s)" % ", ".join(
+ mp.class_.__name__ for mp in self.with_polymorphic_mappers)
+ else:
+ with_poly = ""
+ return '<AliasedInsp at 0x%x; %s%s>' % (
+ id(self), self.class_.__name__, with_poly)
inspection._inspects(AliasedClass)(lambda target: target._aliased_insp)
@@ -648,7 +653,8 @@ def aliased(element, alias=None, name=None, flat=False, adapt_on_names=False):
def with_polymorphic(base, classes, selectable=False,
flat=False,
polymorphic_on=None, aliased=False,
- innerjoin=False, _use_mapper_path=False):
+ innerjoin=False, _use_mapper_path=False,
+ _existing_alias=None):
"""Produce an :class:`.AliasedClass` construct which specifies
columns for descendant mappers of the given base.
@@ -713,6 +719,16 @@ def with_polymorphic(base, classes, selectable=False,
only be specified if querying for one specific subtype only
"""
primary_mapper = _class_to_mapper(base)
+ if _existing_alias:
+ assert _existing_alias.mapper is primary_mapper
+ classes = util.to_set(classes)
+ new_classes = set([
+ mp.class_ for mp in
+ _existing_alias.with_polymorphic_mappers])
+ if classes == new_classes:
+ return _existing_alias
+ else:
+ classes = classes.union(new_classes)
mappers, selectable = primary_mapper.\
_with_polymorphic_args(classes, selectable,
innerjoin=innerjoin)