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

Commit 5251e7b

Browse files
committed
CREATE TABLE foo (x,y,z) AS SELECT ... can't apply target column names
to the target list in gram.y; it must wait till after expansion of the target list in analyze.c. Per bug report 4-Nov: lx=# CREATE TABLE abc (a char, b char, c char); CREATE lx=# CREATE TABLE xyz (x, y, z) AS SELECT * FROM abc; ERROR: CREATE TABLE/AS SELECT has mismatched column count
1 parent d556920 commit 5251e7b

File tree

5 files changed

+45
-32
lines changed

5 files changed

+45
-32
lines changed

src/backend/nodes/copyfuncs.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.159 2001/10/25 05:49:30 momjian Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.160 2001/11/05 05:00:14 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1835,6 +1835,7 @@ _copySelectStmt(SelectStmt *from)
18351835
if (from->into)
18361836
newnode->into = pstrdup(from->into);
18371837
newnode->istemp = from->istemp;
1838+
Node_Copy(from, newnode, intoColNames);
18381839
Node_Copy(from, newnode, targetList);
18391840
Node_Copy(from, newnode, fromClause);
18401841
Node_Copy(from, newnode, whereClause);

src/backend/nodes/equalfuncs.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* Portions Copyright (c) 1994, Regents of the University of California
2121
*
2222
* IDENTIFICATION
23-
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.107 2001/10/25 05:49:30 momjian Exp $
23+
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.108 2001/11/05 05:00:14 tgl Exp $
2424
*
2525
*-------------------------------------------------------------------------
2626
*/
@@ -681,6 +681,8 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
681681
return false;
682682
if (a->istemp != b->istemp)
683683
return false;
684+
if (!equal(a->intoColNames, b->intoColNames))
685+
return false;
684686
if (!equal(a->targetList, b->targetList))
685687
return false;
686688
if (!equal(a->fromClause, b->fromClause))

src/backend/parser/analyze.c

+34-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.209 2001/11/04 03:08:11 momjian Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.210 2001/11/05 05:00:14 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -88,6 +88,7 @@ static void transformFKConstraints(ParseState *pstate,
8888
CreateStmtContext *cxt);
8989
static Node *transformTypeRefs(ParseState *pstate, Node *stmt);
9090

91+
static void applyColumnNames(List *dst, List *src);
9192
static void transformTypeRefsList(ParseState *pstate, List *l);
9293
static void transformTypeRef(ParseState *pstate, TypeName *tn);
9394
static List *getSetColTypes(ParseState *pstate, Node *node);
@@ -1942,9 +1943,13 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
19421943
/* process the FROM clause */
19431944
transformFromClause(pstate, stmt->fromClause);
19441945

1945-
/* transform targetlist and WHERE */
1946+
/* transform targetlist */
19461947
qry->targetList = transformTargetList(pstate, stmt->targetList);
19471948

1949+
if (stmt->intoColNames)
1950+
applyColumnNames(qry->targetList, stmt->intoColNames);
1951+
1952+
/* transform WHERE */
19481953
qual = transformWhereClause(pstate, stmt->whereClause);
19491954

19501955
/*
@@ -2003,6 +2008,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
20032008
SetOperationStmt *sostmt;
20042009
char *into;
20052010
bool istemp;
2011+
List *intoColNames;
20062012
char *portalname;
20072013
bool binary;
20082014
List *sortClause;
@@ -2031,12 +2037,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
20312037
leftmostSelect->larg == NULL);
20322038
into = leftmostSelect->into;
20332039
istemp = leftmostSelect->istemp;
2040+
intoColNames = leftmostSelect->intoColNames;
20342041
portalname = stmt->portalname;
20352042
binary = stmt->binary;
20362043

20372044
/* clear them to prevent complaints in transformSetOperationTree() */
20382045
leftmostSelect->into = NULL;
20392046
leftmostSelect->istemp = false;
2047+
leftmostSelect->intoColNames = NIL;
20402048
stmt->portalname = NULL;
20412049
stmt->binary = false;
20422050

@@ -2149,6 +2157,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
21492157
qry->isBinary = FALSE;
21502158
}
21512159

2160+
if (intoColNames)
2161+
applyColumnNames(qry->targetList, intoColNames);
2162+
21522163
/*
21532164
* As a first step towards supporting sort clauses that are
21542165
* expressions using the output columns, generate a namespace entry
@@ -2377,6 +2388,27 @@ getSetColTypes(ParseState *pstate, Node *node)
23772388
}
23782389
}
23792390

2391+
/* Attach column names from a ColumnDef list to a TargetEntry list */
2392+
static void
2393+
applyColumnNames(List *dst, List *src)
2394+
{
2395+
if (length(src) > length(dst))
2396+
elog(ERROR,"CREATE TABLE AS specifies too many column names");
2397+
2398+
while (src != NIL && dst != NIL)
2399+
{
2400+
TargetEntry *d = (TargetEntry *) lfirst(dst);
2401+
ColumnDef *s = (ColumnDef *) lfirst(src);
2402+
2403+
Assert(d->resdom && !d->resdom->resjunk);
2404+
2405+
d->resdom->resname = pstrdup(s->colname);
2406+
2407+
dst = lnext(dst);
2408+
src = lnext(src);
2409+
}
2410+
}
2411+
23802412

23812413
/*
23822414
* transformUpdateStmt -

src/backend/parser/gram.y

+4-27
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.271 2001/10/31 04:49:43 momjian Exp $
14+
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.272 2001/11/05 05:00:14 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -86,7 +86,6 @@ static Node *makeTypeCast(Node *arg, TypeName *typename);
8686
static Node *makeStringConst(char *str, TypeName *typename);
8787
static Node *makeFloatConst(char *str);
8888
static Node *makeRowExpr(char *opr, List *largs, List *rargs);
89-
static void mapTargetColumns(List *source, List *target);
9089
static SelectStmt *findLeftmostSelect(SelectStmt *node);
9190
static void insertSelectOptions(SelectStmt *stmt,
9291
List *sortClause, List *forUpdate,
@@ -1611,11 +1610,10 @@ CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SelectStmt
16111610
*/
16121611
SelectStmt *n = findLeftmostSelect((SelectStmt *) $7);
16131612
if (n->into != NULL)
1614-
elog(ERROR,"CREATE TABLE / AS SELECT may not specify INTO");
1613+
elog(ERROR,"CREATE TABLE AS may not specify INTO");
16151614
n->istemp = $2;
16161615
n->into = $4;
1617-
if ($5 != NIL)
1618-
mapTargetColumns($5, n->targetList);
1616+
n->intoColNames = $5;
16191617
$$ = $7;
16201618
}
16211619
;
@@ -3552,6 +3550,7 @@ simple_select: SELECT opt_distinct target_list
35523550
n->targetList = $3;
35533551
n->istemp = (bool) ((Value *) lfirst($4))->val.ival;
35543552
n->into = (char *) lnext($4);
3553+
n->intoColNames = NIL;
35553554
n->fromClause = $5;
35563555
n->whereClause = $6;
35573556
n->groupClause = $7;
@@ -6106,28 +6105,6 @@ makeRowExpr(char *opr, List *largs, List *rargs)
61066105
return expr;
61076106
}
61086107

6109-
static void
6110-
mapTargetColumns(List *src, List *dst)
6111-
{
6112-
ColumnDef *s;
6113-
ResTarget *d;
6114-
6115-
if (length(src) != length(dst))
6116-
elog(ERROR,"CREATE TABLE / AS SELECT has mismatched column count");
6117-
6118-
while ((src != NIL) && (dst != NIL))
6119-
{
6120-
s = (ColumnDef *)lfirst(src);
6121-
d = (ResTarget *)lfirst(dst);
6122-
6123-
d->name = s->colname;
6124-
6125-
src = lnext(src);
6126-
dst = lnext(dst);
6127-
}
6128-
} /* mapTargetColumns() */
6129-
6130-
61316108
/* findLeftmostSelect()
61326109
* Find the leftmost component SelectStmt in a set-operation parsetree.
61336110
*/

src/include/nodes/parsenodes.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: parsenodes.h,v 1.149 2001/10/28 06:26:07 momjian Exp $
10+
* $Id: parsenodes.h,v 1.150 2001/11/05 05:00:14 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -881,6 +881,7 @@ typedef struct SelectStmt
881881
* DISTINCT) */
882882
char *into; /* name of table (for select into table) */
883883
bool istemp; /* into is a temp table? */
884+
List *intoColNames; /* column names for into table */
884885
List *targetList; /* the target list (of ResTarget) */
885886
List *fromClause; /* the FROM clause */
886887
Node *whereClause; /* WHERE qualification */

0 commit comments

Comments
 (0)