From 8778446121af20b4e3911d4f9d8bd0957ed1a2b5 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Sun, 5 Apr 2026 03:58:23 +0300 Subject: [PATCH v18 1/5] mark_async_capable(): subpath should match subplan mark_async_capable() believes that the path corresponds to the plan. This is not true when creating_[merge_]append_plan() inserts (Incremental)Sort node. In this case, mark_async_capable() can treat the Sort plan node as some other node and crash. Fix this by explicitly handling the (Incremental)Sort nodes as not async-capable. Also, move this check on top of the switch() as it repeats in all the cases. This is needed to make the MergeAppend node async-capable, which will be implemented in the subsequent commits. Discussion: https://postgr.es/m/59be194c5a409fb9fc9f2031581b8a44%40postgrespro.ru Author: Alexander Pyhalov Reviewed-by: Matheus Alcantara Reviewed-by: Alena Rybakina --- src/backend/optimizer/plan/createplan.c | 29 +++++++------------------ 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index c7bc41c30d7..150289613cd 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -1131,19 +1131,20 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path) static bool mark_async_capable_plan(Plan *plan, Path *path) { + /* + * If the generated plan node includes a gating Result node, a Sort node, + * or an IncrementalSort node, we can't execute it asynchronously. + */ + if (IsA(plan, Result) || IsA(plan, Sort) || + IsA(plan, IncrementalSort)) + return false; + switch (nodeTag(path)) { case T_SubqueryScanPath: { SubqueryScan *scan_plan = (SubqueryScan *) plan; - /* - * If the generated plan node includes a gating Result node, - * we can't execute it asynchronously. - */ - if (IsA(plan, Result)) - return false; - /* * If a SubqueryScan node atop of an async-capable plan node * is deletable, consider it as async-capable. @@ -1158,13 +1159,6 @@ mark_async_capable_plan(Plan *plan, Path *path) { FdwRoutine *fdwroutine = path->parent->fdwroutine; - /* - * If the generated plan node includes a gating Result node, - * we can't execute it asynchronously. - */ - if (IsA(plan, Result)) - return false; - Assert(fdwroutine != NULL); if (fdwroutine->IsForeignPathAsyncCapable != NULL && fdwroutine->IsForeignPathAsyncCapable((ForeignPath *) path)) @@ -1173,13 +1167,6 @@ mark_async_capable_plan(Plan *plan, Path *path) } case T_ProjectionPath: - /* - * If the generated plan node includes a Result node for the - * projection, we can't execute it asynchronously. - */ - if (IsA(plan, Result)) - return false; - /* * create_projection_plan() would have pulled up the subplan, so * check the capability using the subpath. -- 2.39.5 (Apple Git-154)