PostgreSQL Source Code git master
psqlscanslash.l
Go to the documentation of this file.
1%top{
2/*-------------------------------------------------------------------------
3 *
4 * psqlscanslash.l
5 * lexical scanner for psql backslash commands
6 *
7 * XXX Avoid creating backtracking cases --- see the backend lexer for info.
8 *
9 * See fe_utils/psqlscan_int.h for additional commentary.
10 *
11 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
13 *
14 * IDENTIFICATION
15 * src/bin/psql/psqlscanslash.l
16 *
17 *-------------------------------------------------------------------------
18 */
19#include "postgres_fe.h"
20
21#include <ctype.h>
22
23#include "common.h"
24#include "psqlscanslash.h"
25
26#include "common/logging.h"
28
29#include "libpq-fe.h"
30}
31
32%{
34
35/*
36 * We must have a typedef YYSTYPE for yylex's first argument, but this lexer
37 * doesn't presently make use of that argument, so just declare it as int.
38 */
39typedef int YYSTYPE;
40
41/*
42 * These variables do not need to be saved across calls. Yeah, it's a bit
43 * of a hack, but putting them into PsqlScanStateData would be klugy too.
44 */
46static char *option_quote;
49
50
51/* Return values from yylex() */
52#define LEXRES_EOL 0 /* end of input */
53#define LEXRES_OK 1 /* OK completion of backslash argument */
54
55
57
58#define ECHO psqlscan_emit(cur_state, yytext, yyleng)
59
60/* LCOV_EXCL_START */
61
slash_option_type
Definition: psqlscanslash.h:16
int YYSTYPE
Definition: psqlscanslash.l:39
static int backtick_start_offset
Definition: psqlscanslash.l:48
static int unquoted_option_chars
Definition: psqlscanslash.l:47
static char * option_quote
Definition: psqlscanslash.l:46
static enum slash_option_type option_type
Definition: psqlscanslash.l:45
static void evaluate_backtick(PsqlScanState state)
Definition: regguts.h:323
62%}
63
64/* Except for the prefix, these options should match psqlscan.l */
65%option reentrant
66%option bison-bridge
67%option 8bit
68%option never-interactive
69%option nodefault
70%option noinput
71%option nounput
72%option noyywrap
73%option warn
74%option prefix="slash_yy"
75
76/*
77 * Set the type of yyextra; we use it as a pointer back to the containing
78 * PsqlScanState.
79 */
80%option extra-type="PsqlScanState"
81
82/*
83 * OK, here is a short description of lex/flex rules behavior.
84 * The longest pattern which matches an input string is always chosen.
85 * For equal-length patterns, the first occurring in the rules list is chosen.
86 * INITIAL is the starting state, to which all non-conditional rules apply.
87 * Exclusive states change parsing rules while the state is active. When in
88 * an exclusive state, only those rules defined for that state apply.
89 */
90
91/* Exclusive states for lexing backslash commands */
92%x xslashcmd
93%x xslashargstart
94%x xslasharg
95%x xslashquote
96%x xslashbackquote
97%x xslashdquote
98%x xslashwholeline
99%x xslashend
100
101/*
102 * Assorted character class definitions that should match psqlscan.l.
103 */
104space [ \t\n\r\f\v]
105quote '
106xeoctesc [\\][0-7]{1,3}
107xehexesc [\\]x[0-9A-Fa-f]{1,2}
108xqdouble {quote}{quote}
109dquote \"
110variable_char [A-Za-z\200-\377_0-9]
111
112other .
113
115
116%{
117 /* Declare some local variables inside yylex(), for convenience */
118 PsqlScanState cur_state = yyextra;
#define yyextra
Definition: scan.l:1118
119 PQExpBuffer output_buf = cur_state->output_buf;
120
121 /*
122 * Force flex into the state indicated by start_state. This has a
123 * couple of purposes: it lets some of the functions below set a new
124 * starting state without ugly direct access to flex variables, and it
125 * allows us to transition from one flex lexer to another so that we
126 * can lex different parts of the source string using separate lexers.
127 */
128 BEGIN(cur_state->start_state);
129%}
130
131 /*
132 * We don't really expect to be invoked in the INITIAL state in this
133 * lexer; but if we are, just spit data to the output_buf until EOF.
134 */
135
136{other}|\n { ECHO; }
#define ECHO
Definition: psqlscanslash.l:58
137
138 /*
139 * Exclusive lexer states to handle backslash command lexing
140 */
141
142<xslashcmd>{
143 /* command name ends at whitespace or backslash; eat all else */
144
145{space}|"\\" {
146 yyless(0);
147 cur_state->start_state = YY_START;
148 return LEXRES_OK;
149 }
#define LEXRES_OK
Definition: psqlscanslash.l:53
150
151{other} { ECHO; }
152
153}
154
155<xslashargstart>{
156 /*
157 * Discard any whitespace before argument, then go to xslasharg state.
158 * An exception is that "|" is only special at start of argument, so we
159 * check for it here.
160 */
161
162{space}+ { }
163
164"|" {
166 {
167 /* treat like whole-string case */
168 ECHO;
169 BEGIN(xslashwholeline);
170 }
171 else
172 {
173 /* vertical bar is not special otherwise */
174 yyless(0);
175 BEGIN(xslasharg);
176 }
177 }
@ OT_FILEPIPE
Definition: psqlscanslash.h:20
178
179{other} {
180 yyless(0);
181 BEGIN(xslasharg);
182 }
183
184}
185
186<xslasharg>{
187 /*
188 * Default processing of text in a slash command's argument.
189 *
190 * Note: unquoted_option_chars counts the number of characters at the
191 * end of the argument that were not subject to any form of quoting.
192 * psql_scan_slash_option needs this to strip trailing semicolons safely.
193 */
194
195{space}|"\\" {
196 /*
197 * Unquoted space is end of arg; do not eat. Likewise
198 * backslash is end of command or next command, do not eat
199 *
200 * XXX this means we can't conveniently accept options
201 * that include unquoted backslashes; therefore, option
202 * processing that encourages use of backslashes is rather
203 * broken.
204 */
205 yyless(0);
206 cur_state->start_state = YY_START;
207 return LEXRES_OK;
208 }
209
210{quote} {
211 *option_quote = '\'';
213 BEGIN(xslashquote);
214 }
215
216"`" {
217 backtick_start_offset = output_buf->len;
218 *option_quote = '`';
220 BEGIN(xslashbackquote);
221 }
222
223{dquote} {
224 ECHO;
225 *option_quote = '"';
227 BEGIN(xslashdquote);
228 }
229
230:{variable_char}+ {
231 /* Possible psql variable substitution */
232 if (cur_state->callbacks->get_variable == NULL)
233 ECHO;
234 else
235 {
236 char *varname;
237 char *value;
238
239 varname = psqlscan_extract_substring(cur_state,
240 yytext + 1,
241 yyleng - 1);
242 value = cur_state->callbacks->get_variable(varname,
244 cur_state->cb_passthrough);
245 free(varname);
246
247 /*
248 * The variable value is just emitted without any
249 * further examination. This is consistent with the
250 * pre-8.0 code behavior, if not with the way that
251 * variables are handled outside backslash commands.
252 * Note that we needn't guard against recursion here.
253 */
254 if (value)
255 {
256 appendPQExpBufferStr(output_buf, value);
257 free(value);
258 }
259 else
260 ECHO;
261
262 *option_quote = ':';
263 }
265 }
#define free(a)
Definition: header.h:65
static struct @162 value
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
@ PQUOTE_PLAIN
Definition: psqlscan.h:54
char * psqlscan_extract_substring(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1495
#define yyleng
Definition: scan.l:1124
266
267:'{variable_char}+' {
268 psqlscan_escape_variable(cur_state, yytext, yyleng,
270 *option_quote = ':';
272 }
@ PQUOTE_SQL_LITERAL
Definition: psqlscan.h:55
void psqlscan_escape_variable(PsqlScanState state, const char *txt, int len, PsqlScanQuoteType quote)
Definition: psqlscan.l:1531
273
274
275:\"{variable_char}+\" {
276 psqlscan_escape_variable(cur_state, yytext, yyleng,
278 *option_quote = ':';
280 }
@ PQUOTE_SQL_IDENT
Definition: psqlscan.h:56
281
282:\{\?{variable_char}+\} {
283 psqlscan_test_variable(cur_state, yytext, yyleng);
284 }
void psqlscan_test_variable(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1560
285
286:'{variable_char}* {
287 /* Throw back everything but the colon */
288 yyless(1);
290 ECHO;
291 }
292
293:\"{variable_char}* {
294 /* Throw back everything but the colon */
295 yyless(1);
297 ECHO;
298 }
299
300:\{\?{variable_char}* {
301 /* Throw back everything but the colon */
302 yyless(1);
304 ECHO;
305 }
306
307:\{ {
308 /* Throw back everything but the colon */
309 yyless(1);
311 ECHO;
312 }
313
314{other} {
316 ECHO;
317 }
318
319}
320
321<xslashquote>{
322 /*
323 * single-quoted text: copy literally except for '' and backslash
324 * sequences
325 */
326
327{quote} { BEGIN(xslasharg); }
328
329{xqdouble} { appendPQExpBufferChar(output_buf, '\''); }
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
330
331"\\n" { appendPQExpBufferChar(output_buf, '\n'); }
332"\\t" { appendPQExpBufferChar(output_buf, '\t'); }
333"\\b" { appendPQExpBufferChar(output_buf, '\b'); }
334"\\r" { appendPQExpBufferChar(output_buf, '\r'); }
335"\\f" { appendPQExpBufferChar(output_buf, '\f'); }
336
337{xeoctesc} {
338 /* octal case */
339 appendPQExpBufferChar(output_buf,
340 (char) strtol(yytext + 1, NULL, 8));
341 }
342
343{xehexesc} {
344 /* hex case */
345 appendPQExpBufferChar(output_buf,
346 (char) strtol(yytext + 2, NULL, 16));
347 }
348
349"\\". { psqlscan_emit(cur_state, yytext + 1, 1); }
void psqlscan_emit(PsqlScanState state, const char *txt, int len)
Definition: psqlscan.l:1463
350
351{other}|\n { ECHO; }
352
353}
354
355<xslashbackquote>{
356 /*
357 * backticked text: copy everything until next backquote (expanding
358 * variable references, but doing nought else), then evaluate.
359 */
360
361"`" {
362 /* In an inactive \if branch, don't evaluate the command */
363 if (cur_state->cb_passthrough == NULL ||
364 conditional_active((ConditionalStack) cur_state->cb_passthrough))
365 evaluate_backtick(cur_state);
366 BEGIN(xslasharg);
367 }
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:140
368
369:{variable_char}+ {
370 /* Possible psql variable substitution */
371 if (cur_state->callbacks->get_variable == NULL)
372 ECHO;
373 else
374 {
375 char *varname;
376 char *value;
377
378 varname = psqlscan_extract_substring(cur_state,
379 yytext + 1,
380 yyleng - 1);
381 value = cur_state->callbacks->get_variable(varname,
383 cur_state->cb_passthrough);
384 free(varname);
385
386 if (value)
387 {
388 appendPQExpBufferStr(output_buf, value);
389 free(value);
390 }
391 else
392 ECHO;
393 }
394 }
395
396:'{variable_char}+' {
397 psqlscan_escape_variable(cur_state, yytext, yyleng,
399 }
@ PQUOTE_SHELL_ARG
Definition: psqlscan.h:57
400
401:'{variable_char}* {
402 /* Throw back everything but the colon */
403 yyless(1);
404 ECHO;
405 }
406
407{other}|\n { ECHO; }
408
409}
410
411<xslashdquote>{
412 /* double-quoted text: copy verbatim, including the double quotes */
413
414{dquote} {
415 ECHO;
416 BEGIN(xslasharg);
417 }
418
419{other}|\n { ECHO; }
420
421}
422
423<xslashwholeline>{
424 /* copy everything until end of input line */
425 /* but suppress leading whitespace */
426
427{space}+ {
428 if (output_buf->len > 0)
429 ECHO;
430 }
431
432{other} { ECHO; }
433
434}
435
436<xslashend>{
437 /* at end of command, eat a double backslash, but not anything else */
438
439"\\\\" {
440 cur_state->start_state = YY_START;
441 return LEXRES_OK;
442 }
443
444{other}|\n {
445 yyless(0);
446 cur_state->start_state = YY_START;
447 return LEXRES_OK;
448 }
449
450}
451
452<<EOF>> {
453 if (cur_state->buffer_stack == NULL)
454 {
455 cur_state->start_state = YY_START;
456 return LEXRES_EOL; /* end of input reached */
457 }
458
459 /*
460 * We were expanding a variable, so pop the inclusion
461 * stack and keep lexing
462 */
463 psqlscan_pop_buffer_stack(cur_state);
465 }
void psqlscan_select_top_buffer(PsqlScanState state)
Definition: psqlscan.l:1377
void psqlscan_pop_buffer_stack(PsqlScanState state)
Definition: psqlscan.l:1359
#define LEXRES_EOL
Definition: psqlscanslash.l:52
466
467%%
468
469/* LCOV_EXCL_STOP */
470
471/*
472 * Scan the command name of a psql backslash command. This should be called
473 * after psql_scan() returns PSCAN_BACKSLASH. It is assumed that the input
474 * has been consumed through the leading backslash.
475 *
476 * The return value is a malloc'd copy of the command name, as parsed off
477 * from the input.
478 */
479char *
481{
482 PQExpBufferData mybuf;
483
484 /* Must be scanning already */
485 Assert(state->scanbufhandle != NULL);
486
487 /* Build a local buffer that we'll return the data of */
488 initPQExpBuffer(&mybuf);
489
490 /* Set current output target */
491 state->output_buf = &mybuf;
492
493 /* Set input source */
494 if (state->buffer_stack != NULL)
495 yy_switch_to_buffer(state->buffer_stack->buf, state->scanner);
496 else
497 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
498
499 /*
500 * Set lexer start state. Note that this is sufficient to switch
501 * state->scanner over to using the tables in this lexer file.
502 */
503 state->start_state = xslashcmd;
504
505 /* And lex. */
506 yylex(NULL, state->scanner);
507
508 /* There are no possible errors in this lex state... */
509
510 /*
511 * In case the caller returns to using the regular SQL lexer, reselect the
512 * appropriate initial state.
513 */
515
516 return mybuf.data;
517}
518
519/*
520 * Parse off the next argument for a backslash command, and return it as a
521 * malloc'd string. If there are no more arguments, returns NULL.
522 *
523 * type tells what processing, if any, to perform on the option string;
524 * for example, if it's a SQL identifier, we want to downcase any unquoted
525 * letters.
526 *
527 * if quote is not NULL, *quote is set to 0 if no quoting was found, else
528 * the last quote symbol used in the argument.
529 *
530 * if semicolon is true, unquoted trailing semicolon(s) that would otherwise
531 * be taken as part of the option string will be stripped.
532 *
533 * NOTE: the only possible syntax errors for backslash options are unmatched
534 * quotes, which are detected when we run out of input. Therefore, on a
535 * syntax error we just throw away the string and return NULL; there is no
536 * need to worry about flushing remaining input.
537 */
538char *
541 char *quote,
542 bool semicolon)
543{
544 PQExpBufferData mybuf;
545 int lexresult PG_USED_FOR_ASSERTS_ONLY;
546 int final_state;
547 char local_quote;
548
549 /* Must be scanning already */
550 Assert(state->scanbufhandle != NULL);
551
552 if (quote == NULL)
553 quote = &local_quote;
554 *quote = 0;
555
556 /* Build a local buffer that we'll return the data of */
557 initPQExpBuffer(&mybuf);
558
559 /* Set up static variables that will be used by yylex */
561 option_quote = quote;
563
564 /* Set current output target */
565 state->output_buf = &mybuf;
566
567 /* Set input source */
568 if (state->buffer_stack != NULL)
569 yy_switch_to_buffer(state->buffer_stack->buf, state->scanner);
570 else
571 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
572
573 /* Set lexer start state */
574 if (type == OT_WHOLE_LINE)
575 state->start_state = xslashwholeline;
576 else
577 state->start_state = xslashargstart;
578
579 /* And lex. */
580 lexresult = yylex(NULL, state->scanner);
581
582 /* Save final state for a moment... */
583 final_state = state->start_state;
584
585 /*
586 * In case the caller returns to using the regular SQL lexer, reselect the
587 * appropriate initial state.
588 */
590
591 /*
592 * Check the lex result: we should have gotten back either LEXRES_OK or
593 * LEXRES_EOL (the latter indicating end of string). If we were inside a
594 * quoted string, as indicated by final_state, EOL is an error.
595 */
596 Assert(lexresult == LEXRES_EOL || lexresult == LEXRES_OK);
597
598 switch (final_state)
599 {
600 case xslashargstart:
601 /* empty arg */
602 break;
603 case xslasharg:
604 /* Strip any unquoted trailing semicolons if requested */
605 if (semicolon)
606 {
607 while (unquoted_option_chars-- > 0 &&
608 mybuf.len > 0 &&
609 mybuf.data[mybuf.len - 1] == ';')
610 {
611 mybuf.data[--mybuf.len] = '\0';
612 }
613 }
614
615 /*
616 * If SQL identifier processing was requested, then we strip out
617 * excess double quotes and optionally downcase unquoted letters.
618 */
619 if (type == OT_SQLID || type == OT_SQLIDHACK)
620 {
622 (type != OT_SQLIDHACK),
623 state->encoding);
624 /* update mybuf.len for possible shortening */
625 mybuf.len = strlen(mybuf.data);
626 }
627 break;
628 case xslashquote:
629 case xslashbackquote:
630 case xslashdquote:
631 /* must have hit EOL inside quotes */
632 pg_log_error("unterminated quoted string");
633 termPQExpBuffer(&mybuf);
634 return NULL;
635 case xslashwholeline:
636
637 /*
638 * In whole-line mode, we interpret semicolon = true as stripping
639 * trailing whitespace as well as semicolons; this gives the
640 * nearest equivalent to what semicolon = true does in normal
641 * mode. Note there's no concept of quoting in this mode.
642 */
643 if (semicolon)
644 {
645 while (mybuf.len > 0 &&
646 (mybuf.data[mybuf.len - 1] == ';' ||
647 (isascii((unsigned char) mybuf.data[mybuf.len - 1]) &&
648 isspace((unsigned char) mybuf.data[mybuf.len - 1]))))
649 {
650 mybuf.data[--mybuf.len] = '\0';
651 }
652 }
653 break;
654 default:
655 /* can't get here */
656 fprintf(stderr, "invalid YY_START\n");
657 exit(1);
658 }
659
660 /*
661 * An unquoted empty argument isn't possible unless we are at end of
662 * command. Return NULL instead.
663 */
664 if (mybuf.len == 0 && *quote == 0)
665 {
666 termPQExpBuffer(&mybuf);
667 return NULL;
668 }
669
670 /* Else return the completed string. */
671 return mybuf.data;
672}
673
674/*
675 * Eat up any unused \\ to complete a backslash command.
676 */
677void
679{
680 /* Must be scanning already */
681 Assert(state->scanbufhandle != NULL);
682
683 /* Set current output target */
684 state->output_buf = NULL; /* we won't output anything */
685
686 /* Set input source */
687 if (state->buffer_stack != NULL)
688 yy_switch_to_buffer(state->buffer_stack->buf, state->scanner);
689 else
690 yy_switch_to_buffer(state->scanbufhandle, state->scanner);
691
692 /* Set lexer start state */
693 state->start_state = xslashend;
694
695 /* And lex. */
696 yylex(NULL, state->scanner);
697
698 /* There are no possible errors in this lex state... */
699
700 /*
701 * We expect the caller to return to using the regular SQL lexer, so
702 * reselect the appropriate initial state.
703 */
705}
706
707/*
708 * Fetch current paren nesting depth
709 */
710int
712{
713 return state->paren_depth;
714}
715
716/*
717 * Set paren nesting depth
718 */
719void
721{
722 Assert(depth >= 0);
723 state->paren_depth = depth;
724}
725
726/*
727 * De-quote and optionally downcase a SQL identifier.
728 *
729 * The string at *str is modified in-place; it can become shorter,
730 * but not longer.
731 *
732 * If downcase is true then non-quoted letters are folded to lower case.
733 * Ideally this behavior will match the backend's downcase_identifier();
734 * but note that it could differ if LC_CTYPE is different in the frontend.
735 *
736 * Note that a string like FOO"BAR"BAZ will be converted to fooBARbaz;
737 * this is somewhat inconsistent with the SQL spec, which would have us
738 * parse it as several identifiers. But for psql's purposes, we want a
739 * string like "foo"."bar" to be treated as one option, so there's little
740 * choice; this routine doesn't get to change the token boundaries.
741 */
742void
743dequote_downcase_identifier(char *str, bool downcase, int encoding)
744{
745 bool inquotes = false;
746 char *cp = str;
747
748 while (*cp)
749 {
750 if (*cp == '"')
751 {
752 if (inquotes && cp[1] == '"')
753 {
754 /* Keep the first quote, remove the second */
755 cp++;
756 }
757 else
758 inquotes = !inquotes;
759 /* Collapse out quote at *cp */
760 memmove(cp, cp + 1, strlen(cp));
761 /* do not advance cp */
762 }
763 else
764 {
765 if (downcase && !inquotes)
766 *cp = pg_tolower((unsigned char) *cp);
767 cp += PQmblenBounded(cp, encoding);
768 }
769 }
770}
771
772/*
773 * Evaluate a backticked substring of a slash command's argument.
774 *
775 * The portion of output_buf starting at backtick_start_offset is evaluated
776 * as a shell command and then replaced by the command's output.
777 */
778static void
780{
781 PQExpBuffer output_buf = state->output_buf;
782 char *cmd = output_buf->data + backtick_start_offset;
783 PQExpBufferData cmd_output;
784 FILE *fd;
785 bool error = false;
786 int exit_code = 0;
787 char buf[512];
788 size_t result;
789
790 initPQExpBuffer(&cmd_output);
791
792 fflush(NULL);
793 fd = popen(cmd, "r");
794 if (!fd)
795 {
796 pg_log_error("%s: %m", cmd);
797 error = true;
798 exit_code = -1;
799 }
800
801 if (!error)
802 {
803 do
804 {
805 result = fread(buf, 1, sizeof(buf), fd);
806 if (ferror(fd))
807 {
808 pg_log_error("%s: %m", cmd);
809 error = true;
810 break;
811 }
812 appendBinaryPQExpBuffer(&cmd_output, buf, result);
813 } while (!feof(fd));
814 }
815
816 if (fd)
817 {
818 /*
819 * Although pclose's result always sets the shell result variables, we
820 * historically have abandoned the backtick substitution only if it
821 * returns -1.
822 */
823 exit_code = pclose(fd);
824 if (exit_code == -1)
825 {
826 pg_log_error("%s: %m", cmd);
827 error = true;
828 }
829 }
830
831 if (PQExpBufferDataBroken(cmd_output))
832 {
833 pg_log_error("%s: out of memory", cmd);
834 error = true;
835 }
836
837 /* Now done with cmd, delete it from output_buf */
838 output_buf->len = backtick_start_offset;
839 output_buf->data[output_buf->len] = '\0';
840
841 /* If no error, transfer result to output_buf */
842 if (!error)
843 {
844 /* strip any trailing newline (but only one) */
845 if (cmd_output.len > 0 &&
846 cmd_output.data[cmd_output.len - 1] == '\n')
847 cmd_output.len--;
848 appendBinaryPQExpBuffer(output_buf, cmd_output.data, cmd_output.len);
849 }
850
851 /* And finally, set the shell result variables */
852 SetShellResultVariables(exit_code);
853
854 termPQExpBuffer(&cmd_output);
855}
void SetShellResultVariables(int wait_result)
Definition: common.c:501
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:204
#define Assert(condition)
Definition: c.h:815
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
int PQmblenBounded(const char *s, int encoding)
Definition: fe-misc.c:1243
const char * str
#define semicolon
Definition: indent_codes.h:44
static void const char fflush(stdout)
exit(1)
#define pg_log_error(...)
Definition: logging.h:106
int32 encoding
Definition: pg_database.h:41
static char * buf
Definition: pg_test_fsync.c:72
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
Definition: pqexpbuffer.c:397
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static int fd(const char *x, int i)
Definition: preproc-init.c:105
void psql_scan_reselect_sql_lexer(PsqlScanState state)
Definition: psqlscan.l:1295
@ OT_SQLID
Definition: psqlscanslash.h:18
@ OT_SQLIDHACK
Definition: psqlscanslash.h:19
@ OT_WHOLE_LINE
Definition: psqlscanslash.h:21
void psql_scan_slash_command_end(PsqlScanState state)
void psql_scan_set_paren_depth(PsqlScanState state, int depth)
void dequote_downcase_identifier(char *str, bool downcase, int encoding)
int yylex(YYSTYPE *yylval_param, yyscan_t yyscanner)
char * psql_scan_slash_option(PsqlScanState state, enum slash_option_type type, char *quote, bool semicolon)
int psql_scan_get_paren_depth(PsqlScanState state)
char * psql_scan_slash_command(PsqlScanState state)
static void error(void)
Definition: sql-dyntest.c:147
const char * type