From 4bc9f5e9ba9a214086c7cb2975f7dc36161c6ed4 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue, 14 Aug 2001 17:12:57 +0000
Subject: [PATCH] Fix brokenness of nested EXCEPT/INTERSECT queries.  prepunion
 was being a tad sloppy about generating the targetlist for some nodes, by
 generating a tlist entry that claimed to be a constant when the value wasn't
 actually constant.  This caused setrefs.c to do the wrong thing later on.

---
 src/backend/optimizer/prep/prepunion.c | 44 +++++++++++++++++++-------
 1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 764fe1836c..dbbe004aef 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.65 2001/06/05 05:26:04 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.66 2001/08/14 17:12:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -275,12 +275,14 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
 	 *
 	 * The tlist for an Append plan isn't important as far as the Append is
 	 * concerned, but we must make it look real anyway for the benefit of
-	 * the next plan level up.
+	 * the next plan level up.  In fact, it has to be real enough that the
+	 * flag column is shown as a variable not a constant, else setrefs.c
+	 * will get confused.
 	 */
 	plan = (Plan *)
 		make_append(makeList2(lplan, rplan),
 					false,
-					generate_setop_tlist(op->colTypes, 0, false,
+					generate_setop_tlist(op->colTypes, 2, false,
 										 lplan->targetlist,
 										 refnames_tlist));
 
@@ -353,6 +355,13 @@ recurse_union_children(Node *setOp, Query *parse,
 
 /*
  * Generate targetlist for a set-operation plan node
+ *
+ * colTypes: column datatypes for non-junk columns
+ * flag: -1 if no flag column needed, 0 or 1 to create a const flag column,
+ *       2 to create a variable flag column
+ * hack_constants: true to copy up constants (see comments in code)
+ * input_tlist: targetlist of this node's input node
+ * refnames_tlist: targetlist to take column names from
  */
 static List *
 generate_setop_tlist(List *colTypes, int flag,
@@ -414,19 +423,32 @@ generate_setop_tlist(List *colTypes, int flag,
 
 	if (flag >= 0)
 	{
-		/* Add a resjunk column yielding specified flag value */
+		/* Add a resjunk flag column */
 		resdom = makeResdom((AttrNumber) resno++,
 							INT4OID,
 							-1,
 							pstrdup("flag"),
 							true);
-		expr = (Node *) makeConst(INT4OID,
-								  sizeof(int4),
-								  Int32GetDatum(flag),
-								  false,
-								  true,
-								  false,
-								  false);
+		if (flag <= 1)
+		{
+			/* flag value is the given constant */
+			expr = (Node *) makeConst(INT4OID,
+									  sizeof(int4),
+									  Int32GetDatum(flag),
+									  false,
+									  true,
+									  false,
+									  false);
+		}
+		else
+		{
+			/* flag value is being copied up from subplan */
+			expr = (Node *) makeVar(0,
+									resdom->resno,
+									INT4OID,
+									-1,
+									0);
+		}
 		tlist = lappend(tlist, makeTargetEntry(resdom, expr));
 	}
 
-- 
2.24.1