@@ -11,7 +11,7 @@ index bbf220407b..8225105893 100644
1111 auth_delay\
1212 auto_explain\
1313diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
14- indexf86983c660..452633ab0e 100644
14+ indexa0311ce9dc..a4fa160d5a 100644
1515--- a/src/backend/commands/explain.c
1616+++ b/src/backend/commands/explain.c
1717@@ -24,6 +24,7 @@
@@ -35,7 +35,7 @@ index f86983c660..452633ab0e 100644
3535
3636 /* OR-able flags for ExplainXMLTag() */
3737 #define X_OPENING 0
38- @@ -676 ,6 +683 ,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
38+ @@ -660 ,6 +667 ,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
3939 ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
4040 es);
4141
@@ -57,7 +57,7 @@ index f86983c660..452633ab0e 100644
5757 if (es->format == EXPLAIN_FORMAT_TEXT)
5858 appendStringInfoChar(es->str, '\n');
5959diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
60- index89d3c4352c..611f320446 100644
60+ index29ae32d960..d009b161da 100644
6161--- a/src/backend/optimizer/path/costsize.c
6262+++ b/src/backend/optimizer/path/costsize.c
6363@@ -99,6 +99,11 @@
@@ -322,7 +322,7 @@ index 89d3c4352c..611f320446 100644
322322 {
323323 doubleparallel_divisor = path->parallel_workers;
324324diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
325- index66139928e8..ae8eaff77e 100644
325+ indexcd68942af0..ab782b47ab 100644
326326--- a/src/backend/optimizer/plan/createplan.c
327327+++ b/src/backend/optimizer/plan/createplan.c
328328@@ -70,6 +70,7 @@
@@ -353,7 +353,7 @@ index 66139928e8..ae8eaff77e 100644
353353
354354 /*
355355diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
356- indexe21e72eb87..3ed0c5c1d2 100644
356+ index05f44faf6e..082e47332d 100644
357357--- a/src/backend/optimizer/plan/planner.c
358358+++ b/src/backend/optimizer/plan/planner.c
359359@@ -145,7 +145,8 @@ static List *extract_rollup_sets(List *groupingSets);
@@ -366,7 +366,7 @@ index e21e72eb87..3ed0c5c1d2 100644
366366 grouping_sets_data *gd,
367367 List *target_list);
368368 static RelOptInfo *create_grouping_paths(PlannerInfo *root,
369- @@ -3443 ,7 +3444 ,8 @@ standard_qp_callback(PlannerInfo *root, void *extra)
369+ @@ -3544 ,7 +3545 ,8 @@ standard_qp_callback(PlannerInfo *root, void *extra)
370370 */
371371 static double
372372 get_number_of_groups(PlannerInfo *root,
@@ -376,7 +376,7 @@ index e21e72eb87..3ed0c5c1d2 100644
376376 grouping_sets_data *gd,
377377 List *target_list)
378378 {
379- @@ -3480 ,7 +3482 ,7 @@ get_number_of_groups(PlannerInfo *root,
379+ @@ -3581 ,7 +3583 ,7 @@ get_number_of_groups(PlannerInfo *root,
380380 GroupingSetData *gs = lfirst_node(GroupingSetData, lc3);
381381 doublenumGroups = estimate_num_groups(root,
382382 groupExprs,
@@ -385,7 +385,7 @@ index e21e72eb87..3ed0c5c1d2 100644
385385 &gset,
386386 NULL);
387387
388- @@ -3506 ,7 +3508 ,7 @@ get_number_of_groups(PlannerInfo *root,
388+ @@ -3607 ,7 +3609 ,7 @@ get_number_of_groups(PlannerInfo *root,
389389 GroupingSetData *gs = lfirst_node(GroupingSetData, lc2);
390390 doublenumGroups = estimate_num_groups(root,
391391 groupExprs,
@@ -394,8 +394,8 @@ index e21e72eb87..3ed0c5c1d2 100644
394394 &gset,
395395 NULL);
396396
397- @@ -3523 ,8 +3525 ,8 @@ get_number_of_groups(PlannerInfo *root,
398- groupExprs = get_sortgrouplist_exprs(parse->groupClause ,
397+ @@ -3624 ,8 +3626 ,8 @@ get_number_of_groups(PlannerInfo *root,
398+ groupExprs = get_sortgrouplist_exprs(root->processed_groupClause ,
399399 target_list);
400400
401401- dNumGroups = estimate_num_groups(root, groupExprs, path_rows,
@@ -405,7 +405,7 @@ index e21e72eb87..3ed0c5c1d2 100644
405405 }
406406 }
407407 else if (parse->groupingSets)
408- @@ -3911 ,7 +3913 ,8 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
408+ @@ -4015 ,7 +4017 ,8 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
409409 * Estimate number of groups.
410410 */
411411 dNumGroups = get_number_of_groups(root,
@@ -415,7 +415,7 @@ index e21e72eb87..3ed0c5c1d2 100644
415415 gd,
416416 extra->targetList);
417417
418- @@ -6823 ,13 +6826 ,15 @@ create_partial_grouping_paths(PlannerInfo *root,
418+ @@ -7115 ,13 +7118 ,15 @@ create_partial_grouping_paths(PlannerInfo *root,
419419 if (cheapest_total_path != NULL)
420420 dNumPartialGroups =
421421 get_number_of_groups(root,
@@ -434,7 +434,7 @@ index e21e72eb87..3ed0c5c1d2 100644
434434 extra->targetList);
435435
436436diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
437- index7085cf3c41..6fcbea2a8e 100644
437+ index18b92336be..d56fd933d8 100644
438438--- a/src/backend/optimizer/util/relnode.c
439439+++ b/src/backend/optimizer/util/relnode.c
440440@@ -265,6 +265,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
@@ -453,31 +453,31 @@ index 7085cf3c41..6fcbea2a8e 100644
453453 elog(ERROR, "no relation entry for relid %d", relid);
454454
455455 return NULL;/* keep compiler quiet */
456- @@ -680 ,6 +680 ,7 @@ build_join_rel(PlannerInfo *root,
456+ @@ -679 ,6 +679 ,7 @@ build_join_rel(PlannerInfo *root,
457457 joinrel->all_partrels = NULL;
458458 joinrel->partexprs = NULL;
459459 joinrel->nullable_partexprs = NULL;
460460+ joinrel->ext_nodes = NULL;
461461
462462 /* Compute information relevant to the foreign relations. */
463463 set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
464- @@ -862 ,6 +863 ,7 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
464+ @@ -858 ,6 +859 ,7 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
465465 joinrel->all_partrels = NULL;
466466 joinrel->partexprs = NULL;
467467 joinrel->nullable_partexprs = NULL;
468468+ joinrel->ext_nodes = NULL;
469469
470470 /* Compute information relevant to foreign relations. */
471471 set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
472- @@ -1302 ,6 +1304 ,7 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
472+ @@ -1298 ,6 +1300 ,7 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
473473 }
474474
475475
476476+ set_parampathinfo_postinit_hook_type parampathinfo_postinit_hook = NULL;
477477 /*
478478 * get_baserel_parampathinfo
479479 *Get the ParamPathInfo for a parameterized path for a base relation,
480- @@ -1370 ,6 +1373 ,10 @@ get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
480+ @@ -1366 ,6 +1369 ,10 @@ get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
481481 ppi->ppi_req_outer = required_outer;
482482 ppi->ppi_rows = rows;
483483 ppi->ppi_clauses = pclauses;
@@ -488,7 +488,7 @@ index 7085cf3c41..6fcbea2a8e 100644
488488 baserel->ppilist = lappend(baserel->ppilist, ppi);
489489
490490 return ppi;
491- @@ -1595 ,6 +1602 ,10 @@ get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel,
491+ @@ -1591 ,6 +1598 ,10 @@ get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel,
492492 ppi->ppi_req_outer = required_outer;
493493 ppi->ppi_rows = rows;
494494 ppi->ppi_clauses = NIL;
@@ -500,18 +500,18 @@ index 7085cf3c41..6fcbea2a8e 100644
500500
501501 return ppi;
502502diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
503- index48858a871a..a6615c5210 100644
503+ index4e4888dde4..5b22f65012 100644
504504--- a/src/backend/utils/adt/selfuncs.c
505505+++ b/src/backend/utils/adt/selfuncs.c
506- @@ -144 ,6 +144 ,7 @@
506+ @@ -145 ,6 +145 ,7 @@
507507 /* Hooks for plugins to get control when we ask for stats */
508508 get_relation_stats_hook_type get_relation_stats_hook = NULL;
509509 get_index_stats_hook_type get_index_stats_hook = NULL;
510510+ estimate_num_groups_hook_type estimate_num_groups_hook = NULL;
511511
512512 static double eqsel_internal(PG_FUNCTION_ARGS, bool negate);
513513 static double eqjoinsel_inner(Oid opfuncoid, Oid collation,
514- @@ -3310 ,6 +3311 ,20 @@ add_unique_group_var(PlannerInfo *root, List *varinfos,
514+ @@ -3311 ,6 +3312 ,20 @@ add_unique_group_var(PlannerInfo *root, List *varinfos,
515515 return varinfos;
516516 }
517517
@@ -533,7 +533,7 @@ index 48858a871a..a6615c5210 100644
533533 * estimate_num_groups- Estimate number of groups in a grouped query
534534 *
535535diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
536- index9ebde089ae..1519e3e6b7 100644
536+ index7c1071ddd1..72e954dd3e 100644
537537--- a/src/include/commands/explain.h
538538+++ b/src/include/commands/explain.h
539539@@ -75,6 +75,18 @@ extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook;
@@ -556,10 +556,10 @@ index 9ebde089ae..1519e3e6b7 100644
556556 extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt,
557557 ParamListInfo params, DestReceiver *dest);
558558diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
559- index654dba61aa..c0ac86b1bc 100644
559+ index2d1d8f4bcd..48d60559f5 100644
560560--- a/src/include/nodes/pathnodes.h
561561+++ b/src/include/nodes/pathnodes.h
562- @@ -997 ,6 +997 ,16 @@ typedef struct RelOptInfo
562+ @@ -1025 ,6 +1025 ,16 @@ typedef struct RelOptInfo
563563 List **partexprs pg_node_attr(read_write_ignore);
564564 /* Nullable partition key expressions */
565565 List **nullable_partexprs pg_node_attr(read_write_ignore);
@@ -576,7 +576,7 @@ index 654dba61aa..c0ac86b1bc 100644
576576 } RelOptInfo;
577577
578578 /*
579- @@ -1467 ,6 +1477 ,10 @@ typedef struct ParamPathInfo
579+ @@ -1495 ,6 +1505 ,10 @@ typedef struct ParamPathInfo
580580 Relidsppi_req_outer;/* rels supplying parameters used by path */
581581 Cardinality ppi_rows;/* estimated number of result tuples */
582582 List *ppi_clauses;/* join clauses available from outer rels */
@@ -588,7 +588,7 @@ index 654dba61aa..c0ac86b1bc 100644
588588
589589
590590diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
591- indexbddfe86191..bedda73792 100644
591+ indexc1234fcf36..8c77da84aa 100644
592592--- a/src/include/nodes/plannodes.h
593593+++ b/src/include/nodes/plannodes.h
594594@@ -173,6 +173,9 @@ typedef struct Plan
@@ -602,7 +602,7 @@ index bddfe86191..bedda73792 100644
602602
603603 /* ----------------
604604diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
605- indexb6cc2c9cd6..ce8de270e8 100644
605+ index6cf49705d3..6a96baf130 100644
606606--- a/src/include/optimizer/cost.h
607607+++ b/src/include/optimizer/cost.h
608608@@ -41,6 +41,37 @@ typedef enum
@@ -686,7 +686,7 @@ index b6cc2c9cd6..ce8de270e8 100644
686686
687687 #endif/* COST_H */
688688diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
689- index050f00e79a..15a1970744 100644
689+ index02305ef902..5226ddc8e8 100644
690690--- a/src/include/optimizer/pathnode.h
691691+++ b/src/include/optimizer/pathnode.h
692692@@ -18,6 +18,10 @@
@@ -701,7 +701,7 @@ index 050f00e79a..15a1970744 100644
701701 * prototypes for pathnode.c
702702 */
703703diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
704- index9dffdcfd1e..78d58b7d45 100644
704+ index95ecefdade..a732d24fb6 100644
705705--- a/src/include/optimizer/planmain.h
706706+++ b/src/include/optimizer/planmain.h
707707@@ -24,6 +24,12 @@ extern PGDLLIMPORT double cursor_tuple_fraction;
@@ -718,7 +718,7 @@ index 9dffdcfd1e..78d58b7d45 100644
718718 * prototypes for plan/planmain.c
719719 */
720720diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
721- index8f3d73edfb..91537e2325 100644
721+ index2f76c473db..98b9a95d0f 100644
722722--- a/src/include/utils/selfuncs.h
723723+++ b/src/include/utils/selfuncs.h
724724@@ -144,6 +144,13 @@ typedef bool (*get_index_stats_hook_type) (PlannerInfo *root,