From be768f8bd9aaa2cd291c1130a419c82ee2908275 Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Sun, 19 Jul 2026 19:25:49 +0200 Subject: [PATCH v10 04/21] Make sure Gather nodes don't have filters We don't allow passing filters between the leader and workers, so make sure to not create such Gather nodes. We still can have filters in paralell query, but they have to be created and consumed in the same process. For example, if a worker both builds and consumes the filter, it's fine. XXX Ultimately we'd want filters for parallel hash joins, and shared between the leader and workers, but for now we don't have that. --- src/backend/optimizer/path/allpaths.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 8cdfdf62318..e7e97ff8457 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -3750,6 +3750,13 @@ generate_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_rows) NULL, rowsp); add_path(rel, simple_gather_path); + /* + * The cheapest partial path must not have any pushed-down filters. Maybe + * in the future we'll be able to push those to parallel workers, but for + * now that's not possible/allowed. + */ + Assert(cheapest_partial_path->expected_filters == NULL); + /* * For each useful ordering, we can consider an order-preserving Gather * Merge. @@ -3762,6 +3769,10 @@ generate_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_rows) if (subpath->pathkeys == NIL) continue; + /* ignore paths with filters (not supported) */ + if (subpath->expected_filters != NULL) + continue; + rows = compute_gather_rows(subpath); path = create_gather_merge_path(root, rel, subpath, rel->reltarget, subpath->pathkeys, NULL, rowsp); @@ -3900,6 +3911,15 @@ generate_useful_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_r Path *subpath = (Path *) lfirst(lc2); GatherMergePath *path; + /* + * Skip paths with pushed-down filters (not supported across a + * Gather). generate_gather_paths() applies the same guard; do it + * here too, otherwise a filter-bearing partial path could still be + * placed under a Gather Merge via the sort paths built below. + */ + if (subpath->expected_filters != NIL) + continue; + is_sorted = pathkeys_count_contained_in(useful_pathkeys, subpath->pathkeys, &presorted_keys); -- 2.50.1 (Apple Git-155)