diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 8bcc18eca61..fa9674d1efa 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -10424,6 +10424,32 @@ DROP TABLE local_tbl; DROP INDEX base_tbl1_idx; DROP INDEX base_tbl2_idx; DROP INDEX async_p3_idx; +-- Disable async execution if we use gating Result nodes for pseudoconstant +-- quals +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM async_pt WHERE CURRENT_USER = SESSION_USER; + QUERY PLAN +---------------------------------------------------------------- + Append + -> Result + Output: async_pt_1.a, async_pt_1.b, async_pt_1.c + One-Time Filter: (CURRENT_USER = SESSION_USER) + -> Foreign Scan on public.async_p1 async_pt_1 + Output: async_pt_1.a, async_pt_1.b, async_pt_1.c + Remote SQL: SELECT a, b, c FROM public.base_tbl1 + -> Result + Output: async_pt_2.a, async_pt_2.b, async_pt_2.c + One-Time Filter: (CURRENT_USER = SESSION_USER) + -> Foreign Scan on public.async_p2 async_pt_2 + Output: async_pt_2.a, async_pt_2.b, async_pt_2.c + Remote SQL: SELECT a, b, c FROM public.base_tbl2 + -> Result + Output: async_pt_3.a, async_pt_3.b, async_pt_3.c + One-Time Filter: (CURRENT_USER = SESSION_USER) + -> Seq Scan on public.async_p3 async_pt_3 + Output: async_pt_3.a, async_pt_3.b, async_pt_3.c +(18 rows) + -- Test that pending requests are processed properly SET enable_mergejoin TO false; SET enable_hashjoin TO false; diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index 855c7ea70ed..89de85c03e3 100644 --- a/contrib/postgres_fdw/sql/postgres_fdw.sql +++ b/contrib/postgres_fdw/sql/postgres_fdw.sql @@ -3317,6 +3317,11 @@ DROP INDEX base_tbl1_idx; DROP INDEX base_tbl2_idx; DROP INDEX async_p3_idx; +-- Disable async execution if we use gating Result nodes for pseudoconstant +-- quals +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM async_pt WHERE CURRENT_USER = SESSION_USER; + -- Test that pending requests are processed properly SET enable_mergejoin TO false; SET enable_hashjoin TO false; diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index a2101fb3fcb..0ed858f305a 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 is_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, @@ -1109,11 +1109,11 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path) } /* - * is_async_capable_path - * Check whether a given Path node is async-capable. + * is_async_capable_plan + * Check whether the Plan node created from a Path node is async-capable. */ static bool -is_async_capable_path(Path *path) +is_async_capable_plan(Plan *plan, Path *path) { switch (nodeTag(path)) { @@ -1121,6 +1121,13 @@ is_async_capable_path(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)) @@ -1295,8 +1302,8 @@ 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 && is_async_capable_plan(subplan, subpath)) { subplan->async_capable = true; ++nasyncplans;