PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
psqlscan.l
Go to the documentation of this file.
1%top{
2/*-------------------------------------------------------------------------
3 *
4 * psqlscan.l
5 * lexical scanner for SQL commands
6 *
7 * This lexer used to be part of psql, and that heritage is reflected in
8 * the file name as well as function and typedef names, though it can now
9 * be used by other frontend programs as well. It's also possible to extend
10 * this lexer with a compatible add-on lexer to handle program-specific
11 * backslash commands.
12 *
13 * This code is mainly concerned with determining where the end of a SQL
14 * statement is: we are looking for semicolons that are not within quotes,
15 * comments, or parentheses. The most reliable way to handle this is to
16 * borrow the backend's flex lexer rules, lock, stock, and barrel. The rules
17 * below are (except for a few) the same as the backend's, but their actions
18 * are just ECHO whereas the backend's actions generally do other things.
19 *
20 * XXX The rules in this file must be kept in sync with the backend lexer!!!
21 *
22 * XXX Avoid creating backtracking cases --- see the backend lexer for info.
23 *
24 * See psqlscan_int.h for additional commentary.
25 *
26 *
27 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
28 * Portions Copyright (c) 1994, Regents of the University of California
29 *
30 * IDENTIFICATION
31 * src/fe_utils/psqlscan.l
32 *
33 *-------------------------------------------------------------------------
34 */
35#include "postgres_fe.h"
36
37#include "common/logging.h"
38#include "fe_utils/psqlscan.h"
39
40#include "libpq-fe.h"
41}
42
43%{
44
45/* LCOV_EXCL_START */
46
48
49/*
50 * We must have a typedef YYSTYPE for yylex's first argument, but this lexer
51 * doesn't presently make use of that argument, so just declare it as int.
52 */
53typedef int YYSTYPE;
54
55
56/* Return values from yylex() */
57#define LEXRES_EOL 0 /* end of input */
58#define LEXRES_SEMI 1 /* command-terminating semicolon found */
59#define LEXRES_BACKSLASH 2 /* backslash command start */
60
61
62#define ECHO psqlscan_emit(cur_state, yytext, yyleng)
63
int YYSTYPE
Definition: psqlscan.l:53
64%}
65
66%option reentrant
67%option bison-bridge
68%option 8bit
69%option never-interactive
70%option nodefault
71%option noinput
72%option nounput
73%option noyywrap
74%option warn
75%option prefix="psql_yy"
76
77/*
78 * Set the type of yyextra; we use it as a pointer back to the containing
79 * PsqlScanState.
80 */
81%option extra-type="PsqlScanState"
82
83/*
84 * All of the following definitions and rules should exactly match
85 * src/backend/parser/scan.l so far as the flex patterns are concerned.
86 * The rule bodies are just ECHO as opposed to what the backend does,
87 * however. (But be sure to duplicate code that affects the lexing process,
88 * such as BEGIN() and yyless().) Also, psqlscan uses a single <<EOF>> rule
89 * whereas scan.l has a separate one for each exclusive state.
90 */
91
92/*
93 * OK, here is a short description of lex/flex rules behavior.
94 * The longest pattern which matches an input string is always chosen.
95 * For equal-length patterns, the first occurring in the rules list is chosen.
96 * INITIAL is the starting state, to which all non-conditional rules apply.
97 * Exclusive states change parsing rules while the state is active. When in
98 * an exclusive state, only those rules defined for that state apply.
99 *
100 * We use exclusive states for quoted strings, extended comments,
101 * and to eliminate parsing troubles for numeric strings.
102 * Exclusive states:
103 * <xb> bit string literal
104 * <xc> extended C-style comments
105 * <xd> delimited identifiers (double-quoted identifiers)
106 * <xh> hexadecimal byte string
107 * <xq> standard quoted strings
108 * <xqs> quote stop (detect continued strings)
109 * <xe> extended quoted strings (support backslash escape sequences)
110 * <xdolq> $foo$ quoted strings
111 * <xui> quoted identifier with Unicode escapes
112 * <xus> quoted string with Unicode escapes
113 *
114 * Note: we intentionally don't mimic the backend's <xeu> state; we have
115 * no need to distinguish it from <xe> state, and no good way to get out
116 * of it in error cases. The backend just throws yyerror() in those
117 * cases, but that's not an option here.
118 */
119
120%x xb
121%x xc
122%x xd
123%x xh
124%x xq
125%x xqs
126%x xe
127%x xdolq
128%x xui
129%x xus
130
131/*
132 * In order to make the world safe for Windows and Mac clients as well as
133 * Unix ones, we accept either \n or \r as a newline. A DOS-style \r\n
134 * sequence will be seen as two successive newlines, but that doesn't cause
135 * any problems. Comments that start with -- and extend to the next
136 * newline are treated as equivalent to a single whitespace character.
137 *
138 * NOTE a fine point: if there is no newline following --, we will absorb
139 * everything to the end of the input as a comment. This is correct. Older
140 * versions of Postgres failed to recognize -- as a comment if the input
141 * did not end with a newline.
142 *
143 * non_newline_space tracks all space characters except newlines.
144 *
145 * XXX if you change the set of whitespace characters, fix scanner_isspace()
146 * to agree.
147 */
148
149space [ \t\n\r\f\v]
150non_newline_space [ \t\f\v]
151newline [\n\r]
152non_newline [^\n\r]
153
154comment ("--"{non_newline}*)
155
156whitespace ({space}+|{comment})
157
158/*
159 * SQL requires at least one newline in the whitespace separating
160 * string literals that are to be concatenated. Silly, but who are we
161 * to argue? Note that {whitespace_with_newline} should not have * after
162 * it, whereas {whitespace} should generally have a * after it...
163 */
164
165special_whitespace ({space}+|{comment}{newline})
166non_newline_whitespace ({non_newline_space}|{comment})
167whitespace_with_newline ({non_newline_whitespace}*{newline}{special_whitespace}*)
168
169quote '
170/* If we see {quote} then {quotecontinue}, the quoted string continues */
171quotecontinue {whitespace_with_newline}{quote}
172
173/*
174 * {quotecontinuefail} is needed to avoid lexer backup when we fail to match
175 * {quotecontinue}. It might seem that this could just be {whitespace}*,
176 * but if there's a dash after {whitespace_with_newline}, it must be consumed
177 * to see if there's another dash --- which would start a {comment} and thus
178 * allow continuation of the {quotecontinue} token.
179 */
180quotecontinuefail {whitespace}*"-"?
181
182/* Bit string
183 * It is tempting to scan the string for only those characters
184 * which are allowed. However, this leads to silently swallowed
185 * characters if illegal characters are included in the string.
186 * For example, if xbinside is [01] then B'ABCD' is interpreted
187 * as a zero-length string, and the ABCD' is lost!
188 * Better to pass the string forward and let the input routines
189 * validate the contents.
190 */
191xbstart [bB]{quote}
192xbinside [^']*
193
194/* Hexadecimal byte string */
195xhstart [xX]{quote}
196xhinside [^']*
197
198/* National character */
199xnstart [nN]{quote}
200
201/* Quoted string that allows backslash escapes */
202xestart [eE]{quote}
203xeinside [^\\']+
204xeescape [\\][^0-7]
205xeoctesc [\\][0-7]{1,3}
206xehexesc [\\]x[0-9A-Fa-f]{1,2}
207xeunicode [\\](u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})
208xeunicodefail [\\](u[0-9A-Fa-f]{0,3}|U[0-9A-Fa-f]{0,7})
209
210/* Extended quote
211 * xqdouble implements embedded quote, ''''
212 */
213xqstart {quote}
214xqdouble {quote}{quote}
215xqinside [^']+
216
217/* $foo$ style quotes ("dollar quoting")
218 * The quoted string starts with $foo$ where "foo" is an optional string
219 * in the form of an identifier, except that it may not contain "$",
220 * and extends to the first occurrence of an identical string.
221 * There is *no* processing of the quoted text.
222 *
223 * {dolqfailed} is an error rule to avoid scanner backup when {dolqdelim}
224 * fails to match its trailing "$".
225 */
226dolq_start [A-Za-z\200-\377_]
227dolq_cont [A-Za-z\200-\377_0-9]
228dolqdelim \$({dolq_start}{dolq_cont}*)?\$
229dolqfailed \${dolq_start}{dolq_cont}*
230dolqinside [^$]+
231
232/* Double quote
233 * Allows embedded spaces and other special characters into identifiers.
234 */
235dquote \"
236xdstart {dquote}
237xdstop {dquote}
238xddouble {dquote}{dquote}
239xdinside [^"]+
240
241/* Quoted identifier with Unicode escapes */
242xuistart [uU]&{dquote}
243
244/* Quoted string with Unicode escapes */
245xusstart [uU]&{quote}
246
247/* error rule to avoid backup */
248xufailed [uU]&
249
250
251/* C-style comments
252 *
253 * The "extended comment" syntax closely resembles allowable operator syntax.
254 * The tricky part here is to get lex to recognize a string starting with
255 * slash-star as a comment, when interpreting it as an operator would produce
256 * a longer match --- remember lex will prefer a longer match! Also, if we
257 * have something like plus-slash-star, lex will think this is a 3-character
258 * operator whereas we want to see it as a + operator and a comment start.
259 * The solution is two-fold:
260 * 1. append {op_chars}* to xcstart so that it matches as much text as
261 * {operator} would. Then the tie-breaker (first matching rule of same
262 * length) ensures xcstart wins. We put back the extra stuff with yyless()
263 * in case it contains a star-slash that should terminate the comment.
264 * 2. In the operator rule, check for slash-star within the operator, and
265 * if found throw it back with yyless(). This handles the plus-slash-star
266 * problem.
267 * Dash-dash comments have similar interactions with the operator rule.
268 */
269xcstart \/\*{op_chars}*
270xcstop \*+\/
271xcinside [^*/]+
272
273ident_start [A-Za-z\200-\377_]
274ident_cont [A-Za-z\200-\377_0-9\$]
275
276identifier {ident_start}{ident_cont}*
277
278/* Assorted special-case operators and operator-like tokens */
279typecast "::"
280dot_dot \.\.
281colon_equals ":="
282
283/*
284 * These operator-like tokens (unlike the above ones) also match the {operator}
285 * rule, which means that they might be overridden by a longer match if they
286 * are followed by a comment start or a + or - character. Accordingly, if you
287 * add to this list, you must also add corresponding code to the {operator}
288 * block to return the correct token in such cases. (This is not needed in
289 * psqlscan.l since the token value is ignored there.)
290 */
291equals_greater "=>"
292less_equals "<="
293greater_equals ">="
294less_greater "<>"
295not_equals "!="
296
297/*
298 * "self" is the set of chars that should be returned as single-character
299 * tokens. "op_chars" is the set of chars that can make up "Op" tokens,
300 * which can be one or more characters long (but if a single-char token
301 * appears in the "self" set, it is not to be returned as an Op). Note
302 * that the sets overlap, but each has some chars that are not in the other.
303 *
304 * If you change either set, adjust the character lists appearing in the
305 * rule for "operator"!
306 */
307self [,()\[\].;\:\+\-\*\/\%\^<>\=]
308op_chars [\~\!\@\#\^\&\|\`\?\+\-\*\/\%<>\=]
309operator {op_chars}+
310
311/*
312 * Numbers
313 *
314 * Unary minus is not part of a number here. Instead we pass it separately to
315 * the parser, and there it gets coerced via doNegate().
316 *
317 * {numericfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
318 *
319 * {realfail} is added to prevent the need for scanner
320 * backup when the {real} rule fails to match completely.
321 */
322decdigit [0-9]
323hexdigit [0-9A-Fa-f]
324octdigit [0-7]
325bindigit [0-1]
326
327decinteger {decdigit}(_?{decdigit})*
328hexinteger 0[xX](_?{hexdigit})+
329octinteger 0[oO](_?{octdigit})+
330bininteger 0[bB](_?{bindigit})+
331
332hexfail 0[xX]_?
333octfail 0[oO]_?
334binfail 0[bB]_?
335
336numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
337numericfail {decinteger}\.\.
338
339real ({decinteger}|{numeric})[Ee][-+]?{decinteger}
340realfail ({decinteger}|{numeric})[Ee][-+]
341
342/* Positional parameters don't accept underscores. */
343param \${decdigit}+
344
345/*
346 * An identifier immediately following an integer literal is disallowed because
347 * in some cases it's ambiguous what is meant: for example, 0x1234 could be
348 * either a hexinteger or a decinteger "0" and an identifier "x1234". We can
349 * detect such problems by seeing if integer_junk matches a longer substring
350 * than any of the XXXinteger patterns (decinteger, hexinteger, octinteger,
351 * bininteger). One "junk" pattern is sufficient because
352 * {decinteger}{identifier} will match all the same strings we'd match with
353 * {hexinteger}{identifier} etc.
354 *
355 * Note that the rule for integer_junk must appear after the ones for
356 * XXXinteger to make this work correctly: 0x1234 will match both hexinteger
357 * and integer_junk, and we need hexinteger to be chosen in that case.
358 *
359 * Also disallow strings matched by numeric_junk, real_junk and param_junk
360 * for consistency.
361 */
362integer_junk {decinteger}{identifier}
363numeric_junk {numeric}{identifier}
364real_junk {real}{identifier}
365param_junk \${decdigit}+{identifier}
366
367/* psql-specific: characters allowed in variable names */
368variable_char [A-Za-z\200-\377_0-9]
369
370other .
371
372/*
373 * Dollar quoted strings are totally opaque, and no escaping is done on them.
374 * Other quoted strings must allow some special characters such as single-quote
375 * and newline.
376 * Embedded single-quotes are implemented both in the SQL standard
377 * style of two adjacent single quotes "''" and in the Postgres/Java style
378 * of escaped-quote "\'".
379 * Other embedded escaped characters are matched explicitly and the leading
380 * backslash is dropped from the string.
381 * Note that xcstart must appear before operator, as explained above!
382 * Also whitespace (comment) must appear before operator.
383 */
384
386
387%{
388 /* Declare some local variables inside yylex(), for convenience */
389 PsqlScanState cur_state = yyextra;
#define yyextra
Definition: scan.l:1118
390 PQExpBuffer output_buf = cur_state->output_buf;
391
392 /*
393 * Force flex into the state indicated by start_state. This has a
394 * couple of purposes: it lets some of the functions below set a new
395 * starting state without ugly direct access to flex variables, and it
396 * allows us to transition from one flex lexer to another so that we
397 * can lex different parts of the source string using separate lexers.
398 */
399 BEGIN(cur_state->start_state);
400%}
401
402{whitespace} {
403 /*
404 * Note that the whitespace rule includes both true
405 * whitespace and single-line ("--" style) comments.
406 * We suppress whitespace until we have collected some
407 * non-whitespace data. (This interacts with some
408 * decisions in MainLoop(); see there for details.)
409 */
410 if (output_buf->len > 0)
411 ECHO;
412 }
#define ECHO
Definition: psqlscan.l:62
413
414{xcstart} {
415 cur_state->xcdepth = 0;
416 BEGIN(xc);
417 /* Put back any characters past slash-star; see above */
418 yyless(2);
419 ECHO;
420 }
421
422<xc>{
423{xcstart} {
424 cur_state->xcdepth++;
425 /* Put back any characters past slash-star; see above */
426 yyless(2);
427 ECHO;
428 }
429
430{xcstop} {
431 if (cur_state->xcdepth <= 0)
432 BEGIN(INITIAL);
433 else
434 cur_state->xcdepth--;
435 ECHO;
436 }
437
438{xcinside} {
439 ECHO;
440 }
441
442{op_chars} {
443 ECHO;
444 }
445
446\*+ {
447 ECHO;
448 }
449} /* <xc> */
450
451{xbstart} {
452 BEGIN(xb);
453 ECHO;
454 }
455<xh>{xhinside} |
456<xb>{xbinside} {
457 ECHO;
458 }
459
460{xhstart} {
461 /* Hexadecimal bit type.
462 * At some point we should simply pass the string
463 * forward to the parser and label it there.
464 * In the meantime, place a leading "x" on the string
465 * to mark it for the input routine as a hex string.
466 */
467 BEGIN(xh);
468 ECHO;
469 }
470
471{xnstart} {
472 yyless(1); /* eat only 'n' this time */
473 ECHO;
474 }
475
476{xqstart} {
477 if (cur_state->std_strings)
478 BEGIN(xq);
479 else
480 BEGIN(xe);
481 ECHO;
482 }
483{xestart} {
484 BEGIN(xe);
485 ECHO;
486 }
487{xusstart} {
488 BEGIN(xus);
489 ECHO;
490 }
491
492<xb,xh,xq,xe,xus>{quote} {
493 /*
494 * When we are scanning a quoted string and see an end
495 * quote, we must look ahead for a possible continuation.
496 * If we don't see one, we know the end quote was in fact
497 * the end of the string. To reduce the lexer table size,
498 * we use a single "xqs" state to do the lookahead for all
499 * types of strings.
500 */
501 cur_state->state_before_str_stop = YYSTATE;
502 BEGIN(xqs);
503 ECHO;
504 }
505<xqs>{quotecontinue} {
506 /*
507 * Found a quote continuation, so return to the in-quote
508 * state and continue scanning the literal. Nothing is
509 * added to the literal's contents.
510 */
511 BEGIN(cur_state->state_before_str_stop);
512 ECHO;
513 }
514<xqs>{quotecontinuefail} |
515<xqs>{other} {
516 /*
517 * Failed to see a quote continuation. Throw back
518 * everything after the end quote, and handle the string
519 * according to the state we were in previously.
520 */
521 yyless(0);
522 BEGIN(INITIAL);
523 /* There's nothing to echo ... */
524 }
525
526<xq,xe,xus>{xqdouble} {
527 ECHO;
528 }
529<xq,xus>{xqinside} {
530 ECHO;
531 }
532<xe>{xeinside} {
533 ECHO;
534 }
535<xe>{xeunicode} {
536 ECHO;
537 }
538<xe>{xeunicodefail} {
539 ECHO;
540 }
541<xe>{xeescape} {
542 ECHO;
543 }
544<xe>{xeoctesc} {
545 ECHO;
546 }
547<xe>{xehexesc} {
548 ECHO;
549 }
550<xe>. {
551 /* This is only needed for \ just before EOF */
552 ECHO;
553 }
554
555{dolqdelim} {
556 cur_state->dolqstart = pg_strdup(yytext);
557 BEGIN(xdolq);
558 ECHO;
559 }
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
560{dolqfailed} {
561 /* throw back all but the initial "$" */
562 yyless(1);
563 ECHO;
564 }
565<xdolq>{dolqdelim} {
566 if (strcmp(yytext, cur_state->dolqstart) == 0)
567 {
568 free(cur_state->dolqstart);
569 cur_state->dolqstart = NULL;
570 BEGIN(INITIAL);
571 }
572 else
573 {
574 /*
575 * When we fail to match $...$ to dolqstart, transfer
576 * the $... part to the output, but put back the final
577 * $ for rescanning. Consider $delim$...$junk$delim$
578 */
579 yyless(yyleng - 1);
580 }
581 ECHO;
582 }
#define free(a)
Definition: header.h:65
#define yyleng
Definition: scan.l:1124
583<xdolq>{dolqinside} {
584 ECHO;
585 }
586<xdolq>{dolqfailed} {
587 ECHO;
588 }
589<xdolq>. {
590 /* This is only needed for $ inside the quoted text */
591 ECHO;
592 }
593
594{xdstart} {
595 BEGIN(xd);
596 ECHO;
597 }
598{xuistart} {
599 BEGIN(xui);
600 ECHO;
601 }
602<xd>{xdstop} {
603 BEGIN(INITIAL);
604 ECHO;
605 }
606<xui>{dquote} {
607 BEGIN(INITIAL);
608 ECHO;
609 }
610<xd,xui>{xddouble} {
611 ECHO;
612 }
613<xd,xui>{xdinside} {
614 ECHO;
615 }
616
617{xufailed} {
618 /* throw back all but the initial u/U */
619 yyless(1);
620 ECHO;
621 }
622
623{typecast} {
624 ECHO;
625 }
626
627{dot_dot} {
628 ECHO;
629 }
630
631{colon_equals} {
632 ECHO;
633 }
634
635{equals_greater} {
636 ECHO;
637 }
638
639{less_equals} {
640 ECHO;
641 }
642
643{greater_equals} {
644 ECHO;
645 }
646
647{less_greater} {
648 ECHO;
649 }
650
651{not_equals} {
652 ECHO;
653 }
654
655 /*
656 * These rules are specific to psql --- they implement parenthesis
657 * counting and detection of command-ending semicolon. These must
658 * appear before the {self} rule so that they take precedence over it.
659 */
660
661"(" {
662 cur_state->paren_depth++;
663 ECHO;
664 }
665
666")" {
667 if (cur_state->paren_depth > 0)
668 cur_state->paren_depth--;
669 ECHO;
670 }
671
672";" {
673 ECHO;
674 if (cur_state->paren_depth == 0 && cur_state->begin_depth == 0)
675 {
676 /* Terminate lexing temporarily */
677 cur_state->start_state = YY_START;
678 cur_state->identifier_count = 0;
679 return LEXRES_SEMI;
680 }
681 }
#define LEXRES_SEMI
Definition: psqlscan.l:58
682
683 /*
684 * psql-specific rules to handle backslash commands and variable
685 * substitution. We want these before {self}, also.
686 */
687
688"\\"[;:] {
689 /* Force a semi-colon or colon into the query buffer */
690 psqlscan_emit(cur_state, yytext + 1, 1);
691 if (yytext[1] == ';')
692 cur_state->identifier_count = 0;
693 }
void psqlscan_emit(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1517
694
695"\\" {
696 /* Terminate lexing temporarily */
697 cur_state->start_state = YY_START;
698 return LEXRES_BACKSLASH;
699 }
#define LEXRES_BACKSLASH
Definition: psqlscan.l:59
700
701:{variable_char}+ {
702 /* Possible psql variable substitution */
703 char *varname;
704 char *value;
705
706 varname = psqlscan_extract_substring(cur_state,
707 yytext + 1,
708 yyleng - 1);
709 if (cur_state->callbacks->get_variable)
710 value = cur_state->callbacks->get_variable(varname,
712 cur_state->cb_passthrough);
713 else
714 value = NULL;
715
716 if (value)
717 {
718 /* It is a variable, check for recursion */
719 if (psqlscan_var_is_current_source(cur_state, varname))
720 {
721 /* Recursive expansion --- don't go there */
722 pg_log_warning("skipping recursive expansion of variable \"%s\"",
723 varname);
724 /* Instead copy the string as is */
725 ECHO;
726 }
727 else
728 {
729 /* OK, perform substitution */
730 psqlscan_push_new_buffer(cur_state, value, varname);
731 /* yy_scan_string already made buffer active */
732 }
733 free(value);
734 }
735 else
736 {
737 /*
738 * if the variable doesn't exist we'll copy the string
739 * as is
740 */
741 ECHO;
742 }
743
744 free(varname);
745 }
static struct @165 value
#define pg_log_warning(...)
Definition: pgfnames.c:24
@ PQUOTE_PLAIN
Definition: psqlscan.h:54
char * psqlscan_extract_substring(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1549
void psqlscan_push_new_buffer(PsqlScanState state, const char *newstr, const char *varname)
Definition: psqlscan.l:1374
bool psqlscan_var_is_current_source(PsqlScanState state, const char *varname)
Definition: psqlscan.l:1454
746
747:'{variable_char}+' {
748 psqlscan_escape_variable(cur_state, yytext, yyleng,
750 }
@ PQUOTE_SQL_LITERAL
Definition: psqlscan.h:55
void psqlscan_escape_variable(PsqlScanState state, const char *txt, int len, PsqlScanQuoteType quote)
Definition: psqlscan.l:1585
751
752:\"{variable_char}+\" {
753 psqlscan_escape_variable(cur_state, yytext, yyleng,
755 }
@ PQUOTE_SQL_IDENT
Definition: psqlscan.h:56
756
757:\{\?{variable_char}+\} {
758 psqlscan_test_variable(cur_state, yytext, yyleng);
759 }
void psqlscan_test_variable(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1614
760
761 /*
762 * These rules just avoid the need for scanner backup if one of the
763 * three rules above fails to match completely.
764 */
765
766:'{variable_char}* {
767 /* Throw back everything but the colon */
768 yyless(1);
769 ECHO;
770 }
771
772:\"{variable_char}* {
773 /* Throw back everything but the colon */
774 yyless(1);
775 ECHO;
776 }
777
778:\{\?{variable_char}* {
779 /* Throw back everything but the colon */
780 yyless(1);
781 ECHO;
782 }
783:\{ {
784 /* Throw back everything but the colon */
785 yyless(1);
786 ECHO;
787 }
788
789 /*
790 * Back to backend-compatible rules.
791 */
792
793{self} {
794 ECHO;
795 }
796
797{operator} {
798 /*
799 * Check for embedded slash-star or dash-dash; those
800 * are comment starts, so operator must stop there.
801 * Note that slash-star or dash-dash at the first
802 * character will match a prior rule, not this one.
803 */
804 int nchars = yyleng;
805 char *slashstar = strstr(yytext, "/*");
806 char *dashdash = strstr(yytext, "--");
807
808 if (slashstar && dashdash)
809 {
810 /* if both appear, take the first one */
811 if (slashstar > dashdash)
812 slashstar = dashdash;
813 }
814 else if (!slashstar)
815 slashstar = dashdash;
816 if (slashstar)
817 nchars = slashstar - yytext;
818
819 /*
820 * For SQL compatibility, '+' and '-' cannot be the
821 * last char of a multi-char operator unless the operator
822 * contains chars that are not in SQL operators.
823 * The idea is to lex '=-' as two operators, but not
824 * to forbid operator names like '?-' that could not be
825 * sequences of SQL operators.
826 */
827 if (nchars > 1 &&
828 (yytext[nchars - 1] == '+' ||
829 yytext[nchars - 1] == '-'))
830 {
831 int ic;
832
833 for (ic = nchars - 2; ic >= 0; ic--)
834 {
835 char c = yytext[ic];
836 if (c == '~' || c == '!' || c == '@' ||
837 c == '#' || c == '^' || c == '&' ||
838 c == '|' || c == '`' || c == '?' ||
839 c == '%')
840 break;
841 }
842 if (ic < 0)
843 {
844 /*
845 * didn't find a qualifying character, so remove
846 * all trailing [+-]
847 */
848 do {
849 nchars--;
850 } while (nchars > 1 &&
851 (yytext[nchars - 1] == '+' ||
852 yytext[nchars - 1] == '-'));
853 }
854 }
855
856 if (nchars < yyleng)
857 {
858 /* Strip the unwanted chars from the token */
859 yyless(nchars);
860 }
861 ECHO;
862 }
char * c
863
864{param} {
865 ECHO;
866 }
867{param_junk} {
868 ECHO;
869 }
870
871{decinteger} {
872 ECHO;
873 }
874{hexinteger} {
875 ECHO;
876 }
877{octinteger} {
878 ECHO;
879 }
880{bininteger} {
881 ECHO;
882 }
883{hexfail} {
884 ECHO;
885 }
886{octfail} {
887 ECHO;
888 }
889{binfail} {
890 ECHO;
891 }
892{numeric} {
893 ECHO;
894 }
895{numericfail} {
896 /* throw back the .., and treat as integer */
897 yyless(yyleng - 2);
898 ECHO;
899 }
900{real} {
901 ECHO;
902 }
903{realfail} {
904 ECHO;
905 }
906{integer_junk} {
907 ECHO;
908 }
909{numeric_junk} {
910 ECHO;
911 }
912{real_junk} {
913 ECHO;
914 }
915
916
917{identifier} {
918 /*
919 * We need to track if we are inside a BEGIN .. END block
920 * in a function definition, so that semicolons contained
921 * therein don't terminate the whole statement. Short of
922 * writing a full parser here, the following heuristic
923 * should work. First, we track whether the beginning of
924 * the statement matches CREATE [OR REPLACE]
925 * {FUNCTION|PROCEDURE}
926 */
927
928 if (cur_state->identifier_count == 0)
929 memset(cur_state->identifiers, 0, sizeof(cur_state->identifiers));
930
931 if (pg_strcasecmp(yytext, "create") == 0 ||
932 pg_strcasecmp(yytext, "function") == 0 ||
933 pg_strcasecmp(yytext, "procedure") == 0 ||
934 pg_strcasecmp(yytext, "or") == 0 ||
935 pg_strcasecmp(yytext, "replace") == 0)
936 {
937 if (cur_state->identifier_count < sizeof(cur_state->identifiers))
938 cur_state->identifiers[cur_state->identifier_count] = pg_tolower((unsigned char) yytext[0]);
939 }
940
941 cur_state->identifier_count++;
942
943 if (cur_state->identifiers[0] == 'c' &&
944 (cur_state->identifiers[1] == 'f' || cur_state->identifiers[1] == 'p' ||
945 (cur_state->identifiers[1] == 'o' && cur_state->identifiers[2] == 'r' &&
946 (cur_state->identifiers[3] == 'f' || cur_state->identifiers[3] == 'p'))) &&
947 cur_state->paren_depth == 0)
948 {
949 if (pg_strcasecmp(yytext, "begin") == 0)
950 cur_state->begin_depth++;
951 else if (pg_strcasecmp(yytext, "case") == 0)
952 {
953 /*
954 * CASE also ends with END. We only need to track
955 * this if we are already inside a BEGIN.
956 */
957 if (cur_state->begin_depth >= 1)
958 cur_state->begin_depth++;
959 }
960 else if (pg_strcasecmp(yytext, "end") == 0)
961 {
962 if (cur_state->begin_depth > 0)
963 cur_state->begin_depth--;
964 }
965 }
966
967 ECHO;
968 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122
969
970{other} {
971 ECHO;
972 }
973
974<<EOF>> {
975 if (cur_state->buffer_stack == NULL)
976 {
977 cur_state->start_state = YY_START;
978 return LEXRES_EOL; /* end of input reached */
979 }
980
981 /*
982 * We were expanding a variable, so pop the inclusion
983 * stack and keep lexing
984 */
985 psqlscan_pop_buffer_stack(cur_state);
987 }
void psqlscan_select_top_buffer(PsqlScanState state)
Definition: psqlscan.l:1431
#define LEXRES_EOL
Definition: psqlscan.l:57
void psqlscan_pop_buffer_stack(PsqlScanState state)
Definition: psqlscan.l:1413
988
989%%
990
991/* LCOV_EXCL_STOP */
992
993/*
994 * Create a lexer working state struct.
995 *
996 * callbacks is a struct of function pointers that encapsulate some
997 * behavior we need from the surrounding program. This struct must
998 * remain valid for the lifespan of the PsqlScanState.
999 */
1002{
1004
1006
1007 state->callbacks = callbacks;
1008
1009 yylex_init(&state->scanner);
1010
1011 yyset_extra(state, state->scanner);
1012
1014
1015 return state;
1016}
1017
1018/*
1019 * Destroy a lexer working state struct, releasing all resources.
1020 */
1021void
1023{
1025
1027
1028 yylex_destroy(state->scanner);
1029
1030 free(state);
1031}
1032
1033/*
1034 * Set the callback passthrough pointer for the lexer.
1035 *
1036 * This could have been integrated into psql_scan_create, but keeping it
1037 * separate allows the application to change the pointer later, which might
1038 * be useful.
1039 */
1040void
1042{
1043 state->cb_passthrough = passthrough;
1044}
1045
1046/*
1047 * Set up to perform lexing of the given input line.
1048 *
1049 * The text at *line, extending for line_len bytes, will be scanned by
1050 * subsequent calls to the psql_scan routines. psql_scan_finish should
1051 * be called when scanning is complete. Note that the lexer retains
1052 * a pointer to the storage at *line --- this string must not be altered
1053 * or freed until after psql_scan_finish is called.
1054 *
1055 * encoding is the libpq identifier for the character encoding in use,
1056 * and std_strings says whether standard_conforming_strings is on.
1057 */
1058void
1060 const char *line, int line_len,
1061 int encoding, bool std_strings)
1062{
1063 /* Mustn't be scanning already */
1064 Assert(state->scanbufhandle == NULL);
1065 Assert(state->buffer_stack == NULL);
1066
1067 /* Do we need to hack the character set encoding? */
1068 state->encoding = encoding;
1069 state->safe_encoding = pg_valid_server_encoding_id(encoding);
1070
1071 /* Save standard-strings flag as well */
1072 state->std_strings = std_strings;
1073
1074 /* Set up flex input buffer with appropriate translation and padding */
1075 state->scanbufhandle = psqlscan_prepare_buffer(state, line, line_len,
1076 &state->scanbuf);
1077 state->scanline = line;
1078
1079 /* Set lookaside data in case we have to map unsafe encoding */
1080 state->curline = state->scanbuf;
1081 state->refline = state->scanline;
1082
1083 /* Initialize state for psql_scan_get_location() */
1084 state->cur_line_no = 0; /* yylex not called yet */
1085 state->cur_line_ptr = state->scanbuf;
1086}
1087
1088/*
1089 * Do lexical analysis of SQL command text.
1090 *
1091 * The text previously passed to psql_scan_setup is scanned, and appended
1092 * (possibly with transformation) to query_buf.
1093 *
1094 * The return value indicates the condition that stopped scanning:
1095 *
1096 * PSCAN_SEMICOLON: found a command-ending semicolon. (The semicolon is
1097 * transferred to query_buf.) The command accumulated in query_buf should
1098 * be executed, then clear query_buf and call again to scan the remainder
1099 * of the line.
1100 *
1101 * PSCAN_BACKSLASH: found a backslash that starts a special command.
1102 * Any previous data on the line has been transferred to query_buf.
1103 * The caller will typically next apply a separate flex lexer to scan
1104 * the special command.
1105 *
1106 * PSCAN_INCOMPLETE: the end of the line was reached, but we have an
1107 * incomplete SQL command. *prompt is set to the appropriate prompt type.
1108 *
1109 * PSCAN_EOL: the end of the line was reached, and there is no lexical
1110 * reason to consider the command incomplete. The caller may or may not
1111 * choose to send it. *prompt is set to the appropriate prompt type if
1112 * the caller chooses to collect more input.
1113 *
1114 * In the PSCAN_INCOMPLETE and PSCAN_EOL cases, psql_scan_finish() should
1115 * be called next, then the cycle may be repeated with a fresh input line.
1116 *
1117 * In all cases, *prompt is set to an appropriate prompt type code for the
1118 * next line-input operation.
1119 */
1122 PQExpBuffer query_buf,
1123 promptStatus_t *prompt)
1124{
1125 PsqlScanResult result;
1126 int lexresult;
1127
1128 /* Must be scanning already */
1129 Assert(state->scanbufhandle != NULL);
1130
1131 /* Set current output target */
1132 state->output_buf = query_buf;
1133
1134 /* Set input source */
1135 if (state->buffer_stack != NULL)
1136 yy_switch_to_buffer(state->buffer_stack->buf, state->scanner);
1137 else
1138 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
1139
1140 /* And lex. */
1141 lexresult = yylex(NULL, state->scanner);
1142
1143 /* Notify psql_scan_get_location() that a yylex call has been made. */
1144 if (state->cur_line_no == 0)
1145 state->cur_line_no = 1;
1146
1147 /*
1148 * Check termination state and return appropriate result info.
1149 */
1150 switch (lexresult)
1151 {
1152 case LEXRES_EOL: /* end of input */
1153 switch (state->start_state)
1154 {
1155 case INITIAL:
1156 case xqs: /* we treat this like INITIAL */
1157 if (state->paren_depth > 0)
1158 {
1159 result = PSCAN_INCOMPLETE;
1160 *prompt = PROMPT_PAREN;
1161 }
1162 else if (state->begin_depth > 0)
1163 {
1164 result = PSCAN_INCOMPLETE;
1165 *prompt = PROMPT_CONTINUE;
1166 }
1167 else if (query_buf->len > 0)
1168 {
1169 result = PSCAN_EOL;
1170 *prompt = PROMPT_CONTINUE;
1171 }
1172 else
1173 {
1174 /* never bother to send an empty buffer */
1175 result = PSCAN_INCOMPLETE;
1176 *prompt = PROMPT_READY;
1177 }
1178 break;
1179 case xb:
1180 result = PSCAN_INCOMPLETE;
1181 *prompt = PROMPT_SINGLEQUOTE;
1182 break;
1183 case xc:
1184 result = PSCAN_INCOMPLETE;
1185 *prompt = PROMPT_COMMENT;
1186 break;
1187 case xd:
1188 result = PSCAN_INCOMPLETE;
1189 *prompt = PROMPT_DOUBLEQUOTE;
1190 break;
1191 case xh:
1192 result = PSCAN_INCOMPLETE;
1193 *prompt = PROMPT_SINGLEQUOTE;
1194 break;
1195 case xe:
1196 result = PSCAN_INCOMPLETE;
1197 *prompt = PROMPT_SINGLEQUOTE;
1198 break;
1199 case xq:
1200 result = PSCAN_INCOMPLETE;
1201 *prompt = PROMPT_SINGLEQUOTE;
1202 break;
1203 case xdolq:
1204 result = PSCAN_INCOMPLETE;
1205 *prompt = PROMPT_DOLLARQUOTE;
1206 break;
1207 case xui:
1208 result = PSCAN_INCOMPLETE;
1209 *prompt = PROMPT_DOUBLEQUOTE;
1210 break;
1211 case xus:
1212 result = PSCAN_INCOMPLETE;
1213 *prompt = PROMPT_SINGLEQUOTE;
1214 break;
1215 default:
1216 /* can't get here */
1217 fprintf(stderr, "invalid YY_START\n");
1218 exit(1);
1219 }
1220 break;
1221 case LEXRES_SEMI: /* semicolon */
1222 result = PSCAN_SEMICOLON;
1223 *prompt = PROMPT_READY;
1224 break;
1225 case LEXRES_BACKSLASH: /* backslash */
1226 result = PSCAN_BACKSLASH;
1227 *prompt = PROMPT_READY;
1228 break;
1229 default:
1230 /* can't get here */
1231 fprintf(stderr, "invalid yylex result\n");
1232 exit(1);
1233 }
1234
1235 return result;
1236}
1237
1238/*
1239 * Clean up after scanning a string. This flushes any unread input and
1240 * releases resources (but not the PsqlScanState itself). Note however
1241 * that this does not reset the lexer scan state; that can be done by
1242 * psql_scan_reset(), which is an orthogonal operation.
1243 *
1244 * It is legal to call this when not scanning anything (makes it easier
1245 * to deal with error recovery).
1246 */
1247void
1249{
1250 /* Drop any incomplete variable expansions. */
1251 while (state->buffer_stack != NULL)
1253
1254 /* Done with the outer scan buffer, too */
1255 if (state->scanbufhandle)
1256 yy_delete_buffer(state->scanbufhandle, state->scanner);
1257 state->scanbufhandle = NULL;
1258 if (state->scanbuf)
1259 free(state->scanbuf);
1260 state->scanbuf = NULL;
1261}
1262
1263/*
1264 * Reset lexer scanning state to start conditions. This is appropriate
1265 * for executing \r psql commands (or any other time that we discard the
1266 * prior contents of query_buf). It is not, however, necessary to do this
1267 * when we execute and clear the buffer after getting a PSCAN_SEMICOLON or
1268 * PSCAN_EOL scan result, because the scan state must be INITIAL when those
1269 * conditions are returned.
1270 *
1271 * Note that this is unrelated to flushing unread input; that task is
1272 * done by psql_scan_finish().
1273 */
1274void
1276{
1277 state->start_state = INITIAL;
1278 state->paren_depth = 0;
1279 state->xcdepth = 0; /* not really necessary */
1280 if (state->dolqstart)
1281 free(state->dolqstart);
1282 state->dolqstart = NULL;
1283 state->identifier_count = 0;
1284 state->begin_depth = 0;
1285}
1286
1287/*
1288 * Reselect this lexer (psqlscan.l) after using another one.
1289 *
1290 * Currently and for foreseeable uses, it's sufficient to reset to INITIAL
1291 * state, because we'd never switch to another lexer in a different state.
1292 * However, we don't want to reset e.g. paren_depth, so this can't be
1293 * the same as psql_scan_reset().
1294 *
1295 * Note: psql setjmp error recovery just calls psql_scan_reset(), so that
1296 * must be a superset of this.
1297 *
1298 * Note: it seems likely that other lexers could just assign INITIAL for
1299 * themselves, since that probably has the value zero in every flex-generated
1300 * lexer. But let's not assume that.
1301 */
1302void
1304{
1305 state->start_state = INITIAL;
1306}
1307
1308/*
1309 * Return true if lexer is currently in an "inside quotes" state.
1310 *
1311 * This is pretty grotty but is needed to preserve the old behavior
1312 * that mainloop.c drops blank lines not inside quotes without even
1313 * echoing them.
1314 */
1315bool
1317{
1318 return state->start_state != INITIAL &&
1319 state->start_state != xqs;
1320}
1321
1322/*
1323 * Return the current scanning location (end+1 of last scanned token),
1324 * as a line number counted from 1 and an offset from string start.
1325 *
1326 * This considers only the outermost input string, and therefore is of
1327 * limited use for programs that use psqlscan_push_new_buffer().
1328 *
1329 * It would be a bit easier probably to use "%option yylineno" to count
1330 * lines, but the flex manual says that has a performance cost, and only
1331 * a minority of programs using psqlscan have need for this functionality.
1332 * So we implement it ourselves without adding overhead to the lexer itself.
1333 */
1334void
1336 int *lineno, int *offset)
1337{
1338 const char *line_end;
1339
1340 /*
1341 * We rely on flex's having stored a NUL after the current token in
1342 * scanbuf. Therefore we must specially handle the state before yylex()
1343 * has been called, when obviously that won't have happened yet.
1344 */
1345 if (state->cur_line_no == 0)
1346 {
1347 *lineno = 1;
1348 *offset = 0;
1349 return;
1350 }
1351
1352 /*
1353 * Advance cur_line_no/cur_line_ptr past whatever has been lexed so far.
1354 * Doing this prevents repeated calls from being O(N^2) for long inputs.
1355 */
1356 while ((line_end = strchr(state->cur_line_ptr, '\n')) != NULL)
1357 {
1358 state->cur_line_no++;
1359 state->cur_line_ptr = line_end + 1;
1360 }
1361 state->cur_line_ptr += strlen(state->cur_line_ptr);
1362
1363 /* Report current location. */
1364 *lineno = state->cur_line_no;
1365 *offset = state->cur_line_ptr - state->scanbuf;
1366}
1367
1368/*
1369 * Push the given string onto the stack of stuff to scan.
1370 *
1371 * NOTE SIDE EFFECT: the new buffer is made the active flex input buffer.
1372 */
1373void
1375 const char *varname)
1376{
1377 StackElem *stackelem;
1378
1379 stackelem = (StackElem *) pg_malloc(sizeof(StackElem));
1380
1381 /*
1382 * In current usage, the passed varname points at the current flex input
1383 * buffer; we must copy it before calling psqlscan_prepare_buffer()
1384 * because that will change the buffer state.
1385 */
1386 stackelem->varname = varname ? pg_strdup(varname) : NULL;
1387
1388 stackelem->buf = psqlscan_prepare_buffer(state, newstr, strlen(newstr),
1389 &stackelem->bufstring);
1390 state->curline = stackelem->bufstring;
1391 if (state->safe_encoding)
1392 {
1393 stackelem->origstring = NULL;
1394 state->refline = stackelem->bufstring;
1395 }
1396 else
1397 {
1398 stackelem->origstring = pg_strdup(newstr);
1399 state->refline = stackelem->origstring;
1400 }
1401 stackelem->next = state->buffer_stack;
1402 state->buffer_stack = stackelem;
1403}
1404
1405/*
1406 * Pop the topmost buffer stack item (there must be one!)
1407 *
1408 * NB: after this, the flex input state is unspecified; caller must
1409 * switch to an appropriate buffer to continue lexing.
1410 * See psqlscan_select_top_buffer().
1411 */
1412void
1414{
1415 StackElem *stackelem = state->buffer_stack;
1416
1417 state->buffer_stack = stackelem->next;
1418 yy_delete_buffer(stackelem->buf, state->scanner);
1419 free(stackelem->bufstring);
1420 if (stackelem->origstring)
1421 free(stackelem->origstring);
1422 if (stackelem->varname)
1423 free(stackelem->varname);
1424 free(stackelem);
1425}
1426
1427/*
1428 * Select the topmost surviving buffer as the active input.
1429 */
1430void
1432{
1433 StackElem *stackelem = state->buffer_stack;
1434
1435 if (stackelem != NULL)
1436 {
1437 yy_switch_to_buffer(stackelem->buf, state->scanner);
1438 state->curline = stackelem->bufstring;
1439 state->refline = stackelem->origstring ? stackelem->origstring : stackelem->bufstring;
1440 }
1441 else
1442 {
1443 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
1444 state->curline = state->scanbuf;
1445 state->refline = state->scanline;
1446 }
1447}
1448
1449/*
1450 * Check if specified variable name is the source for any string
1451 * currently being scanned
1452 */
1453bool
1455{
1456 StackElem *stackelem;
1457
1458 for (stackelem = state->buffer_stack;
1459 stackelem != NULL;
1460 stackelem = stackelem->next)
1461 {
1462 if (stackelem->varname && strcmp(stackelem->varname, varname) == 0)
1463 return true;
1464 }
1465 return false;
1466}
1467
1468/*
1469 * Set up a flex input buffer to scan the given data. We always make a
1470 * copy of the data. If working in an unsafe encoding, the copy has
1471 * multibyte sequences replaced by FFs to avoid fooling the lexer rules.
1472 *
1473 * NOTE SIDE EFFECT: the new buffer is made the active flex input buffer.
1474 */
1477 char **txtcopy)
1478{
1479 char *newtxt;
1480
1481 /* Flex wants two \0 characters after the actual data */
1482 newtxt = pg_malloc(len + 2);
1483 *txtcopy = newtxt;
1484 newtxt[len] = newtxt[len + 1] = YY_END_OF_BUFFER_CHAR;
1485
1486 if (state->safe_encoding)
1487 memcpy(newtxt, txt, len);
1488 else
1489 {
1490 /* Gotta do it the hard way */
1491 int i = 0;
1492
1493 while (i < len)
1494 {
1495 int thislen = PQmblen(txt + i, state->encoding);
1496
1497 /* first byte should always be okay... */
1498 newtxt[i] = txt[i];
1499 i++;
1500 while (--thislen > 0 && i < len)
1501 newtxt[i++] = (char) 0xFF;
1502 }
1503 }
1504
1505 return yy_scan_buffer(newtxt, len + 2, state->scanner);
1506}
1507
1508/*
1509 * psqlscan_emit() --- body for ECHO macro
1510 *
1511 * NB: this must be used for ALL and ONLY the text copied from the flex
1512 * input data. If you pass it something that is not part of the yytext
1513 * string, you are making a mistake. Internally generated text can be
1514 * appended directly to state->output_buf.
1515 */
1516void
1517psqlscan_emit(PsqlScanState state, const char *txt, int len)
1518{
1519 PQExpBuffer output_buf = state->output_buf;
1520
1521 if (state->safe_encoding)
1522 appendBinaryPQExpBuffer(output_buf, txt, len);
1523 else
1524 {
1525 /* Gotta do it the hard way */
1526 const char *reference = state->refline;
1527 int i;
1528
1529 reference += (txt - state->curline);
1530
1531 for (i = 0; i < len; i++)
1532 {
1533 char ch = txt[i];
1534
1535 if (ch == (char) 0xFF)
1536 ch = reference[i];
1537 appendPQExpBufferChar(output_buf, ch);
1538 }
1539 }
1540}
1541
1542/*
1543 * psqlscan_extract_substring --- fetch value of (part of) the current token
1544 *
1545 * This is like psqlscan_emit(), except that the data is returned as a
1546 * malloc'd string rather than being pushed directly to state->output_buf.
1547 */
1548char *
1550{
1551 char *result = (char *) pg_malloc(len + 1);
1552
1553 if (state->safe_encoding)
1554 memcpy(result, txt, len);
1555 else
1556 {
1557 /* Gotta do it the hard way */
1558 const char *reference = state->refline;
1559 int i;
1560
1561 reference += (txt - state->curline);
1562
1563 for (i = 0; i < len; i++)
1564 {
1565 char ch = txt[i];
1566
1567 if (ch == (char) 0xFF)
1568 ch = reference[i];
1569 result[i] = ch;
1570 }
1571 }
1572 result[len] = '\0';
1573 return result;
1574}
1575
1576/*
1577 * psqlscan_escape_variable --- process :'VARIABLE' or :"VARIABLE"
1578 *
1579 * If the variable name is found, escape its value using the appropriate
1580 * quoting method and emit the value to output_buf. (Since the result is
1581 * surely quoted, there is never any reason to rescan it.) If we don't
1582 * find the variable or escaping fails, emit the token as-is.
1583 */
1584void
1586 PsqlScanQuoteType quote)
1587{
1588 char *varname;
1589 char *value;
1590
1591 /* Variable lookup. */
1592 varname = psqlscan_extract_substring(state, txt + 2, len - 3);
1593 if (state->callbacks->get_variable)
1594 value = state->callbacks->get_variable(varname, quote,
1595 state->cb_passthrough);
1596 else
1597 value = NULL;
1598 free(varname);
1599
1600 if (value)
1601 {
1602 /* Emit the suitably-escaped value */
1603 appendPQExpBufferStr(state->output_buf, value);
1604 free(value);
1605 }
1606 else
1607 {
1608 /* Emit original token as-is */
1609 psqlscan_emit(state, txt, len);
1610 }
1611}
1612
1613void
1615{
1616 char *varname;
1617 char *value;
1618
1619 varname = psqlscan_extract_substring(state, txt + 3, len - 4);
1620 if (state->callbacks->get_variable)
1621 value = state->callbacks->get_variable(varname, PQUOTE_PLAIN,
1622 state->cb_passthrough);
1623 else
1624 value = NULL;
1625 free(varname);
1626
1627 if (value != NULL)
1628 {
1629 appendPQExpBufferStr(state->output_buf, "TRUE");
1630 free(value);
1631 }
1632 else
1633 {
1634 appendPQExpBufferStr(state->output_buf, "FALSE");
1635 }
1636}
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1233
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
Assert(PointerIsAligned(start, uint64))
int i
Definition: isn.c:77
const void size_t len
int32 encoding
Definition: pg_database.h:41
#define pg_valid_server_encoding_id
Definition: pg_wchar.h:632
void appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
Definition: pqexpbuffer.c:397
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
PsqlScanResult
Definition: psqlscan.h:31
@ PSCAN_BACKSLASH
Definition: psqlscan.h:33
@ PSCAN_EOL
Definition: psqlscan.h:35
@ PSCAN_INCOMPLETE
Definition: psqlscan.h:34
@ PSCAN_SEMICOLON
Definition: psqlscan.h:32
enum _promptStatus promptStatus_t
PsqlScanQuoteType
Definition: psqlscan.h:53
@ PROMPT_READY
Definition: psqlscan.h:41
@ PROMPT_PAREN
Definition: psqlscan.h:47
@ PROMPT_COMMENT
Definition: psqlscan.h:43
@ PROMPT_CONTINUE
Definition: psqlscan.h:42
@ PROMPT_SINGLEQUOTE
Definition: psqlscan.h:44
@ PROMPT_DOLLARQUOTE
Definition: psqlscan.h:46
@ PROMPT_DOUBLEQUOTE
Definition: psqlscan.h:45
YY_BUFFER_STATE psqlscan_prepare_buffer(PsqlScanState state, const char *txt, int len, char **txtcopy)
Definition: psqlscan.l:1476
void psql_scan_get_location(PsqlScanState state, int *lineno, int *offset)
Definition: psqlscan.l:1335
void psql_scan_reset(PsqlScanState state)
Definition: psqlscan.l:1275
void psql_scan_destroy(PsqlScanState state)
Definition: psqlscan.l:1022
PsqlScanResult psql_scan(PsqlScanState state, PQExpBuffer query_buf, promptStatus_t *prompt)
Definition: psqlscan.l:1121
PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks)
Definition: psqlscan.l:1001
void psql_scan_set_passthrough(PsqlScanState state, void *passthrough)
Definition: psqlscan.l:1041
void psql_scan_setup(PsqlScanState state, const char *line, int line_len, int encoding, bool std_strings)
Definition: psqlscan.l:1059
int yylex(YYSTYPE *yylval_param, yyscan_t yyscanner)
Definition: psqlscan.l:385
void psql_scan_reselect_sql_lexer(PsqlScanState state)
Definition: psqlscan.l:1303
bool psql_scan_in_quote(PsqlScanState state)
Definition: psqlscan.l:1316
void psql_scan_finish(PsqlScanState state)
Definition: psqlscan.l:1248
struct yy_buffer_state * YY_BUFFER_STATE
Definition: psqlscan_int.h:56
char * origstring
Definition: psqlscan_int.h:73
char * varname
Definition: psqlscan_int.h:74
YY_BUFFER_STATE buf
Definition: psqlscan_int.h:71
char * bufstring
Definition: psqlscan_int.h:72
struct StackElem * next
Definition: psqlscan_int.h:75
Definition: regguts.h:323