Index: doc/src/sgml/ref/create_table_as.sgml =================================================================== RCS file: /home/neilc/private-cvsroot/pgsql-server/doc/src/sgml/ref/create_table_as.sgml,v retrieving revision 1.23 diff -c -r1.23 create_table_as.sgml *** doc/src/sgml/ref/create_table_as.sgml 24 Aug 2004 00:06:51 -0000 1.23 --- doc/src/sgml/ref/create_table_as.sgml 22 Sep 2004 08:41:44 -0000 *************** *** 21,27 **** CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name [ (column_name [, ...] ) ] [ [ WITH | WITHOUT ] OIDS ] ! AS query --- 21,27 ---- CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name [ (column_name [, ...] ) ] [ [ WITH | WITHOUT ] OIDS ] ! AS query [ WITH [ NO ] DATA ] *************** *** 29,37 **** Description ! CREATE TABLE AS creates a table and fills it ! with data computed by a SELECT command or an ! EXECUTE that runs a prepared SELECT command. The table columns have the names and data types associated with the output columns of the SELECT (except that you can override the column --- 29,37 ---- Description ! CREATE TABLE AS creates a table and optionally ! fills it with data computed by a SELECT command ! or an EXECUTE that runs a prepared SELECT command. The table columns have the names and data types associated with the output columns of the SELECT (except that you can override the column *************** *** 125,130 **** --- 125,145 ---- + + + WITH DATA + WITH NO DATA + + + This optional clause specifies whether the table created by + CREATE TABLE AS should contain any data. If + WITH NO DATA is specified, the schema of the + new table is created, but no rows are inserted into it. If this + clause is not specified, WITH DATA is the + default. + + + *************** *** 166,176 **** Compatibility ! This command is modeled after an Oracle ! feature. There is no command with equivalent functionality in ! the SQL standard. However, a combination of CREATE ! TABLE and INSERT ... SELECT can ! accomplish the same thing with little more effort. --- 181,214 ---- Compatibility ! CREATE TABLE AS is specified by the SQL2003 ! standard. There are some small differences between the definition ! of the command in SQL2003 and its implementation in ! PostgreSQL: ! ! ! ! ! The WITH DATA clause is mandatory in the ! standard, whereas it is optional in PostgreSQL. ! ! ! ! ! ! The standard requires parentheses around the subquery clause; in ! PostgreSQL, these parentheses are ! optional. ! ! ! ! ! ! The standard defines an ON COMMIT clause; ! this is not currently implemented by PostgreSQL. ! ! ! Index: src/backend/parser/gram.y =================================================================== RCS file: /home/neilc/private-cvsroot/pgsql-server/src/backend/parser/gram.y,v retrieving revision 2.475 diff -c -r2.475 gram.y *** src/backend/parser/gram.y 29 Aug 2004 04:12:35 -0000 2.475 --- src/backend/parser/gram.y 22 Sep 2004 08:41:48 -0000 *************** *** 321,327 **** %type constraints_set_list %type constraints_set_mode %type OptTableSpace OptConsTableSpace OptTableSpaceOwner ! /* * If you make any token changes, update the keyword table in --- 321,327 ---- %type constraints_set_list %type constraints_set_mode %type OptTableSpace OptConsTableSpace OptTableSpaceOwner ! %type OptWithData /* * If you make any token changes, update the keyword table in *************** *** 344,350 **** CREATEUSER CROSS CSV CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE ! DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP --- 344,350 ---- CREATEUSER CROSS CSV CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE ! DATA_P DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP *************** *** 415,421 **** * list and so can never be entered directly. The filter in parser.c * creates these tokens when required. */ ! %token UNIONJOIN /* Special token types, not actually keywords - see the "lex" file */ %token IDENT FCONST SCONST BCONST XCONST Op --- 415,421 ---- * list and so can never be entered directly. The filter in parser.c * creates these tokens when required. */ ! %token UNIONJOIN WITH_DATA WITH_NO /* Special token types, not actually keywords - see the "lex" file */ %token IDENT FCONST SCONST BCONST XCONST Op *************** *** 1961,1967 **** */ CreateAsStmt: ! CREATE OptTemp TABLE qualified_name OptCreateAs WithOidsAs SelectStmt { /* * When the SelectStmt is a set-operation tree, we must --- 1961,1967 ---- */ CreateAsStmt: ! CREATE OptTemp TABLE qualified_name OptCreateAs WithOidsAs SelectStmt OptWithData { /* * When the SelectStmt is a set-operation tree, we must *************** *** 1979,1984 **** --- 1979,1998 ---- n->into = $4; n->intoColNames = $5; n->intoHasOids = $6; + /* + * If "WITH NO DATA" was specified, just create + * the table's schema. The kludge we use to + * achieve this is to add a "LIMIT 0" clause to + * the query. + */ + if ($8 == FALSE) + { + SelectStmt *stmt = (SelectStmt *) $7; + if (stmt->limitCount) + pfree(stmt->limitCount); + stmt->limitCount = makeIntConst(0); + } + $$ = $7; } ; *************** *** 1995,2000 **** --- 2009,2025 ---- | AS { $$ = DEFAULT_OIDS; } ; + /* + * In order to avoid shift/reduce conflicts, we need to play some + * games in the lexer (see parser.c) to merge "WITH DATA" and "WITH + * NO" into single tokens. + */ + OptWithData: + WITH_DATA { $$ = TRUE; } + | WITH_NO DATA_P { $$ = FALSE; } + | /* EMPTY */ { $$ = TRUE; } + ; + OptCreateAs: '(' CreateAsList ')' { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } *************** *** 7681,7686 **** --- 7706,7712 ---- | CSV | CURSOR | CYCLE + | DATA_P | DATABASE | DAY_P | DEALLOCATE Index: src/backend/parser/keywords.c =================================================================== RCS file: /home/neilc/private-cvsroot/pgsql-server/src/backend/parser/keywords.c,v retrieving revision 1.153 diff -c -r1.153 keywords.c *** src/backend/parser/keywords.c 29 Aug 2004 04:12:40 -0000 1.153 --- src/backend/parser/keywords.c 22 Sep 2004 08:41:48 -0000 *************** *** 97,102 **** --- 97,103 ---- {"current_user", CURRENT_USER}, {"cursor", CURSOR}, {"cycle", CYCLE}, + {"data", DATA_P}, {"database", DATABASE}, {"day", DAY_P}, {"deallocate", DEALLOCATE}, Index: src/backend/parser/parser.c =================================================================== RCS file: /home/neilc/private-cvsroot/pgsql-server/src/backend/parser/parser.c,v retrieving revision 1.62 diff -c -r1.62 parser.c *** src/backend/parser/parser.c 29 Aug 2004 04:12:42 -0000 1.62 --- src/backend/parser/parser.c 22 Sep 2004 08:41:48 -0000 *************** *** 98,104 **** else have_lookahead = true; break; ! default: break; } --- 98,112 ---- else have_lookahead = true; break; ! case WITH: ! /* Look ahead to see if we are doing WITH DATA or WITH NO DATA */ ! lookahead_token = base_yylex(); ! if(lookahead_token == DATA_P) ! cur_token = WITH_DATA; ! else if(lookahead_token == NO) ! cur_token = WITH_NO; ! else ! have_lookahead = true; default: break; } Index: src/test/regress/expected/select_into.out =================================================================== RCS file: /home/neilc/private-cvsroot/pgsql-server/src/test/regress/expected/select_into.out,v retrieving revision 1.5 diff -c -r1.5 select_into.out *** src/test/regress/expected/select_into.out 4 Jun 2000 17:52:53 -0000 1.5 --- src/test/regress/expected/select_into.out 22 Sep 2004 08:41:49 -0000 *************** *** 11,13 **** --- 11,45 ---- FROM onek2 WHERE onek2.unique1 < 2; DROP TABLE tmp1; + -- + -- CREATE TABLE AS (tested here since it is closely related + -- to SELECT INTO) + -- + CREATE TABLE with_data AS SELECT * FROM onek WITH DATA; + CREATE TABLE with_no_data AS SELECT * FROM onek WITH NO DATA; + SELECT COUNT(*) FROM with_data; + count + ------- + 1000 + (1 row) + + SELECT COUNT(*) FROM with_no_data; + count + ------- + 0 + (1 row) + + DROP TABLE with_data; + DROP TABLE with_no_data; + CREATE TABLE with_no_data AS + SELECT * FROM onek UNION + SELECT * FROM onek2 + ORDER BY 1 LIMIT 100 + WITH NO DATA; + SELECT COUNT(*) FROM with_no_data; + count + ------- + 0 + (1 row) + + DROP TABLE with_no_data; Index: src/test/regress/sql/select_into.sql =================================================================== RCS file: /home/neilc/private-cvsroot/pgsql-server/src/test/regress/sql/select_into.sql,v retrieving revision 1.4 diff -c -r1.4 select_into.sql *** src/test/regress/sql/select_into.sql 4 Jun 2000 17:52:54 -0000 1.4 --- src/test/regress/sql/select_into.sql 22 Sep 2004 08:41:49 -0000 *************** *** 16,18 **** --- 16,39 ---- DROP TABLE tmp1; + -- + -- CREATE TABLE AS (tested here since it is closely related + -- to SELECT INTO) + -- + CREATE TABLE with_data AS SELECT * FROM onek WITH DATA; + CREATE TABLE with_no_data AS SELECT * FROM onek WITH NO DATA; + + SELECT COUNT(*) FROM with_data; + SELECT COUNT(*) FROM with_no_data; + + DROP TABLE with_data; + DROP TABLE with_no_data; + + CREATE TABLE with_no_data AS + SELECT * FROM onek UNION + SELECT * FROM onek2 + ORDER BY 1 LIMIT 100 + WITH NO DATA; + + SELECT COUNT(*) FROM with_no_data; + DROP TABLE with_no_data; \ No newline at end of file