aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/createplan.c
diff options
context:
space:
mode:
authorEtsuro Fujita <efujita@postgresql.org>2022-04-06 15:45:00 +0900
committerEtsuro Fujita <efujita@postgresql.org>2022-04-06 15:45:00 +0900
commitc2bb02bc2e858ba345b8b33f1f3a54628f719d93 (patch)
treefe742ab96982b0a74ed615d0c1e4c0982715a6e6 /src/backend/optimizer/plan/createplan.c
parent376dc437de40bd17e99a37f72f88627a16d7f200 (diff)
downloadpostgresql-c2bb02bc2e858ba345b8b33f1f3a54628f719d93.tar.gz
postgresql-c2bb02bc2e858ba345b8b33f1f3a54628f719d93.zip
Allow asynchronous execution in more cases.
In commit 27e1f1456, create_append_plan() only allowed the subplan created from a given subpath to be executed asynchronously when it was an async-capable ForeignPath. To extend coverage, this patch handles cases when the given subpath includes some other Path types as well that can be omitted in the plan processing, such as a ProjectionPath directly atop an async-capable ForeignPath, allowing asynchronous execution in partitioned-scan/partitioned-join queries with non-Var tlist expressions and more UNION queries. Andrey Lepikhov and Etsuro Fujita, reviewed by Alexander Pyhalov and Zhihong Yu. Discussion: https://postgr.es/m/659c37a8-3e71-0ff2-394c-f04428c76f08%40postgrespro.ru
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r--src/backend/optimizer/plan/createplan.c57
1 files changed, 44 insertions, 13 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 179c87c6714..51591bb8128 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -82,7 +82,7 @@ static List *get_gating_quals(PlannerInfo *root, List *quals);
static Plan *create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
List *gating_quals);
static Plan *create_join_plan(PlannerInfo *root, JoinPath *best_path);
-static bool is_async_capable_path(Path *path);
+static bool mark_async_capable_plan(Plan *plan, Path *path);
static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path,
int flags);
static Plan *create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
@@ -1110,14 +1110,30 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path)
}
/*
- * is_async_capable_path
- * Check whether a given Path node is async-capable.
+ * mark_async_capable_plan
+ * Check whether a given Path node is async-capable, and if so, mark the
+ * Plan node created from it as such and return true, otherwise return
+ * false.
*/
static bool
-is_async_capable_path(Path *path)
+mark_async_capable_plan(Plan *plan, Path *path)
{
switch (nodeTag(path))
{
+ case T_SubqueryScanPath:
+ {
+ SubqueryScan *scan_plan = (SubqueryScan *) plan;
+
+ /*
+ * If a SubqueryScan node atop of an async-capable plan node
+ * is deletable, consider it as async-capable.
+ */
+ if (trivial_subqueryscan(scan_plan) &&
+ mark_async_capable_plan(scan_plan->subplan,
+ ((SubqueryScanPath *) path)->subpath))
+ break;
+ return false;
+ }
case T_ForeignPath:
{
FdwRoutine *fdwroutine = path->parent->fdwroutine;
@@ -1125,13 +1141,27 @@ is_async_capable_path(Path *path)
Assert(fdwroutine != NULL);
if (fdwroutine->IsForeignPathAsyncCapable != NULL &&
fdwroutine->IsForeignPathAsyncCapable((ForeignPath *) path))
- return true;
+ break;
+ return false;
}
- break;
+ case T_ProjectionPath:
+
+ /*
+ * If the generated plan node doesn't include a Result node,
+ * consider it as async-capable if the subpath is async-capable.
+ */
+ if (!IsA(plan, Result) &&
+ mark_async_capable_plan(plan,
+ ((ProjectionPath *) path)->subpath))
+ return true;
+ return false;
default:
- break;
+ return false;
}
- return false;
+
+ plan->async_capable = true;
+
+ return true;
}
/*
@@ -1294,14 +1324,14 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
}
}
- subplans = lappend(subplans, subplan);
-
- /* Check to see if subplan can be executed asynchronously */
- if (consider_async && is_async_capable_path(subpath))
+ /* If needed, check to see if subplan can be executed asynchronously */
+ if (consider_async && mark_async_capable_plan(subplan, subpath))
{
- subplan->async_capable = true;
+ Assert(subplan->async_capable);
++nasyncplans;
}
+
+ subplans = lappend(subplans, subplan);
}
/*
@@ -5598,6 +5628,7 @@ make_subqueryscan(List *qptlist,
plan->righttree = NULL;
node->scan.scanrelid = scanrelid;
node->subplan = subplan;
+ node->scanstatus = SUBQUERY_SCAN_UNKNOWN;
return node;
}