aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/createplan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r--src/backend/optimizer/plan/createplan.c392
1 files changed, 230 insertions, 162 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index a865da61b92..4069ed66e58 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.99 2000/10/26 21:36:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.100 2000/11/12 00:36:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -32,35 +32,38 @@
#include "utils/syscache.h"
-static List *switch_outer(List *clauses);
-static Scan *create_scan_node(Query *root, Path *best_path, List *tlist);
-static Join *create_join_node(Query *root, JoinPath *best_path, List *tlist);
-static SeqScan *create_seqscan_node(Path *best_path, List *tlist,
+static Scan *create_scan_plan(Query *root, Path *best_path);
+static Join *create_join_plan(Query *root, JoinPath *best_path);
+static Append *create_append_plan(Query *root, AppendPath *best_path);
+static SeqScan *create_seqscan_plan(Path *best_path, List *tlist,
List *scan_clauses);
-static IndexScan *create_indexscan_node(Query *root, IndexPath *best_path,
+static IndexScan *create_indexscan_plan(Query *root, IndexPath *best_path,
List *tlist, List *scan_clauses);
-static TidScan *create_tidscan_node(TidPath *best_path, List *tlist,
+static TidScan *create_tidscan_plan(TidPath *best_path, List *tlist,
List *scan_clauses);
-static SubqueryScan *create_subqueryscan_node(Path *best_path,
+static SubqueryScan *create_subqueryscan_plan(Path *best_path,
List *tlist, List *scan_clauses);
-static NestLoop *create_nestloop_node(NestPath *best_path, List *tlist,
+static NestLoop *create_nestloop_plan(NestPath *best_path, List *tlist,
List *joinclauses, List *otherclauses,
- Plan *outer_node, List *outer_tlist,
- Plan *inner_node, List *inner_tlist);
-static MergeJoin *create_mergejoin_node(MergePath *best_path, List *tlist,
+ Plan *outer_plan, List *outer_tlist,
+ Plan *inner_plan, List *inner_tlist);
+static MergeJoin *create_mergejoin_plan(MergePath *best_path, List *tlist,
List *joinclauses, List *otherclauses,
- Plan *outer_node, List *outer_tlist,
- Plan *inner_node, List *inner_tlist);
-static HashJoin *create_hashjoin_node(HashPath *best_path, List *tlist,
+ Plan *outer_plan, List *outer_tlist,
+ Plan *inner_plan, List *inner_tlist);
+static HashJoin *create_hashjoin_plan(HashPath *best_path, List *tlist,
List *joinclauses, List *otherclauses,
- Plan *outer_node, List *outer_tlist,
- Plan *inner_node, List *inner_tlist);
+ Plan *outer_plan, List *outer_tlist,
+ Plan *inner_plan, List *inner_tlist);
static List *fix_indxqual_references(List *indexquals, IndexPath *index_path);
static List *fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
Form_pg_index index);
static Node *fix_indxqual_operand(Node *node, int baserelid,
Form_pg_index index,
Oid *opclass);
+static List *switch_outer(List *clauses);
+static void copy_path_costsize(Plan *dest, Path *src);
+static void copy_plan_costsize(Plan *dest, Plan *src);
static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
List *indxid, List *indxqual,
@@ -83,7 +86,6 @@ static MergeJoin *make_mergejoin(List *tlist,
List *mergeclauses,
Plan *lefttree, Plan *righttree,
JoinType jointype);
-static void copy_path_costsize(Plan *dest, Path *src);
/*
* create_plan
@@ -98,13 +100,12 @@ static void copy_path_costsize(Plan *dest, Path *src);
*
* best_path is the best access path
*
- * Returns the access plan.
+ * Returns a Plan tree.
*/
Plan *
create_plan(Query *root, Path *best_path)
{
- List *tlist = best_path->parent->targetlist;
- Plan *plan_node = (Plan *) NULL;
+ Plan *plan;
switch (best_path->pathtype)
{
@@ -112,18 +113,22 @@ create_plan(Query *root, Path *best_path)
case T_SeqScan:
case T_TidScan:
case T_SubqueryScan:
- plan_node = (Plan *) create_scan_node(root, best_path, tlist);
+ plan = (Plan *) create_scan_plan(root, best_path);
break;
case T_HashJoin:
case T_MergeJoin:
case T_NestLoop:
- plan_node = (Plan *) create_join_node(root,
- (JoinPath *) best_path,
- tlist);
+ plan = (Plan *) create_join_plan(root,
+ (JoinPath *) best_path);
+ break;
+ case T_Append:
+ plan = (Plan *) create_append_plan(root,
+ (AppendPath *) best_path);
break;
default:
elog(ERROR, "create_plan: unknown pathtype %d",
best_path->pathtype);
+ plan = NULL; /* keep compiler quiet */
break;
}
@@ -131,30 +136,29 @@ create_plan(Query *root, Path *best_path)
/* sort clauses by cost/(1-selectivity) -- JMH 2/26/92 */
if (XfuncMode != XFUNC_OFF)
{
- set_qpqual((Plan) plan_node,
- lisp_qsort(get_qpqual((Plan) plan_node),
+ set_qpqual((Plan) plan,
+ lisp_qsort(get_qpqual((Plan) plan),
xfunc_clause_compare));
if (XfuncMode != XFUNC_NOR)
/* sort the disjuncts within each clause by cost -- JMH 3/4/92 */
- xfunc_disjunct_sort(plan_node->qpqual);
+ xfunc_disjunct_sort(plan->qpqual);
}
#endif
- return plan_node;
+ return plan;
}
/*
- * create_scan_node
- * Create a scan path for the parent relation of 'best_path'.
+ * create_scan_plan
+ * Create a scan plan for the parent relation of 'best_path'.
*
- * tlist is the targetlist for the base relation scanned by 'best_path'
- *
- * Returns the scan node.
+ * Returns a Plan node.
*/
static Scan *
-create_scan_node(Query *root, Path *best_path, List *tlist)
+create_scan_plan(Query *root, Path *best_path)
{
- Scan *node = NULL;
+ Scan *plan;
+ List *tlist = best_path->parent->targetlist;
List *scan_clauses;
/*
@@ -166,65 +170,64 @@ create_scan_node(Query *root, Path *best_path, List *tlist)
switch (best_path->pathtype)
{
case T_SeqScan:
- node = (Scan *) create_seqscan_node(best_path,
+ plan = (Scan *) create_seqscan_plan(best_path,
tlist,
scan_clauses);
break;
case T_IndexScan:
- node = (Scan *) create_indexscan_node(root,
+ plan = (Scan *) create_indexscan_plan(root,
(IndexPath *) best_path,
tlist,
scan_clauses);
break;
case T_TidScan:
- node = (Scan *) create_tidscan_node((TidPath *) best_path,
+ plan = (Scan *) create_tidscan_plan((TidPath *) best_path,
tlist,
scan_clauses);
break;
case T_SubqueryScan:
- node = (Scan *) create_subqueryscan_node(best_path,
+ plan = (Scan *) create_subqueryscan_plan(best_path,
tlist,
scan_clauses);
break;
default:
- elog(ERROR, "create_scan_node: unknown node type: %d",
+ elog(ERROR, "create_scan_plan: unknown node type: %d",
best_path->pathtype);
+ plan = NULL; /* keep compiler quiet */
break;
}
- return node;
+ return plan;
}
/*
- * create_join_node
- * Create a join path for 'best_path' and(recursively) paths for its
+ * create_join_plan
+ * Create a join plan for 'best_path' and (recursively) plans for its
* inner and outer paths.
*
- * 'tlist' is the targetlist for the join relation corresponding to
- * 'best_path'
- *
- * Returns the join node.
+ * Returns a Plan node.
*/
static Join *
-create_join_node(Query *root, JoinPath *best_path, List *tlist)
+create_join_plan(Query *root, JoinPath *best_path)
{
- Plan *outer_node;
+ List *join_tlist = best_path->path.parent->targetlist;
+ Plan *outer_plan;
List *outer_tlist;
- Plan *inner_node;
+ Plan *inner_plan;
List *inner_tlist;
List *joinclauses;
List *otherclauses;
- Join *retval = NULL;
+ Join *plan;
- outer_node = create_plan(root, best_path->outerjoinpath);
- outer_tlist = outer_node->targetlist;
+ outer_plan = create_plan(root, best_path->outerjoinpath);
+ outer_tlist = outer_plan->targetlist;
- inner_node = create_plan(root, best_path->innerjoinpath);
- inner_tlist = inner_node->targetlist;
+ inner_plan = create_plan(root, best_path->innerjoinpath);
+ inner_tlist = inner_plan->targetlist;
if (IS_OUTER_JOIN(best_path->jointype))
{
@@ -241,38 +244,40 @@ create_join_node(Query *root, JoinPath *best_path, List *tlist)
switch (best_path->path.pathtype)
{
case T_MergeJoin:
- retval = (Join *) create_mergejoin_node((MergePath *) best_path,
- tlist,
- joinclauses,
- otherclauses,
- outer_node,
- outer_tlist,
- inner_node,
- inner_tlist);
+ plan = (Join *) create_mergejoin_plan((MergePath *) best_path,
+ join_tlist,
+ joinclauses,
+ otherclauses,
+ outer_plan,
+ outer_tlist,
+ inner_plan,
+ inner_tlist);
break;
case T_HashJoin:
- retval = (Join *) create_hashjoin_node((HashPath *) best_path,
- tlist,
- joinclauses,
- otherclauses,
- outer_node,
- outer_tlist,
- inner_node,
- inner_tlist);
+ plan = (Join *) create_hashjoin_plan((HashPath *) best_path,
+ join_tlist,
+ joinclauses,
+ otherclauses,
+ outer_plan,
+ outer_tlist,
+ inner_plan,
+ inner_tlist);
break;
case T_NestLoop:
- retval = (Join *) create_nestloop_node((NestPath *) best_path,
- tlist,
- joinclauses,
- otherclauses,
- outer_node,
- outer_tlist,
- inner_node,
- inner_tlist);
+ plan = (Join *) create_nestloop_plan((NestPath *) best_path,
+ join_tlist,
+ joinclauses,
+ otherclauses,
+ outer_plan,
+ outer_tlist,
+ inner_plan,
+ inner_tlist);
break;
default:
- elog(ERROR, "create_join_node: unknown node type: %d",
+ elog(ERROR, "create_join_plan: unknown node type: %d",
best_path->path.pathtype);
+ plan = NULL; /* keep compiler quiet */
+ break;
}
#ifdef NOT_USED
@@ -283,14 +288,42 @@ create_join_node(Query *root, JoinPath *best_path, List *tlist)
* JMH, 6/15/92
*/
if (get_loc_restrictinfo(best_path) != NIL)
- set_qpqual((Plan) retval,
- nconc(get_qpqual((Plan) retval),
+ set_qpqual((Plan) plan,
+ nconc(get_qpqual((Plan) plan),
get_actual_clauses(get_loc_restrictinfo(best_path))));
#endif
- return retval;
+ return plan;
}
+/*
+ * create_append_plan
+ * Create an Append plan for 'best_path' and (recursively) plans
+ * for its subpaths.
+ *
+ * Returns a Plan node.
+ */
+static Append *
+create_append_plan(Query *root, AppendPath *best_path)
+{
+ Append *plan;
+ List *tlist = best_path->path.parent->targetlist;
+ List *subplans = NIL;
+ List *subpaths;
+
+ foreach(subpaths, best_path->subpaths)
+ {
+ Path *subpath = (Path *) lfirst(subpaths);
+
+ subplans = lappend(subplans, create_plan(root, subpath));
+ }
+
+ plan = make_append(subplans, false, tlist);
+
+ return plan;
+}
+
+
/*****************************************************************************
*
* BASE-RELATION SCAN METHODS
@@ -299,14 +332,14 @@ create_join_node(Query *root, JoinPath *best_path, List *tlist)
/*
- * create_seqscan_node
- * Returns a seqscan node for the base relation scanned by 'best_path'
+ * create_seqscan_plan
+ * Returns a seqscan plan for the base relation scanned by 'best_path'
* with restriction clauses 'scan_clauses' and targetlist 'tlist'.
*/
static SeqScan *
-create_seqscan_node(Path *best_path, List *tlist, List *scan_clauses)
+create_seqscan_plan(Path *best_path, List *tlist, List *scan_clauses)
{
- SeqScan *scan_node;
+ SeqScan *scan_plan;
Index scan_relid;
/* there should be exactly one base rel involved... */
@@ -315,18 +348,18 @@ create_seqscan_node(Path *best_path, List *tlist, List *scan_clauses)
scan_relid = (Index) lfirsti(best_path->parent->relids);
- scan_node = make_seqscan(tlist,
+ scan_plan = make_seqscan(tlist,
scan_clauses,
scan_relid);
- copy_path_costsize(&scan_node->plan, best_path);
+ copy_path_costsize(&scan_plan->plan, best_path);
- return scan_node;
+ return scan_plan;
}
/*
- * create_indexscan_node
- * Returns a indexscan node for the base relation scanned by 'best_path'
+ * create_indexscan_plan
+ * Returns a indexscan plan for the base relation scanned by 'best_path'
* with restriction clauses 'scan_clauses' and targetlist 'tlist'.
*
* The indexqual of the path contains a sublist of implicitly-ANDed qual
@@ -338,7 +371,7 @@ create_seqscan_node(Path *best_path, List *tlist, List *scan_clauses)
* scan.
*/
static IndexScan *
-create_indexscan_node(Query *root,
+create_indexscan_plan(Query *root,
IndexPath *best_path,
List *tlist,
List *scan_clauses)
@@ -348,7 +381,7 @@ create_indexscan_node(Query *root,
List *qpqual;
List *fixed_indxqual;
List *ixid;
- IndexScan *scan_node;
+ IndexScan *scan_plan;
bool lossy = false;
/* there should be exactly one base rel involved... */
@@ -433,7 +466,7 @@ create_indexscan_node(Query *root,
*/
fixed_indxqual = fix_indxqual_references(indxqual, best_path);
- scan_node = make_indexscan(tlist,
+ scan_plan = make_indexscan(tlist,
qpqual,
baserelid,
best_path->indexid,
@@ -441,22 +474,22 @@ create_indexscan_node(Query *root,
indxqual,
best_path->indexscandir);
- copy_path_costsize(&scan_node->scan.plan, &best_path->path);
+ copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
/* use the indexscan-specific rows estimate, not the parent rel's */
- scan_node->scan.plan.plan_rows = best_path->rows;
+ scan_plan->scan.plan.plan_rows = best_path->rows;
- return scan_node;
+ return scan_plan;
}
/*
- * create_tidscan_node
- * Returns a tidscan node for the base relation scanned by 'best_path'
+ * create_tidscan_plan
+ * Returns a tidscan plan for the base relation scanned by 'best_path'
* with restriction clauses 'scan_clauses' and targetlist 'tlist'.
*/
static TidScan *
-create_tidscan_node(TidPath *best_path, List *tlist, List *scan_clauses)
+create_tidscan_plan(TidPath *best_path, List *tlist, List *scan_clauses)
{
- TidScan *scan_node;
+ TidScan *scan_plan;
Index scan_relid;
/* there should be exactly one base rel involved... */
@@ -465,28 +498,28 @@ create_tidscan_node(TidPath *best_path, List *tlist, List *scan_clauses)
scan_relid = (Index) lfirsti(best_path->path.parent->relids);
- scan_node = make_tidscan(tlist,
+ scan_plan = make_tidscan(tlist,
scan_clauses,
scan_relid,
best_path->tideval);
if (best_path->unjoined_relids)
- scan_node->needRescan = true;
+ scan_plan->needRescan = true;
- copy_path_costsize(&scan_node->scan.plan, &best_path->path);
+ copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
- return scan_node;
+ return scan_plan;
}
/*
- * create_subqueryscan_node
- * Returns a subqueryscan node for the base relation scanned by 'best_path'
+ * create_subqueryscan_plan
+ * Returns a subqueryscan plan for the base relation scanned by 'best_path'
* with restriction clauses 'scan_clauses' and targetlist 'tlist'.
*/
static SubqueryScan *
-create_subqueryscan_node(Path *best_path, List *tlist, List *scan_clauses)
+create_subqueryscan_plan(Path *best_path, List *tlist, List *scan_clauses)
{
- SubqueryScan *scan_node;
+ SubqueryScan *scan_plan;
Index scan_relid;
/* there should be exactly one base rel involved... */
@@ -496,14 +529,12 @@ create_subqueryscan_node(Path *best_path, List *tlist, List *scan_clauses)
scan_relid = (Index) lfirsti(best_path->parent->relids);
- scan_node = make_subqueryscan(tlist,
+ scan_plan = make_subqueryscan(tlist,
scan_clauses,
scan_relid,
best_path->parent->subplan);
- copy_path_costsize(&scan_node->scan.plan, best_path);
-
- return scan_node;
+ return scan_plan;
}
/*****************************************************************************
@@ -528,18 +559,18 @@ create_subqueryscan_node(Path *best_path, List *tlist, List *scan_clauses)
*****************************************************************************/
static NestLoop *
-create_nestloop_node(NestPath *best_path,
+create_nestloop_plan(NestPath *best_path,
List *tlist,
List *joinclauses,
List *otherclauses,
- Plan *outer_node,
+ Plan *outer_plan,
List *outer_tlist,
- Plan *inner_node,
+ Plan *inner_plan,
List *inner_tlist)
{
- NestLoop *join_node;
+ NestLoop *join_plan;
- if (IsA(inner_node, IndexScan))
+ if (IsA(inner_plan, IndexScan))
{
/*
@@ -563,7 +594,7 @@ create_nestloop_node(NestPath *best_path,
* and therefore has not itself done join_references renumbering
* of the vars in its quals.
*/
- IndexScan *innerscan = (IndexScan *) inner_node;
+ IndexScan *innerscan = (IndexScan *) inner_plan;
List *indxqualorig = innerscan->indxqualorig;
/* No work needed if indxqual refers only to its own relation... */
@@ -591,23 +622,23 @@ create_nestloop_node(NestPath *best_path,
NIL,
innerrel);
/* fix the inner qpqual too, if it has join clauses */
- if (NumRelids((Node *) inner_node->qual) > 1)
- inner_node->qual = join_references(inner_node->qual,
+ if (NumRelids((Node *) inner_plan->qual) > 1)
+ inner_plan->qual = join_references(inner_plan->qual,
outer_tlist,
NIL,
innerrel);
}
}
- else if (IsA(inner_node, TidScan))
+ else if (IsA(inner_plan, TidScan))
{
- TidScan *innerscan = (TidScan *) inner_node;
+ TidScan *innerscan = (TidScan *) inner_plan;
innerscan->tideval = join_references(innerscan->tideval,
outer_tlist,
inner_tlist,
innerscan->scan.scanrelid);
}
- else if (IsA_Join(inner_node))
+ else if (IsA_Join(inner_plan))
{
/*
@@ -617,8 +648,8 @@ create_nestloop_node(NestPath *best_path,
* join --- how can we estimate whether this is a good thing to
* do?
*/
- inner_node = (Plan *) make_material(inner_tlist,
- inner_node);
+ inner_plan = (Plan *) make_material(inner_tlist,
+ inner_plan);
}
/*
@@ -633,30 +664,30 @@ create_nestloop_node(NestPath *best_path,
inner_tlist,
(Index) 0);
- join_node = make_nestloop(tlist,
+ join_plan = make_nestloop(tlist,
joinclauses,
otherclauses,
- outer_node,
- inner_node,
+ outer_plan,
+ inner_plan,
best_path->jointype);
- copy_path_costsize(&join_node->join.plan, &best_path->path);
+ copy_path_costsize(&join_plan->join.plan, &best_path->path);
- return join_node;
+ return join_plan;
}
static MergeJoin *
-create_mergejoin_node(MergePath *best_path,
+create_mergejoin_plan(MergePath *best_path,
List *tlist,
List *joinclauses,
List *otherclauses,
- Plan *outer_node,
+ Plan *outer_plan,
List *outer_tlist,
- Plan *inner_node,
+ Plan *inner_plan,
List *inner_tlist)
{
List *mergeclauses;
- MergeJoin *join_node;
+ MergeJoin *join_plan;
mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
@@ -692,15 +723,15 @@ create_mergejoin_node(MergePath *best_path,
* necessary. The sort cost was already accounted for in the path.
*/
if (best_path->outersortkeys)
- outer_node = (Plan *)
+ outer_plan = (Plan *)
make_sort_from_pathkeys(outer_tlist,
- outer_node,
+ outer_plan,
best_path->outersortkeys);
if (best_path->innersortkeys)
- inner_node = (Plan *)
+ inner_plan = (Plan *)
make_sort_from_pathkeys(inner_tlist,
- inner_node,
+ inner_plan,
best_path->innersortkeys);
/*
@@ -723,7 +754,7 @@ create_mergejoin_node(MergePath *best_path,
* This check must agree with ExecMarkPos/ExecRestrPos in
* executor/execAmi.c!
*/
- switch (nodeTag(inner_node))
+ switch (nodeTag(inner_plan))
{
case T_SeqScan:
case T_IndexScan:
@@ -734,40 +765,40 @@ create_mergejoin_node(MergePath *best_path,
default:
/* Ooops, need to materialize the inner plan */
- inner_node = (Plan *) make_material(inner_tlist,
- inner_node);
+ inner_plan = (Plan *) make_material(inner_tlist,
+ inner_plan);
break;
}
/*
* Now we can build the mergejoin node.
*/
- join_node = make_mergejoin(tlist,
+ join_plan = make_mergejoin(tlist,
joinclauses,
otherclauses,
mergeclauses,
- outer_node,
- inner_node,
+ outer_plan,
+ inner_plan,
best_path->jpath.jointype);
- copy_path_costsize(&join_node->join.plan, &best_path->jpath.path);
+ copy_path_costsize(&join_plan->join.plan, &best_path->jpath.path);
- return join_node;
+ return join_plan;
}
static HashJoin *
-create_hashjoin_node(HashPath *best_path,
+create_hashjoin_plan(HashPath *best_path,
List *tlist,
List *joinclauses,
List *otherclauses,
- Plan *outer_node,
+ Plan *outer_plan,
List *outer_tlist,
- Plan *inner_node,
+ Plan *inner_plan,
List *inner_tlist)
{
List *hashclauses;
- HashJoin *join_node;
- Hash *hash_node;
+ HashJoin *join_plan;
+ Hash *hash_plan;
Node *innerhashkey;
/*
@@ -811,18 +842,18 @@ create_hashjoin_node(HashPath *best_path,
/*
* Build the hash node and hash join node.
*/
- hash_node = make_hash(inner_tlist, innerhashkey, inner_node);
- join_node = make_hashjoin(tlist,
+ hash_plan = make_hash(inner_tlist, innerhashkey, inner_plan);
+ join_plan = make_hashjoin(tlist,
joinclauses,
otherclauses,
hashclauses,
- outer_node,
- (Plan *) hash_node,
+ outer_plan,
+ (Plan *) hash_plan,
best_path->jpath.jointype);
- copy_path_costsize(&join_node->join.plan, &best_path->jpath.path);
+ copy_path_costsize(&join_plan->join.plan, &best_path->jpath.path);
- return join_node;
+ return join_plan;
}
@@ -1106,7 +1137,7 @@ copy_path_costsize(Plan *dest, Path *src)
* but it helps produce more reasonable-looking EXPLAIN output.
* (Some callers alter the info after copying it.)
*/
-void
+static void
copy_plan_costsize(Plan *dest, Plan *src)
{
if (src)
@@ -1128,6 +1159,10 @@ copy_plan_costsize(Plan *dest, Plan *src)
/*****************************************************************************
*
+ * PLAN NODE BUILDING ROUTINES
+ *
+ * Some of these are exported because they are called to build plan nodes
+ * in contexts where we're not deriving the plan node from a path node.
*
*****************************************************************************/
@@ -1212,7 +1247,7 @@ make_subqueryscan(List *qptlist,
SubqueryScan *node = makeNode(SubqueryScan);
Plan *plan = &node->scan.plan;
- /* cost should be inserted by caller */
+ copy_plan_costsize(plan, subplan);
plan->state = (EState *) NULL;
plan->targetlist = qptlist;
plan->qual = qpqual;
@@ -1225,6 +1260,39 @@ make_subqueryscan(List *qptlist,
return node;
}
+Append *
+make_append(List *appendplans, bool isTarget, List *tlist)
+{
+ Append *node = makeNode(Append);
+ Plan *plan = &node->plan;
+ List *subnode;
+
+ /* compute costs from subplan costs */
+ plan->startup_cost = 0;
+ plan->total_cost = 0;
+ plan->plan_rows = 0;
+ plan->plan_width = 0;
+ foreach(subnode, appendplans)
+ {
+ Plan *subplan = (Plan *) lfirst(subnode);
+
+ if (subnode == appendplans) /* first node? */
+ plan->startup_cost = subplan->startup_cost;
+ plan->total_cost += subplan->total_cost;
+ plan->plan_rows += subplan->plan_rows;
+ if (plan->plan_width < subplan->plan_width)
+ plan->plan_width = subplan->plan_width;
+ }
+ plan->state = (EState *) NULL;
+ plan->targetlist = tlist;
+ plan->qual = NIL;
+ plan->lefttree = NULL;
+ plan->righttree = NULL;
+ node->appendplans = appendplans;
+ node->isTarget = isTarget;
+
+ return node;
+}
static NestLoop *
make_nestloop(List *tlist,