6
6
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
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 $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
@@ -2093,14 +2093,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
2093
2093
/* transform targetlist */
2094
2094
qry -> targetList = transformTargetList (pstate , stmt -> targetList );
2095
2095
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
-
2104
2096
/* mark column origins */
2105
2097
markTargetListOrigins (pstate , qry -> targetList );
2106
2098
@@ -2137,6 +2129,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
2137
2129
qry -> limitCount = transformLimitClause (pstate , stmt -> limitCount ,
2138
2130
"LIMIT" );
2139
2131
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
+
2140
2143
qry -> rtable = pstate -> p_rtable ;
2141
2144
qry -> jointree = makeFromExpr (pstate -> p_joinlist , qual );
2142
2145
@@ -2271,21 +2274,14 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
2271
2274
rtr -> rtindex = list_length (pstate -> p_rtable );
2272
2275
Assert (rte == rt_fetch (rtr -> rtindex , pstate -> p_rtable ));
2273
2276
pstate -> p_joinlist = lappend (pstate -> p_joinlist , rtr );
2277
+ pstate -> p_varnamespace = lappend (pstate -> p_varnamespace , rte );
2274
2278
2275
2279
/*
2276
2280
* Generate a targetlist as though expanding "*"
2277
2281
*/
2278
2282
Assert (pstate -> p_next_resno == 1 );
2279
2283
qry -> targetList = expandRelAttrs (pstate , rte , rtr -> rtindex , 0 );
2280
2284
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
-
2289
2285
/*
2290
2286
* The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE
2291
2287
* to a VALUES, so cope.
@@ -2305,6 +2301,17 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
2305
2301
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2306
2302
errmsg ("SELECT FOR UPDATE/SHARE cannot be applied to VALUES" )));
2307
2303
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
+
2308
2315
/*
2309
2316
* There mustn't have been any table references in the expressions,
2310
2317
* else strange things would happen, like Cartesian products of
@@ -2360,7 +2367,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
2360
2367
int leftmostRTI ;
2361
2368
Query * leftmostQuery ;
2362
2369
SetOperationStmt * sostmt ;
2363
- List * intoColNames ;
2370
+ List * intoColNames = NIL ;
2364
2371
List * sortClause ;
2365
2372
Node * limitOffset ;
2366
2373
Node * limitCount ;
@@ -2391,11 +2398,14 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
2391
2398
leftmostSelect = leftmostSelect -> larg ;
2392
2399
Assert (leftmostSelect && IsA (leftmostSelect , SelectStmt ) &&
2393
2400
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
+ }
2399
2409
2400
2410
/* clear this to prevent complaints in transformSetOperationTree() */
2401
2411
leftmostSelect -> into = NULL ;
@@ -2481,19 +2491,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
2481
2491
left_tlist = lnext (left_tlist );
2482
2492
}
2483
2493
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
-
2497
2494
/*
2498
2495
* As a first step towards supporting sort clauses that are expressions
2499
2496
* using the output columns, generate a varnamespace entry that makes the
@@ -2547,6 +2544,19 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
2547
2544
qry -> limitCount = transformLimitClause (pstate , limitCount ,
2548
2545
"LIMIT" );
2549
2546
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
+
2550
2560
qry -> rtable = pstate -> p_rtable ;
2551
2561
qry -> jointree = makeFromExpr (pstate -> p_joinlist , NULL );
2552
2562
@@ -2788,19 +2798,32 @@ applyColumnNames(List *dst, List *src)
2788
2798
ListCell * dst_item ;
2789
2799
ListCell * src_item ;
2790
2800
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 );
2795
2802
2796
- forboth (dst_item , dst , src_item , src )
2803
+ foreach (dst_item , dst )
2797
2804
{
2798
2805
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 );
2800
2818
2801
- Assert (!d -> resjunk );
2802
2819
d -> resname = pstrdup (s -> colname );
2803
2820
}
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" )));
2804
2827
}
2805
2828
2806
2829
0 commit comments