From 51f4739a003b487699886a6fb22a26d7a90a7d95 Mon Sep 17 00:00:00 2001 From: Tender Wang Date: Mon, 17 Aug 2026 14:47:25 +0800 Subject: [PATCH] Fix disabled_nodes propagation for single-child Append paths create_append_path() avoids calling cost_append() when an Append has a single child with the same parallel-awareness, since such an Append is effectively a no-op. In that case, it copies the child's row estimate and costs directly, but failed to copy disabled_nodes. This could cause a path containing a disabled plan node to be treated as having no disabled nodes. For example, an ordered Append over a disabled IndexScan could then be preferred over an unordered, non-disabled path that would otherwise be sorted. Propagate disabled_nodes from the child along with the other cost information in the single-child case. --- src/backend/optimizer/util/pathnode.c | 1 + src/test/regress/expected/partition_prune.out | 20 +++++++++++++++++++ src/test/regress/sql/partition_prune.sql | 19 ++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index a8dcad72958..298761491fa 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -1453,6 +1453,7 @@ create_append_path(PlannerInfo *root, if (child->parallel_aware == parallel_aware) { pathnode->path.rows = child->rows; + pathnode->path.disabled_nodes = child->disabled_nodes; pathnode->path.startup_cost = child->startup_cost; pathnode->path.total_cost = child->total_cost; } diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out index aa821646011..23d0964401a 100644 --- a/src/test/regress/expected/partition_prune.out +++ b/src/test/regress/expected/partition_prune.out @@ -5002,3 +5002,23 @@ select * from (select a, b from phv_boolpart) t (2 rows) drop table phv_boolpart; +-- Prefer a non-disabled path even when a disabled path provides ordering. +CREATE TABLE append_disabled_test (a int, b int) PARTITION BY LIST (a); +CREATE TABLE append_disabled_test_1 + PARTITION OF append_disabled_test FOR VALUES IN (1); +CREATE INDEX append_disabled_test_1_a_idx + ON append_disabled_test_1 (a); +INSERT INTO append_disabled_test VALUES (1, 1), (1, 2), (1, 3); +ANALYZE append_disabled_test; +SET enable_indexscan = off; +EXPLAIN (COSTS OFF) +SELECT * FROM append_disabled_test ORDER BY a; + QUERY PLAN +--------------------------------------------------------------- + Sort + Sort Key: append_disabled_test.a + -> Seq Scan on append_disabled_test_1 append_disabled_test +(3 rows) + +RESET enable_indexscan; +DROP TABLE append_disabled_test; diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql index dac673ef80a..455972b837c 100644 --- a/src/test/regress/sql/partition_prune.sql +++ b/src/test/regress/sql/partition_prune.sql @@ -1538,3 +1538,22 @@ select * from (select a, b from phv_boolpart) t group by grouping sets (a, b); drop table phv_boolpart; + +-- Prefer a non-disabled path even when a disabled path provides ordering. +CREATE TABLE append_disabled_test (a int, b int) PARTITION BY LIST (a); +CREATE TABLE append_disabled_test_1 + PARTITION OF append_disabled_test FOR VALUES IN (1); +CREATE INDEX append_disabled_test_1_a_idx + ON append_disabled_test_1 (a); + +INSERT INTO append_disabled_test VALUES (1, 1), (1, 2), (1, 3); +ANALYZE append_disabled_test; + +SET enable_indexscan = off; + +EXPLAIN (COSTS OFF) +SELECT * FROM append_disabled_test ORDER BY a; + +RESET enable_indexscan; + +DROP TABLE append_disabled_test; -- 2.43.0