]> granicus.if.org Git - postgresql/commitdiff
postgres_fdw: Push down partition-wise aggregation.
authorRobert Haas <rhaas@postgresql.org>
Mon, 2 Apr 2018 14:51:50 +0000 (10:51 -0400)
committerRobert Haas <rhaas@postgresql.org>
Mon, 2 Apr 2018 14:51:50 +0000 (10:51 -0400)
Since commit 7012b132d07c2b4ea15b0b3cb1ea9f3278801d98, postgres_fdw
has been able to push down the toplevel aggregation operation to the
remote server.  Commit e2f1eb0ee30d144628ab523432320f174a2c8966 made
it possible to break down the toplevel aggregation into one
aggregate per partition.  This commit lets postgres_fdw push down
aggregation in that case just as it does at the top level.

In order to make this work, this commit adds an additional argument
to the GetForeignUpperPaths FDW API.  A matching argument is added
to the signature for create_upper_paths_hook.  Third-party code using
either of these will need to be updated.

Also adjust create_foreignscan_plan() so that it picks up the correct
set of relids in this case.

Jeevan Chalke, reviewed by Ashutosh Bapat and by me and with some
adjustments by me.  The larger patch series of which this patch is a
part was also reviewed and tested by Antonin Houska, Rajkumar
Raghuwanshi, David Rowley, Dilip Kumar, Konstantin Knizhnik, Pascal
Legrand, and Rafia Sabih.

Discussion: http://postgr.es/m/CAM2+6=V64_xhstVHie0Rz=KPEQnLJMZt_e314P0jaT_oJ9MR8A@mail.gmail.com
Discussion: http://postgr.es/m/CAM2+6=XPWujjmj5zUaBTGDoB38CemwcPmjkRy0qOcsQj_V+2sQ@mail.gmail.com

contrib/postgres_fdw/expected/postgres_fdw.out
contrib/postgres_fdw/postgres_fdw.c
contrib/postgres_fdw/sql/postgres_fdw.sql
doc/src/sgml/fdwhandler.sgml
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/prep/prepunion.c
src/include/foreign/fdwapi.h
src/include/optimizer/planner.h

index 6dcbcc598d6aa5591a59903541eaa7f4cf7d11d2..fa0d1db5fbc73f106246eb0bbb658330fc402d18 100644 (file)
@@ -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;
index e8a0d5482a865038d728ba0db0d0e10cedff16a6..a15ce28a48b3b575b9a6166229f83502d12198b1 100644 (file)
@@ -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,
index 4d2e43c9f0594cd1e6adef8a3f68c22049e215d0..cf32be4bfe2cc48b00f5b94c8a19982a0ca34b5d 100644 (file)
@@ -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;
index 0ed3a47233d575dad1fdd87b337a80ec8f662fc2..9291b8f6d4be8364cb8e126544eafc3d31505da7 100644 (file)
@@ -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,11 @@ 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.  The <literal>extra</literal> parameter provides additional details,
+     currently, it is set only for <literal>UPPERREL_PARTIAL_GROUP_AGG</>
+     or <literal>UPPERREL_GROUP_AGG</literal>, in which case it points to a
+     <literal>GroupPathExtraData</> structure.
+     (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
index 477b11f11dc690fff490e17a921f77246f129c00..ccdd5cdaba2031b96c8e85b05e4e2456f1270307 100644 (file)
@@ -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;
index b387c6213b620c373ce038c6aee68188108dd626..53ed6f8a17fdbeee458b3569c9bcda0eb9dd2ed0 100644 (file)
@@ -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;
index 6e510f9d94af87eeed14689f42005d744768a0fb..5236ab378e14fd7f5aa528eca6c9cbdcdf5e2a84 100644 (file)
@@ -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);
index e88fee301f18ef3af9d8dbc091c78090562b809a..ea83c7b7a4341ed1a4732216fa4dc2ae52dc788f 100644 (file)
@@ -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,
index 0d8b88d78beb149a2845fc0adbb18e6f9e0efc0a..07a3bc0627cb8458d120b5eef06c4a7898cb0154 100644 (file)
@@ -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;