]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - parser/parser.c
Attempt to send a proper failure message to frontend when authentication
[pgpool-ii/pgpool-ii_2.2.5] / parser / parser.c
1 /*-------------------------------------------------------------------------
2  *
3  * parser.c
4  *              Main entry point/driver for PostgreSQL grammar
5  *
6  * Note that the grammar is not allowed to perform any table access
7  * (since we need to be able to do basic parsing even while inside an
8  * aborted transaction).  Therefore, the data structures returned by
9  * the grammar are "raw" parsetrees that still need to be analyzed by
10  * parse_analyze.
11  *
12  *
13  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
14  * Portions Copyright (c) 1994, Regents of the University of California
15  *
16  * IDENTIFICATION
17  *        $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.63 2004/12/31 22:00:27 pgsql Exp $
18  *
19  *-------------------------------------------------------------------------
20  */
21
22 #include <string.h>
23 #include "pool_parser.h"
24 #include "pool_memory.h"
25 #include "gramparse.h"
26 #include "gram.h"
27 #include "parser.h"
28 #include "value.h"
29
30 List       *parsetree;                  /* result of parsing is left here */
31 jmp_buf    jmpbuffer;
32
33 static int      lookahead_token;        /* one-token lookahead */
34 static bool have_lookahead;             /* lookahead_token set? */
35 static YYSTYPE lookahead_yylval;        /* yylval for lookahead token */
36 static YYLTYPE lookahead_yylloc;        /* yylloc for lookahead token */
37
38
39 /*
40  * raw_parser
41  *              Given a query in string form, do lexical and grammatical analysis.
42  *
43  * Returns a list of raw (un-analyzed) parse trees.
44  */
45 List *
46 raw_parser(const char *str)
47 {
48         int                     yyresult;
49
50         if (pool_memory == NULL)
51                 pool_memory = pool_memory_create(PARSER_BLOCK_SIZE);
52
53         parsetree = NIL;                        /* in case grammar forgets to set it */
54         have_lookahead = false;
55
56         scanner_init(str);
57         parser_init();
58
59         if (setjmp(jmpbuffer) != 0)
60         {
61                 scanner_finish();
62                 return NIL; /* error */
63         }
64         else
65         {
66                 yyresult = base_yyparse();
67
68                 scanner_finish();
69
70                 if (yyresult)                           /* error */
71                         return NIL;
72         }
73         return parsetree;
74 }
75
76 void free_parser(void)
77 {
78         pool_memory_delete(pool_memory, 1);
79 }
80
81 /*
82  * Intermediate filter between parser and base lexer (base_yylex in scan.l).
83  *
84  * The filter is needed because in some cases the standard SQL grammar
85  * requires more than one token lookahead.      We reduce these cases to one-token
86  * lookahead by combining tokens here, in order to keep the grammar LALR(1).
87  *
88  * Using a filter is simpler than trying to recognize multiword tokens
89  * directly in scan.l, because we'd have to allow for comments between the
90  * words.  Furthermore it's not clear how to do it without re-introducing
91  * scanner backtrack, which would cost more performance than this filter
92  * layer does.
93  */
94 int
95 filtered_base_yylex(void)
96 {
97         int                     cur_token;
98         int                     next_token;
99         YYSTYPE         cur_yylval;
100         YYLTYPE         cur_yylloc;
101
102         /* Get next token --- we might already have it */
103         if (have_lookahead)
104         {
105                 cur_token = lookahead_token;
106                 base_yylval = lookahead_yylval;
107                 base_yylloc = lookahead_yylloc;
108                 have_lookahead = false;
109         }
110         else
111                 cur_token = base_yylex();
112
113         /* Do we need to look ahead for a possible multiword token? */
114         switch (cur_token)
115         {
116                 case NULLS_P:
117                         /*
118                          * NULLS FIRST and NULLS LAST must be reduced to one token
119                          */
120                         cur_yylval = base_yylval;
121                         cur_yylloc = base_yylloc;
122                         next_token = base_yylex();
123                         switch (next_token)
124                         {
125                                 case FIRST_P:
126                                         cur_token = NULLS_FIRST;
127                                         break;
128                                 case LAST_P:
129                                         cur_token = NULLS_LAST;
130                                         break;
131                                 default:
132                                         /* save the lookahead token for next time */
133                                         lookahead_token = next_token;
134                                         lookahead_yylval = base_yylval;
135                                         lookahead_yylloc = base_yylloc;
136                                         have_lookahead = true;
137                                         /* and back up the output info to cur_token */
138                                         base_yylval = cur_yylval;
139                                         base_yylloc = cur_yylloc;
140                                         break;
141                         }
142                         break;
143
144                 case WITH:
145                         /*
146                          * WITH CASCADED, LOCAL, or CHECK must be reduced to one token
147                          *
148                          * XXX an alternative way is to recognize just WITH_TIME and put
149                          * the ugliness into the datetime datatype productions instead of
150                          * WITH CHECK OPTION.  However that requires promoting WITH to a
151                          * fully reserved word.  If we ever have to do that anyway
152                          * (perhaps for SQL99 recursive queries), come back and simplify
153                          * this code.
154                          */
155                         cur_yylval = base_yylval;
156                         cur_yylloc = base_yylloc;
157                         next_token = base_yylex();
158                         switch (next_token)
159                         {
160                                 case CASCADED:
161                                         cur_token = WITH_CASCADED;
162                                         break;
163                                 case LOCAL:
164                                         cur_token = WITH_LOCAL;
165                                         break;
166                                 case CHECK:
167                                         cur_token = WITH_CHECK;
168                                         break;
169                                 default:
170                                         /* save the lookahead token for next time */
171                                         lookahead_token = next_token;
172                                         lookahead_yylval = base_yylval;
173                                         lookahead_yylloc = base_yylloc;
174                                         have_lookahead = true;
175                                         /* and back up the output info to cur_token */
176                                         base_yylval = cur_yylval;
177                                         base_yylloc = cur_yylloc;
178                                         break;
179                         }
180                         break;
181
182                 default:
183                         break;
184         }
185
186         return cur_token;
187 }