Commit 0780ce6a authored by Tom Lane's avatar Tom Lane

Re-introduce the yylex filter function formerly used to support UNION

JOIN, which I removed in a recent fit of over-optimism that we wouldn't
have any future use for it.  Now it's needed to support disambiguating
WITH CHECK OPTION from WITH TIME ZONE.  As proof of concept, add stub
grammar productions for WITH CHECK OPTION.
parent 51b40f03
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# #
# Makefile for parser # Makefile for parser
# #
# $PostgreSQL: pgsql/src/backend/parser/Makefile,v 1.43 2006/03/07 01:00:17 tgl Exp $ # $PostgreSQL: pgsql/src/backend/parser/Makefile,v 1.44 2006/05/27 17:38:45 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -57,7 +57,7 @@ endif ...@@ -57,7 +57,7 @@ endif
# Force these dependencies to be known even without dependency info built: # Force these dependencies to be known even without dependency info built:
gram.o keywords.o: $(srcdir)/parse.h gram.o keywords.o parser.o: $(srcdir)/parse.h
# gram.c, parse.h, and scan.c are in the distribution tarball, so they # gram.c, parse.h, and scan.c are in the distribution tarball, so they
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.544 2006/04/30 18:30:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.545 2006/05/27 17:38:45 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -70,6 +70,12 @@ ...@@ -70,6 +70,12 @@
(Current) = (Rhs)[0]; \ (Current) = (Rhs)[0]; \
} while (0) } while (0)
/*
* The %name-prefix option below will make bison call base_yylex, but we
* really want it to call filtered_base_yylex (see parser.c).
*/
#define base_yylex filtered_base_yylex
extern List *parsetree; /* final parse result is delivered here */ extern List *parsetree; /* final parse result is delivered here */
static bool QueryIsRule = FALSE; static bool QueryIsRule = FALSE;
...@@ -339,6 +345,7 @@ static void doNegateFloat(Value *v); ...@@ -339,6 +345,7 @@ static void doNegateFloat(Value *v);
%type <list> constraints_set_list %type <list> constraints_set_list
%type <boolean> constraints_set_mode %type <boolean> constraints_set_mode
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner %type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
%type <list> opt_check_option
/* /*
...@@ -356,7 +363,7 @@ static void doNegateFloat(Value *v); ...@@ -356,7 +363,7 @@ static void doNegateFloat(Value *v);
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
BOOLEAN_P BOTH BY BOOLEAN_P BOTH BY
CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P CACHE CALLED CASCADE CASCADED CASE CAST CHAIN CHAR_P
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
COMMITTED CONNECTION CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB COMMITTED CONNECTION CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB
...@@ -431,6 +438,12 @@ static void doNegateFloat(Value *v); ...@@ -431,6 +438,12 @@ static void doNegateFloat(Value *v);
ZONE ZONE
/* The grammar thinks these are keywords, but they are not in the keywords.c
* list and so can never be entered directly. The filter in parser.c
* creates these tokens when required.
*/
%token WITH_CASCADED WITH_LOCAL WITH_CHECK
/* 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
%token <ival> ICONST PARAM %token <ival> ICONST PARAM
...@@ -4618,12 +4631,13 @@ transaction_mode_list_or_empty: ...@@ -4618,12 +4631,13 @@ transaction_mode_list_or_empty:
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
* CREATE [ OR REPLACE ] [ TEMP ] VIEW <viewname> '('target-list ')' AS <query> * CREATE [ OR REPLACE ] [ TEMP ] VIEW <viewname> '('target-list ')'
* AS <query> [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
* *
*****************************************************************************/ *****************************************************************************/
ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
AS SelectStmt AS SelectStmt opt_check_option
{ {
ViewStmt *n = makeNode(ViewStmt); ViewStmt *n = makeNode(ViewStmt);
n->replace = false; n->replace = false;
...@@ -4634,7 +4648,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list ...@@ -4634,7 +4648,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
$$ = (Node *) n; $$ = (Node *) n;
} }
| CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list | CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list
AS SelectStmt AS SelectStmt opt_check_option
{ {
ViewStmt *n = makeNode(ViewStmt); ViewStmt *n = makeNode(ViewStmt);
n->replace = true; n->replace = true;
...@@ -4646,6 +4660,32 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list ...@@ -4646,6 +4660,32 @@ 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:
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),
errmsg("WITH CHECK OPTION is not implemented")));
}
| /* EMPTY */ { $$ = NIL; }
;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -8319,6 +8359,7 @@ unreserved_keyword: ...@@ -8319,6 +8359,7 @@ unreserved_keyword:
| CACHE | CACHE
| CALLED | CALLED
| CASCADE | CASCADE
| CASCADED
| CHAIN | CHAIN
| CHARACTERISTICS | CHARACTERISTICS
| CHECKPOINT | CHECKPOINT
...@@ -9139,4 +9180,10 @@ doNegateFloat(Value *v) ...@@ -9139,4 +9180,10 @@ doNegateFloat(Value *v)
} }
} }
/*
* Must undefine base_yylex before including scan.c, since we want it
* to create the function base_yylex not filtered_base_yylex.
*/
#undef base_yylex
#include "scan.c" #include "scan.c"
...@@ -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.65 2006/03/07 01:00:17 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.66 2006/05/27 17:38:46 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -22,11 +22,15 @@ ...@@ -22,11 +22,15 @@
#include "postgres.h" #include "postgres.h"
#include "parser/gramparse.h" #include "parser/gramparse.h"
#include "parser/parse.h"
#include "parser/parser.h" #include "parser/parser.h"
List *parsetree; /* result of parsing is left here */ List *parsetree; /* result of parsing is left here */
static int lookahead_token; /* one-token lookahead */
static bool have_lookahead; /* lookahead_token set? */
/* /*
* raw_parser * raw_parser
...@@ -40,6 +44,7 @@ raw_parser(const char *str) ...@@ -40,6 +44,7 @@ raw_parser(const char *str)
int yyresult; int yyresult;
parsetree = NIL; /* in case grammar forgets to set it */ parsetree = NIL; /* in case grammar forgets to set it */
have_lookahead = false;
scanner_init(str); scanner_init(str);
parser_init(); parser_init();
...@@ -53,3 +58,70 @@ raw_parser(const char *str) ...@@ -53,3 +58,70 @@ raw_parser(const char *str)
return parsetree; return parsetree;
} }
/*
* Intermediate filter between parser and base lexer (base_yylex in scan.l).
*
* The filter is needed because in some cases the standard SQL grammar
* requires more than one token lookahead. We reduce these cases to one-token
* lookahead by combining tokens here, in order to keep the grammar LALR(1).
*
* Using a filter is simpler than trying to recognize multiword tokens
* directly in scan.l, because we'd have to allow for comments between the
* words. Furthermore it's not clear how to do it without re-introducing
* scanner backtrack, which would cost more performance than this filter
* layer does.
*/
int
filtered_base_yylex(void)
{
int cur_token;
/* Get next token --- we might already have it */
if (have_lookahead)
{
cur_token = lookahead_token;
have_lookahead = false;
}
else
cur_token = base_yylex();
/* Do we need to look ahead for a possible multiword token? */
switch (cur_token)
{
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.
*/
lookahead_token = base_yylex();
switch (lookahead_token)
{
case CASCADED:
cur_token = WITH_CASCADED;
break;
case LOCAL:
cur_token = WITH_LOCAL;
break;
case CHECK:
cur_token = WITH_CHECK;
break;
default:
have_lookahead = true;
break;
}
break;
default:
break;
}
return cur_token;
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.36 2006/05/21 20:10:42 tgl Exp $ * $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.37 2006/05/27 17:38:46 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -40,6 +40,9 @@ extern bool escape_string_warning; ...@@ -40,6 +40,9 @@ extern bool escape_string_warning;
extern bool standard_conforming_strings; extern bool standard_conforming_strings;
/* from parser.c */
extern int filtered_base_yylex(void);
/* from scan.l */ /* from scan.l */
extern void scanner_init(const char *str); extern void scanner_init(const char *str);
extern void scanner_finish(void); extern void scanner_finish(void);
......
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