1 %{
2 /*-------------------------------------------------------------------------
3 *
4 * repl_scanner.l
5 * a lexical scanner for the replication commands
6 *
7 * Portions Copyright (c) 1996-2016, 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
fprintf_to_ereport(const char * fmt,const char * msg)26 fprintf_to_ereport(const char *fmt, const char *msg)
27 {
28 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 BASE_BACKUP { return K_BASE_BACKUP; }
84 FAST { return K_FAST; }
85 IDENTIFY_SYSTEM { return K_IDENTIFY_SYSTEM; }
86 LABEL { return K_LABEL; }
87 NOWAIT { return K_NOWAIT; }
88 PROGRESS { return K_PROGRESS; }
89 MAX_RATE { return K_MAX_RATE; }
90 WAL { return K_WAL; }
91 TABLESPACE_MAP { return K_TABLESPACE_MAP; }
92 TIMELINE { return K_TIMELINE; }
93 START_REPLICATION { return K_START_REPLICATION; }
94 CREATE_REPLICATION_SLOT { return K_CREATE_REPLICATION_SLOT; }
95 DROP_REPLICATION_SLOT { return K_DROP_REPLICATION_SLOT; }
96 TIMELINE_HISTORY { return K_TIMELINE_HISTORY; }
97 PHYSICAL { return K_PHYSICAL; }
98 RESERVE_WAL { return K_RESERVE_WAL; }
99 LOGICAL { return K_LOGICAL; }
100 SLOT { return K_SLOT; }
101
102 "," { return ','; }
103 ";" { return ';'; }
104 "(" { return '('; }
105 ")" { return ')'; }
106
107 [\n] ;
108 [\t] ;
109 " " ;
110
111 {digit}+ {
112 yylval.uintval = strtoul(yytext, NULL, 10);
113 return UCONST;
114 }
115
116 {hexdigit}+\/{hexdigit}+ {
117 uint32 hi,
118 lo;
119 if (sscanf(yytext, "%X/%X", &hi, &lo) != 2)
120 yyerror("invalid streaming start location");
121 yylval.recptr = ((uint64) hi) << 32 | lo;
122 return RECPTR;
123 }
124
125 {xqstart} {
126 BEGIN(xq);
127 startlit();
128 }
129
130 <xq>{quotestop} {
131 yyless(1);
132 BEGIN(INITIAL);
133 yylval.str = litbufdup();
134 return SCONST;
135 }
136
137 <xq>{xqdouble} {
138 addlitchar('\'');
139 }
140
141 <xq>{xqinside} {
142 addlit(yytext, yyleng);
143 }
144
145 {xdstart} {
146 BEGIN(xd);
147 startlit();
148 }
149
150 <xd>{xdstop} {
151 int len;
152 yyless(1);
153 BEGIN(INITIAL);
154 yylval.str = litbufdup();
155 len = strlen(yylval.str);
156 truncate_identifier(yylval.str, len, true);
157 return IDENT;
158 }
159
160 <xd>{xdinside} {
161 addlit(yytext, yyleng);
162 }
163
164 {identifier} {
165 int len = strlen(yytext);
166
167 yylval.str = downcase_truncate_identifier(yytext, len, true);
168 return IDENT;
169 }
170
171 <xq,xd><<EOF>> { yyerror("unterminated quoted string"); }
172
173
174 <<EOF>> {
175 yyterminate();
176 }
177
178 . {
179 ereport(ERROR,
180 (errcode(ERRCODE_SYNTAX_ERROR),
181 errmsg("syntax error: unexpected character \"%s\"", yytext)));
182 }
183 %%
184
185
186 static void
187 startlit(void)
188 {
189 initStringInfo(&litbuf);
190 }
191
192 static char *
litbufdup(void)193 litbufdup(void)
194 {
195 return litbuf.data;
196 }
197
198 static void
addlit(char * ytext,int yleng)199 addlit(char *ytext, int yleng)
200 {
201 appendBinaryStringInfo(&litbuf, ytext, yleng);
202 }
203
204 static void
addlitchar(unsigned char ychar)205 addlitchar(unsigned char ychar)
206 {
207 appendStringInfoChar(&litbuf, ychar);
208 }
209
210 void
yyerror(const char * message)211 yyerror(const char *message)
212 {
213 ereport(ERROR,
214 (errcode(ERRCODE_SYNTAX_ERROR),
215 errmsg_internal("%s", message)));
216 }
217
218
219 void
replication_scanner_init(const char * str)220 replication_scanner_init(const char *str)
221 {
222 Size slen = strlen(str);
223 char *scanbuf;
224
225 /*
226 * Might be left over after ereport()
227 */
228 if (YY_CURRENT_BUFFER)
229 yy_delete_buffer(YY_CURRENT_BUFFER);
230
231 /*
232 * Make a scan buffer with special termination needed by flex.
233 */
234 scanbuf = (char *) palloc(slen + 2);
235 memcpy(scanbuf, str, slen);
236 scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
237 scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
238 }
239
240 void
replication_scanner_finish(void)241 replication_scanner_finish(void)
242 {
243 yy_delete_buffer(scanbufhandle);
244 scanbufhandle = NULL;
245 }
246