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)
388390 ListCell * l ;
389391 int attrno ,
390392 numattrs ;
393+ List * colvars ;
391394
392395 switch (rte -> rtekind )
393396 {
@@ -429,6 +432,10 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
429432 {
430433 TargetEntry * 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+ */
432439 var = makeVar (varno ,
433440 tle -> resno ,
434441 exprType ((Node * ) tle -> expr ),
@@ -443,6 +450,30 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
443450 }
444451 break ;
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+
446477 default :
447478 /* caller error */
448479 elog (ERROR , "unsupported RTE kind %d in build_physical_tlist" ,
0 commit comments