CREATE TABLE AS WITH NO DATA

Started by Peter Eisentrautabout 17 years ago3 messages
#1Peter Eisentraut
peter_e@gmx.net
1 attachment(s)

Another small piece of parser acrobatics to become standard conforming.

Attachments:

ctas-with-no-data.difftext/plain; name=ctas-with-no-data.diff; x-mac-creator=0; x-mac-type=0Download
? src/backend/parser/gram.output
Index: doc/src/sgml/ref/create_table_as.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/ref/create_table_as.sgml,v
retrieving revision 1.37
diff -u -3 -p -c -r1.37 create_table_as.sgml
*** doc/src/sgml/ref/create_table_as.sgml	3 Jun 2007 17:06:12 -0000	1.37
--- doc/src/sgml/ref/create_table_as.sgml	27 Oct 2008 16:54:29 -0000
*************** CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY 
*** 26,31 ****
--- 26,32 ----
      [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
      [ TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable> ]
      AS <replaceable>query</replaceable>
+     [ WITH [ NO ] DATA ]
  </synopsis>
   </refsynopsisdiv>
    
*************** CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY 
*** 201,206 ****
--- 202,219 ----
       </para>
      </listitem>
     </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>
   </refsect1>
  
*************** CREATE TEMP TABLE films_recent WITH (OID
*** 265,271 ****
  
    <para>
     <command>CREATE TABLE AS</command> conforms to the <acronym>SQL</acronym>
!    standard, with the following exceptions:
  
     <itemizedlist spacing="compact">
      <listitem>
--- 278,284 ----
  
    <para>
     <command>CREATE TABLE AS</command> conforms to the <acronym>SQL</acronym>
!    standard.  The following are nonstandard extensions:
  
     <itemizedlist spacing="compact">
      <listitem>
*************** CREATE TEMP TABLE films_recent WITH (OID
*** 278,289 ****
  
      <listitem>
       <para>
!       The standard defines a <literal>WITH [ NO ] DATA</literal> clause;
!       this is not currently implemented by <productname>PostgreSQL</>.
!       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>
      </listitem>
  
--- 291,298 ----
  
      <listitem>
       <para>
!       In the standard, the <literal>WITH [ NO ] DATA</literal> clause
!       is required; in PostgreSQL it is optional.
       </para>
      </listitem>
  
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.628
diff -u -3 -p -c -r2.628 gram.y
*** src/backend/parser/gram.y	22 Oct 2008 11:00:34 -0000	2.628
--- src/backend/parser/gram.y	27 Oct 2008 16:54:29 -0000
*************** static TypeName *TableFuncTypeName(List 
*** 216,222 ****
  %type <ival>	opt_lock lock_type cast_context
  %type <boolean>	opt_force opt_or_replace
  				opt_grant_grant_option opt_grant_admin_option
! 				opt_nowait opt_if_exists
  
  %type <list>	OptRoleList
  %type <defelt>	OptRoleElem
--- 216,222 ----
  %type <ival>	opt_lock lock_type cast_context
  %type <boolean>	opt_force opt_or_replace
  				opt_grant_grant_option opt_grant_admin_option
! 				opt_nowait opt_if_exists opt_with_data
  
  %type <list>	OptRoleList
  %type <defelt>	OptRoleElem
*************** static TypeName *TableFuncTypeName(List 
*** 484,490 ****
   * list and so can never be entered directly.  The filter in parser.c
   * creates these tokens when required.
   */
! %token			NULLS_FIRST NULLS_LAST WITH_CASCADED WITH_LOCAL WITH_CHECK
  
  /* Special token types, not actually keywords - see the "lex" file */
  %token <str>	IDENT FCONST SCONST BCONST XCONST Op
--- 484,490 ----
   * list and so can never be entered directly.  The filter in parser.c
   * creates these tokens when required.
   */
! %token			NULLS_FIRST NULLS_LAST WITH_CASCADED WITH_CHECK WITH_DATA WITH_LOCAL WITH_NO
  
  /* Special token types, not actually keywords - see the "lex" file */
  %token <str>	IDENT FCONST SCONST BCONST XCONST Op
*************** OptConsTableSpace:   USING INDEX TABLESP
*** 2399,2405 ****
   */
  
  CreateAsStmt:
! 		CREATE OptTemp TABLE create_as_target AS SelectStmt
  				{
  					/*
  					 * When the SelectStmt is a set-operation tree, we must
--- 2399,2405 ----
   */
  
  CreateAsStmt:
! 		CREATE OptTemp TABLE create_as_target AS SelectStmt opt_with_data
  				{
  					/*
  					 * When the SelectStmt is a set-operation tree, we must
*************** CreateAsStmt:
*** 2416,2421 ****
--- 2416,2423 ----
  								 scanner_errposition(exprLocation((Node *) n->intoClause))));
  					$4->rel->istemp = $2;
  					n->intoClause = $4;
+ 					if (!$7)
+ 						((SelectStmt *)$6)->limitCount = makeIntConst(0, -1);
  					$$ = $6;
  				}
  		;
*************** CreateAsElement:
*** 2458,2463 ****
--- 2460,2471 ----
  				}
  		;
  
+ opt_with_data:
+ 			WITH_DATA								{ $$ = TRUE; }
+ 			| WITH_NO DATA_P							{ $$ = FALSE; }
+ 			| /*EMPTY*/								{ $$ = TRUE; }
+ 		;
+ 
  
  /*****************************************************************************
   *
Index: src/backend/parser/parser.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/parser.c,v
retrieving revision 1.74
diff -u -3 -p -c -r1.74 parser.c
*** src/backend/parser/parser.c	29 Aug 2008 13:02:32 -0000	1.74
--- src/backend/parser/parser.c	27 Oct 2008 16:54:29 -0000
*************** filtered_base_yylex(void)
*** 129,142 ****
  		case WITH:
  
  			/*
! 			 * WITH CASCADED, LOCAL, or CHECK 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_yylloc = base_yylloc;
--- 129,141 ----
  		case WITH:
  
  			/*
! 			 * WITH CASCADED, DATA, LOCAL, or CHECK 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,
! 			 * come back and simplify this code.
  			 */
  			cur_yylval = base_yylval;
  			cur_yylloc = base_yylloc;
*************** filtered_base_yylex(void)
*** 146,156 ****
  				case CASCADED:
  					cur_token = WITH_CASCADED;
  					break;
  				case LOCAL:
  					cur_token = WITH_LOCAL;
  					break;
! 				case CHECK:
! 					cur_token = WITH_CHECK;
  					break;
  				default:
  					/* save the lookahead token for next time */
--- 145,161 ----
  				case CASCADED:
  					cur_token = WITH_CASCADED;
  					break;
+ 				case CHECK:
+ 					cur_token = WITH_CHECK;
+ 					break;
+ 				case DATA_P:
+ 					cur_token = WITH_DATA;
+ 					break;
  				case LOCAL:
  					cur_token = WITH_LOCAL;
  					break;
! 				case NO:
! 					cur_token = WITH_NO;
  					break;
  				default:
  					/* save the lookahead token for next time */
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#1)
Re: CREATE TABLE AS WITH NO DATA

Peter Eisentraut <peter_e@gmx.net> writes:

Another small piece of parser acrobatics to become standard conforming.

I think we deliberately decided that we weren't going to implement this
syntax because it required this sort of pushup to provide a uselessly
redundant behavior. Adding more special cases to base_yylex is not
free, either in maintenance or in surprises for users. An example is
that trying to use LOCAL or NO as the name of a CTE will fail if this
patch is applied.

I'd like us to be trying to get rid of the special cases in base_yylex
not add more. (It strikes me that now that WITH is fully reserved,
we might not need some of the ones that are there anymore.)

regards, tom lane

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#2)
Re: CREATE TABLE AS WITH NO DATA

I wrote:

I'd like us to be trying to get rid of the special cases in base_yylex
not add more. (It strikes me that now that WITH is fully reserved,
we might not need some of the ones that are there anymore.)

In fact, it looks like what we should do is heed the existing comment
in parser.c: remove the existing WITH_foo combined tokens and invent
WITH_TIME instead. Then, no additional combined tokens are needed to
handle WITH [NO] DATA. So I propose the attached form of the patch
instead (docs omitted).

regards, tom lane