Commit 2ad94d38 authored by Tom Lane's avatar Tom Lane

Fix problems with column name list of CREATE TABLE AS being applied to

the input query's target list too soon, causing it to affect processing
of ORDER BY in the input query.
parent e8efd983
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.350 2006/09/18 00:52:14 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.351 2006/09/18 16:04:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2093,14 +2093,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2093,14 +2093,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
/* transform targetlist */ /* transform targetlist */
qry->targetList = transformTargetList(pstate, stmt->targetList); qry->targetList = transformTargetList(pstate, stmt->targetList);
/* handle any SELECT INTO/CREATE TABLE AS spec */
qry->into = stmt->into;
if (stmt->intoColNames)
applyColumnNames(qry->targetList, stmt->intoColNames);
qry->intoOptions = copyObject(stmt->intoOptions);
qry->intoOnCommit = stmt->intoOnCommit;
qry->intoTableSpaceName = stmt->intoTableSpaceName;
/* mark column origins */ /* mark column origins */
markTargetListOrigins(pstate, qry->targetList); markTargetListOrigins(pstate, qry->targetList);
...@@ -2137,6 +2129,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2137,6 +2129,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
qry->limitCount = transformLimitClause(pstate, stmt->limitCount, qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
"LIMIT"); "LIMIT");
/* handle any SELECT INTO/CREATE TABLE AS spec */
if (stmt->into)
{
qry->into = stmt->into;
if (stmt->intoColNames)
applyColumnNames(qry->targetList, stmt->intoColNames);
qry->intoOptions = copyObject(stmt->intoOptions);
qry->intoOnCommit = stmt->intoOnCommit;
qry->intoTableSpaceName = stmt->intoTableSpaceName;
}
qry->rtable = pstate->p_rtable; qry->rtable = pstate->p_rtable;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual); qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
...@@ -2271,6 +2274,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) ...@@ -2271,6 +2274,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
rtr->rtindex = list_length(pstate->p_rtable); rtr->rtindex = list_length(pstate->p_rtable);
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);
pstate->p_varnamespace = lappend(pstate->p_varnamespace, rte);
/* /*
* Generate a targetlist as though expanding "*" * Generate a targetlist as though expanding "*"
...@@ -2278,14 +2282,6 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) ...@@ -2278,14 +2282,6 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
Assert(pstate->p_next_resno == 1); Assert(pstate->p_next_resno == 1);
qry->targetList = expandRelAttrs(pstate, rte, rtr->rtindex, 0); qry->targetList = expandRelAttrs(pstate, rte, rtr->rtindex, 0);
/* handle any CREATE TABLE AS spec */
qry->into = stmt->into;
if (stmt->intoColNames)
applyColumnNames(qry->targetList, stmt->intoColNames);
qry->intoOptions = copyObject(stmt->intoOptions);
qry->intoOnCommit = stmt->intoOnCommit;
qry->intoTableSpaceName = stmt->intoTableSpaceName;
/* /*
* The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE * The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE
* to a VALUES, so cope. * to a VALUES, so cope.
...@@ -2305,6 +2301,17 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) ...@@ -2305,6 +2301,17 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELECT FOR UPDATE/SHARE cannot be applied to VALUES"))); errmsg("SELECT FOR UPDATE/SHARE cannot be applied to VALUES")));
/* handle any CREATE TABLE AS spec */
if (stmt->into)
{
qry->into = stmt->into;
if (stmt->intoColNames)
applyColumnNames(qry->targetList, stmt->intoColNames);
qry->intoOptions = copyObject(stmt->intoOptions);
qry->intoOnCommit = stmt->intoOnCommit;
qry->intoTableSpaceName = stmt->intoTableSpaceName;
}
/* /*
* There mustn't have been any table references in the expressions, * There mustn't have been any table references in the expressions,
* else strange things would happen, like Cartesian products of * else strange things would happen, like Cartesian products of
...@@ -2360,7 +2367,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2360,7 +2367,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
int leftmostRTI; int leftmostRTI;
Query *leftmostQuery; Query *leftmostQuery;
SetOperationStmt *sostmt; SetOperationStmt *sostmt;
List *intoColNames; List *intoColNames = NIL;
List *sortClause; List *sortClause;
Node *limitOffset; Node *limitOffset;
Node *limitCount; Node *limitCount;
...@@ -2391,11 +2398,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2391,11 +2398,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
leftmostSelect = leftmostSelect->larg; leftmostSelect = leftmostSelect->larg;
Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) && Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
leftmostSelect->larg == NULL); leftmostSelect->larg == NULL);
qry->into = leftmostSelect->into; if (leftmostSelect->into)
intoColNames = leftmostSelect->intoColNames; {
qry->intoOptions = copyObject(leftmostSelect->intoOptions); qry->into = leftmostSelect->into;
qry->intoOnCommit = leftmostSelect->intoOnCommit; intoColNames = leftmostSelect->intoColNames;
qry->intoTableSpaceName = leftmostSelect->intoTableSpaceName; qry->intoOptions = copyObject(leftmostSelect->intoOptions);
qry->intoOnCommit = leftmostSelect->intoOnCommit;
qry->intoTableSpaceName = leftmostSelect->intoTableSpaceName;
}
/* clear this to prevent complaints in transformSetOperationTree() */ /* clear this to prevent complaints in transformSetOperationTree() */
leftmostSelect->into = NULL; leftmostSelect->into = NULL;
...@@ -2481,19 +2491,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2481,19 +2491,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
left_tlist = lnext(left_tlist); left_tlist = lnext(left_tlist);
} }
/*
* Handle SELECT INTO/CREATE TABLE AS.
*
* Any column names from CREATE TABLE AS need to be attached to both the
* top level and the leftmost subquery. We do not do this earlier because
* we do *not* want the targetnames list to be affected.
*/
if (intoColNames)
{
applyColumnNames(qry->targetList, intoColNames);
applyColumnNames(leftmostQuery->targetList, intoColNames);
}
/* /*
* As a first step towards supporting sort clauses that are expressions * As a first step towards supporting sort clauses that are expressions
* using the output columns, generate a varnamespace entry that makes the * using the output columns, generate a varnamespace entry that makes the
...@@ -2547,6 +2544,19 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2547,6 +2544,19 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
qry->limitCount = transformLimitClause(pstate, limitCount, qry->limitCount = transformLimitClause(pstate, limitCount,
"LIMIT"); "LIMIT");
/*
* Handle SELECT INTO/CREATE TABLE AS.
*
* Any column names from CREATE TABLE AS need to be attached to both the
* top level and the leftmost subquery. We do not do this earlier because
* we do *not* want sortClause processing to be affected.
*/
if (intoColNames)
{
applyColumnNames(qry->targetList, intoColNames);
applyColumnNames(leftmostQuery->targetList, intoColNames);
}
qry->rtable = pstate->p_rtable; qry->rtable = pstate->p_rtable;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL); qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
...@@ -2788,19 +2798,32 @@ applyColumnNames(List *dst, List *src) ...@@ -2788,19 +2798,32 @@ applyColumnNames(List *dst, List *src)
ListCell *dst_item; ListCell *dst_item;
ListCell *src_item; ListCell *src_item;
if (list_length(src) > list_length(dst)) src_item = list_head(src);
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("CREATE TABLE AS specifies too many column names")));
forboth(dst_item, dst, src_item, src) foreach(dst_item, dst)
{ {
TargetEntry *d = (TargetEntry *) lfirst(dst_item); TargetEntry *d = (TargetEntry *) lfirst(dst_item);
ColumnDef *s = (ColumnDef *) lfirst(src_item); ColumnDef *s;
/* junk targets don't count */
if (d->resjunk)
continue;
/* fewer ColumnDefs than target entries is OK */
if (src_item == NULL)
break;
s = (ColumnDef *) lfirst(src_item);
src_item = lnext(src_item);
Assert(!d->resjunk);
d->resname = pstrdup(s->colname); d->resname = pstrdup(s->colname);
} }
/* more ColumnDefs than target entries is not OK */
if (src_item != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("CREATE TABLE AS specifies too many column names")));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment