diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/nodes/outfuncs.c | 46 | ||||
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 22 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 20 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 8 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planmain.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 44 | ||||
-rw-r--r-- | src/backend/optimizer/util/placeholder.c | 14 | ||||
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 23 | ||||
-rw-r--r-- | src/backend/optimizer/util/tlist.c | 6 | ||||
-rw-r--r-- | src/include/nodes/nodes.h | 1 | ||||
-rw-r--r-- | src/include/nodes/relation.h | 65 |
14 files changed, 133 insertions, 128 deletions
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index eb0fc1e121b..548a3b9e57c 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1598,22 +1598,8 @@ _outPathInfo(StringInfo str, const Path *node) WRITE_ENUM_FIELD(pathtype, NodeTag); appendStringInfoString(str, " :parent_relids "); _outBitmapset(str, node->parent->relids); - if (node->pathtarget != &(node->parent->reltarget)) - { - WRITE_NODE_FIELD(pathtarget->exprs); - if (node->pathtarget->sortgrouprefs) - { - int i; - - appendStringInfoString(str, " :pathtarget->sortgrouprefs"); - for (i = 0; i < list_length(node->pathtarget->exprs); i++) - appendStringInfo(str, " %u", - node->pathtarget->sortgrouprefs[i]); - } - WRITE_FLOAT_FIELD(pathtarget->cost.startup, "%.2f"); - WRITE_FLOAT_FIELD(pathtarget->cost.per_tuple, "%.2f"); - WRITE_INT_FIELD(pathtarget->width); - } + if (node->pathtarget != node->parent->reltarget) + WRITE_NODE_FIELD(pathtarget); appendStringInfoString(str, " :required_outer "); if (node->param_info) _outBitmapset(str, node->param_info->ppi_req_outer); @@ -2094,11 +2080,7 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node) WRITE_BOOL_FIELD(consider_startup); WRITE_BOOL_FIELD(consider_param_startup); WRITE_BOOL_FIELD(consider_parallel); - WRITE_NODE_FIELD(reltarget.exprs); - /* reltarget.sortgrouprefs is never interesting, at present anyway */ - WRITE_FLOAT_FIELD(reltarget.cost.startup, "%.2f"); - WRITE_FLOAT_FIELD(reltarget.cost.per_tuple, "%.2f"); - WRITE_INT_FIELD(reltarget.width); + WRITE_NODE_FIELD(reltarget); WRITE_NODE_FIELD(pathlist); WRITE_NODE_FIELD(ppilist); WRITE_NODE_FIELD(partial_pathlist); @@ -2202,6 +2184,25 @@ _outPathKey(StringInfo str, const PathKey *node) } static void +_outPathTarget(StringInfo str, const PathTarget *node) +{ + WRITE_NODE_TYPE("PATHTARGET"); + + WRITE_NODE_FIELD(exprs); + if (node->sortgrouprefs) + { + int i; + + appendStringInfoString(str, " :sortgrouprefs"); + for (i = 0; i < list_length(node->exprs); i++) + appendStringInfo(str, " %u", node->sortgrouprefs[i]); + } + WRITE_FLOAT_FIELD(cost.startup, "%.2f"); + WRITE_FLOAT_FIELD(cost.per_tuple, "%.2f"); + WRITE_INT_FIELD(width); +} + +static void _outParamPathInfo(StringInfo str, const ParamPathInfo *node) { WRITE_NODE_TYPE("PARAMPATHINFO"); @@ -3612,6 +3613,9 @@ _outNode(StringInfo str, const void *obj) case T_PathKey: _outPathKey(str, obj); break; + case T_PathTarget: + _outPathTarget(str, obj); + break; case T_ParamPathInfo: _outParamPathInfo(str, obj); break; diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 05c51ff07e0..4f60b85861d 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -936,7 +936,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, /* * CE failed, so finish copying/modifying targetlist and join quals. * - * Note: the resulting childrel->reltarget.exprs may contain arbitrary + * NB: the resulting childrel->reltarget->exprs may contain arbitrary * expressions, which otherwise would not occur in a rel's targetlist. * Code that might be looking at an appendrel child must cope with * such. (Normally, a rel's targetlist would only include Vars and @@ -947,9 +947,9 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, adjust_appendrel_attrs(root, (Node *) rel->joininfo, appinfo); - childrel->reltarget.exprs = (List *) + childrel->reltarget->exprs = (List *) adjust_appendrel_attrs(root, - (Node *) rel->reltarget.exprs, + (Node *) rel->reltarget->exprs, appinfo); /* @@ -994,7 +994,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, Assert(childrel->rows > 0); parent_rows += childrel->rows; - parent_size += childrel->reltarget.width * childrel->rows; + parent_size += childrel->reltarget->width * childrel->rows; /* * Accumulate per-column estimates too. We need not do anything for @@ -1004,8 +1004,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, * * By construction, child's targetlist is 1-to-1 with parent's. */ - forboth(parentvars, rel->reltarget.exprs, - childvars, childrel->reltarget.exprs) + forboth(parentvars, rel->reltarget->exprs, + childvars, childrel->reltarget->exprs) { Var *parentvar = (Var *) lfirst(parentvars); Node *childvar = (Node *) lfirst(childvars); @@ -1040,7 +1040,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, Assert(parent_rows > 0); rel->rows = parent_rows; - rel->reltarget.width = rint(parent_size / parent_rows); + rel->reltarget->width = rint(parent_size / parent_rows); for (i = 0; i < nattrs; i++) rel->attr_widths[i] = rint(parent_attrsizes[i] / parent_rows); @@ -1515,7 +1515,7 @@ set_dummy_rel_pathlist(RelOptInfo *rel) { /* Set dummy size estimates --- we leave attr_widths[] as zeroes */ rel->rows = 0; - rel->reltarget.width = 0; + rel->reltarget->width = 0; /* Discard any pre-existing paths; no further need for them */ rel->pathlist = NIL; @@ -1771,7 +1771,7 @@ set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) * not reference the ordinality column, or at least not in any way * that would be interesting for sorting. */ - foreach(lc, rel->reltarget.exprs) + foreach(lc, rel->reltarget->exprs) { Var *node = (Var *) lfirst(lc); @@ -2717,7 +2717,7 @@ remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel) * isn't computed for inheritance child rels, cf set_append_rel_size(). * (XXX might be worth changing that sometime.) */ - pull_varattnos((Node *) rel->reltarget.exprs, rel->relid, &attrs_used); + pull_varattnos((Node *) rel->reltarget->exprs, rel->relid, &attrs_used); /* Add all the attributes used by un-pushed-down restriction clauses. */ foreach(lc, rel->baserestrictinfo) @@ -3028,7 +3028,7 @@ debug_print_rel(PlannerInfo *root, RelOptInfo *rel) printf("RELOPTINFO ("); print_relids(rel->relids); - printf("): rows=%.0f width=%d\n", rel->rows, rel->reltarget.width); + printf("): rows=%.0f width=%d\n", rel->rows, rel->reltarget->width); if (rel->baserestrictinfo) { diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 5350329998a..943fcde3b8e 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -4218,7 +4218,7 @@ set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel) * that have to be calculated at this relation. This is the amount of data * we'd need to pass upwards in case of a sort, hash, etc. * - * This function also sets reltarget.cost, so it's a bit misnamed now. + * This function also sets reltarget->cost, so it's a bit misnamed now. * * NB: this works best on plain relations because it prefers to look at * real Vars. For subqueries, set_subquery_size_estimates will already have @@ -4239,10 +4239,10 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel) ListCell *lc; /* Vars are assumed to have cost zero, but other exprs do not */ - rel->reltarget.cost.startup = 0; - rel->reltarget.cost.per_tuple = 0; + rel->reltarget->cost.startup = 0; + rel->reltarget->cost.per_tuple = 0; - foreach(lc, rel->reltarget.exprs) + foreach(lc, rel->reltarget->exprs) { Node *node = (Node *) lfirst(lc); @@ -4309,7 +4309,7 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel) { /* * We will need to evaluate the PHV's contained expression while - * scanning this rel, so be sure to include it in reltarget.cost. + * scanning this rel, so be sure to include it in reltarget->cost. */ PlaceHolderVar *phv = (PlaceHolderVar *) node; PlaceHolderInfo *phinfo = find_placeholder_info(root, phv, false); @@ -4317,8 +4317,8 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel) tuple_width += phinfo->ph_width; cost_qual_eval_node(&cost, (Node *) phv->phexpr, root); - rel->reltarget.cost.startup += cost.startup; - rel->reltarget.cost.per_tuple += cost.per_tuple; + rel->reltarget->cost.startup += cost.startup; + rel->reltarget->cost.per_tuple += cost.per_tuple; } else { @@ -4335,8 +4335,8 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel) tuple_width += item_width; /* Not entirely clear if we need to account for cost, but do so */ cost_qual_eval_node(&cost, node, root); - rel->reltarget.cost.startup += cost.startup; - rel->reltarget.cost.per_tuple += cost.per_tuple; + rel->reltarget->cost.startup += cost.startup; + rel->reltarget->cost.per_tuple += cost.per_tuple; } } @@ -4373,7 +4373,7 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel) } Assert(tuple_width >= 0); - rel->reltarget.width = tuple_width; + rel->reltarget->width = tuple_width; } /* diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index ddb4ca50c63..b48f5f28ea9 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -1550,7 +1550,7 @@ bitmap_scan_cost_est(PlannerInfo *root, RelOptInfo *rel, Path *ipath) bpath.path.type = T_BitmapHeapPath; bpath.path.pathtype = T_BitmapHeapScan; bpath.path.parent = rel; - bpath.path.pathtarget = &(rel->reltarget); + bpath.path.pathtarget = rel->reltarget; bpath.path.param_info = get_baserel_parampathinfo(root, rel, required_outer); bpath.path.pathkeys = NIL; @@ -1579,7 +1579,7 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths) apath.path.type = T_BitmapAndPath; apath.path.pathtype = T_BitmapAnd; apath.path.parent = rel; - apath.path.pathtarget = &(rel->reltarget); + apath.path.pathtarget = rel->reltarget; apath.path.param_info = NULL; /* not used in bitmap trees */ apath.path.pathkeys = NIL; apath.bitmapquals = paths; @@ -1592,7 +1592,7 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths) bpath.path.type = T_BitmapHeapPath; bpath.path.pathtype = T_BitmapHeapScan; bpath.path.parent = rel; - bpath.path.pathtarget = &(rel->reltarget); + bpath.path.pathtarget = rel->reltarget; bpath.path.param_info = get_baserel_parampathinfo(root, rel, required_outer); bpath.path.pathkeys = NIL; @@ -1815,7 +1815,7 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index) * look at rel's targetlist, not the attr_needed data, because attr_needed * isn't computed for inheritance child rels. */ - pull_varattnos((Node *) rel->reltarget.exprs, rel->relid, &attrs_used); + pull_varattnos((Node *) rel->reltarget->exprs, rel->relid, &attrs_used); /* Add all the attributes used by restriction clauses. */ foreach(lc, rel->baserestrictinfo) diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 913ac844f09..e37bdfd2cfd 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -3279,7 +3279,7 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, * Note: we must look at rel's targetlist, not the attr_needed data, * because attr_needed isn't computed for inheritance child rels. */ - pull_varattnos((Node *) rel->reltarget.exprs, scan_relid, &attrs_used); + pull_varattnos((Node *) rel->reltarget->exprs, scan_relid, &attrs_used); /* Add all the attributes used by restriction clauses. */ foreach(lc, rel->baserestrictinfo) diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 64bc8a8e597..9999eea4991 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -215,8 +215,8 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars, { /* Variable not yet requested, so add to rel's targetlist */ /* XXX is copyObject necessary here? */ - rel->reltarget.exprs = lappend(rel->reltarget.exprs, - copyObject(var)); + rel->reltarget->exprs = lappend(rel->reltarget->exprs, + copyObject(var)); /* reltarget cost and width will be computed later */ } rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno], diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index 443e64e9691..88d7ea45479 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -83,7 +83,7 @@ query_planner(PlannerInfo *root, List *tlist, /* The only path for it is a trivial Result path */ add_path(final_rel, (Path *) create_result_path(root, final_rel, - &(final_rel->reltarget), + final_rel->reltarget, (List *) parse->jointree->quals)); /* Select cheapest path (pretty easy in this case...) */ diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 8afac0bda73..f3a0a44fd88 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -4534,7 +4534,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) * set_baserel_size_estimates, just do a quick hack for rows and width. */ rel->rows = rel->tuples; - rel->reltarget.width = get_relation_data_width(tableOid, NULL); + rel->reltarget->width = get_relation_data_width(tableOid, NULL); root->total_table_pages = rel->pages; @@ -4550,7 +4550,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) /* Estimate the cost of seq scan + sort */ seqScanPath = create_seqscan_path(root, rel, NULL, 0); cost_sort(&seqScanAndSortPath, root, NIL, - seqScanPath->total_cost, rel->tuples, rel->reltarget.width, + seqScanPath->total_cost, rel->tuples, rel->reltarget->width, comparisonCost, maintenance_work_mem, -1.0); /* Estimate the cost of index scan */ diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 6e7980041f7..8f089c59884 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -929,7 +929,7 @@ create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, pathnode->pathtype = T_SeqScan; pathnode->parent = rel; - pathnode->pathtarget = &(rel->reltarget); + pathnode->pathtarget = rel->reltarget; pathnode->param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->parallel_aware = parallel_degree > 0 ? true : false; @@ -953,7 +953,7 @@ create_samplescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer pathnode->pathtype = T_SampleScan; pathnode->parent = rel; - pathnode->pathtarget = &(rel->reltarget); + pathnode->pathtarget = rel->reltarget; pathnode->param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->parallel_aware = false; @@ -1010,7 +1010,7 @@ create_index_path(PlannerInfo *root, pathnode->path.pathtype = indexonly ? T_IndexOnlyScan : T_IndexScan; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->path.parallel_aware = false; @@ -1059,7 +1059,7 @@ create_bitmap_heap_path(PlannerInfo *root, pathnode->path.pathtype = T_BitmapHeapScan; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->path.parallel_aware = false; @@ -1089,7 +1089,7 @@ create_bitmap_and_path(PlannerInfo *root, pathnode->path.pathtype = T_BitmapAnd; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = NULL; /* not used in bitmap trees */ /* @@ -1125,7 +1125,7 @@ create_bitmap_or_path(PlannerInfo *root, pathnode->path.pathtype = T_BitmapOr; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = NULL; /* not used in bitmap trees */ /* @@ -1160,7 +1160,7 @@ create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tidquals, pathnode->path.pathtype = T_TidScan; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->path.parallel_aware = false; @@ -1192,7 +1192,7 @@ create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer, pathnode->path.pathtype = T_Append; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = get_appendrel_parampathinfo(rel, required_outer); pathnode->path.parallel_aware = false; @@ -1251,7 +1251,7 @@ create_merge_append_path(PlannerInfo *root, pathnode->path.pathtype = T_MergeAppend; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = get_appendrel_parampathinfo(rel, required_outer); pathnode->path.parallel_aware = false; @@ -1375,7 +1375,7 @@ create_material_path(RelOptInfo *rel, Path *subpath) pathnode->path.pathtype = T_Material; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = subpath->param_info; pathnode->path.parallel_aware = false; pathnode->path.parallel_safe = rel->consider_parallel && @@ -1440,7 +1440,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.pathtype = T_Unique; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = subpath->param_info; pathnode->path.parallel_aware = false; pathnode->path.parallel_safe = rel->consider_parallel && @@ -1656,7 +1656,7 @@ create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.pathtype = T_Gather; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->path.parallel_aware = false; @@ -1692,7 +1692,7 @@ create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.pathtype = T_SubqueryScan; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->path.parallel_aware = false; @@ -1720,7 +1720,7 @@ create_functionscan_path(PlannerInfo *root, RelOptInfo *rel, pathnode->pathtype = T_FunctionScan; pathnode->parent = rel; - pathnode->pathtarget = &(rel->reltarget); + pathnode->pathtarget = rel->reltarget; pathnode->param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->parallel_aware = false; @@ -1746,7 +1746,7 @@ create_valuesscan_path(PlannerInfo *root, RelOptInfo *rel, pathnode->pathtype = T_ValuesScan; pathnode->parent = rel; - pathnode->pathtarget = &(rel->reltarget); + pathnode->pathtarget = rel->reltarget; pathnode->param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->parallel_aware = false; @@ -1771,7 +1771,7 @@ create_ctescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer) pathnode->pathtype = T_CteScan; pathnode->parent = rel; - pathnode->pathtarget = &(rel->reltarget); + pathnode->pathtarget = rel->reltarget; pathnode->param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->parallel_aware = false; @@ -1797,7 +1797,7 @@ create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel, pathnode->pathtype = T_WorkTableScan; pathnode->parent = rel; - pathnode->pathtarget = &(rel->reltarget); + pathnode->pathtarget = rel->reltarget; pathnode->param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->parallel_aware = false; @@ -1833,7 +1833,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.pathtype = T_ForeignScan; pathnode->path.parent = rel; - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = get_baserel_parampathinfo(root, rel, required_outer); pathnode->path.parallel_aware = false; @@ -1966,7 +1966,7 @@ create_nestloop_path(PlannerInfo *root, pathnode->path.pathtype = T_NestLoop; pathnode->path.parent = joinrel; - pathnode->path.pathtarget = &(joinrel->reltarget); + pathnode->path.pathtarget = joinrel->reltarget; pathnode->path.param_info = get_joinrel_parampathinfo(root, joinrel, @@ -2029,7 +2029,7 @@ create_mergejoin_path(PlannerInfo *root, pathnode->jpath.path.pathtype = T_MergeJoin; pathnode->jpath.path.parent = joinrel; - pathnode->jpath.path.pathtarget = &(joinrel->reltarget); + pathnode->jpath.path.pathtarget = joinrel->reltarget; pathnode->jpath.path.param_info = get_joinrel_parampathinfo(root, joinrel, @@ -2091,7 +2091,7 @@ create_hashjoin_path(PlannerInfo *root, pathnode->jpath.path.pathtype = T_HashJoin; pathnode->jpath.path.parent = joinrel; - pathnode->jpath.path.pathtarget = &(joinrel->reltarget); + pathnode->jpath.path.pathtarget = joinrel->reltarget; pathnode->jpath.path.param_info = get_joinrel_parampathinfo(root, joinrel, @@ -2876,7 +2876,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.pathtype = T_ModifyTable; pathnode->path.parent = rel; /* pathtarget is not interesting, just make it minimally valid */ - pathnode->path.pathtarget = &(rel->reltarget); + pathnode->path.pathtarget = rel->reltarget; /* For now, assume we are above any joins, so no parameterization */ pathnode->path.param_info = NULL; pathnode->path.parallel_aware = false; diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c index 9e1c0e53333..b210914b853 100644 --- a/src/backend/optimizer/util/placeholder.c +++ b/src/backend/optimizer/util/placeholder.c @@ -391,8 +391,8 @@ add_placeholders_to_base_rels(PlannerInfo *root) { RelOptInfo *rel = find_base_rel(root, varno); - rel->reltarget.exprs = lappend(rel->reltarget.exprs, - copyObject(phinfo->ph_var)); + rel->reltarget->exprs = lappend(rel->reltarget->exprs, + copyObject(phinfo->ph_var)); /* reltarget's cost and width fields will be updated later */ } } @@ -425,9 +425,9 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, if (bms_is_subset(phinfo->ph_eval_at, relids)) { /* Yup, add it to the output */ - joinrel->reltarget.exprs = lappend(joinrel->reltarget.exprs, - phinfo->ph_var); - joinrel->reltarget.width += phinfo->ph_width; + joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs, + phinfo->ph_var); + joinrel->reltarget->width += phinfo->ph_width; /* * Charge the cost of evaluating the contained expression if @@ -447,8 +447,8 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, cost_qual_eval_node(&cost, (Node *) phinfo->ph_var->phexpr, root); - joinrel->reltarget.cost.startup += cost.startup; - joinrel->reltarget.cost.per_tuple += cost.per_tuple; + joinrel->reltarget->cost.startup += cost.startup; + joinrel->reltarget->cost.per_tuple += cost.per_tuple; } /* Adjust joinrel's direct_lateral_relids as needed */ diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 763d39d1429..20e4bf7d125 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -24,6 +24,7 @@ #include "optimizer/placeholder.h" #include "optimizer/plancat.h" #include "optimizer/restrictinfo.h" +#include "optimizer/tlist.h" #include "utils/hsearch.h" @@ -106,11 +107,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) rel->consider_startup = (root->tuple_fraction > 0); rel->consider_param_startup = false; /* might get changed later */ rel->consider_parallel = false; /* might get changed later */ - rel->reltarget.exprs = NIL; - rel->reltarget.sortgrouprefs = NULL; - rel->reltarget.cost.startup = 0; - rel->reltarget.cost.per_tuple = 0; - rel->reltarget.width = 0; + rel->reltarget = create_empty_pathtarget(); rel->pathlist = NIL; rel->ppilist = NIL; rel->partial_pathlist = NIL; @@ -393,11 +390,7 @@ build_join_rel(PlannerInfo *root, joinrel->consider_startup = (root->tuple_fraction > 0); joinrel->consider_param_startup = false; joinrel->consider_parallel = false; - joinrel->reltarget.exprs = NIL; - joinrel->reltarget.sortgrouprefs = NULL; - joinrel->reltarget.cost.startup = 0; - joinrel->reltarget.cost.per_tuple = 0; - joinrel->reltarget.width = 0; + joinrel->reltarget = create_empty_pathtarget(); joinrel->pathlist = NIL; joinrel->ppilist = NIL; joinrel->partial_pathlist = NIL; @@ -613,7 +606,7 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, Relids relids = joinrel->relids; ListCell *vars; - foreach(vars, input_rel->reltarget.exprs) + foreach(vars, input_rel->reltarget->exprs) { Var *var = (Var *) lfirst(vars); RelOptInfo *baserel; @@ -643,9 +636,9 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, if (bms_nonempty_difference(baserel->attr_needed[ndx], relids)) { /* Yup, add it to the output */ - joinrel->reltarget.exprs = lappend(joinrel->reltarget.exprs, var); - /* Vars have cost zero, so no need to adjust reltarget.cost */ - joinrel->reltarget.width += baserel->attr_widths[ndx]; + joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs, var); + /* Vars have cost zero, so no need to adjust reltarget->cost */ + joinrel->reltarget->width += baserel->attr_widths[ndx]; } } } @@ -832,6 +825,7 @@ build_empty_join_rel(PlannerInfo *root) joinrel->relids = NULL; /* empty set */ joinrel->rows = 1; /* we produce one row for such cases */ joinrel->rtekind = RTE_JOIN; + joinrel->reltarget = create_empty_pathtarget(); root->join_rel_list = lappend(root->join_rel_list, joinrel); @@ -882,6 +876,7 @@ fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids) upperrel->consider_startup = (root->tuple_fraction > 0); upperrel->consider_param_startup = false; upperrel->consider_parallel = false; /* might get changed later */ + upperrel->reltarget = create_empty_pathtarget(); upperrel->pathlist = NIL; upperrel->cheapest_startup_path = NULL; upperrel->cheapest_total_path = NULL; diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index 9f85dee3872..b297d87e7ec 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -546,7 +546,7 @@ grouping_is_hashable(List *groupClause) PathTarget * make_pathtarget_from_tlist(List *tlist) { - PathTarget *target = (PathTarget *) palloc0(sizeof(PathTarget)); + PathTarget *target = makeNode(PathTarget); int i; ListCell *lc; @@ -606,7 +606,7 @@ make_tlist_from_pathtarget(PathTarget *target) PathTarget * copy_pathtarget(PathTarget *src) { - PathTarget *dst = (PathTarget *) palloc(sizeof(PathTarget)); + PathTarget *dst = makeNode(PathTarget); /* Copy scalar fields */ memcpy(dst, src, sizeof(PathTarget)); @@ -631,7 +631,7 @@ PathTarget * create_empty_pathtarget(void) { /* This is easy, but we don't want callers to hard-wire this ... */ - return (PathTarget *) palloc0(sizeof(PathTarget)); + return makeNode(PathTarget); } /* diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index fad9988119f..42c958258b6 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -259,6 +259,7 @@ typedef enum NodeTag T_EquivalenceClass, T_EquivalenceMember, T_PathKey, + T_PathTarget, T_RestrictInfo, T_PlaceHolderVar, T_SpecialJoinInfo, diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index bdea72c3f47..b48a6183dc2 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -62,34 +62,6 @@ typedef struct AggClauseCosts } AggClauseCosts; /* - * This struct contains what we need to know during planning about the - * targetlist (output columns) that a Path will compute. Each RelOptInfo - * includes a default PathTarget, which its individual Paths may merely point - * to. However, in some cases a Path may compute outputs different from other - * Paths, and in that case we make a custom PathTarget struct for it. For - * example, an indexscan might return index expressions that would otherwise - * need to be explicitly calculated. - * - * exprs contains bare expressions; they do not have TargetEntry nodes on top, - * though those will appear in finished Plans. - * - * sortgrouprefs[] is an array of the same length as exprs, containing the - * corresponding sort/group refnos, or zeroes for expressions not referenced - * by sort/group clauses. If sortgrouprefs is NULL (which it always is in - * RelOptInfo.reltarget structs; only upper-level Paths contain this info), we - * have not identified sort/group columns in this tlist. This allows us to - * deal with sort/group refnos when needed with less expense than including - * TargetEntry nodes in the exprs list. - */ -typedef struct PathTarget -{ - List *exprs; /* list of expressions to be computed */ - Index *sortgrouprefs; /* corresponding sort/group refnos, or 0 */ - QualCost cost; /* cost of evaluating the expressions */ - int width; /* estimated avg width of result tuples */ -} PathTarget; - -/* * This enum identifies the different types of "upper" (post-scan/join) * relations that we might deal with during planning. */ @@ -514,7 +486,7 @@ typedef struct RelOptInfo bool consider_parallel; /* consider parallel paths? */ /* default result targetlist for Paths scanning this relation */ - PathTarget reltarget; /* list of Vars/Exprs, cost, width */ + struct PathTarget *reltarget; /* list of Vars/Exprs, cost, width */ /* materialization information */ List *pathlist; /* Path structures */ @@ -766,6 +738,39 @@ typedef struct PathKey /* + * PathTarget + * + * This struct contains what we need to know during planning about the + * targetlist (output columns) that a Path will compute. Each RelOptInfo + * includes a default PathTarget, which its individual Paths may simply + * reference. However, in some cases a Path may compute outputs different + * from other Paths, and in that case we make a custom PathTarget for it. + * For example, an indexscan might return index expressions that would + * otherwise need to be explicitly calculated. (Note also that "upper" + * relations generally don't have useful default PathTargets.) + * + * exprs contains bare expressions; they do not have TargetEntry nodes on top, + * though those will appear in finished Plans. + * + * sortgrouprefs[] is an array of the same length as exprs, containing the + * corresponding sort/group refnos, or zeroes for expressions not referenced + * by sort/group clauses. If sortgrouprefs is NULL (which it generally is in + * RelOptInfo.reltarget targets; only upper-level Paths contain this info), + * we have not identified sort/group columns in this tlist. This allows us to + * deal with sort/group refnos when needed with less expense than including + * TargetEntry nodes in the exprs list. + */ +typedef struct PathTarget +{ + NodeTag type; + List *exprs; /* list of expressions to be computed */ + Index *sortgrouprefs; /* corresponding sort/group refnos, or 0 */ + QualCost cost; /* cost of evaluating the expressions */ + int width; /* estimated avg width of result tuples */ +} PathTarget; + + +/* * ParamPathInfo * * All parameterized paths for a given relation with given required outer rels @@ -802,7 +807,7 @@ typedef struct ParamPathInfo * "parent" identifies the relation this Path scans, and "pathtarget" * describes the precise set of output columns the Path would compute. * In simple cases all Paths for a given rel share the same targetlist, - * which we represent by having path->pathtarget point to parent->reltarget. + * which we represent by having path->pathtarget equal to parent->reltarget. * * "param_info", if not NULL, links to a ParamPathInfo that identifies outer * relation(s) that provide parameter values to each scan of this path. |