From 7b19b80a7f231e46184e378d76b3157f0e856b4d Mon Sep 17 00:00:00 2001
From: Alexander Pyhalov <a.pyhalov@postgrespro.ru>
Date: Tue, 3 Nov 2026 16:31:37 +0300
Subject: [PATCH] Make Append subplans async capable in more cases

---
 .../postgres_fdw/expected/postgres_fdw.out    | 38 +++++++++++++++++++
 contrib/postgres_fdw/sql/postgres_fdw.sql     |  4 ++
 src/backend/optimizer/plan/createplan.c       |  6 ++-
 3 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index cb0c525bd2d..a23ddf3f3d8 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -12365,6 +12365,44 @@ SELECT * FROM result_tbl ORDER BY a;
 (2 rows)
 
 DELETE FROM result_tbl;
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM async_pt WHERE b % 100 = 0 ORDER BY a;
+                                                 QUERY PLAN                                                 
+------------------------------------------------------------------------------------------------------------
+ Append
+   ->  Async 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 WHERE (((b % 100) = 0)) ORDER BY a ASC NULLS LAST
+   ->  Async 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 WHERE (((b % 100) = 0)) ORDER BY a ASC NULLS LAST
+(7 rows)
+
+SELECT * FROM async_pt WHERE b % 100 = 0 ORDER BY a;
+  a   |  b  |  c   
+------+-----+------
+ 1000 |   0 | 0000
+ 1100 | 100 | 0100
+ 1200 | 200 | 0200
+ 1300 | 300 | 0300
+ 1400 | 400 | 0400
+ 1500 | 500 | 0500
+ 1600 | 600 | 0600
+ 1700 | 700 | 0700
+ 1800 | 800 | 0800
+ 1900 | 900 | 0900
+ 2000 |   0 | 0000
+ 2100 | 100 | 0100
+ 2200 | 200 | 0200
+ 2300 | 300 | 0300
+ 2400 | 400 | 0400
+ 2500 | 500 | 0500
+ 2600 | 600 | 0600
+ 2700 | 700 | 0700
+ 2800 | 800 | 0800
+ 2900 | 900 | 0900
+(20 rows)
+
 -- Merge Append cases
 EXPLAIN (VERBOSE, COSTS OFF)
 SELECT * FROM async_pt WHERE b % 100 = 0 ORDER BY b, a;
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 5d6caf0e41e..2c70dec2213 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -4291,6 +4291,10 @@ INSERT INTO result_tbl SELECT a, b, 'AAA' || c FROM async_pt WHERE b === 505;
 SELECT * FROM result_tbl ORDER BY a;
 DELETE FROM result_tbl;
 
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT * FROM async_pt WHERE b % 100 = 0 ORDER BY a;
+SELECT * FROM async_pt WHERE b % 100 = 0 ORDER BY a;
+
 -- Merge Append cases
 EXPLAIN (VERBOSE, COSTS OFF)
 SELECT * FROM async_pt WHERE b % 100 = 0 ORDER BY b, a;
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 73438e76945..2b9d00e1b9c 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1298,7 +1298,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
 	}
 
 	/* If appropriate, consider async append */
-	consider_async = (enable_async_append && pathkeys == NIL &&
+	consider_async = (enable_async_append &&
 					  !best_path->path.parallel_safe &&
 					  list_length(best_path->subpaths) > 1);
 
@@ -1307,6 +1307,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
 	{
 		Path	   *subpath = (Path *) lfirst(subpaths);
 		Plan	   *subplan;
+		bool	created_sort_plan = false;
 
 		/* Must insist that all children return the same tlist */
 		subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST);
@@ -1390,11 +1391,12 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
 				}
 
 				subplan = sort_plan;
+				created_sort_plan = true;
 			}
 		}
 
 		/* If needed, check to see if subplan can be executed asynchronously */
-		if (consider_async && mark_async_capable_plan(subplan, subpath))
+		if (consider_async && !created_sort_plan && mark_async_capable_plan(subplan, subpath))
 		{
 			Assert(subplan->async_capable);
 			++nasyncplans;
-- 
2.43.0

