aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/nodes/outfuncs.c46
-rw-r--r--src/backend/optimizer/path/allpaths.c22
-rw-r--r--src/backend/optimizer/path/costsize.c20
-rw-r--r--src/backend/optimizer/path/indxpath.c8
-rw-r--r--src/backend/optimizer/plan/createplan.c2
-rw-r--r--src/backend/optimizer/plan/initsplan.c4
-rw-r--r--src/backend/optimizer/plan/planmain.c2
-rw-r--r--src/backend/optimizer/plan/planner.c4
-rw-r--r--src/backend/optimizer/util/pathnode.c44
-rw-r--r--src/backend/optimizer/util/placeholder.c14
-rw-r--r--src/backend/optimizer/util/relnode.c23
-rw-r--r--src/backend/optimizer/util/tlist.c6
-rw-r--r--src/include/nodes/nodes.h1
-rw-r--r--src/include/nodes/relation.h65
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.