* 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 $
*
*-------------------------------------------------------------------------
*/
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;
* be able to see.
*/
ParseState *sub_pstate = make_parsestate(pstate);
- Query *selectQuery;
RangeTblEntry *rte;
RangeTblRef *rtr;
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,
* 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)
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,
(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);