Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2ad94d3

Browse files
committed
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.
1 parent e8efd98 commit 2ad94d3

File tree

1 file changed

+66
-43
lines changed

1 file changed

+66
-43
lines changed

src/backend/parser/analyze.c

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.350 2006/09/18 00:52:14 tgl Exp $
9+
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.351 2006/09/18 16:04:04 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -2093,14 +2093,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
20932093
/* transform targetlist */
20942094
qry->targetList = transformTargetList(pstate, stmt->targetList);
20952095

2096-
/* handle any SELECT INTO/CREATE TABLE AS spec */
2097-
qry->into = stmt->into;
2098-
if (stmt->intoColNames)
2099-
applyColumnNames(qry->targetList, stmt->intoColNames);
2100-
qry->intoOptions = copyObject(stmt->intoOptions);
2101-
qry->intoOnCommit = stmt->intoOnCommit;
2102-
qry->intoTableSpaceName = stmt->intoTableSpaceName;
2103-
21042096
/* mark column origins */
21052097
markTargetListOrigins(pstate, qry->targetList);
21062098

@@ -2137,6 +2129,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
21372129
qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
21382130
"LIMIT");
21392131

2132+
/* handle any SELECT INTO/CREATE TABLE AS spec */
2133+
if (stmt->into)
2134+
{
2135+
qry->into = stmt->into;
2136+
if (stmt->intoColNames)
2137+
applyColumnNames(qry->targetList, stmt->intoColNames);
2138+
qry->intoOptions = copyObject(stmt->intoOptions);
2139+
qry->intoOnCommit = stmt->intoOnCommit;
2140+
qry->intoTableSpaceName = stmt->intoTableSpaceName;
2141+
}
2142+
21402143
qry->rtable = pstate->p_rtable;
21412144
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
21422145

@@ -2271,21 +2274,14 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
22712274
rtr->rtindex = list_length(pstate->p_rtable);
22722275
Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
22732276
pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
2277+
pstate->p_varnamespace = lappend(pstate->p_varnamespace, rte);
22742278

22752279
/*
22762280
* Generate a targetlist as though expanding "*"
22772281
*/
22782282
Assert(pstate->p_next_resno == 1);
22792283
qry->targetList = expandRelAttrs(pstate, rte, rtr->rtindex, 0);
22802284

2281-
/* handle any CREATE TABLE AS spec */
2282-
qry->into = stmt->into;
2283-
if (stmt->intoColNames)
2284-
applyColumnNames(qry->targetList, stmt->intoColNames);
2285-
qry->intoOptions = copyObject(stmt->intoOptions);
2286-
qry->intoOnCommit = stmt->intoOnCommit;
2287-
qry->intoTableSpaceName = stmt->intoTableSpaceName;
2288-
22892285
/*
22902286
* The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE
22912287
* to a VALUES, so cope.
@@ -2305,6 +2301,17 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
23052301
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
23062302
errmsg("SELECT FOR UPDATE/SHARE cannot be applied to VALUES")));
23072303

2304+
/* handle any CREATE TABLE AS spec */
2305+
if (stmt->into)
2306+
{
2307+
qry->into = stmt->into;
2308+
if (stmt->intoColNames)
2309+
applyColumnNames(qry->targetList, stmt->intoColNames);
2310+
qry->intoOptions = copyObject(stmt->intoOptions);
2311+
qry->intoOnCommit = stmt->intoOnCommit;
2312+
qry->intoTableSpaceName = stmt->intoTableSpaceName;
2313+
}
2314+
23082315
/*
23092316
* There mustn't have been any table references in the expressions,
23102317
* else strange things would happen, like Cartesian products of
@@ -2360,7 +2367,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
23602367
int leftmostRTI;
23612368
Query *leftmostQuery;
23622369
SetOperationStmt *sostmt;
2363-
List *intoColNames;
2370+
List *intoColNames = NIL;
23642371
List *sortClause;
23652372
Node *limitOffset;
23662373
Node *limitCount;
@@ -2391,11 +2398,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
23912398
leftmostSelect = leftmostSelect->larg;
23922399
Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
23932400
leftmostSelect->larg == NULL);
2394-
qry->into = leftmostSelect->into;
2395-
intoColNames = leftmostSelect->intoColNames;
2396-
qry->intoOptions = copyObject(leftmostSelect->intoOptions);
2397-
qry->intoOnCommit = leftmostSelect->intoOnCommit;
2398-
qry->intoTableSpaceName = leftmostSelect->intoTableSpaceName;
2401+
if (leftmostSelect->into)
2402+
{
2403+
qry->into = leftmostSelect->into;
2404+
intoColNames = leftmostSelect->intoColNames;
2405+
qry->intoOptions = copyObject(leftmostSelect->intoOptions);
2406+
qry->intoOnCommit = leftmostSelect->intoOnCommit;
2407+
qry->intoTableSpaceName = leftmostSelect->intoTableSpaceName;
2408+
}
23992409

24002410
/* clear this to prevent complaints in transformSetOperationTree() */
24012411
leftmostSelect->into = NULL;
@@ -2481,19 +2491,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
24812491
left_tlist = lnext(left_tlist);
24822492
}
24832493

2484-
/*
2485-
* Handle SELECT INTO/CREATE TABLE AS.
2486-
*
2487-
* Any column names from CREATE TABLE AS need to be attached to both the
2488-
* top level and the leftmost subquery. We do not do this earlier because
2489-
* we do *not* want the targetnames list to be affected.
2490-
*/
2491-
if (intoColNames)
2492-
{
2493-
applyColumnNames(qry->targetList, intoColNames);
2494-
applyColumnNames(leftmostQuery->targetList, intoColNames);
2495-
}
2496-
24972494
/*
24982495
* As a first step towards supporting sort clauses that are expressions
24992496
* using the output columns, generate a varnamespace entry that makes the
@@ -2547,6 +2544,19 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
25472544
qry->limitCount = transformLimitClause(pstate, limitCount,
25482545
"LIMIT");
25492546

2547+
/*
2548+
* Handle SELECT INTO/CREATE TABLE AS.
2549+
*
2550+
* Any column names from CREATE TABLE AS need to be attached to both the
2551+
* top level and the leftmost subquery. We do not do this earlier because
2552+
* we do *not* want sortClause processing to be affected.
2553+
*/
2554+
if (intoColNames)
2555+
{
2556+
applyColumnNames(qry->targetList, intoColNames);
2557+
applyColumnNames(leftmostQuery->targetList, intoColNames);
2558+
}
2559+
25502560
qry->rtable = pstate->p_rtable;
25512561
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
25522562

@@ -2788,19 +2798,32 @@ applyColumnNames(List *dst, List *src)
27882798
ListCell *dst_item;
27892799
ListCell *src_item;
27902800

2791-
if (list_length(src) > list_length(dst))
2792-
ereport(ERROR,
2793-
(errcode(ERRCODE_SYNTAX_ERROR),
2794-
errmsg("CREATE TABLE AS specifies too many column names")));
2801+
src_item = list_head(src);
27952802

2796-
forboth(dst_item, dst, src_item, src)
2803+
foreach(dst_item, dst)
27972804
{
27982805
TargetEntry *d = (TargetEntry *) lfirst(dst_item);
2799-
ColumnDef *s = (ColumnDef *) lfirst(src_item);
2806+
ColumnDef *s;
2807+
2808+
/* junk targets don't count */
2809+
if (d->resjunk)
2810+
continue;
2811+
2812+
/* fewer ColumnDefs than target entries is OK */
2813+
if (src_item == NULL)
2814+
break;
2815+
2816+
s = (ColumnDef *) lfirst(src_item);
2817+
src_item = lnext(src_item);
28002818

2801-
Assert(!d->resjunk);
28022819
d->resname = pstrdup(s->colname);
28032820
}
2821+
2822+
/* more ColumnDefs than target entries is not OK */
2823+
if (src_item != NULL)
2824+
ereport(ERROR,
2825+
(errcode(ERRCODE_SYNTAX_ERROR),
2826+
errmsg("CREATE TABLE AS specifies too many column names")));
28042827
}
28052828

28062829

0 commit comments

Comments
 (0)