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
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.630
diff -c -r2.630 gram.y
*** src/backend/parser/gram.y 27 Oct 2008 09:37:47 -0000 2.630
--- src/backend/parser/gram.y 28 Oct 2008 00:46:25 -0000
***************
*** 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
***************
*** 485,491 ****
* 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
--- 485,491 ----
* list and so can never be entered directly. The filter in parser.c
* creates these tokens when required.
*/
! %token NULLS_FIRST NULLS_LAST WITH_TIME
/* Special token types, not actually keywords - see the "lex" file */
%token <str> IDENT FCONST SCONST BCONST XCONST Op
***************
*** 2416,2422 ****
*/
CreateAsStmt:
! CREATE OptTemp TABLE create_as_target AS SelectStmt
{
/*
* When the SelectStmt is a set-operation tree, we must
--- 2416,2422 ----
*/
CreateAsStmt:
! CREATE OptTemp TABLE create_as_target AS SelectStmt opt_with_data
{
/*
* When the SelectStmt is a set-operation tree, we must
***************
*** 2433,2438 ****
--- 2433,2441 ----
scanner_errposition(exprLocation((Node *) n->intoClause))));
$4->rel->istemp = $2;
n->intoClause = $4;
+ /* Implement WITH NO DATA by forcing top-level LIMIT 0 */
+ if (!$7)
+ ((SelectStmt *) $6)->limitCount = makeIntConst(0, -1);
$$ = $6;
}
;
***************
*** 2475,2480 ****
--- 2478,2489 ----
}
;
+ opt_with_data:
+ WITH DATA_P { $$ = TRUE; }
+ | WITH NO DATA_P { $$ = FALSE; }
+ | /*EMPTY*/ { $$ = TRUE; }
+ ;
+
/*****************************************************************************
*
***************
*** 5387,5410 ****
}
;
- /*
- * We use merged tokens here to avoid creating shift/reduce conflicts against
- * a whole lot of other uses of WITH.
- */
opt_check_option:
! WITH_CHECK OPTION
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WITH CHECK OPTION is not implemented")));
}
! | WITH_CASCADED CHECK OPTION
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WITH CHECK OPTION is not implemented")));
}
! | WITH_LOCAL CHECK OPTION
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
--- 5396,5415 ----
}
;
opt_check_option:
! WITH CHECK OPTION
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WITH CHECK OPTION is not implemented")));
}
! | WITH CASCADED CHECK OPTION
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WITH CHECK OPTION is not implemented")));
}
! | WITH LOCAL CHECK OPTION
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
***************
*** 7509,7515 ****
;
opt_timezone:
! WITH TIME ZONE { $$ = TRUE; }
| WITHOUT TIME ZONE { $$ = FALSE; }
| /*EMPTY*/ { $$ = FALSE; }
;
--- 7514,7520 ----
;
opt_timezone:
! WITH_TIME ZONE { $$ = TRUE; }
| WITHOUT TIME ZONE { $$ = FALSE; }
| /*EMPTY*/ { $$ = FALSE; }
;
Index: src/backend/parser/parser.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/parser.c,v
retrieving revision 1.74
diff -c -r1.74 parser.c
*** src/backend/parser/parser.c 29 Aug 2008 13:02:32 -0000 1.74
--- src/backend/parser/parser.c 28 Oct 2008 00:46:25 -0000
***************
*** 129,156 ****
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;
next_token = base_yylex();
switch (next_token)
{
! 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 */
--- 129,143 ----
case WITH:
/*
! * WITH TIME must be reduced to one token
*/
cur_yylval = base_yylval;
cur_yylloc = base_yylloc;
next_token = base_yylex();
switch (next_token)
{
! case TIME:
! cur_token = WITH_TIME;
break;
default:
/* save the lookahead token for next time */
Index: src/interfaces/ecpg/preproc/parser.c
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/ecpg/preproc/parser.c,v
retrieving revision 1.3
diff -c -r1.3 parser.c
*** src/interfaces/ecpg/preproc/parser.c 1 Jan 2008 19:45:59 -0000 1.3
--- src/interfaces/ecpg/preproc/parser.c 28 Oct 2008 00:46:25 -0000
***************
*** 98,125 ****
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;
next_token = base_yylex();
switch (next_token)
{
! 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 */
--- 98,112 ----
case WITH:
/*
! * WITH TIME must be reduced to one token
*/
cur_yylval = base_yylval;
cur_yylloc = base_yylloc;
next_token = base_yylex();
switch (next_token)
{
! case TIME:
! cur_token = WITH_TIME;
break;
default:
/* save the lookahead token for next time */
Index: src/interfaces/ecpg/preproc/preproc.y
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/ecpg/preproc/preproc.y,v
retrieving revision 1.378
diff -c -r1.378 preproc.y
*** src/interfaces/ecpg/preproc/preproc.y 27 Oct 2008 09:37:47 -0000 1.378
--- src/interfaces/ecpg/preproc/preproc.y 28 Oct 2008 00:46:25 -0000
***************
*** 505,511 ****
* 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 SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST
--- 505,511 ----
* list and so can never be entered directly. The filter in parser.c
* creates these tokens when required.
*/
! %token NULLS_FIRST NULLS_LAST WITH_TIME
/* Special token types, not actually keywords - see the "lex" file */
%token <str> IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST
***************
*** 3100,3121 ****
{ $$ = 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:
! WITH_CHECK OPTION
{
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY;
}
! | WITH_CASCADED CHECK OPTION
{
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY;
}
! | WITH_LOCAL CHECK OPTION
{
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY;
--- 3100,3117 ----
{ $$ = cat_str(8, make_str("create or replace"), $4, make_str("view"), $6, $7, make_str("as"), $9, $10);
}
;
opt_check_option:
! WITH CHECK OPTION
{
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY;
}
! | WITH CASCADED CHECK OPTION
{
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY;
}
! | WITH LOCAL CHECK OPTION
{
mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
$$ = EMPTY;
***************
*** 4155,4161 ****
{ $$ = make_str("interval"); }
;
! opt_timezone: WITH TIME ZONE
{ $$ = make_str("with time zone"); }
| WITHOUT TIME ZONE
{ $$ = make_str("without time zone"); }
--- 4151,4157 ----
{ $$ = make_str("interval"); }
;
! opt_timezone: WITH_TIME ZONE
{ $$ = make_str("with time zone"); }
| WITHOUT TIME ZONE
{ $$ = make_str("without time zone"); }