diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-01-20 12:41:22 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-01-20 16:25:33 -0500 |
| commit | 20e14633fb15018ccf1f5d127fd67609bfe2b3e5 (patch) | |
| tree | ae05d084bd39b1020eaabd2a8a4c8da868cda6a5 /lib/sqlalchemy | |
| parent | d8ac1e9e6bfc931d2f14f9846d6924106f56b7e6 (diff) | |
| download | sqlalchemy-20e14633fb15018ccf1f5d127fd67609bfe2b3e5.tar.gz | |
Adjust natural path to relationship's base mapper for aliased class also
Fixed regression in loader options introduced in 1.3.0b3 via :ticket:`4468`
where the ability to create a loader option using
:meth:`.PropComparator.of_type` targeting an aliased entity that is an
inheriting subclass of the entity which the preceding relationship refers
to would fail to produce a matching path. See also :ticket:`5082` fixed
in this same release which involves a similar kind of issue.
Fixes: #5107
Change-Id: I5c6717b925060c3f8da42190d1f00d05248befd8
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/path_registry.py | 96 |
1 files changed, 53 insertions, 43 deletions
diff --git a/lib/sqlalchemy/orm/path_registry.py b/lib/sqlalchemy/orm/path_registry.py index 2df1b3b4c..2c0847426 100644 --- a/lib/sqlalchemy/orm/path_registry.py +++ b/lib/sqlalchemy/orm/path_registry.py @@ -250,51 +250,61 @@ class PropRegistry(PathRegistry): # given MapperProperty's parent. insp = inspection.inspect(parent[-1]) natural_parent = parent + if not insp.is_aliased_class or insp._use_mapper_path: parent = natural_parent = parent.parent[prop.parent] - elif insp.is_aliased_class and insp.with_polymorphic_mappers: - if ( - prop.parent is not insp.mapper - and prop.parent in insp.with_polymorphic_mappers - ): - subclass_entity = parent[-1]._entity_for_mapper(prop.parent) - parent = parent.parent[subclass_entity] - - # when building a path where with_polymorphic() is in use, - # special logic to determine the "natural path" when subclass - # entities are used. - # - # here we are trying to distinguish between a path that starts - # on a the with_polymorhpic entity vs. one that starts on a - # normal entity that introduces a with_polymorphic() in the - # middle using of_type(): - # - # # as in test_polymorphic_rel-> - # # test_subqueryload_on_subclass_uses_path_correctly - # wp = with_polymorphic(RegularEntity, "*") - # sess.query(wp).options(someload(wp.SomeSubEntity.foos)) - # - # vs - # - # # as in test_relationship->JoinedloadWPolyOfTypeContinued - # wp = with_polymorphic(SomeFoo, "*") - # sess.query(RegularEntity).options( - # someload(RegularEntity.foos.of_type(wp)) - # .someload(wp.SubFoo.bar) - # ) - # - # in the former case, the Query as it generates a path that we - # want to match will be in terms of the with_polymorphic at the - # beginning. in the latter case, Query will generate simple - # paths that don't know about this with_polymorphic, so we must - # use a separate natural path. - # - # - if parent.parent: - natural_parent = parent.parent[subclass_entity.mapper] - self.is_unnatural = True - else: - natural_parent = parent + elif ( + insp.is_aliased_class + and insp.with_polymorphic_mappers + and prop.parent is not insp.mapper + and prop.parent in insp.with_polymorphic_mappers + ): + subclass_entity = parent[-1]._entity_for_mapper(prop.parent) + parent = parent.parent[subclass_entity] + + # when building a path where with_polymorphic() is in use, + # special logic to determine the "natural path" when subclass + # entities are used. + # + # here we are trying to distinguish between a path that starts + # on a the with_polymorhpic entity vs. one that starts on a + # normal entity that introduces a with_polymorphic() in the + # middle using of_type(): + # + # # as in test_polymorphic_rel-> + # # test_subqueryload_on_subclass_uses_path_correctly + # wp = with_polymorphic(RegularEntity, "*") + # sess.query(wp).options(someload(wp.SomeSubEntity.foos)) + # + # vs + # + # # as in test_relationship->JoinedloadWPolyOfTypeContinued + # wp = with_polymorphic(SomeFoo, "*") + # sess.query(RegularEntity).options( + # someload(RegularEntity.foos.of_type(wp)) + # .someload(wp.SubFoo.bar) + # ) + # + # in the former case, the Query as it generates a path that we + # want to match will be in terms of the with_polymorphic at the + # beginning. in the latter case, Query will generate simple + # paths that don't know about this with_polymorphic, so we must + # use a separate natural path. + # + # + if parent.parent: + natural_parent = parent.parent[subclass_entity.mapper] + self.is_unnatural = True + else: + natural_parent = parent + elif ( + natural_parent.parent + and insp.is_aliased_class + and prop.parent # this should always be the case here + is not insp.mapper + and insp.mapper.isa(prop.parent) + ): + natural_parent = parent.parent[prop.parent] self.prop = prop self.parent = parent |
