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/1800:52:14 tgl Exp $
9+ *$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.351 2006/09/1816:04:04 tgl Exp $
1010 *
1111 *-------------------------------------------------------------------------
1212 */
@@ -2093,14 +2093,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
20932093/* transform targetlist */
20942094qry -> 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 */
21052097markTargetListOrigins (pstate ,qry -> targetList );
21062098
@@ -2137,6 +2129,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
21372129qry -> 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+
21402143qry -> rtable = pstate -> p_rtable ;
21412144qry -> jointree = makeFromExpr (pstate -> p_joinlist ,qual );
21422145
@@ -2271,21 +2274,14 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
22712274rtr -> rtindex = list_length (pstate -> p_rtable );
22722275Assert (rte == rt_fetch (rtr -> rtindex ,pstate -> p_rtable ));
22732276pstate -> 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 */
22782282Assert (pstate -> p_next_resno == 1 );
22792283qry -> 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 ),
23062302errmsg ("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)
23602367int leftmostRTI ;
23612368Query * leftmostQuery ;
23622369SetOperationStmt * sostmt ;
2363- List * intoColNames ;
2370+ List * intoColNames = NIL ;
23642371List * sortClause ;
23652372Node * limitOffset ;
23662373Node * limitCount ;
@@ -2391,11 +2398,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
23912398leftmostSelect = leftmostSelect -> larg ;
23922399Assert (leftmostSelect && IsA (leftmostSelect ,SelectStmt )&&
23932400leftmostSelect -> 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() */
24012411leftmostSelect -> into = NULL ;
@@ -2481,19 +2491,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
24812491left_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)
25472544qry -> 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+
25502560qry -> rtable = pstate -> p_rtable ;
25512561qry -> jointree = makeFromExpr (pstate -> p_joinlist ,NULL );
25522562
@@ -2788,19 +2798,32 @@ applyColumnNames(List *dst, List *src)
27882798ListCell * dst_item ;
27892799ListCell * 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{
27982805TargetEntry * 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 );
28022819d -> 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