]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix problems with column name list of CREATE TABLE AS being applied to
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Sep 2006 16:04:04 +0000 (16:04 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Sep 2006 16:04:04 +0000 (16:04 +0000)
the input query's target list too soon, causing it to affect processing
of ORDER BY in the input query.

src/backend/parser/analyze.c

index 4a8175e0cad3a00bb66edea6360a130fffa93b3a..582747a23f4bb7f996f5a08163e0bfc33d654b41 100644 (file)
@@ -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")));
 }