Skip to content
Snippets Groups Projects
Commit 9650d6c7 authored by Tom Lane's avatar Tom Lane
Browse files

Ensure that the resolved datatype of any unknown Param is propagated

into the sub-SELECT targetlist when it appears in the context
INSERT INTO foo SELECT $1 ...  Per report from Abhijit Menon-Sen.
parent 2abe40aa
No related branches found
No related tags found
No related merge requests found
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment