mirror of
https://github.com/postgres/postgres.git
synced 2025-05-17 06:41:24 +03:00
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.
This commit is contained in:
parent
42e386f257
commit
2df2c3dca2
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.290.2.2 2004/11/17 00:18:26 neilc Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.290.2.3 2005/02/19 19:33:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -498,6 +498,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
|||||||
List **extras_before, List **extras_after)
|
List **extras_before, List **extras_after)
|
||||||
{
|
{
|
||||||
Query *qry = makeNode(Query);
|
Query *qry = makeNode(Query);
|
||||||
|
Query *selectQuery = NULL;
|
||||||
|
bool copy_up_hack = false;
|
||||||
List *sub_rtable;
|
List *sub_rtable;
|
||||||
List *sub_namespace;
|
List *sub_namespace;
|
||||||
List *icolumns;
|
List *icolumns;
|
||||||
@ -552,7 +554,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
|||||||
* be able to see.
|
* be able to see.
|
||||||
*/
|
*/
|
||||||
ParseState *sub_pstate = make_parsestate(pstate);
|
ParseState *sub_pstate = make_parsestate(pstate);
|
||||||
Query *selectQuery;
|
|
||||||
RangeTblEntry *rte;
|
RangeTblEntry *rte;
|
||||||
RangeTblRef *rtr;
|
RangeTblRef *rtr;
|
||||||
|
|
||||||
@ -599,7 +600,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
|||||||
Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
|
Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
|
||||||
pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
|
pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
|
||||||
|
|
||||||
/*
|
/*----------
|
||||||
* Generate a targetlist for the INSERT that selects all the
|
* Generate a targetlist for the INSERT that selects all the
|
||||||
* non-resjunk columns from the subquery. (We need this to be
|
* non-resjunk columns from the subquery. (We need this to be
|
||||||
* separate from the subquery's tlist because we may add columns,
|
* separate from the subquery's tlist because we may add columns,
|
||||||
@ -609,8 +610,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
|||||||
* are copied up as-is rather than being referenced as subquery
|
* are copied up as-is rather than being referenced as subquery
|
||||||
* outputs. This is to ensure that when we try to coerce them to
|
* outputs. This is to ensure that when we try to coerce them to
|
||||||
* the target column's datatype, the right things happen (see
|
* the target column's datatype, the right things happen (see
|
||||||
* special cases in coerce_type). Otherwise, this fails: INSERT
|
* special cases in coerce_type). Otherwise, this fails:
|
||||||
* INTO foo SELECT 'bar', ... FROM baz
|
* INSERT INTO foo SELECT 'bar', ... FROM baz
|
||||||
|
*----------
|
||||||
*/
|
*/
|
||||||
qry->targetList = NIL;
|
qry->targetList = NIL;
|
||||||
foreach(tl, selectQuery->targetList)
|
foreach(tl, selectQuery->targetList)
|
||||||
@ -624,7 +626,10 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
|||||||
if (tle->expr &&
|
if (tle->expr &&
|
||||||
(IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
|
(IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
|
||||||
exprType((Node *) tle->expr) == UNKNOWNOID)
|
exprType((Node *) tle->expr) == UNKNOWNOID)
|
||||||
|
{
|
||||||
expr = tle->expr;
|
expr = tle->expr;
|
||||||
|
copy_up_hack = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
expr = (Expr *) makeVar(rtr->rtindex,
|
expr = (Expr *) makeVar(rtr->rtindex,
|
||||||
resnode->resno,
|
resnode->resno,
|
||||||
@ -698,6 +703,28 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
|||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("INSERT has more target columns than expressions")));
|
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 */
|
/* done building the range table and jointree */
|
||||||
qry->rtable = pstate->p_rtable;
|
qry->rtable = pstate->p_rtable;
|
||||||
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
|
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user