1010 *
1111 *
1212 * IDENTIFICATION
13- * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.166 2004/01/07 18:56:26 neilc Exp $
13+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.167 2004/01/18 00:50:02 tgl Exp $
1414 *
1515 *-------------------------------------------------------------------------
1616 */
@@ -97,13 +97,13 @@ static HashJoin *make_hashjoin(List *tlist,
9797List * hashclauses ,
9898Plan * lefttree ,Plan * righttree ,
9999JoinType jointype );
100- static Hash * make_hash (List * tlist , Plan * lefttree );
100+ static Hash * make_hash (Plan * lefttree );
101101static MergeJoin * make_mergejoin (List * tlist ,
102102List * joinclauses ,List * otherclauses ,
103103List * mergeclauses ,
104104Plan * lefttree ,Plan * righttree ,
105105JoinType jointype );
106- static Sort * make_sort (Query * root ,List * tlist , Plan * lefttree ,int numCols ,
106+ static Sort * make_sort (Query * root ,Plan * lefttree ,int numCols ,
107107AttrNumber * sortColIdx ,Oid * sortOperators );
108108static Sort * make_sort_from_pathkeys (Query * root ,Plan * lefttree ,
109109Relids relids ,List * pathkeys );
@@ -492,7 +492,7 @@ create_material_plan(Query *root, MaterialPath *best_path)
492492/* We don't want any excess columns in the materialized tuples */
493493disuse_physical_tlist (subplan ,best_path -> subpath );
494494
495- plan = make_material (subplan -> targetlist , subplan );
495+ plan = make_material (subplan );
496496
497497copy_path_costsize (& plan -> plan , (Path * )best_path );
498498
@@ -518,7 +518,6 @@ create_unique_plan(Query *root, UniquePath *best_path)
518518List * newtlist ;
519519int nextresno ;
520520bool newitems ;
521- List * my_tlist ;
522521List * l ;
523522
524523subplan = create_plan (root ,best_path -> subpath );
@@ -596,11 +595,8 @@ create_unique_plan(Query *root, UniquePath *best_path)
596595/*
597596 * If the top plan node can't do projections, we need to add a
598597 * Result node to help it along.
599- *
600- * Currently, the only non-projection-capable plan type we can see
601- * here is Append.
602598 */
603- if (IsA (subplan , Append ))
599+ if (! is_projection_capable_plan (subplan ))
604600subplan = (Plan * )make_result (newtlist ,NULL ,subplan );
605601else
606602subplan -> targetlist = newtlist ;
@@ -610,17 +606,14 @@ create_unique_plan(Query *root, UniquePath *best_path)
610606if (best_path -> umethod == UNIQUE_PATH_NOOP )
611607return subplan ;
612608
613- /* Copy tlist again to make one we can put sorting labels on */
614- my_tlist = copyObject (subplan -> targetlist );
615-
616609if (best_path -> umethod == UNIQUE_PATH_HASH )
617610{
618611long numGroups ;
619612
620613numGroups = (long )Min (best_path -> rows , (double )LONG_MAX );
621614
622615plan = (Plan * )make_agg (root ,
623- my_tlist ,
616+ copyObject ( subplan -> targetlist ) ,
624617NIL ,
625618AGG_HASHED ,
626619numGroupCols ,
@@ -637,15 +630,15 @@ create_unique_plan(Query *root, UniquePath *best_path)
637630{
638631TargetEntry * tle ;
639632
640- tle = get_tle_by_resno (my_tlist ,groupColIdx [groupColPos ]);
633+ tle = get_tle_by_resno (subplan -> targetlist ,
634+ groupColIdx [groupColPos ]);
641635Assert (tle != NULL );
642636sortList = addTargetToSortList (NULL ,tle ,
643- sortList ,my_tlist ,
637+ sortList ,subplan -> targetlist ,
644638SORTBY_ASC ,NIL , false);
645639}
646- plan = (Plan * )make_sort_from_sortclauses (root ,my_tlist ,
647- subplan ,sortList );
648- plan = (Plan * )make_unique (my_tlist ,plan ,sortList );
640+ plan = (Plan * )make_sort_from_sortclauses (root ,sortList ,subplan );
641+ plan = (Plan * )make_unique (plan ,sortList );
649642}
650643
651644/* Adjust output size estimate (other fields should be OK already) */
@@ -1145,8 +1138,7 @@ create_hashjoin_plan(Query *root,
11451138/*
11461139 * Build the hash node and hash join node.
11471140 */
1148- hash_plan = make_hash (inner_plan -> targetlist ,
1149- inner_plan );
1141+ hash_plan = make_hash (inner_plan );
11501142join_plan = make_hashjoin (tlist ,
11511143joinclauses ,
11521144otherclauses ,
@@ -1735,7 +1727,7 @@ make_hashjoin(List *tlist,
17351727}
17361728
17371729static Hash *
1738- make_hash (List * tlist , Plan * lefttree )
1730+ make_hash (Plan * lefttree )
17391731{
17401732Hash * node = makeNode (Hash );
17411733Plan * plan = & node -> plan ;
@@ -1747,7 +1739,7 @@ make_hash(List *tlist, Plan *lefttree)
17471739 * input plan; this only affects EXPLAIN display not decisions.
17481740 */
17491741plan -> startup_cost = plan -> total_cost ;
1750- plan -> targetlist = tlist ;
1742+ plan -> targetlist = copyObject ( lefttree -> targetlist ) ;
17511743plan -> qual = NIL ;
17521744plan -> lefttree = lefttree ;
17531745plan -> righttree = NULL ;
@@ -1785,7 +1777,7 @@ make_mergejoin(List *tlist,
17851777 * Caller must have built the sortColIdx and sortOperators arrays already.
17861778 */
17871779static Sort *
1788- make_sort (Query * root ,List * tlist , Plan * lefttree ,int numCols ,
1780+ make_sort (Query * root ,Plan * lefttree ,int numCols ,
17891781AttrNumber * sortColIdx ,Oid * sortOperators )
17901782{
17911783Sort * node = makeNode (Sort );
@@ -1799,7 +1791,7 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int numCols,
17991791lefttree -> plan_width );
18001792plan -> startup_cost = sort_path .startup_cost ;
18011793plan -> total_cost = sort_path .total_cost ;
1802- plan -> targetlist = tlist ;
1794+ plan -> targetlist = copyObject ( lefttree -> targetlist ) ;
18031795plan -> qual = NIL ;
18041796plan -> lefttree = lefttree ;
18051797plan -> righttree = NULL ;
@@ -1862,7 +1854,6 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
18621854Relids relids ,List * pathkeys )
18631855{
18641856List * tlist = lefttree -> targetlist ;
1865- List * sort_tlist ;
18661857List * i ;
18671858int numsortkeys ;
18681859AttrNumber * sortColIdx ;
@@ -1916,11 +1907,8 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
19161907
19171908/*
19181909 * Do we need to insert a Result node?
1919- *
1920- * Currently, the only non-projection-capable plan type we can
1921- * see here is Append.
19221910 */
1923- if (IsA (lefttree , Append ))
1911+ if (! is_projection_capable_plan (lefttree ))
19241912{
19251913tlist = copyObject (tlist );
19261914lefttree = (Plan * )make_result (tlist ,NULL ,lefttree );
@@ -1952,26 +1940,21 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
19521940
19531941Assert (numsortkeys > 0 );
19541942
1955- /* Give Sort node its own copy of the tlist (still necessary?) */
1956- sort_tlist = copyObject (tlist );
1957-
1958- return make_sort (root ,sort_tlist ,lefttree ,numsortkeys ,
1943+ return make_sort (root ,lefttree ,numsortkeys ,
19591944sortColIdx ,sortOperators );
19601945}
19611946
19621947/*
19631948 * make_sort_from_sortclauses
19641949 * Create sort plan to sort according to given sortclauses
19651950 *
1966- * 'tlist' is the targetlist
1967- * 'lefttree' is the node which yields input tuples
19681951 * 'sortcls' is a list of SortClauses
1952+ * 'lefttree' is the node which yields input tuples
19691953 */
19701954Sort *
1971- make_sort_from_sortclauses (Query * root ,List * tlist ,
1972- Plan * lefttree ,List * sortcls )
1955+ make_sort_from_sortclauses (Query * root ,List * sortcls ,Plan * lefttree )
19731956{
1974- List * sort_tlist ;
1957+ List * sub_tlist = lefttree -> targetlist ;
19751958List * i ;
19761959int numsortkeys ;
19771960AttrNumber * sortColIdx ;
@@ -1987,24 +1970,20 @@ make_sort_from_sortclauses(Query *root, List *tlist,
19871970foreach (i ,sortcls )
19881971{
19891972SortClause * sortcl = (SortClause * )lfirst (i );
1990- TargetEntry * tle = get_sortgroupclause_tle (sortcl ,tlist );
1991- Resdom * resdom = tle -> resdom ;
1973+ TargetEntry * tle = get_sortgroupclause_tle (sortcl ,sub_tlist );
19921974
19931975/*
19941976 * Check for the possibility of duplicate order-by clauses --- the
19951977 * parser should have removed 'em, but no point in sorting
19961978 * redundantly.
19971979 */
1998- numsortkeys = add_sort_column (resdom -> resno ,sortcl -> sortop ,
1980+ numsortkeys = add_sort_column (tle -> resdom -> resno ,sortcl -> sortop ,
19991981numsortkeys ,sortColIdx ,sortOperators );
20001982}
20011983
20021984Assert (numsortkeys > 0 );
20031985
2004- /* Give Sort node its own copy of the tlist (still necessary?) */
2005- sort_tlist = copyObject (tlist );
2006-
2007- return make_sort (root ,sort_tlist ,lefttree ,numsortkeys ,
1986+ return make_sort (root ,lefttree ,numsortkeys ,
20081987sortColIdx ,sortOperators );
20091988}
20101989
@@ -2028,7 +2007,6 @@ make_sort_from_groupcols(Query *root,
20282007Plan * lefttree )
20292008{
20302009List * sub_tlist = lefttree -> targetlist ;
2031- List * sort_tlist ;
20322010int grpno = 0 ;
20332011List * i ;
20342012int numsortkeys ;
@@ -2046,35 +2024,31 @@ make_sort_from_groupcols(Query *root,
20462024{
20472025GroupClause * grpcl = (GroupClause * )lfirst (i );
20482026TargetEntry * tle = get_tle_by_resno (sub_tlist ,grpColIdx [grpno ]);
2049- Resdom * resdom = tle -> resdom ;
20502027
20512028/*
20522029 * Check for the possibility of duplicate group-by clauses --- the
20532030 * parser should have removed 'em, but no point in sorting
20542031 * redundantly.
20552032 */
2056- numsortkeys = add_sort_column (resdom -> resno ,grpcl -> sortop ,
2033+ numsortkeys = add_sort_column (tle -> resdom -> resno ,grpcl -> sortop ,
20572034numsortkeys ,sortColIdx ,sortOperators );
20582035grpno ++ ;
20592036}
20602037
20612038Assert (numsortkeys > 0 );
20622039
2063- /* Give Sort node its own copy of the tlist (still necessary?) */
2064- sort_tlist = copyObject (sub_tlist );
2065-
2066- return make_sort (root ,sort_tlist ,lefttree ,numsortkeys ,
2040+ return make_sort (root ,lefttree ,numsortkeys ,
20672041sortColIdx ,sortOperators );
20682042}
20692043
20702044Material *
2071- make_material (List * tlist , Plan * lefttree )
2045+ make_material (Plan * lefttree )
20722046{
20732047Material * node = makeNode (Material );
20742048Plan * plan = & node -> plan ;
20752049
20762050/* cost should be inserted by caller */
2077- plan -> targetlist = tlist ;
2051+ plan -> targetlist = copyObject ( lefttree -> targetlist ) ;
20782052plan -> qual = NIL ;
20792053plan -> lefttree = lefttree ;
20802054plan -> righttree = NULL ;
@@ -2098,7 +2072,7 @@ materialize_finished_plan(Plan *subplan)
20982072Plan * matplan ;
20992073Path matpath ;/* dummy for result of cost_material */
21002074
2101- matplan = (Plan * )make_material (subplan -> targetlist , subplan );
2075+ matplan = (Plan * )make_material (subplan );
21022076
21032077/* Set cost data */
21042078cost_material (& matpath ,
@@ -2239,7 +2213,7 @@ make_group(Query *root,
22392213 * that should be considered by the Unique filter.
22402214 */
22412215Unique *
2242- make_unique (List * tlist , Plan * lefttree ,List * distinctList )
2216+ make_unique (Plan * lefttree ,List * distinctList )
22432217{
22442218Unique * node = makeNode (Unique );
22452219Plan * plan = & node -> plan ;
@@ -2263,7 +2237,7 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList)
22632237 * this if he has a better idea.
22642238 */
22652239
2266- plan -> targetlist = tlist ;
2240+ plan -> targetlist = copyObject ( lefttree -> targetlist ) ;
22672241plan -> qual = NIL ;
22682242plan -> lefttree = lefttree ;
22692243plan -> righttree = NULL ;
@@ -2278,7 +2252,7 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList)
22782252foreach (slitem ,distinctList )
22792253{
22802254SortClause * sortcl = (SortClause * )lfirst (slitem );
2281- TargetEntry * tle = get_sortgroupclause_tle (sortcl ,tlist );
2255+ TargetEntry * tle = get_sortgroupclause_tle (sortcl ,plan -> targetlist );
22822256
22832257uniqColIdx [keyno ++ ]= tle -> resdom -> resno ;
22842258}
@@ -2295,7 +2269,7 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList)
22952269 */
22962270
22972271SetOp *
2298- make_setop (SetOpCmd cmd ,List * tlist , Plan * lefttree ,
2272+ make_setop (SetOpCmd cmd ,Plan * lefttree ,
22992273List * distinctList ,AttrNumber flagColIdx )
23002274{
23012275SetOp * node = makeNode (SetOp );
@@ -2321,7 +2295,7 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
23212295if (plan -> plan_rows < 1 )
23222296plan -> plan_rows = 1 ;
23232297
2324- plan -> targetlist = tlist ;
2298+ plan -> targetlist = copyObject ( lefttree -> targetlist ) ;
23252299plan -> qual = NIL ;
23262300plan -> lefttree = lefttree ;
23272301plan -> righttree = NULL ;
@@ -2336,7 +2310,7 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
23362310foreach (slitem ,distinctList )
23372311{
23382312SortClause * sortcl = (SortClause * )lfirst (slitem );
2339- TargetEntry * tle = get_sortgroupclause_tle (sortcl ,tlist );
2313+ TargetEntry * tle = get_sortgroupclause_tle (sortcl ,plan -> targetlist );
23402314
23412315dupColIdx [keyno ++ ]= tle -> resdom -> resno ;
23422316}
@@ -2350,8 +2324,7 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
23502324}
23512325
23522326Limit *
2353- make_limit (List * tlist ,Plan * lefttree ,
2354- Node * limitOffset ,Node * limitCount )
2327+ make_limit (Plan * lefttree ,Node * limitOffset ,Node * limitCount )
23552328{
23562329Limit * node = makeNode (Limit );
23572330Plan * plan = & node -> plan ;
@@ -2401,7 +2374,7 @@ make_limit(List *tlist, Plan *lefttree,
24012374}
24022375}
24032376
2404- plan -> targetlist = tlist ;
2377+ plan -> targetlist = copyObject ( lefttree -> targetlist ) ;
24052378plan -> qual = NIL ;
24062379plan -> lefttree = lefttree ;
24072380plan -> righttree = NULL ;
@@ -2448,3 +2421,27 @@ make_result(List *tlist,
24482421
24492422return node ;
24502423}
2424+
2425+ /*
2426+ * is_projection_capable_plan
2427+ *Check whether a given Plan node is able to do projection.
2428+ */
2429+ bool
2430+ is_projection_capable_plan (Plan * plan )
2431+ {
2432+ /* Most plan types can project, so just list the ones that can't */
2433+ switch (nodeTag (plan ))
2434+ {
2435+ case T_Hash :
2436+ case T_Material :
2437+ case T_Sort :
2438+ case T_Unique :
2439+ case T_SetOp :
2440+ case T_Limit :
2441+ case T_Append :
2442+ return false;
2443+ default :
2444+ break ;
2445+ }
2446+ return true;
2447+ }