PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
mainloop.c
Go to the documentation of this file.
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2017, PostgreSQL Global Development Group
5  *
6  * src/bin/psql/mainloop.c
7  */
8 #include "postgres_fe.h"
9 #include "mainloop.h"
10 
11 #include "command.h"
12 #include "common.h"
13 #include "input.h"
14 #include "prompt.h"
15 #include "settings.h"
16 
17 #include "mb/pg_wchar.h"
18 
19 
20 /* callback functions for our flex lexer */
24 };
25 
26 
27 /*
28  * Main processing loop for reading lines of input
29  * and sending them to the backend.
30  *
31  * This loop is re-entrant. May be called by \i command
32  * which reads input from a file.
33  */
34 int
35 MainLoop(FILE *source)
36 {
37  PsqlScanState scan_state; /* lexer working state */
38  volatile PQExpBuffer query_buf; /* buffer for query being accumulated */
39  volatile PQExpBuffer previous_buf; /* if there isn't anything in the new
40  * buffer yet, use this one for \e,
41  * etc. */
42  PQExpBuffer history_buf; /* earlier lines of a multi-line command, not
43  * yet saved to readline history */
44  char *line; /* current line of input */
45  int added_nl_pos;
46  bool success;
47  bool line_saved_in_history;
48  volatile int successResult = EXIT_SUCCESS;
49  volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
50  volatile promptStatus_t prompt_status = PROMPT_READY;
51  volatile int count_eof = 0;
52  volatile bool die_on_error = false;
53 
54  /* Save the prior command source */
55  FILE *prev_cmd_source;
56  bool prev_cmd_interactive;
57  uint64 prev_lineno;
58 
59  /* Save old settings */
60  prev_cmd_source = pset.cur_cmd_source;
61  prev_cmd_interactive = pset.cur_cmd_interactive;
62  prev_lineno = pset.lineno;
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 
73  query_buf = createPQExpBuffer();
74  previous_buf = createPQExpBuffer();
75  history_buf = createPQExpBuffer();
76  if (PQExpBufferBroken(query_buf) ||
77  PQExpBufferBroken(previous_buf) ||
78  PQExpBufferBroken(history_buf))
79  {
80  psql_error("out of memory\n");
81  exit(EXIT_FAILURE);
82  }
83 
84  /* main loop to get queries and execute them */
85  while (successResult == EXIT_SUCCESS)
86  {
87  /*
88  * Clean up after a previous Control-C
89  */
90  if (cancel_pressed)
91  {
93  {
94  /*
95  * You get here if you stopped a script with Ctrl-C.
96  */
97  successResult = EXIT_USER;
98  break;
99  }
100 
101  cancel_pressed = false;
102  }
103 
104  /*
105  * Establish longjmp destination for exiting from wait-for-input. We
106  * must re-do this each time through the loop for safety, since the
107  * jmpbuf might get changed during command execution.
108  */
109  if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
110  {
111  /* got here with longjmp */
112 
113  /* reset parsing state */
114  psql_scan_finish(scan_state);
115  psql_scan_reset(scan_state);
116  resetPQExpBuffer(query_buf);
117  resetPQExpBuffer(history_buf);
118  count_eof = 0;
119  slashCmdStatus = PSQL_CMD_UNKNOWN;
120  prompt_status = PROMPT_READY;
121  pset.stmt_lineno = 1;
122  cancel_pressed = false;
123 
125  putc('\n', stdout);
126  else
127  {
128  successResult = EXIT_USER;
129  break;
130  }
131  }
132 
133  fflush(stdout);
134 
135  /*
136  * get another line
137  */
139  {
140  /* May need to reset prompt, eg after \r command */
141  if (query_buf->len == 0)
142  prompt_status = PROMPT_READY;
143  line = gets_interactive(get_prompt(prompt_status), query_buf);
144  }
145  else
146  {
147  line = gets_fromFile(source);
148  if (!line && ferror(source))
149  successResult = EXIT_FAILURE;
150  }
151 
152  /*
153  * query_buf holds query already accumulated. line is the malloc'd
154  * new line of input (note it must be freed before looping around!)
155  */
156 
157  /* No more input. Time to quit, or \i done */
158  if (line == NULL)
159  {
161  {
162  /* This tries to mimic bash's IGNOREEOF feature. */
163  count_eof++;
164 
165  if (count_eof < pset.ignoreeof)
166  {
167  if (!pset.quiet)
168  printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
169  continue;
170  }
171 
172  puts(pset.quiet ? "" : "\\q");
173  }
174  break;
175  }
176 
177  count_eof = 0;
178 
179  pset.lineno++;
180 
181  /* ignore UTF-8 Unicode byte-order mark */
182  if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
183  memmove(line, line + 3, strlen(line + 3) + 1);
184 
185  /* Detect attempts to run custom-format dumps as SQL scripts */
186  if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
187  strncmp(line, "PGDMP", 5) == 0)
188  {
189  free(line);
190  puts(_("The input is a PostgreSQL custom-format dump.\n"
191  "Use the pg_restore command-line client to restore this dump to a database.\n"));
192  fflush(stdout);
193  successResult = EXIT_FAILURE;
194  break;
195  }
196 
197  /* no further processing of empty lines, unless within a literal */
198  if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
199  {
200  free(line);
201  continue;
202  }
203 
204  /* A request for help? Be friendly and give them some guidance */
205  if (pset.cur_cmd_interactive && query_buf->len == 0 &&
206  pg_strncasecmp(line, "help", 4) == 0 &&
207  (line[4] == '\0' || line[4] == ';' || isspace((unsigned char) line[4])))
208  {
209  free(line);
210  puts(_("You are using psql, the command-line interface to PostgreSQL."));
211  printf(_("Type: \\copyright for distribution terms\n"
212  " \\h for help with SQL commands\n"
213  " \\? for help with psql commands\n"
214  " \\g or terminate with semicolon to execute query\n"
215  " \\q to quit\n"));
216 
217  fflush(stdout);
218  continue;
219  }
220 
221  /* echo back if flag is set, unless interactive */
223  {
224  puts(line);
225  fflush(stdout);
226  }
227 
228  /* insert newlines into query buffer between source lines */
229  if (query_buf->len > 0)
230  {
231  appendPQExpBufferChar(query_buf, '\n');
232  added_nl_pos = query_buf->len;
233  }
234  else
235  added_nl_pos = -1; /* flag we didn't add one */
236 
237  /* Setting this will not have effect until next line. */
238  die_on_error = pset.on_error_stop;
239 
240  /*
241  * Parse line, looking for command separators.
242  */
243  psql_scan_setup(scan_state, line, strlen(line),
245  success = true;
246  line_saved_in_history = false;
247 
248  while (success || !die_on_error)
249  {
250  PsqlScanResult scan_result;
251  promptStatus_t prompt_tmp = prompt_status;
252  size_t pos_in_query;
253  char *tmp_line;
254 
255  pos_in_query = query_buf->len;
256  scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
257  prompt_status = prompt_tmp;
258 
259  if (PQExpBufferBroken(query_buf))
260  {
261  psql_error("out of memory\n");
262  exit(EXIT_FAILURE);
263  }
264 
265  /*
266  * Increase statement line number counter for each linebreak added
267  * to the query buffer by the last psql_scan() call. There only
268  * will be ones to add when navigating to a statement in
269  * readline's history containing newlines.
270  */
271  tmp_line = query_buf->data + pos_in_query;
272  while (*tmp_line != '\0')
273  {
274  if (*(tmp_line++) == '\n')
275  pset.stmt_lineno++;
276  }
277 
278  if (scan_result == PSCAN_EOL)
279  pset.stmt_lineno++;
280 
281  /*
282  * Send command if semicolon found, or if end of line and we're in
283  * single-line mode.
284  */
285  if (scan_result == PSCAN_SEMICOLON ||
286  (scan_result == PSCAN_EOL && pset.singleline))
287  {
288  /*
289  * Save query in history. We use history_buf to accumulate
290  * multi-line queries into a single history entry.
291  */
292  if (pset.cur_cmd_interactive && !line_saved_in_history)
293  {
294  pg_append_history(line, history_buf);
295  pg_send_history(history_buf);
296  line_saved_in_history = true;
297  }
298 
299  /* execute query */
300  success = SendQuery(query_buf->data);
301  slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
302  pset.stmt_lineno = 1;
303 
304  /* transfer query to previous_buf by pointer-swapping */
305  {
306  PQExpBuffer swap_buf = previous_buf;
307 
308  previous_buf = query_buf;
309  query_buf = swap_buf;
310  }
311  resetPQExpBuffer(query_buf);
312 
313  added_nl_pos = -1;
314  /* we need not do psql_scan_reset() here */
315  }
316  else if (scan_result == PSCAN_BACKSLASH)
317  {
318  /* handle backslash command */
319 
320  /*
321  * If we added a newline to query_buf, and nothing else has
322  * been inserted in query_buf by the lexer, then strip off the
323  * newline again. This avoids any change to query_buf when a
324  * line contains only a backslash command. Also, in this
325  * situation we force out any previous lines as a separate
326  * history entry; we don't want SQL and backslash commands
327  * intermixed in history if at all possible.
328  */
329  if (query_buf->len == added_nl_pos)
330  {
331  query_buf->data[--query_buf->len] = '\0';
332  pg_send_history(history_buf);
333  }
334  added_nl_pos = -1;
335 
336  /* save backslash command in history */
337  if (pset.cur_cmd_interactive && !line_saved_in_history)
338  {
339  pg_append_history(line, history_buf);
340  pg_send_history(history_buf);
341  line_saved_in_history = true;
342  }
343 
344  /* execute backslash command */
345  slashCmdStatus = HandleSlashCmds(scan_state,
346  query_buf->len > 0 ?
347  query_buf : previous_buf);
348 
349  success = slashCmdStatus != PSQL_CMD_ERROR;
350  pset.stmt_lineno = 1;
351 
352  if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
353  query_buf->len == 0)
354  {
355  /* copy previous buffer to current for handling */
356  appendPQExpBufferStr(query_buf, previous_buf->data);
357  }
358 
359  if (slashCmdStatus == PSQL_CMD_SEND)
360  {
361  success = SendQuery(query_buf->data);
362 
363  /* transfer query to previous_buf by pointer-swapping */
364  {
365  PQExpBuffer swap_buf = previous_buf;
366 
367  previous_buf = query_buf;
368  query_buf = swap_buf;
369  }
370  resetPQExpBuffer(query_buf);
371 
372  /* flush any paren nesting info after forced send */
373  psql_scan_reset(scan_state);
374  }
375  else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
376  {
377  /* rescan query_buf as new input */
378  psql_scan_finish(scan_state);
379  free(line);
380  line = pg_strdup(query_buf->data);
381  resetPQExpBuffer(query_buf);
382  /* reset parsing state since we are rescanning whole line */
383  psql_scan_reset(scan_state);
384  psql_scan_setup(scan_state, line, strlen(line),
386  line_saved_in_history = false;
387  prompt_status = PROMPT_READY;
388  }
389  else if (slashCmdStatus == PSQL_CMD_TERMINATE)
390  break;
391  }
392 
393  /* fall out of loop if lexer reached EOL */
394  if (scan_result == PSCAN_INCOMPLETE ||
395  scan_result == PSCAN_EOL)
396  break;
397  }
398 
399  /* Add line to pending history if we didn't execute anything yet */
400  if (pset.cur_cmd_interactive && !line_saved_in_history)
401  pg_append_history(line, history_buf);
402 
403  psql_scan_finish(scan_state);
404  free(line);
405 
406  if (slashCmdStatus == PSQL_CMD_TERMINATE)
407  {
408  successResult = EXIT_SUCCESS;
409  break;
410  }
411 
413  {
414  if (!success && die_on_error)
415  successResult = EXIT_USER;
416  /* Have we lost the db connection? */
417  else if (!pset.db)
418  successResult = EXIT_BADCONN;
419  }
420  } /* while !endoffile/session */
421 
422  /*
423  * Process query at the end of file without a semicolon
424  */
425  if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
426  successResult == EXIT_SUCCESS)
427  {
428  /* save query in history */
430  pg_send_history(history_buf);
431 
432  /* execute query */
433  success = SendQuery(query_buf->data);
434 
435  if (!success && die_on_error)
436  successResult = EXIT_USER;
437  else if (pset.db == NULL)
438  successResult = EXIT_BADCONN;
439  }
440 
441  /*
442  * Let's just make real sure the SIGINT handler won't try to use
443  * sigint_interrupt_jmp after we exit this routine. If there is an outer
444  * MainLoop instance, it will reset sigint_interrupt_jmp to point to
445  * itself at the top of its loop, before any further interactive input
446  * happens.
447  */
448  sigint_interrupt_enabled = false;
449 
450  destroyPQExpBuffer(query_buf);
451  destroyPQExpBuffer(previous_buf);
452  destroyPQExpBuffer(history_buf);
453 
454  psql_scan_destroy(scan_state);
455 
456  pset.cur_cmd_source = prev_cmd_source;
457  pset.cur_cmd_interactive = prev_cmd_interactive;
458  pset.lineno = prev_lineno;
459 
460  return successResult;
461 } /* MainLoop() */
PSQL_ECHO echo
Definition: settings.h:130
PGconn * db
Definition: settings.h:82
PsqlScanResult
Definition: psqlscan.h:30
char * get_prompt(promptStatus_t status)
Definition: prompt.c:69
void pg_send_history(PQExpBuffer history_buf)
Definition: input.c:135
volatile bool sigint_interrupt_enabled
Definition: common.c:230
#define EXIT_SUCCESS
Definition: settings.h:146
PsqlSettings pset
Definition: startup.c:37
PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
char * psql_get_variable(const char *varname, bool escape, bool as_ident)
Definition: common.c:124
bool on_error_stop
Definition: settings.h:123
FILE * cur_cmd_source
Definition: settings.h:102
sigjmp_buf sigint_interrupt_jmp
Definition: common.c:232
#define EXIT_BADCONN
Definition: settings.h:153
volatile bool cancel_pressed
Definition: print.c:47
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:104
static bool success
Definition: pg_basebackup.c:99
#define memmove(d, s, c)
Definition: c.h:1058
const PsqlScanCallbacks psqlscan_callbacks
Definition: mainloop.c:21
void psql_scan_reset(PsqlScanState state)
#define EXIT_USER
Definition: settings.h:155
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
bool singleline
Definition: settings.h:125
char * gets_interactive(const char *prompt, PQExpBuffer query_buf)
Definition: input.c:66
void psql_error(const char *fmt,...)
Definition: common.c:177
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:2008
#define free(a)
Definition: header.h:60
enum _backslashResult backslashResult
#define NULL
Definition: c.h:226
void pg_append_history(const char *s, PQExpBuffer history_buf)
Definition: input.c:113
const char * progname
Definition: settings.h:106
int MainLoop(FILE *source)
Definition: mainloop.c:35
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)
backslashResult HandleSlashCmds(PsqlScanState scan_state, PQExpBuffer query_buf)
Definition: command.c:111
uint64 lineno
Definition: settings.h:108
#define EXIT_FAILURE
Definition: settings.h:150
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:1183
bool psql_scan_in_quote(PsqlScanState state)
void psql_scan_finish(PsqlScanState state)
bool notty
Definition: settings.h:99
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:109