diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 620054380a..6977a6081d 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.159 2001/10/25 05:49:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.160 2001/11/05 05:00:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1835,6 +1835,7 @@ _copySelectStmt(SelectStmt *from) if (from->into) newnode->into = pstrdup(from->into); newnode->istemp = from->istemp; + Node_Copy(from, newnode, intoColNames); Node_Copy(from, newnode, targetList); Node_Copy(from, newnode, fromClause); Node_Copy(from, newnode, whereClause); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 0a48a194df..538a773e31 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.107 2001/10/25 05:49:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.108 2001/11/05 05:00:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -681,6 +681,8 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b) return false; if (a->istemp != b->istemp) return false; + if (!equal(a->intoColNames, b->intoColNames)) + return false; if (!equal(a->targetList, b->targetList)) return false; if (!equal(a->fromClause, b->fromClause)) diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 0d833079e4..40e9700f02 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.209 2001/11/04 03:08:11 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.210 2001/11/05 05:00:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -88,6 +88,7 @@ static void transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt); static Node *transformTypeRefs(ParseState *pstate, Node *stmt); +static void applyColumnNames(List *dst, List *src); static void transformTypeRefsList(ParseState *pstate, List *l); static void transformTypeRef(ParseState *pstate, TypeName *tn); static List *getSetColTypes(ParseState *pstate, Node *node); @@ -1942,9 +1943,13 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) /* process the FROM clause */ transformFromClause(pstate, stmt->fromClause); - /* transform targetlist and WHERE */ + /* transform targetlist */ qry->targetList = transformTargetList(pstate, stmt->targetList); + if (stmt->intoColNames) + applyColumnNames(qry->targetList, stmt->intoColNames); + + /* transform WHERE */ qual = transformWhereClause(pstate, stmt->whereClause); /* @@ -2003,6 +2008,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) SetOperationStmt *sostmt; char *into; bool istemp; + List *intoColNames; char *portalname; bool binary; List *sortClause; @@ -2031,12 +2037,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) leftmostSelect->larg == NULL); into = leftmostSelect->into; istemp = leftmostSelect->istemp; + intoColNames = leftmostSelect->intoColNames; portalname = stmt->portalname; binary = stmt->binary; /* clear them to prevent complaints in transformSetOperationTree() */ leftmostSelect->into = NULL; leftmostSelect->istemp = false; + leftmostSelect->intoColNames = NIL; stmt->portalname = NULL; stmt->binary = false; @@ -2149,6 +2157,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) qry->isBinary = FALSE; } + if (intoColNames) + applyColumnNames(qry->targetList, intoColNames); + /* * As a first step towards supporting sort clauses that are * expressions using the output columns, generate a namespace entry @@ -2377,6 +2388,27 @@ getSetColTypes(ParseState *pstate, Node *node) } } +/* Attach column names from a ColumnDef list to a TargetEntry list */ +static void +applyColumnNames(List *dst, List *src) +{ + if (length(src) > length(dst)) + elog(ERROR,"CREATE TABLE AS specifies too many column names"); + + while (src != NIL && dst != NIL) + { + TargetEntry *d = (TargetEntry *) lfirst(dst); + ColumnDef *s = (ColumnDef *) lfirst(src); + + Assert(d->resdom && !d->resdom->resjunk); + + d->resdom->resname = pstrdup(s->colname); + + dst = lnext(dst); + src = lnext(src); + } +} + /* * transformUpdateStmt - diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c97c9da509..63465c9168 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.271 2001/10/31 04:49:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.272 2001/11/05 05:00:14 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -86,7 +86,6 @@ static Node *makeTypeCast(Node *arg, TypeName *typename); static Node *makeStringConst(char *str, TypeName *typename); static Node *makeFloatConst(char *str); static Node *makeRowExpr(char *opr, List *largs, List *rargs); -static void mapTargetColumns(List *source, List *target); static SelectStmt *findLeftmostSelect(SelectStmt *node); static void insertSelectOptions(SelectStmt *stmt, List *sortClause, List *forUpdate, @@ -1611,11 +1610,10 @@ CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SelectStmt */ SelectStmt *n = findLeftmostSelect((SelectStmt *) $7); if (n->into != NULL) - elog(ERROR,"CREATE TABLE / AS SELECT may not specify INTO"); + elog(ERROR,"CREATE TABLE AS may not specify INTO"); n->istemp = $2; n->into = $4; - if ($5 != NIL) - mapTargetColumns($5, n->targetList); + n->intoColNames = $5; $$ = $7; } ; @@ -3552,6 +3550,7 @@ simple_select: SELECT opt_distinct target_list n->targetList = $3; n->istemp = (bool) ((Value *) lfirst($4))->val.ival; n->into = (char *) lnext($4); + n->intoColNames = NIL; n->fromClause = $5; n->whereClause = $6; n->groupClause = $7; @@ -6106,28 +6105,6 @@ makeRowExpr(char *opr, List *largs, List *rargs) return expr; } -static void -mapTargetColumns(List *src, List *dst) -{ - ColumnDef *s; - ResTarget *d; - - if (length(src) != length(dst)) - elog(ERROR,"CREATE TABLE / AS SELECT has mismatched column count"); - - while ((src != NIL) && (dst != NIL)) - { - s = (ColumnDef *)lfirst(src); - d = (ResTarget *)lfirst(dst); - - d->name = s->colname; - - src = lnext(src); - dst = lnext(dst); - } -} /* mapTargetColumns() */ - - /* findLeftmostSelect() * Find the leftmost component SelectStmt in a set-operation parsetree. */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 1abd7ba365..892177c920 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.149 2001/10/28 06:26:07 momjian Exp $ + * $Id: parsenodes.h,v 1.150 2001/11/05 05:00:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -881,6 +881,7 @@ typedef struct SelectStmt * DISTINCT) */ char *into; /* name of table (for select into table) */ bool istemp; /* into is a temp table? */ + List *intoColNames; /* column names for into table */ List *targetList; /* the target list (of ResTarget) */ List *fromClause; /* the FROM clause */ Node *whereClause; /* WHERE qualification */