Commit 8ecd5351 authored by Peter Eisentraut's avatar Peter Eisentraut

Add WITH [NO] DATA clause to CREATE TABLE AS, per SQL.

Also, since WITH is now a reserved word, simplify the token merging code to
only deal with WITH_TIME.

by Tom Lane and myself
parent 53a5026b
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.37 2007/06/03 17:06:12 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.38 2008/10/28 14:09:44 petere Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -26,6 +26,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name ...@@ -26,6 +26,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable> ] [ TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable> ]
AS <replaceable>query</replaceable> AS <replaceable>query</replaceable>
[ WITH [ NO ] DATA ]
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -201,6 +202,18 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name ...@@ -201,6 +202,18 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>WITH [ NO ] DATA</></term>
<listitem>
<para>
This clause specifies whether or not the data produced by the query
should be copied into the new table. If not, only the table structure
is copied. The default is to copy the data.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>
...@@ -265,7 +278,7 @@ CREATE TEMP TABLE films_recent WITH (OIDS) ON COMMIT DROP AS ...@@ -265,7 +278,7 @@ CREATE TEMP TABLE films_recent WITH (OIDS) ON COMMIT DROP AS
<para> <para>
<command>CREATE TABLE AS</command> conforms to the <acronym>SQL</acronym> <command>CREATE TABLE AS</command> conforms to the <acronym>SQL</acronym>
standard, with the following exceptions: standard. The following are nonstandard extensions:
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem> <listitem>
...@@ -278,12 +291,8 @@ CREATE TEMP TABLE films_recent WITH (OIDS) ON COMMIT DROP AS ...@@ -278,12 +291,8 @@ CREATE TEMP TABLE films_recent WITH (OIDS) ON COMMIT DROP AS
<listitem> <listitem>
<para> <para>
The standard defines a <literal>WITH [ NO ] DATA</literal> clause; In the standard, the <literal>WITH [ NO ] DATA</literal> clause
this is not currently implemented by <productname>PostgreSQL</>. is required; in PostgreSQL it is optional.
The behavior provided by <productname>PostgreSQL</> is equivalent
to the standard's <literal>WITH DATA</literal> case.
<literal>WITH NO DATA</literal> can be simulated by appending
<literal>LIMIT 0</> to the query.
</para> </para>
</listitem> </listitem>
......
...@@ -408,7 +408,7 @@ T141 SIMILAR predicate YES ...@@ -408,7 +408,7 @@ T141 SIMILAR predicate YES
T151 DISTINCT predicate YES T151 DISTINCT predicate YES
T152 DISTINCT predicate with negation YES T152 DISTINCT predicate with negation YES
T171 LIKE clause in table definition YES T171 LIKE clause in table definition YES
T172 AS subquery clause in table definition NO T172 AS subquery clause in table definition YES
T173 Extended LIKE clause in table definition YES T173 Extended LIKE clause in table definition YES
T174 Identity columns NO T174 Identity columns NO
T175 Generated columns NO T175 Generated columns NO
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.630 2008/10/27 09:37:47 petere Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.631 2008/10/28 14:09:45 petere Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -216,7 +216,7 @@ static TypeName *TableFuncTypeName(List *columns); ...@@ -216,7 +216,7 @@ static TypeName *TableFuncTypeName(List *columns);
%type <ival> opt_lock lock_type cast_context %type <ival> opt_lock lock_type cast_context
%type <boolean> opt_force opt_or_replace %type <boolean> opt_force opt_or_replace
opt_grant_grant_option opt_grant_admin_option opt_grant_grant_option opt_grant_admin_option
opt_nowait opt_if_exists opt_nowait opt_if_exists opt_with_data
%type <list> OptRoleList %type <list> OptRoleList
%type <defelt> OptRoleElem %type <defelt> OptRoleElem
...@@ -485,7 +485,7 @@ static TypeName *TableFuncTypeName(List *columns); ...@@ -485,7 +485,7 @@ static TypeName *TableFuncTypeName(List *columns);
* list and so can never be entered directly. The filter in parser.c * list and so can never be entered directly. The filter in parser.c
* creates these tokens when required. * creates these tokens when required.
*/ */
%token NULLS_FIRST NULLS_LAST WITH_CASCADED WITH_LOCAL WITH_CHECK %token NULLS_FIRST NULLS_LAST WITH_TIME
/* Special token types, not actually keywords - see the "lex" file */ /* Special token types, not actually keywords - see the "lex" file */
%token <str> IDENT FCONST SCONST BCONST XCONST Op %token <str> IDENT FCONST SCONST BCONST XCONST Op
...@@ -2416,7 +2416,7 @@ OptConsTableSpace: USING INDEX TABLESPACE name { $$ = $4; } ...@@ -2416,7 +2416,7 @@ OptConsTableSpace: USING INDEX TABLESPACE name { $$ = $4; }
*/ */
CreateAsStmt: CreateAsStmt:
CREATE OptTemp TABLE create_as_target AS SelectStmt CREATE OptTemp TABLE create_as_target AS SelectStmt opt_with_data
{ {
/* /*
* When the SelectStmt is a set-operation tree, we must * When the SelectStmt is a set-operation tree, we must
...@@ -2433,6 +2433,9 @@ CreateAsStmt: ...@@ -2433,6 +2433,9 @@ CreateAsStmt:
scanner_errposition(exprLocation((Node *) n->intoClause)))); scanner_errposition(exprLocation((Node *) n->intoClause))));
$4->rel->istemp = $2; $4->rel->istemp = $2;
n->intoClause = $4; n->intoClause = $4;
/* Implement WITH NO DATA by forcing top-level LIMIT 0 */
if (!$7)
((SelectStmt *) $6)->limitCount = makeIntConst(0, -1);
$$ = $6; $$ = $6;
} }
; ;
...@@ -2475,6 +2478,12 @@ CreateAsElement: ...@@ -2475,6 +2478,12 @@ CreateAsElement:
} }
; ;
opt_with_data:
WITH DATA_P { $$ = TRUE; }
| WITH NO DATA_P { $$ = FALSE; }
| /*EMPTY*/ { $$ = TRUE; }
;
/***************************************************************************** /*****************************************************************************
* *
...@@ -5387,24 +5396,20 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list ...@@ -5387,24 +5396,20 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
} }
; ;
/*
* We use merged tokens here to avoid creating shift/reduce conflicts against
* a whole lot of other uses of WITH.
*/
opt_check_option: opt_check_option:
WITH_CHECK OPTION WITH CHECK OPTION
{ {
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WITH CHECK OPTION is not implemented"))); errmsg("WITH CHECK OPTION is not implemented")));
} }
| WITH_CASCADED CHECK OPTION | WITH CASCADED CHECK OPTION
{ {
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WITH CHECK OPTION is not implemented"))); errmsg("WITH CHECK OPTION is not implemented")));
} }
| WITH_LOCAL CHECK OPTION | WITH LOCAL CHECK OPTION
{ {
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
...@@ -7509,7 +7514,7 @@ ConstInterval: ...@@ -7509,7 +7514,7 @@ ConstInterval:
; ;
opt_timezone: opt_timezone:
WITH TIME ZONE { $$ = TRUE; } WITH_TIME ZONE { $$ = TRUE; }
| WITHOUT TIME ZONE { $$ = FALSE; } | WITHOUT TIME ZONE { $$ = FALSE; }
| /*EMPTY*/ { $$ = FALSE; } | /*EMPTY*/ { $$ = FALSE; }
; ;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.74 2008/08/29 13:02:32 petere Exp $ * $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.75 2008/10/28 14:09:45 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -129,28 +129,15 @@ filtered_base_yylex(void) ...@@ -129,28 +129,15 @@ filtered_base_yylex(void)
case WITH: case WITH:
/* /*
* WITH CASCADED, LOCAL, or CHECK must be reduced to one token * WITH TIME must be reduced to one token
*
* XXX an alternative way is to recognize just WITH_TIME and put
* the ugliness into the datetime datatype productions instead of
* WITH CHECK OPTION. However that requires promoting WITH to a
* fully reserved word. If we ever have to do that anyway
* (perhaps for SQL99 recursive queries), come back and simplify
* this code.
*/ */
cur_yylval = base_yylval; cur_yylval = base_yylval;
cur_yylloc = base_yylloc; cur_yylloc = base_yylloc;
next_token = base_yylex(); next_token = base_yylex();
switch (next_token) switch (next_token)
{ {
case CASCADED: case TIME:
cur_token = WITH_CASCADED; cur_token = WITH_TIME;
break;
case LOCAL:
cur_token = WITH_LOCAL;
break;
case CHECK:
cur_token = WITH_CHECK;
break; break;
default: default:
/* save the lookahead token for next time */ /* save the lookahead token for next time */
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/parser.c,v 1.3 2008/01/01 19:45:59 momjian Exp $ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/parser.c,v 1.4 2008/10/28 14:09:45 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -98,28 +98,15 @@ filtered_base_yylex(void) ...@@ -98,28 +98,15 @@ filtered_base_yylex(void)
case WITH: case WITH:
/* /*
* WITH CASCADED, LOCAL, or CHECK must be reduced to one token * WITH TIME must be reduced to one token
*
* XXX an alternative way is to recognize just WITH_TIME and put
* the ugliness into the datetime datatype productions instead of
* WITH CHECK OPTION. However that requires promoting WITH to a
* fully reserved word. If we ever have to do that anyway
* (perhaps for SQL99 recursive queries), come back and simplify
* this code.
*/ */
cur_yylval = base_yylval; cur_yylval = base_yylval;
cur_yylloc = base_yylloc; cur_yylloc = base_yylloc;
next_token = base_yylex(); next_token = base_yylex();
switch (next_token) switch (next_token)
{ {
case CASCADED: case TIME:
cur_token = WITH_CASCADED; cur_token = WITH_TIME;
break;
case LOCAL:
cur_token = WITH_LOCAL;
break;
case CHECK:
cur_token = WITH_CHECK;
break; break;
default: default:
/* save the lookahead token for next time */ /* save the lookahead token for next time */
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.378 2008/10/27 09:37:47 petere Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.379 2008/10/28 14:09:45 petere Exp $ */
/* Copyright comment */ /* Copyright comment */
%{ %{
...@@ -505,7 +505,7 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu ...@@ -505,7 +505,7 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
* list and so can never be entered directly. The filter in parser.c * list and so can never be entered directly. The filter in parser.c
* creates these tokens when required. * creates these tokens when required.
*/ */
%token NULLS_FIRST NULLS_LAST WITH_CASCADED WITH_LOCAL WITH_CHECK %token NULLS_FIRST NULLS_LAST WITH_TIME
/* Special token types, not actually keywords - see the "lex" file */ /* Special token types, not actually keywords - see the "lex" file */
%token <str> IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST %token <str> IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST
...@@ -3100,22 +3100,18 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list AS SelectStmt opt_ ...@@ -3100,22 +3100,18 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list AS SelectStmt opt_
{ $$ = cat_str(8, make_str("create or replace"), $4, make_str("view"), $6, $7, make_str("as"), $9, $10); } { $$ = cat_str(8, make_str("create or replace"), $4, make_str("view"), $6, $7, make_str("as"), $9, $10); }
; ;
/*
* We use merged tokens here to avoid creating shift/reduce conflicts against
* a whole lot of other uses of WITH.
*/
opt_check_option: opt_check_option:
WITH_CHECK OPTION WITH CHECK OPTION
{ {
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented"); mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY; $$ = EMPTY;
} }
| WITH_CASCADED CHECK OPTION | WITH CASCADED CHECK OPTION
{ {
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented"); mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY; $$ = EMPTY;
} }
| WITH_LOCAL CHECK OPTION | WITH LOCAL CHECK OPTION
{ {
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented"); mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY; $$ = EMPTY;
...@@ -4155,7 +4151,7 @@ ConstInterval: INTERVAL ...@@ -4155,7 +4151,7 @@ ConstInterval: INTERVAL
{ $$ = make_str("interval"); } { $$ = make_str("interval"); }
; ;
opt_timezone: WITH TIME ZONE opt_timezone: WITH_TIME ZONE
{ $$ = make_str("with time zone"); } { $$ = make_str("with time zone"); }
| WITHOUT TIME ZONE | WITHOUT TIME ZONE
{ $$ = make_str("without time zone"); } { $$ = make_str("without time zone"); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment