PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
exprscan.l File Reference
#include "postgres_fe.h"
#include "fe_utils/psqlscan_int.h"
#include "pgbench.h"
#include "exprparse.h"
Include dependency graph for exprscan.l:

Go to the source code of this file.

Functions

int yylex (YYSTYPE *yylval_param, yyscan_t yyscanner)
 
void expr_yyerror_more (yyscan_t yyscanner, const char *message, const char *more)
 
void expr_yyerror (PgBenchExpr **expr_parse_result_p, yyscan_t yyscanner, const char *message)
 
bool expr_lex_one_word (PsqlScanState state, PQExpBuffer word_buf, int *offset)
 
yyscan_t expr_scanner_init (PsqlScanState state, const char *source, int lineno, int start_offset, const char *command)
 
void expr_scanner_finish (yyscan_t yyscanner)
 
char * expr_scanner_get_substring (PsqlScanState state, int start_offset, bool chomp)
 

Variables

static const char * expr_source = NULL
 
static int expr_lineno = 0
 
static int expr_start_offset = 0
 
static const char * expr_command = NULL
 
static bool last_was_newline = false
 

Function Documentation

◆ expr_lex_one_word()

bool expr_lex_one_word ( PsqlScanState  state,
PQExpBuffer  word_buf,
int *  offset 
)

Definition at line 318 of file exprscan.l.

319{
320 int lexresult;
321 YYSTYPE lval;
int YYSTYPE
Definition: psqlscanslash.l:39
322
323 /* Must be scanning already */
324 Assert(state->scanbufhandle != NULL);
Assert(PointerIsAligned(start, uint64))
Definition: regguts.h:323
325
326 /* Set current output target */
327 state->output_buf = word_buf;
328 resetPQExpBuffer(word_buf);
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
329
330 /* Set input source */
331 if (state->buffer_stack != NULL)
332 yy_switch_to_buffer(state->buffer_stack->buf, state->scanner);
333 else
334 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
335
336 /* Set start state */
337 state->start_state = INITIAL;
338
339 /* And lex. */
340 lexresult = yylex(&lval, state->scanner);
int yylex(YYSTYPE *yylval_param, yyscan_t yyscanner)
Definition: exprscan.l:94
341
342 /* Save start offset of word, if any. */
343 if (lexresult)
344 {
345 int lineno;
346 int end_offset;
347
348 psql_scan_get_location(state, &lineno, &end_offset);
349 *offset = end_offset - word_buf->len;
350 }
351 else
352 *offset = -1;
void psql_scan_get_location(PsqlScanState state, int *lineno, int *offset)
Definition: psqlscan.l:1335
353
354 /*
355 * In case the caller returns to using the regular SQL lexer, reselect the
356 * appropriate initial state.
357 */
void psql_scan_reselect_sql_lexer(PsqlScanState state)
Definition: psqlscan.l:1303
359
360 return (bool) lexresult;
361}

References Assert(), PQExpBufferData::len, psql_scan_get_location(), psql_scan_reselect_sql_lexer(), resetPQExpBuffer(), and yylex().

Referenced by process_backslash_command().

◆ expr_scanner_finish()

void expr_scanner_finish ( yyscan_t  yyscanner)

Definition at line 402 of file exprscan.l.

403{
404 PsqlScanState state = yyget_extra(yyscanner);
405
406 /*
407 * Reselect appropriate initial state for SQL lexer.
408 */
410}

References psql_scan_reselect_sql_lexer().

Referenced by process_backslash_command().

◆ expr_scanner_get_substring()

char * expr_scanner_get_substring ( PsqlScanState  state,
int  start_offset,
bool  chomp 
)

Definition at line 425 of file exprscan.l.

428{
429 char *result;
430 const char *scanptr = state->scanbuf + start_offset;
431 size_t slen = strlen(scanptr);
432
433 if (chomp)
434 {
435 while (slen > 0 &&
436 (scanptr[slen - 1] == '\n' || scanptr[slen - 1] == '\r'))
437 slen--;
438 }
439
440 result = (char *) pg_malloc(slen + 1);
441 memcpy(result, scanptr, slen);
442 result[slen] = '\0';
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
443
444 return result;
445}

References pg_malloc().

Referenced by expr_yyerror_more(), and process_backslash_command().

◆ expr_scanner_init()

yyscan_t expr_scanner_init ( PsqlScanState  state,
const char *  source,
int  lineno,
int  start_offset,
const char *  command 
)

Definition at line 370 of file exprscan.l.

373{
374 /* Save error context info */
376 expr_lineno = lineno;
377 expr_start_offset = start_offset;
378 expr_command = command;
static int expr_lineno
Definition: exprscan.l:40
static const char * expr_source
Definition: exprscan.l:39
static int expr_start_offset
Definition: exprscan.l:41
static const char * expr_command
Definition: exprscan.l:42
static rewind_source * source
Definition: pg_rewind.c:89
379
380 /* Must be scanning already */
381 Assert(state->scanbufhandle != NULL);
382
383 /* Set current output target */
384 state->output_buf = NULL;
385
386 /* Set input source */
387 if (state->buffer_stack != NULL)
388 yy_switch_to_buffer(state->buffer_stack->buf, state->scanner);
389 else
390 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
391
392 /* Set start state */
393 state->start_state = EXPR;
394
395 return state->scanner;
396}

References Assert(), expr_command, expr_lineno, expr_source, expr_start_offset, and source.

Referenced by process_backslash_command().

◆ expr_yyerror()

void expr_yyerror ( PgBenchExpr **  expr_parse_result_p,
yyscan_t  yyscanner,
const char *  message 
)

Definition at line 307 of file exprscan.l.

308{
309 expr_yyerror_more(yyscanner, message, NULL);
void expr_yyerror_more(yyscan_t yyscanner, const char *message, const char *more)
Definition: exprscan.l:271
310}

References expr_yyerror_more().

◆ expr_yyerror_more()

void expr_yyerror_more ( yyscan_t  yyscanner,
const char *  message,
const char *  more 
)

Definition at line 271 of file exprscan.l.

272{
273 PsqlScanState state = yyget_extra(yyscanner);
274 int lineno;
275 int error_detection_offset;
276 YYSTYPE lval;
277 char *full_line;
278
279 psql_scan_get_location(state, &lineno, &error_detection_offset);
280 error_detection_offset--;
281
282 /*
283 * While parsing an expression, we may not have collected the whole line
284 * yet from the input source. Lex till EOL so we can report whole line.
285 * (If we're at EOF, it's okay to call yylex() an extra time.)
286 */
287 if (!last_was_newline)
288 {
289 while (yylex(&lval, yyscanner))
290 /* skip */ ;
291 }
static bool last_was_newline
Definition: exprscan.l:45
292
293 /* Extract the line, trimming trailing newline if any */
296 true);
char * expr_scanner_get_substring(PsqlScanState state, int start_offset, bool chomp)
Definition: exprscan.l:425
297
299 message, more, error_detection_offset - expr_start_offset);
void syntax_error(const char *source, int lineno, const char *line, const char *command, const char *msg, const char *more, int column)
Definition: pgbench.c:5517
300}

References expr_command, expr_lineno, expr_scanner_get_substring(), expr_source, expr_start_offset, last_was_newline, psql_scan_get_location(), syntax_error(), and yylex().

Referenced by expr_yyerror().

◆ yylex()

int yylex ( YYSTYPE yylval_param,
yyscan_t  yyscanner 
)

Definition at line 94 of file exprscan.l.

96 {
97 /* Declare some local variables inside yylex(), for convenience */
98 PsqlScanState cur_state = yyextra;
#define yyextra
Definition: scan.l:1118
99
100 /*
101 * Force flex into the state indicated by start_state. This has a
102 * couple of purposes: it lets some of the functions below set a new
103 * starting state without ugly direct access to flex variables, and it
104 * allows us to transition from one flex lexer to another so that we
105 * can lex different parts of the source string using separate lexers.
106 */
107 BEGIN(cur_state->start_state);
108
109 /* Reset was-newline flag */
110 last_was_newline = false;
111%}
112
113 /* INITIAL state */
114
115{nonspace}+ {
116 /* Found a word, emit and return it */
117 psqlscan_emit(cur_state, yytext, yyleng);
118 return 1;
119 }
void psqlscan_emit(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1517
#define yyleng
Definition: scan.l:1124
120
121 /*
122 * We need this rule to avoid returning "word\" instead of recognizing
123 * a continuation marker just after a word:
124 */
125{nonspace}+{continuation} {
126 /* Found "word\\\r?\n", emit and return just "word" */
127 int wordlen = yyleng - 2;
128 if (yytext[wordlen] == '\r')
129 wordlen--;
130 Assert(yytext[wordlen] == '\\');
131 psqlscan_emit(cur_state, yytext, wordlen);
132 return 1;
133 }
134
135{space}+ { /* ignore */ }
136
137{continuation} { /* ignore */ }
138
139{newline} {
140 /* report end of command */
141 last_was_newline = true;
142 return 0;
143 }
144
145 /* EXPR state */
146
147<EXPR>{
148
149"+" { return '+'; }
150"-" { return '-'; }
151"*" { return '*'; }
152"/" { return '/'; }
153"%" { return '%'; } /* C version, also in Pg SQL */
154"=" { return '='; }
155"<>" { return NE_OP; }
156"!=" { return NE_OP; } /* C version, also in Pg SQL */
157"<=" { return LE_OP; }
158">=" { return GE_OP; }
159"<<" { return LS_OP; }
160">>" { return RS_OP; }
161"<" { return '<'; }
162">" { return '>'; }
163"|" { return '|'; }
164"&" { return '&'; }
165"#" { return '#'; }
166"~" { return '~'; }
167
168"(" { return '('; }
169")" { return ')'; }
170"," { return ','; }
171
172{and} { return AND_OP; }
173{or} { return OR_OP; }
174{not} { return NOT_OP; }
175{is} { return IS_OP; }
176{isnull} { return ISNULL_OP; }
177{notnull} { return NOTNULL_OP; }
178
179{case} { return CASE_KW; }
180{when} { return WHEN_KW; }
181{then} { return THEN_KW; }
182{else} { return ELSE_KW; }
183{end} { return END_KW; }
184
185:{alnum}+ {
186 yylval->str = pg_strdup(yytext + 1);
187 return VARIABLE;
188 }
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
189
190{null} { return NULL_CONST; }
191{true} {
192 yylval->bval = true;
193 return BOOLEAN_CONST;
194 }
195{false} {
196 yylval->bval = false;
197 return BOOLEAN_CONST;
198 }
199"9223372036854775808" {
200 /*
201 * Special handling for PG_INT64_MIN, which can't
202 * accurately be represented here, as the minus sign is
203 * lexed separately and INT64_MIN can't be represented as
204 * a positive integer.
205 */
206 return MAXINT_PLUS_ONE_CONST;
207 }
208{digit}+ {
209 if (!strtoint64(yytext, true, &yylval->ival))
210 expr_yyerror_more(yyscanner, "bigint constant overflow",
211 strdup(yytext));
212 return INTEGER_CONST;
213 }
bool strtoint64(const char *str, bool errorOK, int64 *result)
Definition: pgbench.c:1014
214{digit}+(\.{digit}*)?([eE][-+]?{digit}+)? {
215 if (!strtodouble(yytext, true, &yylval->dval))
216 expr_yyerror_more(yyscanner, "double constant overflow",
217 strdup(yytext));
218 return DOUBLE_CONST;
219 }
bool strtodouble(const char *str, bool errorOK, double *dv)
Definition: pgbench.c:1085
220\.{digit}+([eE][-+]?{digit}+)? {
221 if (!strtodouble(yytext, true, &yylval->dval))
222 expr_yyerror_more(yyscanner, "double constant overflow",
223 strdup(yytext));
224 return DOUBLE_CONST;
225 }
226{alpha}{alnum}* {
227 yylval->str = pg_strdup(yytext);
228 return FUNCTION;
229 }
230
231{space}+ { /* ignore */ }
232
233{continuation} { /* ignore */ }
234
235{newline} {
236 /* report end of command */
237 last_was_newline = true;
238 return 0;
239 }
240
241. {
242 /*
243 * must strdup yytext so that expr_yyerror_more doesn't
244 * change it while finding end of line
245 */
246 expr_yyerror_more(yyscanner, "unexpected character",
247 pg_strdup(yytext));
248 /* NOTREACHED, syntax_error calls exit() */
249 return 0;
250 }
251
252}
253
254<<EOF>> {
255 if (cur_state->buffer_stack == NULL)
256 return 0; /* end of input reached */
257
258 /*
259 * We were expanding a variable, so pop the inclusion
260 * stack and keep lexing
261 */
262 psqlscan_pop_buffer_stack(cur_state);
264 }
void psqlscan_select_top_buffer(PsqlScanState state)
Definition: psqlscan.l:1431
void psqlscan_pop_buffer_stack(PsqlScanState state)
Definition: psqlscan.l:1413
265
266%%

Referenced by expr_lex_one_word(), and expr_yyerror_more().

Variable Documentation

◆ expr_command

const char* expr_command = NULL
static

Definition at line 42 of file exprscan.l.

Referenced by expr_scanner_init(), and expr_yyerror_more().

◆ expr_lineno

int expr_lineno = 0
static

Definition at line 40 of file exprscan.l.

Referenced by expr_scanner_init(), and expr_yyerror_more().

◆ expr_source

const char* expr_source = NULL
static

Definition at line 39 of file exprscan.l.

Referenced by expr_scanner_init(), and expr_yyerror_more().

◆ expr_start_offset

int expr_start_offset = 0
static

Definition at line 41 of file exprscan.l.

Referenced by expr_scanner_init(), and expr_yyerror_more().

◆ last_was_newline

bool last_was_newline = false
static

Definition at line 45 of file exprscan.l.

Referenced by expr_yyerror_more().