@@ -52,9 +52,9 @@ static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
5252static Query * transformValuesClause (ParseState * pstate ,SelectStmt * stmt );
5353static Query * transformSetOperationStmt (ParseState * pstate ,SelectStmt * stmt );
5454static Node * transformSetOperationTree (ParseState * pstate ,SelectStmt * stmt ,
55- bool isTopLevel ,List * * colInfo );
55+ bool isTopLevel ,List * * targetlist );
5656static void determineRecursiveColTypes (ParseState * pstate ,
57- Node * larg ,List * lcolinfo );
57+ Node * larg ,List * nrtargetlist );
5858static void applyColumnNames (List * dst ,List * src );
5959static Query * transformUpdateStmt (ParseState * pstate ,UpdateStmt * stmt );
6060static List * transformReturningList (ParseState * pstate ,List * returningList );
@@ -1197,7 +1197,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
11971197int leftmostRTI ;
11981198Query * leftmostQuery ;
11991199SetOperationStmt * sostmt ;
1200- List * socolinfo ;
12011200List * intoColNames = NIL ;
12021201List * sortClause ;
12031202Node * limitOffset ;
@@ -1271,7 +1270,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
12711270 */
12721271sostmt = (SetOperationStmt * )transformSetOperationTree (pstate ,stmt ,
12731272true,
1274- & socolinfo );
1273+ NULL );
12751274Assert (sostmt && IsA (sostmt ,SetOperationStmt ));
12761275qry -> setOperations = (Node * )sostmt ;
12771276
@@ -1425,16 +1424,19 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
14251424 * transformSetOperationTree
14261425 *Recursively transform leaves and internal nodes of a set-op tree
14271426 *
1428- * In addition to returning the transformed node, we return a list of
1429- * expression nodes showing the type, typmod, collation, and location (for error messages)
1430- * of each output column of the set-op node. This is used only during the
1431- * internal recursion of this function. At the upper levels we use
1432- * SetToDefault nodes for this purpose, since they carry exactly the fields
1433- * needed, but any other expression node type would do as well.
1427+ * In addition to returning the transformed node, if targetlist isn't NULL
1428+ * then we return a list of its non-resjunk TargetEntry nodes. For a leaf
1429+ * set-op node these are the actual targetlist entries; otherwise they are
1430+ * dummy entries created to carry the type, typmod, collation, and location
1431+ * (for error messages) of each output column of the set-op node. This info
1432+ * is needed only during the internal recursion of this function, so outside
1433+ * callers pass NULL for targetlist. Note: the reason for passing the
1434+ * actual targetlist entries of a leaf node is so that upper levels can
1435+ * replace UNKNOWN Consts with properly-coerced constants.
14341436 */
14351437static Node *
14361438transformSetOperationTree (ParseState * pstate ,SelectStmt * stmt ,
1437- bool isTopLevel ,List * * colInfo )
1439+ bool isTopLevel ,List * * targetlist )
14381440{
14391441bool isLeaf ;
14401442
@@ -1512,15 +1514,18 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
15121514}
15131515
15141516/*
1515- * Extract a list of theresult expressions for upper-levelchecking .
1517+ * Extract a list of thenon-junk TLEs for upper-levelprocessing .
15161518 */
1517- * colInfo = NIL ;
1518- foreach (tl ,selectQuery -> targetList )
1519+ if (targetlist )
15191520{
1520- TargetEntry * tle = (TargetEntry * )lfirst (tl );
1521+ * targetlist = NIL ;
1522+ foreach (tl ,selectQuery -> targetList )
1523+ {
1524+ TargetEntry * tle = (TargetEntry * )lfirst (tl );
15211525
1522- if (!tle -> resjunk )
1523- * colInfo = lappend (* colInfo ,tle -> expr );
1526+ if (!tle -> resjunk )
1527+ * targetlist = lappend (* targetlist ,tle );
1528+ }
15241529}
15251530
15261531/*
@@ -1546,10 +1551,10 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
15461551{
15471552/* Process an internal node (set operation node) */
15481553SetOperationStmt * op = makeNode (SetOperationStmt );
1549- List * lcolinfo ;
1550- List * rcolinfo ;
1551- ListCell * lci ;
1552- ListCell * rci ;
1554+ List * ltargetlist ;
1555+ List * rtargetlist ;
1556+ ListCell * ltl ;
1557+ ListCell * rtl ;
15531558const char * context ;
15541559
15551560context = (stmt -> op == SETOP_UNION ?"UNION" :
@@ -1564,7 +1569,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
15641569 */
15651570op -> larg = transformSetOperationTree (pstate ,stmt -> larg ,
15661571 false,
1567- & lcolinfo );
1572+ & ltargetlist );
15681573
15691574/*
15701575 * If we are processing a recursive union query, now is the time to
@@ -1575,42 +1580,45 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
15751580if (isTopLevel &&
15761581pstate -> p_parent_cte &&
15771582pstate -> p_parent_cte -> cterecursive )
1578- determineRecursiveColTypes (pstate ,op -> larg ,lcolinfo );
1583+ determineRecursiveColTypes (pstate ,op -> larg ,ltargetlist );
15791584
15801585/*
15811586 * Recursively transform the right child node.
15821587 */
15831588op -> rarg = transformSetOperationTree (pstate ,stmt -> rarg ,
15841589 false,
1585- & rcolinfo );
1590+ & rtargetlist );
15861591
15871592/*
15881593 * Verify that the two children have the same number of non-junk
15891594 * columns, and determine the types of the merged output columns.
15901595 */
1591- if (list_length (lcolinfo )!= list_length (rcolinfo ))
1596+ if (list_length (ltargetlist )!= list_length (rtargetlist ))
15921597ereport (ERROR ,
15931598(errcode (ERRCODE_SYNTAX_ERROR ),
15941599errmsg ("each %s query must have the same number of columns" ,
15951600context ),
15961601parser_errposition (pstate ,
1597- exprLocation ((Node * )rcolinfo ))));
1602+ exprLocation ((Node * )rtargetlist ))));
15981603
1599- * colInfo = NIL ;
1604+ if (targetlist )
1605+ * targetlist = NIL ;
16001606op -> colTypes = NIL ;
16011607op -> colTypmods = NIL ;
16021608op -> colCollations = NIL ;
16031609op -> groupClauses = NIL ;
1604- forboth (lci , lcolinfo , rci , rcolinfo )
1610+ forboth (ltl , ltargetlist , rtl , rtargetlist )
16051611{
1606- Node * lcolnode = (Node * )lfirst (lci );
1607- Node * rcolnode = (Node * )lfirst (rci );
1612+ TargetEntry * ltle = (TargetEntry * )lfirst (ltl );
1613+ TargetEntry * rtle = (TargetEntry * )lfirst (rtl );
1614+ Node * lcolnode = (Node * )ltle -> expr ;
1615+ Node * rcolnode = (Node * )rtle -> expr ;
16081616Oid lcoltype = exprType (lcolnode );
16091617Oid rcoltype = exprType (rcolnode );
16101618int32 lcoltypmod = exprTypmod (lcolnode );
16111619int32 rcoltypmod = exprTypmod (rcolnode );
16121620Node * bestexpr ;
1613- SetToDefault * rescolnode ;
1621+ int bestlocation ;
16141622Oid rescoltype ;
16151623int32 rescoltypmod ;
16161624Oid rescolcoll ;
@@ -1620,6 +1628,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
16201628list_make2 (lcolnode ,rcolnode ),
16211629context ,
16221630& bestexpr );
1631+ bestlocation = exprLocation (bestexpr );
16231632/* if same type and same typmod, use typmod; else default */
16241633if (lcoltype == rcoltype && lcoltypmod == rcoltypmod )
16251634rescoltypmod = lcoltypmod ;
@@ -1637,32 +1646,44 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
16371646 * later anyway, but we want to fail now while we have sufficient
16381647 * context to produce an error cursor position.
16391648 *
1640- * The if-tests might look wrong, but they are correct: we should
1641- * verify if the input is non-UNKNOWN *or* if it is an UNKNOWN
1642- * Const (to verify the literal is valid for the target data type)
1643- * or Param (to possibly resolve the Param's type). We should do
1644- * nothing if the input is say an UNKNOWN Var, which can happen in
1645- * some cases.The planner is sometimes able to fold the Var to a
1649+ * For all non-UNKNOWN-type cases, we verify coercibility but we
1650+ * don't modify the child's expression, for fear of changing the
1651+ * child query's semantics.
1652+ *
1653+ * If a child expression is an UNKNOWN-type Const or Param, we
1654+ * want to replace it with the coerced expression. This can only
1655+ * happen when the child is a leaf set-op node. It's safe to
1656+ * replace the expression because if the child query's semantics
1657+ * depended on the type of this output column, it'd have already
1658+ * coerced the UNKNOWN to something else. We want to do this
1659+ * because (a) we want to verify that a Const is valid for the
1660+ * target type, or resolve the actual type of an UNKNOWN Param,
1661+ * and (b) we want to avoid unnecessary discrepancies between the
1662+ * output type of the child query and the resolved target type.
1663+ * Such a discrepancy would disable optimization in the planner.
1664+ *
1665+ * If it's some other UNKNOWN-type node, eg a Var, we do nothing.
1666+ * The planner is sometimes able to fold an UNKNOWN Var to a
16461667 * constant before it has to coerce the type, so failing now would
16471668 * just break cases that might work.
16481669 */
1649- if (lcoltype != UNKNOWNOID ||
1650- IsA (lcolnode ,Const )|| IsA (lcolnode ,Param ))
1670+ if (lcoltype != UNKNOWNOID )
16511671(void )coerce_to_common_type (pstate ,lcolnode ,
16521672rescoltype ,context );
1653- if (rcoltype != UNKNOWNOID ||
1654- IsA (rcolnode ,Const )|| IsA (rcolnode ,Param ))
1673+ else if (IsA (lcolnode ,Const )|| IsA (lcolnode ,Param ))
1674+ ltle -> expr = (Expr * )
1675+ coerce_to_common_type (pstate ,lcolnode ,
1676+ rescoltype ,context );
1677+
1678+ if (rcoltype != UNKNOWNOID )
16551679(void )coerce_to_common_type (pstate ,rcolnode ,
16561680rescoltype ,context );
1681+ else if (IsA (rcolnode ,Const )|| IsA (rcolnode ,Param ))
1682+ rtle -> expr = (Expr * )
1683+ coerce_to_common_type (pstate ,rcolnode ,
1684+ rescoltype ,context );
16571685
16581686/* emit results */
1659- rescolnode = makeNode (SetToDefault );
1660- rescolnode -> typeId = rescoltype ;
1661- rescolnode -> typeMod = rescoltypmod ;
1662- rescolnode -> collid = rescolcoll ;
1663- rescolnode -> location = exprLocation (bestexpr );
1664- * colInfo = lappend (* colInfo ,rescolnode );
1665-
16661687op -> colTypes = lappend_oid (op -> colTypes ,rescoltype );
16671688op -> colTypmods = lappend_int (op -> colTypmods ,rescoltypmod );
16681689op -> colCollations = lappend_oid (op -> colCollations ,rescolcoll );
@@ -1681,7 +1702,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
16811702ParseCallbackState pcbstate ;
16821703
16831704setup_parser_errposition_callback (& pcbstate ,pstate ,
1684- rescolnode -> location );
1705+ bestlocation );
16851706
16861707/* determine the eqop and optional sortop */
16871708get_sort_group_operators (rescoltype ,
@@ -1700,6 +1721,27 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
17001721
17011722op -> groupClauses = lappend (op -> groupClauses ,grpcl );
17021723}
1724+
1725+ /*
1726+ * Construct a dummy tlist entry to return. We use a SetToDefault
1727+ * node for the expression, since it carries exactly the fields
1728+ * needed, but any other expression node type would do as well.
1729+ */
1730+ if (targetlist )
1731+ {
1732+ SetToDefault * rescolnode = makeNode (SetToDefault );
1733+ TargetEntry * restle ;
1734+
1735+ rescolnode -> typeId = rescoltype ;
1736+ rescolnode -> typeMod = rescoltypmod ;
1737+ rescolnode -> collid = rescolcoll ;
1738+ rescolnode -> location = bestlocation ;
1739+ restle = makeTargetEntry ((Expr * )rescolnode ,
1740+ 0 ,/* no need to set resno */
1741+ NULL ,
1742+ false);
1743+ * targetlist = lappend (* targetlist ,restle );
1744+ }
17031745}
17041746
17051747return (Node * )op ;
@@ -1711,14 +1753,14 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
17111753 * to set up the parent CTE's columns
17121754 */
17131755static void
1714- determineRecursiveColTypes (ParseState * pstate ,Node * larg ,List * lcolinfo )
1756+ determineRecursiveColTypes (ParseState * pstate ,Node * larg ,List * nrtargetlist )
17151757{
17161758Node * node ;
17171759int leftmostRTI ;
17181760Query * leftmostQuery ;
17191761List * targetList ;
17201762ListCell * left_tlist ;
1721- ListCell * lci ;
1763+ ListCell * nrtl ;
17221764int next_resno ;
17231765
17241766/*
@@ -1740,16 +1782,16 @@ determineRecursiveColTypes(ParseState *pstate, Node *larg, List *lcolinfo)
17401782left_tlist = list_head (leftmostQuery -> targetList );
17411783next_resno = 1 ;
17421784
1743- foreach (lci , lcolinfo )
1785+ foreach (nrtl , nrtargetlist )
17441786{
1745- Expr * lcolexpr = (Expr * )lfirst (lci );
1787+ TargetEntry * nrtle = (TargetEntry * )lfirst (nrtl );
17461788TargetEntry * lefttle = (TargetEntry * )lfirst (left_tlist );
17471789char * colName ;
17481790TargetEntry * tle ;
17491791
17501792Assert (!lefttle -> resjunk );
17511793colName = pstrdup (lefttle -> resname );
1752- tle = makeTargetEntry (lcolexpr ,
1794+ tle = makeTargetEntry (nrtle -> expr ,
17531795next_resno ++ ,
17541796colName ,
17551797 false);