PostgreSQL Source Code  git master
mainloop.c File Reference
#include "postgres_fe.h"
#include "mainloop.h"
#include "command.h"
#include "common.h"
#include "input.h"
#include "prompt.h"
#include "settings.h"
#include "mb/pg_wchar.h"
Include dependency graph for mainloop.c:

Go to the source code of this file.

Functions

int MainLoop (FILE *source)
 

Variables

const PsqlScanCallbacks psqlscan_callbacks
 

Function Documentation

◆ MainLoop()

int MainLoop ( FILE *  source)

Definition at line 35 of file mainloop.c.

References _, appendPQExpBufferChar(), Assert, cancel_pressed, conditional_active(), conditional_stack_create(), conditional_stack_destroy(), conditional_stack_empty(), conditional_stack_pop(), createPQExpBuffer(), _psqlSettings::cur_cmd_interactive, _psqlSettings::cur_cmd_source, PQExpBufferData::data, _psqlSettings::db, destroyPQExpBuffer(), _psqlSettings::echo, _psqlSettings::encoding, EXIT_BADCONN, EXIT_FAILURE, EXIT_SUCCESS, EXIT_USER, free, get_prompt(), gets_fromFile(), gets_interactive(), HandleSlashCmds(), _psqlSettings::ignoreeof, PQExpBufferData::len, _psqlSettings::lineno, memmove, _psqlSettings::notty, _psqlSettings::on_error_stop, pg_append_history(), pg_send_history(), pg_strdup(), pg_strncasecmp(), PG_UTF8, PQExpBufferBroken, _psqlSettings::progname, PROMPT_CONTINUE, PROMPT_PAREN, PROMPT_READY, PSCAN_BACKSLASH, PSCAN_EOL, PSCAN_INCOMPLETE, PSCAN_SEMICOLON, pset, PSQL_CMD_ERROR, PSQL_CMD_NEWEDIT, PSQL_CMD_SEND, PSQL_CMD_TERMINATE, PSQL_CMD_UNKNOWN, PSQL_ECHO_ALL, psql_error(), psql_scan(), psql_scan_create(), psql_scan_destroy(), psql_scan_finish(), psql_scan_in_quote(), psql_scan_reset(), psql_scan_set_passthrough(), psql_scan_setup(), _psqlSettings::quiet, resetPQExpBuffer(), SendQuery(), sigint_interrupt_enabled, sigint_interrupt_jmp, _psqlSettings::singleline, standard_strings(), _psqlSettings::stmt_lineno, and success.

Referenced by main(), and process_file().

36 {
37  PsqlScanState scan_state; /* lexer working state */
38  ConditionalStack cond_stack; /* \if status stack */
39  volatile PQExpBuffer query_buf; /* buffer for query being accumulated */
40  volatile PQExpBuffer previous_buf; /* if there isn't anything in the new
41  * buffer yet, use this one for \e,
42  * etc. */
43  PQExpBuffer history_buf; /* earlier lines of a multi-line command, not
44  * yet saved to readline history */
45  char *line; /* current line of input */
46  int added_nl_pos;
47  bool success;
48  bool line_saved_in_history;
49  volatile int successResult = EXIT_SUCCESS;
50  volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
51  volatile promptStatus_t prompt_status = PROMPT_READY;
52  volatile int count_eof = 0;
53  volatile bool die_on_error = false;
54  FILE *prev_cmd_source;
55  bool prev_cmd_interactive;
56  uint64 prev_lineno;
57 
58  /* Save the prior command source */
59  prev_cmd_source = pset.cur_cmd_source;
60  prev_cmd_interactive = pset.cur_cmd_interactive;
61  prev_lineno = pset.lineno;
62  /* pset.stmt_lineno does not need to be saved and restored */
63 
64  /* Establish new source */
65  pset.cur_cmd_source = source;
66  pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
67  pset.lineno = 0;
68  pset.stmt_lineno = 1;
69 
70  /* Create working state */
71  scan_state = psql_scan_create(&psqlscan_callbacks);
72  cond_stack = conditional_stack_create();
73  psql_scan_set_passthrough(scan_state, (void *) cond_stack);
74 
75  query_buf = createPQExpBuffer();
76  previous_buf = createPQExpBuffer();
77  history_buf = createPQExpBuffer();
78  if (PQExpBufferBroken(query_buf) ||
79  PQExpBufferBroken(previous_buf) ||
80  PQExpBufferBroken(history_buf))
81  {
82  psql_error("out of memory\n");
83  exit(EXIT_FAILURE);
84  }
85 
86  /* main loop to get queries and execute them */
87  while (successResult == EXIT_SUCCESS)
88  {
89  /*
90  * Clean up after a previous Control-C
91  */
92  if (cancel_pressed)
93  {
95  {
96  /*
97  * You get here if you stopped a script with Ctrl-C.
98  */
99  successResult = EXIT_USER;
100  break;
101  }
102 
103  cancel_pressed = false;
104  }
105 
106  /*
107  * Establish longjmp destination for exiting from wait-for-input. We
108  * must re-do this each time through the loop for safety, since the
109  * jmpbuf might get changed during command execution.
110  */
111  if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
112  {
113  /* got here with longjmp */
114 
115  /* reset parsing state */
116  psql_scan_finish(scan_state);
117  psql_scan_reset(scan_state);
118  resetPQExpBuffer(query_buf);
119  resetPQExpBuffer(history_buf);
120  count_eof = 0;
121  slashCmdStatus = PSQL_CMD_UNKNOWN;
122  prompt_status = PROMPT_READY;
123  pset.stmt_lineno = 1;
124  cancel_pressed = false;
125 
127  {
128  putc('\n', stdout);
129 
130  /*
131  * if interactive user is in an \if block, then Ctrl-C will
132  * exit from the innermost \if.
133  */
134  if (!conditional_stack_empty(cond_stack))
135  {
136  psql_error("\\if: escaped\n");
137  conditional_stack_pop(cond_stack);
138  }
139  }
140  else
141  {
142  successResult = EXIT_USER;
143  break;
144  }
145  }
146 
147  fflush(stdout);
148 
149  /*
150  * get another line
151  */
153  {
154  /* May need to reset prompt, eg after \r command */
155  if (query_buf->len == 0)
156  prompt_status = PROMPT_READY;
157  line = gets_interactive(get_prompt(prompt_status, cond_stack),
158  query_buf);
159  }
160  else
161  {
162  line = gets_fromFile(source);
163  if (!line && ferror(source))
164  successResult = EXIT_FAILURE;
165  }
166 
167  /*
168  * query_buf holds query already accumulated. line is the malloc'd
169  * new line of input (note it must be freed before looping around!)
170  */
171 
172  /* No more input. Time to quit, or \i done */
173  if (line == NULL)
174  {
176  {
177  /* This tries to mimic bash's IGNOREEOF feature. */
178  count_eof++;
179 
180  if (count_eof < pset.ignoreeof)
181  {
182  if (!pset.quiet)
183  printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
184  continue;
185  }
186 
187  puts(pset.quiet ? "" : "\\q");
188  }
189  break;
190  }
191 
192  count_eof = 0;
193 
194  pset.lineno++;
195 
196  /* ignore UTF-8 Unicode byte-order mark */
197  if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
198  memmove(line, line + 3, strlen(line + 3) + 1);
199 
200  /* Detect attempts to run custom-format dumps as SQL scripts */
201  if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
202  strncmp(line, "PGDMP", 5) == 0)
203  {
204  free(line);
205  puts(_("The input is a PostgreSQL custom-format dump.\n"
206  "Use the pg_restore command-line client to restore this dump to a database.\n"));
207  fflush(stdout);
208  successResult = EXIT_FAILURE;
209  break;
210  }
211 
212  /* no further processing of empty lines, unless within a literal */
213  if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
214  {
215  free(line);
216  continue;
217  }
218 
219  /* Recognize "help", "quit", "exit" only in interactive mode */
221  {
222  char *first_word = line;
223  char *rest_of_line = NULL;
224  bool found_help = false;
225  bool found_exit_or_quit = false;
226  bool found_q = false;
227 
228  /* Search for the words we recognize; must be first word */
229  if (pg_strncasecmp(first_word, "help", 4) == 0)
230  {
231  rest_of_line = first_word + 4;
232  found_help = true;
233  }
234  else if (pg_strncasecmp(first_word, "exit", 4) == 0 ||
235  pg_strncasecmp(first_word, "quit", 4) == 0)
236  {
237  rest_of_line = first_word + 4;
238  found_exit_or_quit = true;
239  }
240 
241  else if (strncmp(first_word, "\\q", 2) == 0)
242  {
243  rest_of_line = first_word + 2;
244  found_q = true;
245  }
246 
247  /*
248  * If we found a command word, check whether the rest of the line
249  * contains only whitespace plus maybe one semicolon. If not,
250  * ignore the command word after all. These commands are only for
251  * compatibility with other SQL clients and are not documented.
252  */
253  if (rest_of_line != NULL)
254  {
255  /*
256  * Ignore unless rest of line is whitespace, plus maybe one
257  * semicolon
258  */
259  while (isspace((unsigned char) *rest_of_line))
260  ++rest_of_line;
261  if (*rest_of_line == ';')
262  ++rest_of_line;
263  while (isspace((unsigned char) *rest_of_line))
264  ++rest_of_line;
265  if (*rest_of_line != '\0')
266  {
267  found_help = false;
268  found_exit_or_quit = false;
269  }
270  }
271 
272  /*
273  * "help" is only a command when the query buffer is empty, but we
274  * emit a one-line message even when it isn't to help confused
275  * users. The text is still added to the query buffer in that
276  * case.
277  */
278  if (found_help)
279  {
280  if (query_buf->len != 0)
281 #ifndef WIN32
282  puts(_("Use \\? for help or press control-C to clear the input buffer."));
283 #else
284  puts(_("Use \\? for help."));
285 #endif
286  else
287  {
288  puts(_("You are using psql, the command-line interface to PostgreSQL."));
289  printf(_("Type: \\copyright for distribution terms\n"
290  " \\h for help with SQL commands\n"
291  " \\? for help with psql commands\n"
292  " \\g or terminate with semicolon to execute query\n"
293  " \\q to quit\n"));
294  free(line);
295  fflush(stdout);
296  continue;
297  }
298  }
299 
300  /*
301  * "quit" and "exit" are only commands when the query buffer is
302  * empty, but we emit a one-line message even when it isn't to
303  * help confused users. The text is still added to the query
304  * buffer in that case.
305  */
306  if (found_exit_or_quit)
307  {
308  if (query_buf->len != 0)
309  {
310  if (prompt_status == PROMPT_READY ||
311  prompt_status == PROMPT_CONTINUE ||
312  prompt_status == PROMPT_PAREN)
313  puts(_("Use \\q to quit."));
314  else
315 #ifndef WIN32
316  puts(_("Use control-D to quit."));
317 #else
318  puts(_("Use control-C to quit."));
319 #endif
320  }
321  else
322  {
323  /* exit app */
324  free(line);
325  fflush(stdout);
326  successResult = EXIT_SUCCESS;
327  break;
328  }
329  }
330 
331  /*
332  * If they typed "\q" in a place where "\q" is not active, supply
333  * a hint. The text is still added to the query buffer.
334  */
335  if (found_q && query_buf->len != 0 &&
336  prompt_status != PROMPT_READY &&
337  prompt_status != PROMPT_CONTINUE &&
338  prompt_status != PROMPT_PAREN)
339 #ifndef WIN32
340  puts(_("Use control-D to quit."));
341 #else
342  puts(_("Use control-C to quit."));
343 #endif
344  }
345 
346  /* echo back if flag is set, unless interactive */
348  {
349  puts(line);
350  fflush(stdout);
351  }
352 
353  /* insert newlines into query buffer between source lines */
354  if (query_buf->len > 0)
355  {
356  appendPQExpBufferChar(query_buf, '\n');
357  added_nl_pos = query_buf->len;
358  }
359  else
360  added_nl_pos = -1; /* flag we didn't add one */
361 
362  /* Setting this will not have effect until next line. */
363  die_on_error = pset.on_error_stop;
364 
365  /*
366  * Parse line, looking for command separators.
367  */
368  psql_scan_setup(scan_state, line, strlen(line),
370  success = true;
371  line_saved_in_history = false;
372 
373  while (success || !die_on_error)
374  {
375  PsqlScanResult scan_result;
376  promptStatus_t prompt_tmp = prompt_status;
377  size_t pos_in_query;
378  char *tmp_line;
379 
380  pos_in_query = query_buf->len;
381  scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
382  prompt_status = prompt_tmp;
383 
384  if (PQExpBufferBroken(query_buf))
385  {
386  psql_error("out of memory\n");
387  exit(EXIT_FAILURE);
388  }
389 
390  /*
391  * Increase statement line number counter for each linebreak added
392  * to the query buffer by the last psql_scan() call. There only
393  * will be ones to add when navigating to a statement in
394  * readline's history containing newlines.
395  */
396  tmp_line = query_buf->data + pos_in_query;
397  while (*tmp_line != '\0')
398  {
399  if (*(tmp_line++) == '\n')
400  pset.stmt_lineno++;
401  }
402 
403  if (scan_result == PSCAN_EOL)
404  pset.stmt_lineno++;
405 
406  /*
407  * Send command if semicolon found, or if end of line and we're in
408  * single-line mode.
409  */
410  if (scan_result == PSCAN_SEMICOLON ||
411  (scan_result == PSCAN_EOL && pset.singleline))
412  {
413  /*
414  * Save line in history. We use history_buf to accumulate
415  * multi-line queries into a single history entry. Note that
416  * history accumulation works on input lines, so it doesn't
417  * matter whether the query will be ignored due to \if.
418  */
419  if (pset.cur_cmd_interactive && !line_saved_in_history)
420  {
421  pg_append_history(line, history_buf);
422  pg_send_history(history_buf);
423  line_saved_in_history = true;
424  }
425 
426  /* execute query unless we're in an inactive \if branch */
427  if (conditional_active(cond_stack))
428  {
429  success = SendQuery(query_buf->data);
430  slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
431  pset.stmt_lineno = 1;
432 
433  /* transfer query to previous_buf by pointer-swapping */
434  {
435  PQExpBuffer swap_buf = previous_buf;
436 
437  previous_buf = query_buf;
438  query_buf = swap_buf;
439  }
440  resetPQExpBuffer(query_buf);
441 
442  added_nl_pos = -1;
443  /* we need not do psql_scan_reset() here */
444  }
445  else
446  {
447  /* if interactive, warn about non-executed query */
449  psql_error("query ignored; use \\endif or Ctrl-C to exit current \\if block\n");
450  /* fake an OK result for purposes of loop checks */
451  success = true;
452  slashCmdStatus = PSQL_CMD_SEND;
453  pset.stmt_lineno = 1;
454  /* note that query_buf doesn't change state */
455  }
456  }
457  else if (scan_result == PSCAN_BACKSLASH)
458  {
459  /* handle backslash command */
460 
461  /*
462  * If we added a newline to query_buf, and nothing else has
463  * been inserted in query_buf by the lexer, then strip off the
464  * newline again. This avoids any change to query_buf when a
465  * line contains only a backslash command. Also, in this
466  * situation we force out any previous lines as a separate
467  * history entry; we don't want SQL and backslash commands
468  * intermixed in history if at all possible.
469  */
470  if (query_buf->len == added_nl_pos)
471  {
472  query_buf->data[--query_buf->len] = '\0';
473  pg_send_history(history_buf);
474  }
475  added_nl_pos = -1;
476 
477  /* save backslash command in history */
478  if (pset.cur_cmd_interactive && !line_saved_in_history)
479  {
480  pg_append_history(line, history_buf);
481  pg_send_history(history_buf);
482  line_saved_in_history = true;
483  }
484 
485  /* execute backslash command */
486  slashCmdStatus = HandleSlashCmds(scan_state,
487  cond_stack,
488  query_buf,
489  previous_buf);
490 
491  success = slashCmdStatus != PSQL_CMD_ERROR;
492 
493  /*
494  * Resetting stmt_lineno after a backslash command isn't
495  * always appropriate, but it's what we've done historically
496  * and there have been few complaints.
497  */
498  pset.stmt_lineno = 1;
499 
500  if (slashCmdStatus == PSQL_CMD_SEND)
501  {
502  /* should not see this in inactive branch */
503  Assert(conditional_active(cond_stack));
504 
505  success = SendQuery(query_buf->data);
506 
507  /* transfer query to previous_buf by pointer-swapping */
508  {
509  PQExpBuffer swap_buf = previous_buf;
510 
511  previous_buf = query_buf;
512  query_buf = swap_buf;
513  }
514  resetPQExpBuffer(query_buf);
515 
516  /* flush any paren nesting info after forced send */
517  psql_scan_reset(scan_state);
518  }
519  else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
520  {
521  /* should not see this in inactive branch */
522  Assert(conditional_active(cond_stack));
523  /* rescan query_buf as new input */
524  psql_scan_finish(scan_state);
525  free(line);
526  line = pg_strdup(query_buf->data);
527  resetPQExpBuffer(query_buf);
528  /* reset parsing state since we are rescanning whole line */
529  psql_scan_reset(scan_state);
530  psql_scan_setup(scan_state, line, strlen(line),
532  line_saved_in_history = false;
533  prompt_status = PROMPT_READY;
534  }
535  else if (slashCmdStatus == PSQL_CMD_TERMINATE)
536  break;
537  }
538 
539  /* fall out of loop if lexer reached EOL */
540  if (scan_result == PSCAN_INCOMPLETE ||
541  scan_result == PSCAN_EOL)
542  break;
543  }
544 
545  /* Add line to pending history if we didn't execute anything yet */
546  if (pset.cur_cmd_interactive && !line_saved_in_history)
547  pg_append_history(line, history_buf);
548 
549  psql_scan_finish(scan_state);
550  free(line);
551 
552  if (slashCmdStatus == PSQL_CMD_TERMINATE)
553  {
554  successResult = EXIT_SUCCESS;
555  break;
556  }
557 
559  {
560  if (!success && die_on_error)
561  successResult = EXIT_USER;
562  /* Have we lost the db connection? */
563  else if (!pset.db)
564  successResult = EXIT_BADCONN;
565  }
566  } /* while !endoffile/session */
567 
568  /*
569  * If we have a non-semicolon-terminated query at the end of file, we
570  * process it unless the input source is interactive --- in that case it
571  * seems better to go ahead and quit. Also skip if this is an error exit.
572  */
573  if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
574  successResult == EXIT_SUCCESS)
575  {
576  /* save query in history */
577  /* currently unneeded since we don't use this block if interactive */
578 #ifdef NOT_USED
580  pg_send_history(history_buf);
581 #endif
582 
583  /* execute query unless we're in an inactive \if branch */
584  if (conditional_active(cond_stack))
585  {
586  success = SendQuery(query_buf->data);
587  }
588  else
589  {
591  psql_error("query ignored; use \\endif or Ctrl-C to exit current \\if block\n");
592  success = true;
593  }
594 
595  if (!success && die_on_error)
596  successResult = EXIT_USER;
597  else if (pset.db == NULL)
598  successResult = EXIT_BADCONN;
599  }
600 
601  /*
602  * Check for unbalanced \if-\endifs unless user explicitly quit, or the
603  * script is erroring out
604  */
605  if (slashCmdStatus != PSQL_CMD_TERMINATE &&
606  successResult != EXIT_USER &&
607  !conditional_stack_empty(cond_stack))
608  {
609  psql_error("reached EOF without finding closing \\endif(s)\n");
610  if (die_on_error && !pset.cur_cmd_interactive)
611  successResult = EXIT_USER;
612  }
613 
614  /*
615  * Let's just make real sure the SIGINT handler won't try to use
616  * sigint_interrupt_jmp after we exit this routine. If there is an outer
617  * MainLoop instance, it will reset sigint_interrupt_jmp to point to
618  * itself at the top of its loop, before any further interactive input
619  * happens.
620  */
621  sigint_interrupt_enabled = false;
622 
623  destroyPQExpBuffer(query_buf);
624  destroyPQExpBuffer(previous_buf);
625  destroyPQExpBuffer(history_buf);
626 
627  psql_scan_destroy(scan_state);
628  conditional_stack_destroy(cond_stack);
629 
630  pset.cur_cmd_source = prev_cmd_source;
631  pset.cur_cmd_interactive = prev_cmd_interactive;
632  pset.lineno = prev_lineno;
633 
634  return successResult;
635 } /* MainLoop() */
PSQL_ECHO echo
Definition: settings.h:132
PGconn * db
Definition: settings.h:82
PsqlScanResult
Definition: psqlscan.h:30
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:128
void pg_send_history(PQExpBuffer history_buf)
Definition: input.c:135
volatile bool sigint_interrupt_enabled
Definition: common.c:274
#define EXIT_SUCCESS
Definition: settings.h:148
PsqlSettings pset
Definition: startup.c:33
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:57
PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks)
char * get_prompt(promptStatus_t status, ConditionalStack cstack)
Definition: prompt.c:69
bool on_error_stop
Definition: settings.h:125
FILE * cur_cmd_source
Definition: settings.h:104
sigjmp_buf sigint_interrupt_jmp
Definition: common.c:276
#define EXIT_BADCONN
Definition: settings.h:155
volatile bool cancel_pressed
Definition: print.c:46
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
bool cur_cmd_interactive
Definition: settings.h:106
static bool success
#define memmove(d, s, c)
Definition: c.h:1135
const PsqlScanCallbacks psqlscan_callbacks
Definition: mainloop.c:21
void psql_scan_reset(PsqlScanState state)
#define EXIT_USER
Definition: settings.h:157
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
bool singleline
Definition: settings.h:127
char * gets_interactive(const char *prompt, PQExpBuffer query_buf)
Definition: input.c:66
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
void psql_error(const char *fmt,...)
Definition: common.c:221
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
void psql_scan_destroy(PsqlScanState state)
bool standard_strings(void)
Definition: common.c:2258
#define free(a)
Definition: header.h:65
enum _backslashResult backslashResult
#define Assert(condition)
Definition: c.h:699
void pg_append_history(const char *s, PQExpBuffer history_buf)
Definition: input.c:113
const char * progname
Definition: settings.h:108
char * gets_fromFile(FILE *source)
Definition: input.c:187
enum _promptStatus promptStatus_t
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
PsqlScanResult psql_scan(PsqlScanState state, PQExpBuffer query_buf, promptStatus_t *prompt)
void conditional_stack_destroy(ConditionalStack cstack)
Definition: conditional.c:30
void psql_scan_set_passthrough(PsqlScanState state, void *passthrough)
uint64 lineno
Definition: settings.h:110
bool conditional_stack_empty(ConditionalStack cstack)
Definition: conditional.c:118
#define EXIT_FAILURE
Definition: settings.h:152
void psql_scan_setup(PsqlScanState state, const char *line, int line_len, int encoding, bool std_strings)
bool SendQuery(const char *query)
Definition: common.c:1280
bool psql_scan_in_quote(PsqlScanState state)
void psql_scan_finish(PsqlScanState state)
backslashResult HandleSlashCmds(PsqlScanState scan_state, ConditionalStack cstack, PQExpBuffer query_buf, PQExpBuffer previous_buf)
Definition: command.c:199
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
int encoding
Definition: settings.h:83
#define _(x)
Definition: elog.c:84
uint64 stmt_lineno
Definition: settings.h:111

Variable Documentation

◆ psqlscan_callbacks

const PsqlScanCallbacks psqlscan_callbacks
Initial value:
= {
}
void psql_error(const char *fmt,...)
Definition: common.c:221
char * psql_get_variable(const char *varname, PsqlScanQuoteType quote, void *passthrough)
Definition: common.c:129

Definition at line 21 of file mainloop.c.

Referenced by main().