66 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
77 * Portions Copyright (c) 1994, Regents of the University of California
88 *
9- *$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.314 2004/12/31 22:00:26 pgsql Exp $
9+ *$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.315 2005/02/19 19:33:08 tgl Exp $
1010 *
1111 *-------------------------------------------------------------------------
1212 */
@@ -506,6 +506,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
506506List * * extras_before ,List * * extras_after )
507507{
508508Query * qry = makeNode (Query );
509+ Query * selectQuery = NULL ;
510+ bool copy_up_hack = false;
509511List * sub_rtable ;
510512List * sub_namespace ;
511513List * icolumns ;
@@ -561,7 +563,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
561563 * be able to see.
562564 */
563565ParseState * sub_pstate = make_parsestate (pstate );
564- Query * selectQuery ;
565566RangeTblEntry * rte ;
566567RangeTblRef * rtr ;
567568
@@ -608,7 +609,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
608609Assert (rte == rt_fetch (rtr -> rtindex ,pstate -> p_rtable ));
609610pstate -> p_joinlist = lappend (pstate -> p_joinlist ,rtr );
610611
611- /*
612+ /*----------
612613 * Generate a targetlist for the INSERT that selects all the
613614 * non-resjunk columns from the subquery. (We need this to be
614615 * separate from the subquery's tlist because we may add columns,
@@ -618,8 +619,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
618619 * are copied up as-is rather than being referenced as subquery
619620 * outputs. This is to ensure that when we try to coerce them to
620621 * the target column's datatype, the right things happen (see
621- * special cases in coerce_type). Otherwise, this fails: INSERT
622- * INTO foo SELECT 'bar', ... FROM baz
622+ * special cases in coerce_type). Otherwise, this fails:
623+ *INSERT INTO foo SELECT 'bar', ... FROM baz
624+ *----------
623625 */
624626qry -> targetList = NIL ;
625627foreach (tl ,selectQuery -> targetList )
@@ -631,9 +633,12 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
631633if (resnode -> resjunk )
632634continue ;
633635if (tle -> expr &&
634- (IsA (tle -> expr ,Const )|| IsA (tle -> expr ,Param ))&&
636+ (IsA (tle -> expr ,Const )|| IsA (tle -> expr ,Param ))&&
635637exprType ((Node * )tle -> expr )== UNKNOWNOID )
638+ {
636639expr = tle -> expr ;
640+ copy_up_hack = true;
641+ }
637642else
638643expr = (Expr * )makeVar (rtr -> rtindex ,
639644resnode -> resno ,
@@ -703,6 +708,28 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
703708(errcode (ERRCODE_SYNTAX_ERROR ),
704709errmsg ("INSERT has more target columns than expressions" )));
705710
711+ /*
712+ * If we copied up any unknown Params (see HACK above) then their
713+ * resolved types need to be propagated into the Resdom nodes of
714+ * the sub-INSERT's tlist. One hack begets another :-(
715+ */
716+ if (copy_up_hack )
717+ {
718+ foreach (tl ,selectQuery -> targetList )
719+ {
720+ TargetEntry * tle = (TargetEntry * )lfirst (tl );
721+ Resdom * resnode = tle -> resdom ;
722+
723+ if (resnode -> resjunk )
724+ continue ;
725+ if (resnode -> restype == UNKNOWNOID )
726+ {
727+ resnode -> restype = exprType ((Node * )tle -> expr );
728+ resnode -> restypmod = exprTypmod ((Node * )tle -> expr );
729+ }
730+ }
731+ }
732+
706733/* done building the range table and jointree */
707734qry -> rtable = pstate -> p_rtable ;
708735qry -> jointree = makeFromExpr (pstate -> p_joinlist ,NULL );