From 014be15047e28388bc221c88933ae32800ba1097 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 11 Jul 2009 04:09:33 +0000
Subject: [PATCH] Fix set_rel_width() to do something reasonable with non-Var
 items in a RelOptInfo targetlist.  It used to be that the only possibility
 other than a Var was a RowExpr representing a whole-row child Var, but as of
 8.4's expanded ability to flatten appendrel members, we can get arbitrary
 expressions in there.  Use the expression's type info and get_typavgwidth()
 to produce an at-least-marginally-sane result.  Note that get_typavgwidth()'s
 fallback estimate (32 bytes) is the same as what was here before, so there
 will be no behavioral change for RowExprs.  Noted while looking at recent
 gripe about constant quals pushed down to FunctionScan appendrel members ...
 not only were we failing to recognize the constant qual, we were getting the
 width estimate wrong :-(

---
 src/backend/optimizer/path/costsize.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 08f1d361bae..1ede488c13b 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -54,7 +54,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.209 2009/06/11 14:48:58 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.210 2009/07/11 04:09:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2997,8 +2997,16 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
 		}
 		else
 		{
-			/* For now, punt on whole-row child Vars */
-			tuple_width += 32;	/* arbitrary */
+			/*
+			 * We could be looking at an expression pulled up from a subquery,
+			 * or a ROW() representing a whole-row child Var, etc.  Do what
+			 * we can using the expression type information.
+			 */
+			int32		item_width;
+
+			item_width = get_typavgwidth(exprType(node), exprTypmod(node));
+			Assert(item_width > 0);
+			tuple_width += item_width;
 		}
 	}
 	Assert(tuple_width >= 0);
-- 
GitLab