From ac25dbd84bbcc288fc93f4053b6df4b848cf5bc6 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 30 May 2005 18:55:49 +0000
Subject: [PATCH] Add support for FUNCTION RTEs to build_physical_tlist(), so
 that the physical-tlist optimization can be applied to FunctionScan nodes as
 well as regular tables and SubqueryScans.

---
 src/backend/optimizer/plan/createplan.c | 14 ++++++----
 src/backend/optimizer/util/plancat.c    | 37 +++++++++++++++++++++++--
 2 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 930355b5204..b743c8348ed 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.189 2005/05/22 22:30:19 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.190 2005/05/30 18:55:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -308,13 +308,17 @@ use_physical_tlist(RelOptInfo *rel)
 	int			i;
 
 	/*
-	 * OK for subquery scans, but not function scans.  (This is mainly
-	 * because build_physical_tlist doesn't support them; worth adding?)
+	 * OK for subquery and function scans; otherwise, can't do it for
+	 * anything except real relations.
 	 */
-	if (rel->rtekind == RTE_SUBQUERY)
-		return true;
 	if (rel->rtekind != RTE_RELATION)
+	{
+		if (rel->rtekind == RTE_SUBQUERY)
+			return true;
+		if (rel->rtekind == RTE_FUNCTION)
+			return true;
 		return false;
+	}
 
 	/*
 	 * Can't do it with inheritance cases either (mainly because Append
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 3520ac96077..35277073569 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.108 2005/05/23 03:01:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.109 2005/05/30 18:55:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,7 @@
 #include "optimizer/tlist.h"
 #include "parser/parsetree.h"
 #include "parser/parse_expr.h"
+#include "parser/parse_relation.h"
 #include "rewrite/rewriteManip.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
@@ -373,8 +374,9 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
  * For now, we don't apply the physical-tlist optimization when there are
  * dropped cols.
  *
- * We also support building a "physical" tlist for subqueries, since the
- * same optimization can occur in SubqueryScan nodes.
+ * We also support building a "physical" tlist for subqueries and functions,
+ * since the same optimization can occur in SubqueryScan and FunctionScan
+ * nodes.
  */
 List *
 build_physical_tlist(Query *root, RelOptInfo *rel)
@@ -388,6 +390,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
 	ListCell   *l;
 	int			attrno,
 				numattrs;
+	List	   *colvars;
 
 	switch (rte->rtekind)
 	{
@@ -429,6 +432,10 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
 			{
 				TargetEntry *tle = (TargetEntry *) lfirst(l);
 
+				/*
+				 * A resjunk column of the subquery can be reflected as
+				 * resjunk in the physical tlist; we need not punt.
+				 */
 				var = makeVar(varno,
 							  tle->resno,
 							  exprType((Node *) tle->expr),
@@ -443,6 +450,30 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
 			}
 			break;
 
+		case RTE_FUNCTION:
+			expandRTE(root->rtable, varno, 0, true /* include dropped */,
+					  NULL, &colvars);
+			foreach(l, colvars)
+			{
+				var = (Var *) lfirst(l);
+				/*
+				 * A non-Var in expandRTE's output means a dropped column;
+				 * must punt.
+				 */
+				if (!IsA(var, Var))
+				{
+					tlist = NIL;
+					break;
+				}
+
+				tlist = lappend(tlist,
+								makeTargetEntry((Expr *) var,
+												var->varattno,
+												NULL,
+												false));
+			}
+			break;
+
 		default:
 			/* caller error */
 			elog(ERROR, "unsupported RTE kind %d in build_physical_tlist",
-- 
GitLab