summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2021-04-09 16:03:43 +0000
committerGerrit Code Review <gerrit@ci3.zzzcomputing.com>2021-04-09 16:03:43 +0000
commit8872cfaa64655f875df30a6f26871c90cccff3ea (patch)
tree3159f3c6dcfc7187f57fb31ff89bc7084417a3fb /lib/sqlalchemy
parenta14303639e03fd295edf1f5fabf6d20b05b1870b (diff)
parenta4f30de1662c9bc2c79e66b80565aaf8ba18f8c4 (diff)
downloadsqlalchemy-8872cfaa64655f875df30a6f26871c90cccff3ea.tar.gz
Merge "Apply recursive check to immediateloader and generalize"
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/strategies.py45
1 files changed, 33 insertions, 12 deletions
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 824df040a..da8e0439f 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -1166,6 +1166,28 @@ class LoadLazyAttribute(object):
class PostLoader(AbstractRelationshipLoader):
"""A relationship loader that emits a second SELECT statement."""
+ def _check_recursive_postload(self, context, path, join_depth=None):
+ effective_path = (
+ context.compile_state.current_path or orm_util.PathRegistry.root
+ ) + path
+
+ if loading.PostLoad.path_exists(
+ context, effective_path, self.parent_property
+ ):
+ return True
+
+ path_w_prop = path[self.parent_property]
+ effective_path_w_prop = effective_path[self.parent_property]
+
+ if not path_w_prop.contains(context.attributes, "loader"):
+ if join_depth:
+ if effective_path_w_prop.length / 2 > join_depth:
+ return True
+ elif effective_path_w_prop.contains_mapper(self.mapper):
+ return True
+
+ return False
+
def _immediateload_create_row_processor(
self,
context,
@@ -1214,6 +1236,9 @@ class ImmediateLoader(PostLoader):
def load_immediate(state, dict_, row):
state.get_impl(self.key).get(state, dict_)
+ if self._check_recursive_postload(context, path):
+ return
+
populators["delayed"].append((self.key, load_immediate))
@@ -1727,6 +1752,7 @@ class SubqueryLoader(PostLoader):
adapter,
populators,
):
+
if context.refresh_state:
return self._immediateload_create_row_processor(
context,
@@ -1738,6 +1764,10 @@ class SubqueryLoader(PostLoader):
adapter,
populators,
)
+ # the subqueryloader does a similar check in setup_query() unlike
+ # the other post loaders, however we have this here for consistency
+ elif self._check_recursive_postload(context, path, self.join_depth):
+ return
if not self.parent.class_manager[self.key].impl.supports_population:
raise sa_exc.InvalidRequestError(
@@ -2689,6 +2719,7 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
adapter,
populators,
):
+
if context.refresh_state:
return self._immediateload_create_row_processor(
context,
@@ -2700,6 +2731,8 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
adapter,
populators,
)
+ elif self._check_recursive_postload(context, path, self.join_depth):
+ return
if not self.parent.class_manager[self.key].impl.supports_population:
raise sa_exc.InvalidRequestError(
@@ -2721,13 +2754,7 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
context.compile_state.current_path or orm_util.PathRegistry.root
) + path
- if loading.PostLoad.path_exists(
- context, selectin_path, self.parent_property
- ):
- return
-
path_w_prop = path[self.parent_property]
- selectin_path_w_prop = selectin_path[self.parent_property]
# build up a path indicating the path from the leftmost
# entity to the thing we're subquery loading.
@@ -2739,12 +2766,6 @@ class SelectInLoader(PostLoader, util.MemoizedSlots):
else:
effective_entity = self.entity
- if not path_w_prop.contains(context.attributes, "loader"):
- if self.join_depth:
- if selectin_path_w_prop.length / 2 > self.join_depth:
- return
- elif selectin_path_w_prop.contains_mapper(self.mapper):
- return
loading.PostLoad.callable_for_path(
context,
selectin_path,