aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/parser/Makefile4
-rw-r--r--src/backend/parser/gram.y57
-rw-r--r--src/backend/parser/parser.c74
-rw-r--r--src/include/parser/gramparse.h5
4 files changed, 131 insertions, 9 deletions
diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile
index 553fda257e1..3099f77ca64 100644
--- a/src/backend/parser/Makefile
+++ b/src/backend/parser/Makefile
@@ -2,7 +2,7 @@
#
# 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
# 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
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 69e7a201425..d84f4034aba 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* 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
* AUTHOR DATE MAJOR EVENT
@@ -70,6 +70,12 @@
(Current) = (Rhs)[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 */
static bool QueryIsRule = FALSE;
@@ -339,6 +345,7 @@ static void doNegateFloat(Value *v);
%type <list> constraints_set_list
%type <boolean> constraints_set_mode
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
+%type <list> opt_check_option
/*
@@ -356,7 +363,7 @@ static void doNegateFloat(Value *v);
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
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
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
COMMITTED CONNECTION CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB
@@ -431,6 +438,12 @@ static void doNegateFloat(Value *v);
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 */
%token <str> IDENT FCONST SCONST BCONST XCONST Op
%token <ival> ICONST PARAM
@@ -4618,12 +4631,13 @@ transaction_mode_list_or_empty:
/*****************************************************************************
*
* 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
- AS SelectStmt
+ AS SelectStmt opt_check_option
{
ViewStmt *n = makeNode(ViewStmt);
n->replace = false;
@@ -4634,7 +4648,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
$$ = (Node *) n;
}
| CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list
- AS SelectStmt
+ AS SelectStmt opt_check_option
{
ViewStmt *n = makeNode(ViewStmt);
n->replace = true;
@@ -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:
@@ -8319,6 +8359,7 @@ unreserved_keyword:
| CACHE
| CALLED
| CASCADE
+ | CASCADED
| CHAIN
| CHARACTERISTICS
| CHECKPOINT
@@ -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"
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index 6c331ad338d..de40e64fa8a 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -14,7 +14,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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 @@
#include "postgres.h"
#include "parser/gramparse.h"
+#include "parser/parse.h"
#include "parser/parser.h"
List *parsetree; /* result of parsing is left here */
+static int lookahead_token; /* one-token lookahead */
+static bool have_lookahead; /* lookahead_token set? */
+
/*
* raw_parser
@@ -40,6 +44,7 @@ raw_parser(const char *str)
int yyresult;
parsetree = NIL; /* in case grammar forgets to set it */
+ have_lookahead = false;
scanner_init(str);
parser_init();
@@ -53,3 +58,70 @@ raw_parser(const char *str)
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;
+}
diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h
index 38f4b26f94e..b61ceb0ac72 100644
--- a/src/include/parser/gramparse.h
+++ b/src/include/parser/gramparse.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* 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;
extern bool standard_conforming_strings;
+/* from parser.c */
+extern int filtered_base_yylex(void);
+
/* from scan.l */
extern void scanner_init(const char *str);
extern void scanner_finish(void);