diff options
Diffstat (limited to 'src/backend/optimizer/plan')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 83 | ||||
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 145 |
2 files changed, 191 insertions, 37 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index cb69c03df00..eeb2a417643 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -44,7 +44,6 @@ #include "utils/lsyscache.h" -static Plan *create_plan_recurse(PlannerInfo *root, Path *best_path); static Plan *create_scan_plan(PlannerInfo *root, Path *best_path); static List *build_path_tlist(PlannerInfo *root, Path *path); static bool use_physical_tlist(PlannerInfo *root, RelOptInfo *rel); @@ -220,7 +219,7 @@ create_plan(PlannerInfo *root, Path *best_path) * create_plan_recurse * Recursive guts of create_plan(). */ -static Plan * +Plan * create_plan_recurse(PlannerInfo *root, Path *best_path) { Plan *plan; @@ -1961,16 +1960,25 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, ForeignScan *scan_plan; RelOptInfo *rel = best_path->path.parent; Index scan_relid = rel->relid; - RangeTblEntry *rte; + Oid rel_oid = InvalidOid; Bitmapset *attrs_used = NULL; ListCell *lc; int i; - /* it should be a base rel... */ - Assert(scan_relid > 0); - Assert(rel->rtekind == RTE_RELATION); - rte = planner_rt_fetch(scan_relid, root); - Assert(rte->rtekind == RTE_RELATION); + /* + * If we're scanning a base relation, look up the OID. + * (We can skip this if scanning a join relation.) + */ + if (scan_relid > 0) + { + RangeTblEntry *rte; + + Assert(rel->rtekind == RTE_RELATION); + rte = planner_rt_fetch(scan_relid, root); + Assert(rte->rtekind == RTE_RELATION); + rel_oid = rte->relid; + } + Assert(rel->fdwroutine != NULL); /* * Sort clauses into best execution order. We do this first since the FDW @@ -1985,13 +1993,39 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, * has selected some join clauses for remote use but also wants them * rechecked locally). */ - scan_plan = rel->fdwroutine->GetForeignPlan(root, rel, rte->relid, + scan_plan = rel->fdwroutine->GetForeignPlan(root, rel, rel_oid, best_path, tlist, scan_clauses); + /* + * Sanity check. There may be resjunk entries in fdw_ps_tlist that + * are included only to help EXPLAIN deparse plans properly. We require + * that these are at the end, so that when the executor builds the scan + * descriptor based on the non-junk entries, it gets the attribute + * numbers correct. + */ + if (scan_plan->scan.scanrelid == 0) + { + bool found_resjunk = false; + + foreach (lc, scan_plan->fdw_ps_tlist) + { + TargetEntry *tle = lfirst(lc); + + if (tle->resjunk) + found_resjunk = true; + else if (found_resjunk) + elog(ERROR, "junk TLE should not apper prior to valid one"); + } + } + /* Set the relids that are represented by this foreign scan for Explain */ + scan_plan->fdw_relids = best_path->path.parent->relids; /* Copy cost data from Path to Plan; no need to make FDW do this */ copy_path_costsize(&scan_plan->scan.plan, &best_path->path); + /* Track FDW server-id; no need to make FDW do this */ + scan_plan->fdw_handler = rel->fdw_handler; + /* * Replace any outer-relation variables with nestloop params in the qual * and fdw_exprs expressions. We do this last so that the FDW doesn't @@ -2053,12 +2087,7 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path, { CustomScan *cplan; RelOptInfo *rel = best_path->path.parent; - - /* - * Right now, all we can support is CustomScan node which is associated - * with a particular base relation to be scanned. - */ - Assert(rel && rel->reloptkind == RELOPT_BASEREL); + ListCell *lc; /* * Sort clauses into the best execution order, although custom-scan @@ -2078,6 +2107,30 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path, Assert(IsA(cplan, CustomScan)); /* + * Sanity check. There may be resjunk entries in custom_ps_tlist that + * are included only to help EXPLAIN deparse plans properly. We require + * that these are at the end, so that when the executor builds the scan + * descriptor based on the non-junk entries, it gets the attribute + * numbers correct. + */ + if (cplan->scan.scanrelid == 0) + { + bool found_resjunk = false; + + foreach (lc, cplan->custom_ps_tlist) + { + TargetEntry *tle = lfirst(lc); + + if (tle->resjunk) + found_resjunk = true; + else if (found_resjunk) + elog(ERROR, "junk TLE should not apper prior to valid one"); + } + } + /* Set the relids that are represented by this custom scan for Explain */ + cplan->custom_relids = best_path->path.parent->relids; + + /* * Copy cost data from Path to Plan; no need to make custom-plan providers * do this */ diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 94b12ab8ca1..69ed2a574e5 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -86,6 +86,12 @@ static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte); static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob); static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte); static Plan *set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset); +static void set_foreignscan_references(PlannerInfo *root, + ForeignScan *fscan, + int rtoffset); +static void set_customscan_references(PlannerInfo *root, + CustomScan *cscan, + int rtoffset); static Plan *set_indexonlyscan_references(PlannerInfo *root, IndexOnlyScan *plan, int rtoffset); @@ -565,31 +571,11 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) } break; case T_ForeignScan: - { - ForeignScan *splan = (ForeignScan *) plan; - - splan->scan.scanrelid += rtoffset; - splan->scan.plan.targetlist = - fix_scan_list(root, splan->scan.plan.targetlist, rtoffset); - splan->scan.plan.qual = - fix_scan_list(root, splan->scan.plan.qual, rtoffset); - splan->fdw_exprs = - fix_scan_list(root, splan->fdw_exprs, rtoffset); - } + set_foreignscan_references(root, (ForeignScan *) plan, rtoffset); break; case T_CustomScan: - { - CustomScan *splan = (CustomScan *) plan; - - splan->scan.scanrelid += rtoffset; - splan->scan.plan.targetlist = - fix_scan_list(root, splan->scan.plan.targetlist, rtoffset); - splan->scan.plan.qual = - fix_scan_list(root, splan->scan.plan.qual, rtoffset); - splan->custom_exprs = - fix_scan_list(root, splan->custom_exprs, rtoffset); - } + set_customscan_references(root, (CustomScan *) plan, rtoffset); break; case T_NestLoop: @@ -877,6 +863,121 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) } /* + * set_foreignscan_references + * Do set_plan_references processing on an ForeignScan + */ +static void +set_foreignscan_references(PlannerInfo *root, + ForeignScan *fscan, + int rtoffset) +{ + if (rtoffset > 0) + { + Bitmapset *tempset = NULL; + int x = -1; + + while ((x = bms_next_member(fscan->fdw_relids, x)) >= 0) + tempset = bms_add_member(tempset, x + rtoffset); + fscan->fdw_relids = tempset; + } + + if (fscan->scan.scanrelid == 0) + { + indexed_tlist *pscan_itlist = build_tlist_index(fscan->fdw_ps_tlist); + + fscan->scan.plan.targetlist = (List *) + fix_upper_expr(root, + (Node *) fscan->scan.plan.targetlist, + pscan_itlist, + INDEX_VAR, + rtoffset); + fscan->scan.plan.qual = (List *) + fix_upper_expr(root, + (Node *) fscan->scan.plan.qual, + pscan_itlist, + INDEX_VAR, + rtoffset); + fscan->fdw_exprs = (List *) + fix_upper_expr(root, + (Node *) fscan->fdw_exprs, + pscan_itlist, + INDEX_VAR, + rtoffset); + fscan->fdw_ps_tlist = + fix_scan_list(root, fscan->fdw_ps_tlist, rtoffset); + pfree(pscan_itlist); + } + else + { + fscan->scan.scanrelid += rtoffset; + fscan->scan.plan.targetlist = + fix_scan_list(root, fscan->scan.plan.targetlist, rtoffset); + fscan->scan.plan.qual = + fix_scan_list(root, fscan->scan.plan.qual, rtoffset); + fscan->fdw_exprs = + fix_scan_list(root, fscan->fdw_exprs, rtoffset); + } +} + +/* + * set_customscan_references + * Do set_plan_references processing on an CustomScan + */ +static void +set_customscan_references(PlannerInfo *root, + CustomScan *cscan, + int rtoffset) +{ + if (rtoffset > 0) + { + Bitmapset *tempset = NULL; + int x = -1; + + while ((x = bms_next_member(cscan->custom_relids, x)) >= 0) + tempset = bms_add_member(tempset, x + rtoffset); + cscan->custom_relids = tempset; + } + + if (cscan->scan.scanrelid == 0) + { + indexed_tlist *pscan_itlist = + build_tlist_index(cscan->custom_ps_tlist); + + cscan->scan.plan.targetlist = (List *) + fix_upper_expr(root, + (Node *) cscan->scan.plan.targetlist, + pscan_itlist, + INDEX_VAR, + rtoffset); + cscan->scan.plan.qual = (List *) + fix_upper_expr(root, + (Node *) cscan->scan.plan.qual, + pscan_itlist, + INDEX_VAR, + rtoffset); + cscan->custom_exprs = (List *) + fix_upper_expr(root, + (Node *) cscan->custom_exprs, + pscan_itlist, + INDEX_VAR, + rtoffset); + cscan->custom_ps_tlist = + fix_scan_list(root, cscan->custom_ps_tlist, rtoffset); + pfree(pscan_itlist); + } + else + { + cscan->scan.scanrelid += rtoffset; + cscan->scan.plan.targetlist = + fix_scan_list(root, cscan->scan.plan.targetlist, rtoffset); + cscan->scan.plan.qual = + fix_scan_list(root, cscan->scan.plan.qual, rtoffset); + cscan->custom_exprs = + fix_scan_list(root, cscan->custom_exprs, rtoffset); + } +} + +/* * set_indexonlyscan_references * Do set_plan_references processing on an IndexOnlyScan * |