diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-11-24 18:49:32 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-11-24 18:49:32 -0500 |
commit | de11f9498258182cbb6668b72067ec3f43a90415 (patch) | |
tree | d5d8aba789516b02391fa38d14085709ef86aca3 /lib/sqlalchemy/orm/util.py | |
parent | ba926a09b493b37c88e7b435aaccc6b399574057 (diff) | |
download | sqlalchemy-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.py | 22 |
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) |