diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 6dcbcc598d..fa0d1db5fb 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -7851,3 +7851,135 @@ SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE (14 rows) RESET enable_partitionwise_join; +-- =================================================================== +-- test partitionwise aggregates +-- =================================================================== +CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a); +CREATE TABLE pagg_tab_p1 (LIKE pagg_tab); +CREATE TABLE pagg_tab_p2 (LIKE pagg_tab); +CREATE TABLE pagg_tab_p3 (LIKE pagg_tab); +INSERT INTO pagg_tab_p1 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 10; +INSERT INTO pagg_tab_p2 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 20 and (i % 30) >= 10; +INSERT INTO pagg_tab_p3 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 30 and (i % 30) >= 20; +-- Create foreign partitions +CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1'); +CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2');; +CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3');; +ANALYZE pagg_tab; +ANALYZE fpagg_tab_p1; +ANALYZE fpagg_tab_p2; +ANALYZE fpagg_tab_p3; +-- When GROUP BY clause matches with PARTITION KEY. +-- Plan with partitionwise aggregates is disabled +SET enable_partitionwise_aggregate TO false; +EXPLAIN (COSTS OFF) +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + QUERY PLAN +------------------------------------------------------- + Sort + Sort Key: fpagg_tab_p1.a + -> HashAggregate + Group Key: fpagg_tab_p1.a + Filter: (avg(fpagg_tab_p1.b) < '22'::numeric) + -> Append + -> Foreign Scan on fpagg_tab_p1 + -> Foreign Scan on fpagg_tab_p2 + -> Foreign Scan on fpagg_tab_p3 +(9 rows) + +-- Plan with partitionwise aggregates is enabled +SET enable_partitionwise_aggregate TO true; +EXPLAIN (COSTS OFF) +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + QUERY PLAN +---------------------------------------------------------------------- + Sort + Sort Key: fpagg_tab_p1.a + -> Append + -> Foreign Scan + Relations: Aggregate on (public.fpagg_tab_p1 pagg_tab) + -> Foreign Scan + Relations: Aggregate on (public.fpagg_tab_p2 pagg_tab) + -> Foreign Scan + Relations: Aggregate on (public.fpagg_tab_p3 pagg_tab) +(9 rows) + +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + a | sum | min | count +----+------+-----+------- + 0 | 2000 | 0 | 100 + 1 | 2100 | 1 | 100 + 10 | 2000 | 0 | 100 + 11 | 2100 | 1 | 100 + 20 | 2000 | 0 | 100 + 21 | 2100 | 1 | 100 +(6 rows) + +-- Check with whole-row reference +-- Should have all the columns in the target list for the given relation +EXPLAIN (VERBOSE, COSTS OFF) +SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + QUERY PLAN +------------------------------------------------------------------------ + Sort + Output: t1.a, (count(((t1.*)::pagg_tab))) + Sort Key: t1.a + -> Append + -> HashAggregate + Output: t1.a, count(((t1.*)::pagg_tab)) + Group Key: t1.a + Filter: (avg(t1.b) < '22'::numeric) + -> Foreign Scan on public.fpagg_tab_p1 t1 + Output: t1.a, t1.*, t1.b + Remote SQL: SELECT a, b, c FROM public.pagg_tab_p1 + -> HashAggregate + Output: t1_1.a, count(((t1_1.*)::pagg_tab)) + Group Key: t1_1.a + Filter: (avg(t1_1.b) < '22'::numeric) + -> Foreign Scan on public.fpagg_tab_p2 t1_1 + Output: t1_1.a, t1_1.*, t1_1.b + Remote SQL: SELECT a, b, c FROM public.pagg_tab_p2 + -> HashAggregate + Output: t1_2.a, count(((t1_2.*)::pagg_tab)) + Group Key: t1_2.a + Filter: (avg(t1_2.b) < '22'::numeric) + -> Foreign Scan on public.fpagg_tab_p3 t1_2 + Output: t1_2.a, t1_2.*, t1_2.b + Remote SQL: SELECT a, b, c FROM public.pagg_tab_p3 +(25 rows) + +SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + a | count +----+------- + 0 | 100 + 1 | 100 + 10 | 100 + 11 | 100 + 20 | 100 + 21 | 100 +(6 rows) + +-- When GROUP BY clause does not match with PARTITION KEY. +EXPLAIN (COSTS OFF) +SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1; + QUERY PLAN +------------------------------------------------------ + Sort + Sort Key: fpagg_tab_p1.b + -> Finalize HashAggregate + Group Key: fpagg_tab_p1.b + Filter: (sum(fpagg_tab_p1.a) < 700) + -> Append + -> Partial HashAggregate + Group Key: fpagg_tab_p1.b + -> Foreign Scan on fpagg_tab_p1 + -> Partial HashAggregate + Group Key: fpagg_tab_p2.b + -> Foreign Scan on fpagg_tab_p2 + -> Partial HashAggregate + Group Key: fpagg_tab_p3.b + -> Foreign Scan on fpagg_tab_p3 +(15 rows) + +-- Clean-up +RESET enable_partitionwise_aggregate; diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index e8a0d5482a..a15ce28a48 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -352,7 +352,8 @@ static bool postgresRecheckForeignScan(ForeignScanState *node, static void postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, - RelOptInfo *output_rel); + RelOptInfo *output_rel, + void *extra); /* * Helper functions @@ -419,7 +420,8 @@ static void conversion_error_callback(void *arg); static bool foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinPathExtraData *extra); -static bool foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel); +static bool foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel, + Node *havingQual); static List *get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel); static List *get_useful_ecs_for_relation(PlannerInfo *root, RelOptInfo *rel); @@ -427,7 +429,8 @@ static void add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, Path *epq_path); static void add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, - RelOptInfo *grouped_rel); + RelOptInfo *grouped_rel, + GroupPathExtraData *extra); static void apply_server_options(PgFdwRelationInfo *fpinfo); static void apply_table_options(PgFdwRelationInfo *fpinfo); static void merge_fdw_options(PgFdwRelationInfo *fpinfo, @@ -2775,12 +2778,15 @@ estimate_path_cost_size(PlannerInfo *root, else if (IS_UPPER_REL(foreignrel)) { PgFdwRelationInfo *ofpinfo; - PathTarget *ptarget = root->upper_targets[UPPERREL_GROUP_AGG]; + PathTarget *ptarget = foreignrel->reltarget; AggClauseCosts aggcosts; double input_rows; int numGroupCols; double numGroups = 1; + /* Make sure the core code set the pathtarget. */ + Assert(ptarget != NULL); + /* * This cost model is mixture of costing done for sorted and * hashed aggregates in cost_agg(). We are not sure which @@ -2805,6 +2811,12 @@ estimate_path_cost_size(PlannerInfo *root, { get_agg_clause_costs(root, (Node *) fpinfo->grouped_tlist, AGGSPLIT_SIMPLE, &aggcosts); + + /* + * The cost of aggregates in the HAVING qual will be the same + * for each child as it is for the parent, so there's no need + * to use a translated version of havingQual. + */ get_agg_clause_costs(root, (Node *) root->parse->havingQual, AGGSPLIT_SIMPLE, &aggcosts); } @@ -5017,11 +5029,12 @@ postgresGetForeignJoinPaths(PlannerInfo *root, * this function to PgFdwRelationInfo of the input relation. */ static bool -foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel) +foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel, + Node *havingQual) { Query *query = root->parse; - PathTarget *grouping_target = root->upper_targets[UPPERREL_GROUP_AGG]; PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) grouped_rel->fdw_private; + PathTarget *grouping_target = grouped_rel->reltarget; PgFdwRelationInfo *ofpinfo; List *aggvars; ListCell *lc; @@ -5131,11 +5144,11 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel) * Classify the pushable and non-pushable HAVING clauses and save them in * remote_conds and local_conds of the grouped rel's fpinfo. */ - if (root->hasHavingQual && query->havingQual) + if (havingQual) { ListCell *lc; - foreach(lc, (List *) query->havingQual) + foreach(lc, (List *) havingQual) { Expr *expr = (Expr *) lfirst(lc); RestrictInfo *rinfo; @@ -5232,7 +5245,8 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel) */ static void postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage, - RelOptInfo *input_rel, RelOptInfo *output_rel) + RelOptInfo *input_rel, RelOptInfo *output_rel, + void *extra) { PgFdwRelationInfo *fpinfo; @@ -5252,7 +5266,8 @@ postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage, fpinfo->pushdown_safe = false; output_rel->fdw_private = fpinfo; - add_foreign_grouping_paths(root, input_rel, output_rel); + add_foreign_grouping_paths(root, input_rel, output_rel, + (GroupPathExtraData *) extra); } /* @@ -5264,13 +5279,13 @@ postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage, */ static void add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, - RelOptInfo *grouped_rel) + RelOptInfo *grouped_rel, + GroupPathExtraData *extra) { Query *parse = root->parse; PgFdwRelationInfo *ifpinfo = input_rel->fdw_private; PgFdwRelationInfo *fpinfo = grouped_rel->fdw_private; ForeignPath *grouppath; - PathTarget *grouping_target; double rows; int width; Cost startup_cost; @@ -5281,7 +5296,8 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, !root->hasHavingQual) return; - grouping_target = root->upper_targets[UPPERREL_GROUP_AGG]; + Assert(extra->patype == PARTITIONWISE_AGGREGATE_NONE || + extra->patype == PARTITIONWISE_AGGREGATE_FULL); /* save the input_rel as outerrel in fpinfo */ fpinfo->outerrel = input_rel; @@ -5295,8 +5311,13 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, fpinfo->user = ifpinfo->user; merge_fdw_options(fpinfo, ifpinfo, NULL); - /* Assess if it is safe to push down aggregation and grouping. */ - if (!foreign_grouping_ok(root, grouped_rel)) + /* + * Assess if it is safe to push down aggregation and grouping. + * + * Use HAVING qual from extra. In case of child partition, it will have + * translated Vars. + */ + if (!foreign_grouping_ok(root, grouped_rel, extra->havingQual)) return; /* Estimate the cost of push down */ @@ -5312,7 +5333,7 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, /* Create and add foreign path to the grouping relation. */ grouppath = create_foreignscan_path(root, grouped_rel, - grouping_target, + grouped_rel->reltarget, rows, startup_cost, total_cost, diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index 4d2e43c9f0..cf32be4bfe 100644 --- a/contrib/postgres_fdw/sql/postgres_fdw.sql +++ b/contrib/postgres_fdw/sql/postgres_fdw.sql @@ -1932,3 +1932,54 @@ SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; RESET enable_partitionwise_join; + + +-- =================================================================== +-- test partitionwise aggregates +-- =================================================================== + +CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a); + +CREATE TABLE pagg_tab_p1 (LIKE pagg_tab); +CREATE TABLE pagg_tab_p2 (LIKE pagg_tab); +CREATE TABLE pagg_tab_p3 (LIKE pagg_tab); + +INSERT INTO pagg_tab_p1 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 10; +INSERT INTO pagg_tab_p2 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 20 and (i % 30) >= 10; +INSERT INTO pagg_tab_p3 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 30 and (i % 30) >= 20; + +-- Create foreign partitions +CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1'); +CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2');; +CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3');; + +ANALYZE pagg_tab; +ANALYZE fpagg_tab_p1; +ANALYZE fpagg_tab_p2; +ANALYZE fpagg_tab_p3; + +-- When GROUP BY clause matches with PARTITION KEY. +-- Plan with partitionwise aggregates is disabled +SET enable_partitionwise_aggregate TO false; +EXPLAIN (COSTS OFF) +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- Plan with partitionwise aggregates is enabled +SET enable_partitionwise_aggregate TO true; +EXPLAIN (COSTS OFF) +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; +SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- Check with whole-row reference +-- Should have all the columns in the target list for the given relation +EXPLAIN (VERBOSE, COSTS OFF) +SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; +SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; + +-- When GROUP BY clause does not match with PARTITION KEY. +EXPLAIN (COSTS OFF) +SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1; + + +-- Clean-up +RESET enable_partitionwise_aggregate; diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml index 0ed3a47233..9291b8f6d4 100644 --- a/doc/src/sgml/fdwhandler.sgml +++ b/doc/src/sgml/fdwhandler.sgml @@ -359,7 +359,8 @@ void GetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, - RelOptInfo *output_rel); + RelOptInfo *output_rel, + void *extra); Create possible access paths for upper relation processing, which is the planner's term for all post-scan/join query processing, such @@ -379,7 +380,11 @@ GetForeignUpperPaths(PlannerInfo *root, currently being considered. output_rel is the upper relation that should receive paths representing computation of this step, and input_rel is the relation representing the input to this - step. (Note that ForeignPath paths added + step. The extra parameter provides additional details, + currently, it is set only for UPPERREL_PARTIAL_GROUP_AGG + or UPPERREL_GROUP_AGG, in which case it points to a + GroupPathExtraData structure. + (Note that ForeignPath paths added to output_rel would typically not have any direct dependency on paths of the input_rel, since their processing is expected to be done externally. However, examining paths previously generated for diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 477b11f11d..ccdd5cdaba 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -3572,7 +3572,7 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, * upper rel doesn't have relids set, but it covers all the base relations * participating in the underlying scan, so use root's all_baserels. */ - if (IS_UPPER_REL(rel)) + if (rel->reloptkind == RELOPT_UPPER_REL) scan_plan->fs_relids = root->all_baserels; else scan_plan->fs_relids = best_path->path.parent->relids; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index b387c6213b..53ed6f8a17 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -2206,12 +2206,13 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, if (final_rel->fdwroutine && final_rel->fdwroutine->GetForeignUpperPaths) final_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_FINAL, - current_rel, final_rel); + current_rel, final_rel, + NULL); /* Let extensions possibly add some more paths */ if (create_upper_paths_hook) (*create_upper_paths_hook) (root, UPPERREL_FINAL, - current_rel, final_rel); + current_rel, final_rel, NULL); /* Note: currently, we leave it to callers to do set_cheapest() */ } @@ -4024,12 +4025,14 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, if (grouped_rel->fdwroutine && grouped_rel->fdwroutine->GetForeignUpperPaths) grouped_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_GROUP_AGG, - input_rel, grouped_rel); + input_rel, grouped_rel, + extra); /* Let extensions possibly add some more paths */ if (create_upper_paths_hook) (*create_upper_paths_hook) (root, UPPERREL_GROUP_AGG, - input_rel, grouped_rel); + input_rel, grouped_rel, + extra); } /* @@ -4461,12 +4464,13 @@ create_window_paths(PlannerInfo *root, if (window_rel->fdwroutine && window_rel->fdwroutine->GetForeignUpperPaths) window_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_WINDOW, - input_rel, window_rel); + input_rel, window_rel, + NULL); /* Let extensions possibly add some more paths */ if (create_upper_paths_hook) (*create_upper_paths_hook) (root, UPPERREL_WINDOW, - input_rel, window_rel); + input_rel, window_rel, NULL); /* Now choose the best path(s) */ set_cheapest(window_rel); @@ -4765,12 +4769,13 @@ create_distinct_paths(PlannerInfo *root, if (distinct_rel->fdwroutine && distinct_rel->fdwroutine->GetForeignUpperPaths) distinct_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_DISTINCT, - input_rel, distinct_rel); + input_rel, distinct_rel, + NULL); /* Let extensions possibly add some more paths */ if (create_upper_paths_hook) (*create_upper_paths_hook) (root, UPPERREL_DISTINCT, - input_rel, distinct_rel); + input_rel, distinct_rel, NULL); /* Now choose the best path(s) */ set_cheapest(distinct_rel); @@ -4908,12 +4913,13 @@ create_ordered_paths(PlannerInfo *root, if (ordered_rel->fdwroutine && ordered_rel->fdwroutine->GetForeignUpperPaths) ordered_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_ORDERED, - input_rel, ordered_rel); + input_rel, ordered_rel, + NULL); /* Let extensions possibly add some more paths */ if (create_upper_paths_hook) (*create_upper_paths_hook) (root, UPPERREL_ORDERED, - input_rel, ordered_rel); + input_rel, ordered_rel, NULL); /* * No need to bother with set_cheapest here; grouping_planner does not @@ -6694,7 +6700,8 @@ create_partial_grouping_paths(PlannerInfo *root, fdwroutine->GetForeignUpperPaths(root, UPPERREL_PARTIAL_GROUP_AGG, - input_rel, partially_grouped_rel); + input_rel, partially_grouped_rel, + extra); } return partially_grouped_rel; diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 6e510f9d94..5236ab378e 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -1032,7 +1032,7 @@ postprocess_setop_rel(PlannerInfo *root, RelOptInfo *rel) */ if (create_upper_paths_hook) (*create_upper_paths_hook) (root, UPPERREL_SETOP, - NULL, rel); + NULL, rel, NULL); /* Select cheapest path */ set_cheapest(rel); diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h index e88fee301f..ea83c7b7a4 100644 --- a/src/include/foreign/fdwapi.h +++ b/src/include/foreign/fdwapi.h @@ -62,7 +62,8 @@ typedef void (*GetForeignJoinPaths_function) (PlannerInfo *root, typedef void (*GetForeignUpperPaths_function) (PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, - RelOptInfo *output_rel); + RelOptInfo *output_rel, + void *extra); typedef void (*AddForeignUpdateTargets_function) (Query *parsetree, RangeTblEntry *target_rte, diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h index 0d8b88d78b..07a3bc0627 100644 --- a/src/include/optimizer/planner.h +++ b/src/include/optimizer/planner.h @@ -28,7 +28,8 @@ extern PGDLLIMPORT planner_hook_type planner_hook; typedef void (*create_upper_paths_hook_type) (PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, - RelOptInfo *output_rel); + RelOptInfo *output_rel, + void *extra); extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook;