diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index c2c0ef4408dcd2e0d5f04e8acdd9785608474cd9..cc27b0b7bad1d9a4441af4505ee94701645a2acf 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.314 2004/12/31 22:00:26 pgsql Exp $
+ *	$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.315 2005/02/19 19:33:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -506,6 +506,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
 					List **extras_before, List **extras_after)
 {
 	Query	   *qry = makeNode(Query);
+	Query	   *selectQuery = NULL;
+	bool		copy_up_hack = false;
 	List	   *sub_rtable;
 	List	   *sub_namespace;
 	List	   *icolumns;
@@ -561,7 +563,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
 		 * be able to see.
 		 */
 		ParseState *sub_pstate = make_parsestate(pstate);
-		Query	   *selectQuery;
 		RangeTblEntry *rte;
 		RangeTblRef *rtr;
 
@@ -608,7 +609,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
 		Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
 		pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
 
-		/*
+		/*----------
 		 * Generate a targetlist for the INSERT that selects all the
 		 * non-resjunk columns from the subquery.  (We need this to be
 		 * separate from the subquery's tlist because we may add columns,
@@ -618,8 +619,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
 		 * are copied up as-is rather than being referenced as subquery
 		 * outputs.  This is to ensure that when we try to coerce them to
 		 * the target column's datatype, the right things happen (see
-		 * special cases in coerce_type).  Otherwise, this fails: INSERT
-		 * INTO foo SELECT 'bar', ... FROM baz
+		 * special cases in coerce_type).  Otherwise, this fails:
+		 *		INSERT INTO foo SELECT 'bar', ... FROM baz
+		 *----------
 		 */
 		qry->targetList = NIL;
 		foreach(tl, selectQuery->targetList)
@@ -631,9 +633,12 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
 			if (resnode->resjunk)
 				continue;
 			if (tle->expr &&
-				(IsA(tle->expr, Const) ||IsA(tle->expr, Param)) &&
+				(IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
 				exprType((Node *) tle->expr) == UNKNOWNOID)
+			{
 				expr = tle->expr;
+				copy_up_hack = true;
+			}
 			else
 				expr = (Expr *) makeVar(rtr->rtindex,
 										resnode->resno,
@@ -703,6 +708,28 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
 				(errcode(ERRCODE_SYNTAX_ERROR),
 			 errmsg("INSERT has more target columns than expressions")));
 
+	/*
+	 * If we copied up any unknown Params (see HACK above) then their
+	 * resolved types need to be propagated into the Resdom nodes of
+	 * the sub-INSERT's tlist.  One hack begets another :-(
+	 */
+	if (copy_up_hack)
+	{
+		foreach(tl, selectQuery->targetList)
+		{
+			TargetEntry *tle = (TargetEntry *) lfirst(tl);
+			Resdom	   *resnode = tle->resdom;
+
+			if (resnode->resjunk)
+				continue;
+			if (resnode->restype == UNKNOWNOID)
+			{
+				resnode->restype = exprType((Node *) tle->expr);
+				resnode->restypmod = exprTypmod((Node *) tle->expr);
+			}
+		}
+	}
+
 	/* done building the range table and jointree */
 	qry->rtable = pstate->p_rtable;
 	qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);