diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 4a8175e0cad3a00bb66edea6360a130fffa93b3a..582747a23f4bb7f996f5a08163e0bfc33d654b41 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * 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) /* transform 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 */ markTargetListOrigins(pstate, qry->targetList); @@ -2137,6 +2129,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) qry->limitCount = transformLimitClause(pstate, stmt->limitCount, "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->jointree = makeFromExpr(pstate->p_joinlist, qual); @@ -2271,6 +2274,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) rtr->rtindex = list_length(pstate->p_rtable); Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable)); pstate->p_joinlist = lappend(pstate->p_joinlist, rtr); + pstate->p_varnamespace = lappend(pstate->p_varnamespace, rte); /* * Generate a targetlist as though expanding "*" @@ -2278,14 +2282,6 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) Assert(pstate->p_next_resno == 1); 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 * to a VALUES, so cope. @@ -2305,6 +2301,17 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 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, * else strange things would happen, like Cartesian products of @@ -2360,7 +2367,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) int leftmostRTI; Query *leftmostQuery; SetOperationStmt *sostmt; - List *intoColNames; + List *intoColNames = NIL; List *sortClause; Node *limitOffset; Node *limitCount; @@ -2391,11 +2398,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) leftmostSelect = leftmostSelect->larg; Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) && leftmostSelect->larg == NULL); - qry->into = leftmostSelect->into; - intoColNames = leftmostSelect->intoColNames; - qry->intoOptions = copyObject(leftmostSelect->intoOptions); - qry->intoOnCommit = leftmostSelect->intoOnCommit; - qry->intoTableSpaceName = leftmostSelect->intoTableSpaceName; + if (leftmostSelect->into) + { + qry->into = leftmostSelect->into; + intoColNames = leftmostSelect->intoColNames; + qry->intoOptions = copyObject(leftmostSelect->intoOptions); + qry->intoOnCommit = leftmostSelect->intoOnCommit; + qry->intoTableSpaceName = leftmostSelect->intoTableSpaceName; + } /* clear this to prevent complaints in transformSetOperationTree() */ leftmostSelect->into = NULL; @@ -2481,19 +2491,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) 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 * using the output columns, generate a varnamespace entry that makes the @@ -2547,6 +2544,19 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) qry->limitCount = transformLimitClause(pstate, limitCount, "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->jointree = makeFromExpr(pstate->p_joinlist, NULL); @@ -2788,19 +2798,32 @@ applyColumnNames(List *dst, List *src) ListCell *dst_item; ListCell *src_item; - if (list_length(src) > list_length(dst)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("CREATE TABLE AS specifies too many column names"))); + src_item = list_head(src); - forboth(dst_item, dst, src_item, src) + foreach(dst_item, dst) { 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); } + + /* 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"))); }