diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-09-18 16:04:04 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-09-18 16:04:04 +0000 |
commit | 2ad94d382c2fa1e1917a46f86c44f95faf110bb2 (patch) | |
tree | 288fe9e56f5ceadb7b23702d5fd03d0dc6376343 /src | |
parent | e8efd983126604ac25e968608ef099fcf904692d (diff) | |
download | postgresql-2ad94d382c2fa1e1917a46f86c44f95faf110bb2.tar.gz postgresql-2ad94d382c2fa1e1917a46f86c44f95faf110bb2.zip |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/parser/analyze.c | 109 |
1 files changed, 66 insertions, 43 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 4a8175e0cad..582747a23f4 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; @@ -2482,19 +2492,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) } /* - * 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 * output columns visible. A Join RTE node is handy for this, since we @@ -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"))); } |