Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0780ce6

Browse files
committed
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.
1 parent 51b40f0 commit 0780ce6

File tree

4 files changed

+131
-9
lines changed

4 files changed

+131
-9
lines changed

src/backend/parser/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# Makefile for parser
44
#
5-
# $PostgreSQL: pgsql/src/backend/parser/Makefile,v 1.43 2006/03/07 01:00:17 tgl Exp $
5+
# $PostgreSQL: pgsql/src/backend/parser/Makefile,v 1.44 2006/05/27 17:38:45 tgl Exp $
66
#
77
#-------------------------------------------------------------------------
88

@@ -57,7 +57,7 @@ endif
5757

5858

5959
# Force these dependencies to be known even without dependency info built:
60-
gram.o keywords.o: $(srcdir)/parse.h
60+
gram.o keywords.o parser.o: $(srcdir)/parse.h
6161

6262

6363
# gram.c, parse.h, and scan.c are in the distribution tarball, so they

src/backend/parser/gram.y

+52-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.544 2006/04/30 18:30:39 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.545 2006/05/27 17:38:45 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -70,6 +70,12 @@
7070
(Current) = (Rhs)[0]; \
7171
} while (0)
7272

73+
/*
74+
* The %name-prefix option below will make bison call base_yylex, but we
75+
* really want it to call filtered_base_yylex (see parser.c).
76+
*/
77+
#define base_yylex filtered_base_yylex
78+
7379
extern List *parsetree; /* final parse result is delivered here */
7480

7581
static bool QueryIsRule = FALSE;
@@ -339,6 +345,7 @@ static void doNegateFloat(Value *v);
339345
%type <list> constraints_set_list
340346
%type <boolean> constraints_set_mode
341347
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
348+
%type <list> opt_check_option
342349

343350

344351
/*
@@ -356,7 +363,7 @@ static void doNegateFloat(Value *v);
356363
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
357364
BOOLEAN_P BOTH BY
358365

359-
CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P
366+
CACHE CALLED CASCADE CASCADED CASE CAST CHAIN CHAR_P
360367
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
361368
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
362369
COMMITTED CONNECTION CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB
@@ -431,6 +438,12 @@ static void doNegateFloat(Value *v);
431438

432439
ZONE
433440

441+
/* The grammar thinks these are keywords, but they are not in the keywords.c
442+
* list and so can never be entered directly. The filter in parser.c
443+
* creates these tokens when required.
444+
*/
445+
%token WITH_CASCADED WITH_LOCAL WITH_CHECK
446+
434447
/* Special token types, not actually keywords - see the "lex" file */
435448
%token <str> IDENT FCONST SCONST BCONST XCONST Op
436449
%token <ival> ICONST PARAM
@@ -4618,12 +4631,13 @@ transaction_mode_list_or_empty:
46184631
/*****************************************************************************
46194632
*
46204633
* QUERY:
4621-
* CREATE [ OR REPLACE ] [ TEMP ] VIEW <viewname> '('target-list ')' AS <query>
4634+
* CREATE [ OR REPLACE ] [ TEMP ] VIEW <viewname> '('target-list ')'
4635+
* AS <query> [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
46224636
*
46234637
*****************************************************************************/
46244638

46254639
ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
4626-
AS SelectStmt
4640+
AS SelectStmt opt_check_option
46274641
{
46284642
ViewStmt *n = makeNode(ViewStmt);
46294643
n->replace = false;
@@ -4634,7 +4648,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
46344648
$$ = (Node *) n;
46354649
}
46364650
| CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list
4637-
AS SelectStmt
4651+
AS SelectStmt opt_check_option
46384652
{
46394653
ViewStmt *n = makeNode(ViewStmt);
46404654
n->replace = true;
@@ -4646,6 +4660,32 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
46464660
}
46474661
;
46484662

4663+
/*
4664+
* We use merged tokens here to avoid creating shift/reduce conflicts against
4665+
* a whole lot of other uses of WITH.
4666+
*/
4667+
opt_check_option:
4668+
WITH_CHECK OPTION
4669+
{
4670+
ereport(ERROR,
4671+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4672+
errmsg("WITH CHECK OPTION is not implemented")));
4673+
}
4674+
| WITH_CASCADED CHECK OPTION
4675+
{
4676+
ereport(ERROR,
4677+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4678+
errmsg("WITH CHECK OPTION is not implemented")));
4679+
}
4680+
| WITH_LOCAL CHECK OPTION
4681+
{
4682+
ereport(ERROR,
4683+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4684+
errmsg("WITH CHECK OPTION is not implemented")));
4685+
}
4686+
| /* EMPTY */ { $$ = NIL; }
4687+
;
4688+
46494689
/*****************************************************************************
46504690
*
46514691
* QUERY:
@@ -8319,6 +8359,7 @@ unreserved_keyword:
83198359
| CACHE
83208360
| CALLED
83218361
| CASCADE
8362+
| CASCADED
83228363
| CHAIN
83238364
| CHARACTERISTICS
83248365
| CHECKPOINT
@@ -9139,4 +9180,10 @@ doNegateFloat(Value *v)
91399180
}
91409181
}
91419182

9183+
/*
9184+
* Must undefine base_yylex before including scan.c, since we want it
9185+
* to create the function base_yylex not filtered_base_yylex.
9186+
*/
9187+
#undef base_yylex
9188+
91429189
#include "scan.c"

src/backend/parser/parser.c

+73-1
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,23 @@
1414
* Portions Copyright (c) 1994, Regents of the University of California
1515
*
1616
* IDENTIFICATION
17-
* $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.65 2006/03/07 01:00:17 tgl Exp $
17+
* $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.66 2006/05/27 17:38:46 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
2121

2222
#include "postgres.h"
2323

2424
#include "parser/gramparse.h"
25+
#include "parser/parse.h"
2526
#include "parser/parser.h"
2627

2728

2829
List *parsetree; /* result of parsing is left here */
2930

31+
static int lookahead_token; /* one-token lookahead */
32+
static bool have_lookahead; /* lookahead_token set? */
33+
3034

3135
/*
3236
* raw_parser
@@ -40,6 +44,7 @@ raw_parser(const char *str)
4044
int yyresult;
4145

4246
parsetree = NIL; /* in case grammar forgets to set it */
47+
have_lookahead = false;
4348

4449
scanner_init(str);
4550
parser_init();
@@ -53,3 +58,70 @@ raw_parser(const char *str)
5358

5459
return parsetree;
5560
}
61+
62+
63+
/*
64+
* Intermediate filter between parser and base lexer (base_yylex in scan.l).
65+
*
66+
* The filter is needed because in some cases the standard SQL grammar
67+
* requires more than one token lookahead. We reduce these cases to one-token
68+
* lookahead by combining tokens here, in order to keep the grammar LALR(1).
69+
*
70+
* Using a filter is simpler than trying to recognize multiword tokens
71+
* directly in scan.l, because we'd have to allow for comments between the
72+
* words. Furthermore it's not clear how to do it without re-introducing
73+
* scanner backtrack, which would cost more performance than this filter
74+
* layer does.
75+
*/
76+
int
77+
filtered_base_yylex(void)
78+
{
79+
int cur_token;
80+
81+
/* Get next token --- we might already have it */
82+
if (have_lookahead)
83+
{
84+
cur_token = lookahead_token;
85+
have_lookahead = false;
86+
}
87+
else
88+
cur_token = base_yylex();
89+
90+
/* Do we need to look ahead for a possible multiword token? */
91+
switch (cur_token)
92+
{
93+
case WITH:
94+
/*
95+
* WITH CASCADED, LOCAL, or CHECK must be reduced to one token
96+
*
97+
* XXX an alternative way is to recognize just WITH_TIME and
98+
* put the ugliness into the datetime datatype productions
99+
* instead of WITH CHECK OPTION. However that requires promoting
100+
* WITH to a fully reserved word. If we ever have to do that
101+
* anyway (perhaps for SQL99 recursive queries), come back and
102+
* simplify this code.
103+
*/
104+
lookahead_token = base_yylex();
105+
switch (lookahead_token)
106+
{
107+
case CASCADED:
108+
cur_token = WITH_CASCADED;
109+
break;
110+
case LOCAL:
111+
cur_token = WITH_LOCAL;
112+
break;
113+
case CHECK:
114+
cur_token = WITH_CHECK;
115+
break;
116+
default:
117+
have_lookahead = true;
118+
break;
119+
}
120+
break;
121+
122+
default:
123+
break;
124+
}
125+
126+
return cur_token;
127+
}

src/include/parser/gramparse.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.36 2006/05/21 20:10:42 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.37 2006/05/27 17:38:46 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -40,6 +40,9 @@ extern bool escape_string_warning;
4040
extern bool standard_conforming_strings;
4141

4242

43+
/* from parser.c */
44+
extern int filtered_base_yylex(void);
45+
4346
/* from scan.l */
4447
extern void scanner_init(const char *str);
4548
extern void scanner_finish(void);

0 commit comments

Comments
 (0)