Line data Source code
1 : %{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * repl_scanner.l
5 : * a lexical scanner for the replication commands
6 : *
7 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : *
11 : * IDENTIFICATION
12 : * src/backend/replication/repl_scanner.l
13 : *
14 : *-------------------------------------------------------------------------
15 : */
16 : #include "postgres.h"
17 :
18 : #include "utils/builtins.h"
19 : #include "parser/scansup.h"
20 :
21 : /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
22 : #undef fprintf
23 : #define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg)
24 :
25 : static void
26 0 : fprintf_to_ereport(const char *fmt, const char *msg)
27 : {
28 0 : ereport(ERROR, (errmsg_internal("%s", msg)));
29 : }
30 :
31 : /* Handle to the buffer that the lexer uses internally */
32 : static YY_BUFFER_STATE scanbufhandle;
33 :
34 : static StringInfoData litbuf;
35 :
36 : static void startlit(void);
37 : static char *litbufdup(void);
38 : static void addlit(char *ytext, int yleng);
39 : static void addlitchar(unsigned char ychar);
40 :
41 : %}
42 :
43 : %option 8bit
44 : %option never-interactive
45 : %option nodefault
46 : %option noinput
47 : %option nounput
48 : %option noyywrap
49 : %option warn
50 : %option prefix="replication_yy"
51 :
52 : %x xq xd
53 :
54 : /* Extended quote
55 : * xqdouble implements embedded quote, ''''
56 : */
57 : xqstart {quote}
58 : xqdouble {quote}{quote}
59 : xqinside [^']+
60 :
61 : /* Double quote
62 : * Allows embedded spaces and other special characters into identifiers.
63 : */
64 : dquote \"
65 : xdstart {dquote}
66 : xdstop {dquote}
67 : xddouble {dquote}{dquote}
68 : xdinside [^"]+
69 :
70 : digit [0-9]+
71 : hexdigit [0-9A-Za-z]+
72 :
73 : quote '
74 : quotestop {quote}
75 :
76 : ident_start [A-Za-z\200-\377_]
77 : ident_cont [A-Za-z\200-\377_0-9\$]
78 :
79 : identifier {ident_start}{ident_cont}*
80 :
81 : %%
82 :
83 0 : BASE_BACKUP { return K_BASE_BACKUP; }
84 0 : FAST { return K_FAST; }
85 0 : IDENTIFY_SYSTEM { return K_IDENTIFY_SYSTEM; }
86 0 : SHOW { return K_SHOW; }
87 0 : LABEL { return K_LABEL; }
88 0 : NOWAIT { return K_NOWAIT; }
89 0 : PROGRESS { return K_PROGRESS; }
90 0 : MAX_RATE { return K_MAX_RATE; }
91 0 : WAL { return K_WAL; }
92 0 : TABLESPACE_MAP { return K_TABLESPACE_MAP; }
93 0 : TIMELINE { return K_TIMELINE; }
94 0 : START_REPLICATION { return K_START_REPLICATION; }
95 0 : CREATE_REPLICATION_SLOT { return K_CREATE_REPLICATION_SLOT; }
96 0 : DROP_REPLICATION_SLOT { return K_DROP_REPLICATION_SLOT; }
97 0 : TIMELINE_HISTORY { return K_TIMELINE_HISTORY; }
98 0 : PHYSICAL { return K_PHYSICAL; }
99 0 : RESERVE_WAL { return K_RESERVE_WAL; }
100 0 : LOGICAL { return K_LOGICAL; }
101 0 : SLOT { return K_SLOT; }
102 0 : TEMPORARY { return K_TEMPORARY; }
103 0 : EXPORT_SNAPSHOT { return K_EXPORT_SNAPSHOT; }
104 0 : NOEXPORT_SNAPSHOT { return K_NOEXPORT_SNAPSHOT; }
105 0 : USE_SNAPSHOT { return K_USE_SNAPSHOT; }
106 0 : WAIT { return K_WAIT; }
107 :
108 0 : "," { return ','; }
109 0 : ";" { return ';'; }
110 0 : "(" { return '('; }
111 0 : ")" { return ')'; }
112 :
113 : [\n] ;
114 0 : [\t] ;
115 0 : " " ;
116 0 :
117 : {digit}+ {
118 0 : yylval.uintval = strtoul(yytext, NULL, 10);
119 0 : return UCONST;
120 : }
121 :
122 : {hexdigit}+\/{hexdigit}+ {
123 : uint32 hi,
124 : lo;
125 0 : if (sscanf(yytext, "%X/%X", &hi, &lo) != 2)
126 0 : yyerror("invalid streaming start location");
127 0 : yylval.recptr = ((uint64) hi) << 32 | lo;
128 0 : return RECPTR;
129 : }
130 :
131 : {xqstart} {
132 0 : BEGIN(xq);
133 0 : startlit();
134 : }
135 0 :
136 : <xq>{quotestop} {
137 0 : yyless(1);
138 0 : BEGIN(INITIAL);
139 0 : yylval.str = litbufdup();
140 0 : return SCONST;
141 : }
142 :
143 : <xq>{xqdouble} {
144 0 : addlitchar('\'');
145 : }
146 0 :
147 : <xq>{xqinside} {
148 0 : addlit(yytext, yyleng);
149 : }
150 0 :
151 : {xdstart} {
152 0 : BEGIN(xd);
153 0 : startlit();
154 : }
155 0 :
156 : <xd>{xdstop} {
157 : int len;
158 0 : yyless(1);
159 0 : BEGIN(INITIAL);
160 0 : yylval.str = litbufdup();
161 0 : len = strlen(yylval.str);
162 0 : truncate_identifier(yylval.str, len, true);
163 0 : return IDENT;
164 : }
165 :
166 : <xd>{xdinside} {
167 0 : addlit(yytext, yyleng);
168 : }
169 0 :
170 : {identifier} {
171 0 : int len = strlen(yytext);
172 :
173 0 : yylval.str = downcase_truncate_identifier(yytext, len, true);
174 0 : return IDENT;
175 : }
176 :
177 0 : <xq,xd><<EOF>> { yyerror("unterminated quoted string"); }
178 :
179 :
180 : <<EOF>> {
181 0 : yyterminate();
182 : }
183 :
184 : . {
185 0 : return T_WORD;
186 : }
187 0 : %%
188 0 :
189 :
190 : static void
191 0 : startlit(void)
192 : {
193 0 : initStringInfo(&litbuf);
194 0 : }
195 :
196 : static char *
197 0 : litbufdup(void)
198 : {
199 0 : return litbuf.data;
200 : }
201 :
202 : static void
203 0 : addlit(char *ytext, int yleng)
204 : {
205 0 : appendBinaryStringInfo(&litbuf, ytext, yleng);
206 0 : }
207 :
208 : static void
209 0 : addlitchar(unsigned char ychar)
210 : {
211 0 : appendStringInfoChar(&litbuf, ychar);
212 0 : }
213 :
214 : void
215 0 : yyerror(const char *message)
216 : {
217 0 : ereport(ERROR,
218 : (errcode(ERRCODE_SYNTAX_ERROR),
219 : errmsg_internal("%s", message)));
220 : }
221 :
222 :
223 : void
224 0 : replication_scanner_init(const char *str)
225 : {
226 0 : Size slen = strlen(str);
227 : char *scanbuf;
228 :
229 : /*
230 : * Might be left over after ereport()
231 : */
232 0 : if (YY_CURRENT_BUFFER)
233 0 : yy_delete_buffer(YY_CURRENT_BUFFER);
234 :
235 : /*
236 : * Make a scan buffer with special termination needed by flex.
237 : */
238 0 : scanbuf = (char *) palloc(slen + 2);
239 0 : memcpy(scanbuf, str, slen);
240 0 : scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
241 0 : scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
242 0 : }
243 :
244 : void
245 0 : replication_scanner_finish(void)
246 : {
247 0 : yy_delete_buffer(scanbufhandle);
248 0 : scanbufhandle = NULL;
249 0 : }
|