#
# 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 $
#
#-------------------------------------------------------------------------
# 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
*
*
* 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
(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;
%type <list> constraints_set_list
%type <boolean> constraints_set_mode
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
+%type <list> opt_check_option
/*
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
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
/*****************************************************************************
*
* 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;
$$ = (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;
}
;
+/*
+ * 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:
| CACHE
| CALLED
| CASCADE
+ | CASCADED
| CHAIN
| CHARACTERISTICS
| CHECKPOINT
}
}
+/*
+ * 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"
* 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 $
*
*-------------------------------------------------------------------------
*/
#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
int yyresult;
parsetree = NIL; /* in case grammar forgets to set it */
+ have_lookahead = false;
scanner_init(str);
parser_init();
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;
+}
* 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 $
*
*-------------------------------------------------------------------------
*/
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);