99 *
1010 *
1111 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.108 2005/05/23 03:01:14 tgl Exp $
12+ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.109 2005/05/30 18:55:49 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
2828#include "optimizer/tlist.h"
2929#include "parser/parsetree.h"
3030#include "parser/parse_expr.h"
31+ #include "parser/parse_relation.h"
3132#include "rewrite/rewriteManip.h"
3233#include "utils/builtins.h"
3334#include "utils/fmgroids.h"
@@ -373,8 +374,9 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
373374 * For now, we don't apply the physical-tlist optimization when there are
374375 * dropped cols.
375376 *
376- * We also support building a "physical" tlist for subqueries, since the
377- * same optimization can occur in SubqueryScan nodes.
377+ * We also support building a "physical" tlist for subqueries and functions,
378+ * since the same optimization can occur in SubqueryScan and FunctionScan
379+ * nodes.
378380 */
379381List *
380382build_physical_tlist (Query * root ,RelOptInfo * rel )
@@ -388,6 +390,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
388390ListCell * l ;
389391int attrno ,
390392numattrs ;
393+ List * colvars ;
391394
392395switch (rte -> rtekind )
393396{
@@ -429,6 +432,10 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
429432{
430433TargetEntry * tle = (TargetEntry * )lfirst (l );
431434
435+ /*
436+ * A resjunk column of the subquery can be reflected as
437+ * resjunk in the physical tlist; we need not punt.
438+ */
432439var = makeVar (varno ,
433440tle -> resno ,
434441exprType ((Node * )tle -> expr ),
@@ -443,6 +450,30 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
443450}
444451break ;
445452
453+ case RTE_FUNCTION :
454+ expandRTE (root -> rtable ,varno ,0 , true/* include dropped */ ,
455+ NULL ,& colvars );
456+ foreach (l ,colvars )
457+ {
458+ var = (Var * )lfirst (l );
459+ /*
460+ * A non-Var in expandRTE's output means a dropped column;
461+ * must punt.
462+ */
463+ if (!IsA (var ,Var ))
464+ {
465+ tlist = NIL ;
466+ break ;
467+ }
468+
469+ tlist = lappend (tlist ,
470+ makeTargetEntry ((Expr * )var ,
471+ var -> varattno ,
472+ NULL ,
473+ false));
474+ }
475+ break ;
476+
446477default :
447478/* caller error */
448479elog (ERROR ,"unsupported RTE kind %d in build_physical_tlist" ,