On Thu, Mar 22, 2018 at 10:28 PM, Robert Haas <robertmh...@gmail.com> wrote:
> On Thu, Mar 22, 2018 at 6:15 AM, Jeevan Chalke > <jeevan.cha...@enterprisedb.com> wrote: > > Leeks cleaner now. Thanks for refactoring it. > > > > I have merged these changes and flatten all previuos changes into the > main > > patch. > > Committed 0001-0005. Thanks Robert. > I made a few further modifications. These were > mostly cosmetic, but with two exceptions: > > 1. I moved one set_cheapest() call to avoid doing that twice for the > top-level grouped_rel. > > 2. I removed the logic to set partition properties for grouped_rels. > As far as I can see, there's nothing that needs this. It would be > important if we wanted subsequent planning stages to be able to do > partition-wise stuff, e.g. when doing window functions or setops, or > at higher query levels. Maybe we'll have that someday; until then, I > think this is just a waste of cycles. > OK. Changes related to postgres_fdw which allows pushing aggregate on the foreign server is not yet committed. Due to this, we will end up getting an error when we have foreign partitions + aggregation. Attached 0001 patch here (0006 from my earlier patch-set) which adds support for this and thus will not have any error. Thanks > -- > Robert Haas > EnterpriseDB: http://www.enterprisedb.com > The Enterprise PostgreSQL Company > -- Jeevan Chalke Technical Architect, Product Development EnterpriseDB Corporation The Enterprise PostgreSQL Company
From 1173c609f6c6b2b45c0d1ce05533b840f7885717 Mon Sep 17 00:00:00 2001 From: Jeevan Chalke <jeevan.cha...@enterprisedb.com> Date: Fri, 23 Mar 2018 14:23:53 +0530 Subject: [PATCH] Teach postgres_fdw to push aggregates for child relations too. GetForeignUpperPaths() now takes an extra void parameter which will be used to pass any additional details required to create an upper path at the remote server. However, we support only grouping over remote server today and thus it passes grouping specific details i.e. GroupPathExtradata, NULL otherwise. Since we don't know how to get a partially aggregated result from a remote server, only full aggregation is pushed on the remote server. --- contrib/postgres_fdw/expected/postgres_fdw.out | 132 +++++++++++++++++++++++++ contrib/postgres_fdw/postgres_fdw.c | 48 ++++++--- contrib/postgres_fdw/postgres_fdw.h | 2 + contrib/postgres_fdw/sql/postgres_fdw.sql | 51 ++++++++++ doc/src/sgml/fdwhandler.sgml | 8 +- src/backend/optimizer/plan/createplan.c | 7 +- src/backend/optimizer/plan/planner.c | 29 +++--- src/backend/optimizer/prep/prepunion.c | 2 +- src/include/foreign/fdwapi.h | 3 +- src/include/optimizer/planner.h | 3 +- 10 files changed, 253 insertions(+), 32 deletions(-) diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 2d6e387..a211aa9 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -7852,3 +7852,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 e8a0d54..42756aa 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 @@ -427,7 +428,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,7 +2777,7 @@ estimate_path_cost_size(PlannerInfo *root, else if (IS_UPPER_REL(foreignrel)) { PgFdwRelationInfo *ofpinfo; - PathTarget *ptarget = root->upper_targets[UPPERREL_GROUP_AGG]; + PathTarget *ptarget = fpinfo->grouped_target; AggClauseCosts aggcosts; double input_rows; int numGroupCols; @@ -2805,7 +2807,7 @@ estimate_path_cost_size(PlannerInfo *root, { get_agg_clause_costs(root, (Node *) fpinfo->grouped_tlist, AGGSPLIT_SIMPLE, &aggcosts); - get_agg_clause_costs(root, (Node *) root->parse->havingQual, + get_agg_clause_costs(root, fpinfo->havingQual, AGGSPLIT_SIMPLE, &aggcosts); } @@ -5020,8 +5022,8 @@ static bool foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel) { Query *query = root->parse; - PathTarget *grouping_target = root->upper_targets[UPPERREL_GROUP_AGG]; PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) grouped_rel->fdw_private; + PathTarget *grouping_target = fpinfo->grouped_target; PgFdwRelationInfo *ofpinfo; List *aggvars; ListCell *lc; @@ -5131,11 +5133,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 (root->hasHavingQual && fpinfo->havingQual) { ListCell *lc; - foreach(lc, (List *) query->havingQual) + foreach(lc, (List *) fpinfo->havingQual) { Expr *expr = (Expr *) lfirst(lc); RestrictInfo *rinfo; @@ -5232,7 +5234,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 +5255,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 +5268,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 +5285,25 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, !root->hasHavingQual) return; - grouping_target = root->upper_targets[UPPERREL_GROUP_AGG]; + /* + * Store passed-in target and havingQual in fpinfo. If its a foreign + * partition, then path target and HAVING quals fetched from the root are + * not correct as Vars within it won't match with this child relation. + * However, server passed them through extra and thus fetch from it. + */ + if (extra) + { + /* Partial aggregates are not supported. */ + Assert(extra->patype != PARTITIONWISE_AGGREGATE_PARTIAL); + + fpinfo->grouped_target = extra->target; + fpinfo->havingQual = extra->havingQual; + } + else + { + fpinfo->grouped_target = root->upper_targets[UPPERREL_GROUP_AGG]; + fpinfo->havingQual = parse->havingQual; + } /* save the input_rel as outerrel in fpinfo */ fpinfo->outerrel = input_rel; @@ -5312,7 +5334,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, + fpinfo->grouped_target, rows, startup_cost, total_cost, diff --git a/contrib/postgres_fdw/postgres_fdw.h b/contrib/postgres_fdw/postgres_fdw.h index d37cc88..0d3c675 100644 --- a/contrib/postgres_fdw/postgres_fdw.h +++ b/contrib/postgres_fdw/postgres_fdw.h @@ -94,6 +94,8 @@ typedef struct PgFdwRelationInfo /* Grouping information */ List *grouped_tlist; + PathTarget *grouped_target; + Node *havingQual; /* Subquery information */ bool make_outerrel_subquery; /* do we deparse outerrel as a diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index 4d2e43c..cf32be4 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 0ed3a47..25915a2 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); </programlisting> Create possible access paths for <firstterm>upper relation</firstterm> processing, which is the planner's term for all post-scan/join query processing, such @@ -379,7 +380,10 @@ GetForeignUpperPaths(PlannerInfo *root, currently being considered. <literal>output_rel</literal> is the upper relation that should receive paths representing computation of this step, and <literal>input_rel</literal> is the relation representing the input to this - step. (Note that <structname>ForeignPath</structname> paths added + step. <literal>extra</literal> parameter provides additional details which may + be needed for the paths creation, like child details in case of partitioning. + The details passed through this parameter is depends on the <literal>stage</literal> + parameter. (Note that <structname>ForeignPath</structname> paths added to <literal>output_rel</literal> would typically not have any direct dependency on paths of the <literal>input_rel</literal>, 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 8b4f031..a54cc96 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -3517,10 +3517,11 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, /* * Likewise, copy the relids that are represented by this foreign scan. An - * 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. + * upper rel (but not the other 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 (IS_UPPER_REL(rel) && !IS_OTHER_REL(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 50f858e..9642489 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -2203,12 +2203,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() */ } @@ -4022,12 +4023,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); } /* @@ -4459,12 +4462,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); @@ -4763,12 +4767,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); @@ -4906,12 +4911,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 @@ -6692,7 +6698,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 6e510f9..5236ab3 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 e88fee3..ea83c7b 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 0d8b88d..07a3bc0 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; -- 1.8.3.1