66 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
77 * Portions Copyright (c) 1994, Regents of the University of California
88 *
9- * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.350 2006/09/18 00:52:14 tgl Exp $
9+ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.351 2006/09/18 16:04:04 tgl Exp $
1010 *
1111 *-------------------------------------------------------------------------
1212 */
@@ -2093,14 +2093,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
20932093 /* transform targetlist */
20942094 qry -> targetList = transformTargetList (pstate , stmt -> targetList );
20952095
2096- /* handle any SELECT INTO/CREATE TABLE AS spec */
2097- qry -> into = stmt -> into ;
2098- if (stmt -> intoColNames )
2099- applyColumnNames (qry -> targetList , stmt -> intoColNames );
2100- qry -> intoOptions = copyObject (stmt -> intoOptions );
2101- qry -> intoOnCommit = stmt -> intoOnCommit ;
2102- qry -> intoTableSpaceName = stmt -> intoTableSpaceName ;
2103-
21042096 /* mark column origins */
21052097 markTargetListOrigins (pstate , qry -> targetList );
21062098
@@ -2137,6 +2129,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
21372129 qry -> limitCount = transformLimitClause (pstate , stmt -> limitCount ,
21382130 "LIMIT" );
21392131
2132+ /* handle any SELECT INTO/CREATE TABLE AS spec */
2133+ if (stmt -> into )
2134+ {
2135+ qry -> into = stmt -> into ;
2136+ if (stmt -> intoColNames )
2137+ applyColumnNames (qry -> targetList , stmt -> intoColNames );
2138+ qry -> intoOptions = copyObject (stmt -> intoOptions );
2139+ qry -> intoOnCommit = stmt -> intoOnCommit ;
2140+ qry -> intoTableSpaceName = stmt -> intoTableSpaceName ;
2141+ }
2142+
21402143 qry -> rtable = pstate -> p_rtable ;
21412144 qry -> jointree = makeFromExpr (pstate -> p_joinlist , qual );
21422145
@@ -2271,21 +2274,14 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
22712274 rtr -> rtindex = list_length (pstate -> p_rtable );
22722275 Assert (rte == rt_fetch (rtr -> rtindex , pstate -> p_rtable ));
22732276 pstate -> p_joinlist = lappend (pstate -> p_joinlist , rtr );
2277+ pstate -> p_varnamespace = lappend (pstate -> p_varnamespace , rte );
22742278
22752279 /*
22762280 * Generate a targetlist as though expanding "*"
22772281 */
22782282 Assert (pstate -> p_next_resno == 1 );
22792283 qry -> targetList = expandRelAttrs (pstate , rte , rtr -> rtindex , 0 );
22802284
2281- /* handle any CREATE TABLE AS spec */
2282- qry -> into = stmt -> into ;
2283- if (stmt -> intoColNames )
2284- applyColumnNames (qry -> targetList , stmt -> intoColNames );
2285- qry -> intoOptions = copyObject (stmt -> intoOptions );
2286- qry -> intoOnCommit = stmt -> intoOnCommit ;
2287- qry -> intoTableSpaceName = stmt -> intoTableSpaceName ;
2288-
22892285 /*
22902286 * The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE
22912287 * to a VALUES, so cope.
@@ -2305,6 +2301,17 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
23052301 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
23062302 errmsg ("SELECT FOR UPDATE/SHARE cannot be applied to VALUES" )));
23072303
2304+ /* handle any CREATE TABLE AS spec */
2305+ if (stmt -> into )
2306+ {
2307+ qry -> into = stmt -> into ;
2308+ if (stmt -> intoColNames )
2309+ applyColumnNames (qry -> targetList , stmt -> intoColNames );
2310+ qry -> intoOptions = copyObject (stmt -> intoOptions );
2311+ qry -> intoOnCommit = stmt -> intoOnCommit ;
2312+ qry -> intoTableSpaceName = stmt -> intoTableSpaceName ;
2313+ }
2314+
23082315 /*
23092316 * There mustn't have been any table references in the expressions,
23102317 * else strange things would happen, like Cartesian products of
@@ -2360,7 +2367,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
23602367 int leftmostRTI ;
23612368 Query * leftmostQuery ;
23622369 SetOperationStmt * sostmt ;
2363- List * intoColNames ;
2370+ List * intoColNames = NIL ;
23642371 List * sortClause ;
23652372 Node * limitOffset ;
23662373 Node * limitCount ;
@@ -2391,11 +2398,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
23912398 leftmostSelect = leftmostSelect -> larg ;
23922399 Assert (leftmostSelect && IsA (leftmostSelect , SelectStmt ) &&
23932400 leftmostSelect -> larg == NULL );
2394- qry -> into = leftmostSelect -> into ;
2395- intoColNames = leftmostSelect -> intoColNames ;
2396- qry -> intoOptions = copyObject (leftmostSelect -> intoOptions );
2397- qry -> intoOnCommit = leftmostSelect -> intoOnCommit ;
2398- qry -> intoTableSpaceName = leftmostSelect -> intoTableSpaceName ;
2401+ if (leftmostSelect -> into )
2402+ {
2403+ qry -> into = leftmostSelect -> into ;
2404+ intoColNames = leftmostSelect -> intoColNames ;
2405+ qry -> intoOptions = copyObject (leftmostSelect -> intoOptions );
2406+ qry -> intoOnCommit = leftmostSelect -> intoOnCommit ;
2407+ qry -> intoTableSpaceName = leftmostSelect -> intoTableSpaceName ;
2408+ }
23992409
24002410 /* clear this to prevent complaints in transformSetOperationTree() */
24012411 leftmostSelect -> into = NULL ;
@@ -2481,19 +2491,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
24812491 left_tlist = lnext (left_tlist );
24822492 }
24832493
2484- /*
2485- * Handle SELECT INTO/CREATE TABLE AS.
2486- *
2487- * Any column names from CREATE TABLE AS need to be attached to both the
2488- * top level and the leftmost subquery. We do not do this earlier because
2489- * we do *not* want the targetnames list to be affected.
2490- */
2491- if (intoColNames )
2492- {
2493- applyColumnNames (qry -> targetList , intoColNames );
2494- applyColumnNames (leftmostQuery -> targetList , intoColNames );
2495- }
2496-
24972494 /*
24982495 * As a first step towards supporting sort clauses that are expressions
24992496 * using the output columns, generate a varnamespace entry that makes the
@@ -2547,6 +2544,19 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
25472544 qry -> limitCount = transformLimitClause (pstate , limitCount ,
25482545 "LIMIT" );
25492546
2547+ /*
2548+ * Handle SELECT INTO/CREATE TABLE AS.
2549+ *
2550+ * Any column names from CREATE TABLE AS need to be attached to both the
2551+ * top level and the leftmost subquery. We do not do this earlier because
2552+ * we do *not* want sortClause processing to be affected.
2553+ */
2554+ if (intoColNames )
2555+ {
2556+ applyColumnNames (qry -> targetList , intoColNames );
2557+ applyColumnNames (leftmostQuery -> targetList , intoColNames );
2558+ }
2559+
25502560 qry -> rtable = pstate -> p_rtable ;
25512561 qry -> jointree = makeFromExpr (pstate -> p_joinlist , NULL );
25522562
@@ -2788,19 +2798,32 @@ applyColumnNames(List *dst, List *src)
27882798 ListCell * dst_item ;
27892799 ListCell * src_item ;
27902800
2791- if (list_length (src ) > list_length (dst ))
2792- ereport (ERROR ,
2793- (errcode (ERRCODE_SYNTAX_ERROR ),
2794- errmsg ("CREATE TABLE AS specifies too many column names" )));
2801+ src_item = list_head (src );
27952802
2796- forboth (dst_item , dst , src_item , src )
2803+ foreach (dst_item , dst )
27972804 {
27982805 TargetEntry * d = (TargetEntry * ) lfirst (dst_item );
2799- ColumnDef * s = (ColumnDef * ) lfirst (src_item );
2806+ ColumnDef * s ;
2807+
2808+ /* junk targets don't count */
2809+ if (d -> resjunk )
2810+ continue ;
2811+
2812+ /* fewer ColumnDefs than target entries is OK */
2813+ if (src_item == NULL )
2814+ break ;
2815+
2816+ s = (ColumnDef * ) lfirst (src_item );
2817+ src_item = lnext (src_item );
28002818
2801- Assert (!d -> resjunk );
28022819 d -> resname = pstrdup (s -> colname );
28032820 }
2821+
2822+ /* more ColumnDefs than target entries is not OK */
2823+ if (src_item != NULL )
2824+ ereport (ERROR ,
2825+ (errcode (ERRCODE_SYNTAX_ERROR ),
2826+ errmsg ("CREATE TABLE AS specifies too many column names" )));
28042827}
28052828
28062829
0 commit comments