From 8ab652c6cb48ca6e157233aa3a23049e318d9d2b Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 3 Nov 2017 11:11:48 -0400 Subject: Intercept contains_eager() with of_type, set aliased / polymorphic Fixed bug in :func:`.contains_eager` query option where making use of a path that used :meth:`.PropComparator.of_type` to refer to a subclass across more than one level of joins would also require that the "alias" argument were provided with the same subtype in order to avoid adding unwanted FROM clauses to the query; additionally, using :func:`.contains_eager` across subclasses that use :func:`.aliased` objects of subclasses as the :meth:`.PropComparator.of_type` argument will also render correctly. Change-Id: Ie1c10924faa45251aab1a076a3ba7ef9fb1bdeee Fixes: #4130 --- lib/sqlalchemy/orm/strategy_options.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'lib/sqlalchemy') diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index 86a48f3b9..775ed6c97 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -211,7 +211,7 @@ class Load(Generative, MapperOption): if getattr(attr, '_of_type', None): ac = attr._of_type - ext_info = inspect(ac) + ext_info = of_type_info = inspect(ac) existing = path.entity_path[prop].get( self.context, "path_with_polymorphic") @@ -221,8 +221,23 @@ class Load(Generative, MapperOption): ext_info.mapper, aliased=True, _use_mapper_path=True, _existing_alias=existing) + ext_info = inspect(ac) + elif not ext_info.with_polymorphic_mappers: + ext_info = orm_util.AliasedInsp( + ext_info.entity, + ext_info.mapper.base_mapper, + ext_info.selectable, + ext_info.name, + ext_info.with_polymorphic_mappers or [ext_info.mapper], + ext_info.polymorphic_on, + ext_info._base_alias, + ext_info._use_mapper_path, + ext_info._adapt_on_names, + ext_info.represents_outer_join + ) + path.entity_path[prop].set( - self.context, "path_with_polymorphic", inspect(ac)) + self.context, "path_with_polymorphic", ext_info) # the path here will go into the context dictionary and # needs to match up to how the class graph is traversed. @@ -235,7 +250,7 @@ class Load(Generative, MapperOption): # it might be better for "path" to really represent, # "the path", but trying to keep the impact of the cache # key feature localized for now - self._of_type = ext_info + self._of_type = of_type_info else: path = path[prop] @@ -787,6 +802,10 @@ def contains_eager(loadopt, attr, alias=None): info = inspect(alias) alias = info.selectable + elif getattr(attr, '_of_type', None): + ot = inspect(attr._of_type) + alias = ot.selectable + cloned = loadopt.set_relationship_strategy( attr, {"lazy": "joined"}, -- cgit v1.2.1