aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-09-18 16:04:04 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-09-18 16:04:04 +0000
commit2ad94d382c2fa1e1917a46f86c44f95faf110bb2 (patch)
tree288fe9e56f5ceadb7b23702d5fd03d0dc6376343 /src
parente8efd983126604ac25e968608ef099fcf904692d (diff)
downloadpostgresql-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.c109
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")));
}