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