Add error pattern checks for some TAP tests for non-existing objects
[pgsql.git] / src / bin / psql / mainloop.c
blob0e0baa3540b14e846b04c644a79f306ce786108c
1 /*
2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2025, PostgreSQL Global Development Group
6 * src/bin/psql/mainloop.c
7 */
8 #include "postgres_fe.h"
10 #include "command.h"
11 #include "common.h"
12 #include "common/logging.h"
13 #include "input.h"
14 #include "mainloop.h"
15 #include "mb/pg_wchar.h"
16 #include "prompt.h"
17 #include "settings.h"
19 /* callback functions for our flex lexer */
20 const PsqlScanCallbacks psqlscan_callbacks = {
21 psql_get_variable,
26 * Main processing loop for reading lines of input
27 * and sending them to the backend.
29 * This loop is re-entrant. May be called by \i command
30 * which reads input from a file.
32 int
33 MainLoop(FILE *source)
35 PsqlScanState scan_state; /* lexer working state */
36 ConditionalStack cond_stack; /* \if status stack */
37 volatile PQExpBuffer query_buf; /* buffer for query being accumulated */
38 volatile PQExpBuffer previous_buf; /* if there isn't anything in the new
39 * buffer yet, use this one for \e,
40 * etc. */
41 PQExpBuffer history_buf; /* earlier lines of a multi-line command, not
42 * yet saved to readline history */
43 char *line; /* current line of input */
44 int added_nl_pos;
45 bool success;
46 bool line_saved_in_history;
47 volatile int successResult = EXIT_SUCCESS;
48 volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
49 volatile promptStatus_t prompt_status = PROMPT_READY;
50 volatile bool need_redisplay = false;
51 volatile int count_eof = 0;
52 volatile bool die_on_error = false;
53 FILE *prev_cmd_source;
54 bool prev_cmd_interactive;
55 uint64 prev_lineno;
57 /* Save the prior command source */
58 prev_cmd_source = pset.cur_cmd_source;
59 prev_cmd_interactive = pset.cur_cmd_interactive;
60 prev_lineno = pset.lineno;
61 /* pset.stmt_lineno does not need to be saved and restored */
63 /* Establish new source */
64 pset.cur_cmd_source = source;
65 pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
66 pset.lineno = 0;
67 pset.stmt_lineno = 1;
69 /* Create working state */
70 scan_state = psql_scan_create(&psqlscan_callbacks);
71 cond_stack = conditional_stack_create();
72 psql_scan_set_passthrough(scan_state, cond_stack);
74 query_buf = createPQExpBuffer();
75 previous_buf = createPQExpBuffer();
76 history_buf = createPQExpBuffer();
77 if (PQExpBufferBroken(query_buf) ||
78 PQExpBufferBroken(previous_buf) ||
79 PQExpBufferBroken(history_buf))
80 pg_fatal("out of memory");
82 /* main loop to get queries and execute them */
83 while (successResult == EXIT_SUCCESS)
86 * Clean up after a previous Control-C
88 if (cancel_pressed)
90 if (!pset.cur_cmd_interactive)
93 * You get here if you stopped a script with Ctrl-C.
95 successResult = EXIT_USER;
96 break;
99 cancel_pressed = false;
103 * Establish longjmp destination for exiting from wait-for-input. We
104 * must re-do this each time through the loop for safety, since the
105 * jmpbuf might get changed during command execution.
107 if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
109 /* got here with longjmp */
111 /* reset parsing state */
112 psql_scan_finish(scan_state);
113 psql_scan_reset(scan_state);
114 resetPQExpBuffer(query_buf);
115 resetPQExpBuffer(history_buf);
116 count_eof = 0;
117 slashCmdStatus = PSQL_CMD_UNKNOWN;
118 prompt_status = PROMPT_READY;
119 need_redisplay = false;
120 pset.stmt_lineno = 1;
121 cancel_pressed = false;
123 if (pset.cur_cmd_interactive)
125 putc('\n', stdout);
128 * if interactive user is in an \if block, then Ctrl-C will
129 * exit from the innermost \if.
131 if (!conditional_stack_empty(cond_stack))
133 pg_log_error("\\if: escaped");
134 conditional_stack_pop(cond_stack);
137 else
139 successResult = EXIT_USER;
140 break;
144 fflush(stdout);
147 * get another line
149 if (pset.cur_cmd_interactive)
151 /* May need to reset prompt, eg after \r command */
152 if (query_buf->len == 0)
153 prompt_status = PROMPT_READY;
154 /* If query buffer came from \e, redisplay it with a prompt */
155 if (need_redisplay)
157 if (query_buf->len > 0)
159 fputs(get_prompt(PROMPT_READY, cond_stack), stdout);
160 fputs(query_buf->data, stdout);
161 fflush(stdout);
163 need_redisplay = false;
165 /* Now we can fetch a line */
166 line = gets_interactive(get_prompt(prompt_status, cond_stack),
167 query_buf);
169 else
171 line = gets_fromFile(source);
172 if (!line && ferror(source))
173 successResult = EXIT_FAILURE;
177 * query_buf holds query already accumulated. line is the malloc'd
178 * new line of input (note it must be freed before looping around!)
181 /* No more input. Time to quit, or \i done */
182 if (line == NULL)
184 if (pset.cur_cmd_interactive)
186 /* This tries to mimic bash's IGNOREEOF feature. */
187 count_eof++;
189 if (count_eof < pset.ignoreeof)
191 if (!pset.quiet)
192 printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
193 continue;
196 puts(pset.quiet ? "" : "\\q");
198 break;
201 count_eof = 0;
203 pset.lineno++;
205 /* ignore UTF-8 Unicode byte-order mark */
206 if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
207 memmove(line, line + 3, strlen(line + 3) + 1);
209 /* Detect attempts to run custom-format dumps as SQL scripts */
210 if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
211 strncmp(line, "PGDMP", 5) == 0)
213 free(line);
214 puts(_("The input is a PostgreSQL custom-format dump.\n"
215 "Use the pg_restore command-line client to restore this dump to a database.\n"));
216 fflush(stdout);
217 successResult = EXIT_FAILURE;
218 break;
221 /* no further processing of empty lines, unless within a literal */
222 if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
224 free(line);
225 continue;
228 /* Recognize "help", "quit", "exit" only in interactive mode */
229 if (pset.cur_cmd_interactive)
231 char *first_word = line;
232 char *rest_of_line = NULL;
233 bool found_help = false;
234 bool found_exit_or_quit = false;
235 bool found_q = false;
238 * The assistance words, help/exit/quit, must have no whitespace
239 * before them, and only whitespace after, with an optional
240 * semicolon. This prevents indented use of these words, perhaps
241 * as identifiers, from invoking the assistance behavior.
243 if (pg_strncasecmp(first_word, "help", 4) == 0)
245 rest_of_line = first_word + 4;
246 found_help = true;
248 else if (pg_strncasecmp(first_word, "exit", 4) == 0 ||
249 pg_strncasecmp(first_word, "quit", 4) == 0)
251 rest_of_line = first_word + 4;
252 found_exit_or_quit = true;
254 else if (strncmp(first_word, "\\q", 2) == 0)
256 rest_of_line = first_word + 2;
257 found_q = true;
261 * If we found a command word, check whether the rest of the line
262 * contains only whitespace plus maybe one semicolon. If not,
263 * ignore the command word after all. These commands are only for
264 * compatibility with other SQL clients and are not documented.
266 if (rest_of_line != NULL)
269 * Ignore unless rest of line is whitespace, plus maybe one
270 * semicolon
272 while (isspace((unsigned char) *rest_of_line))
273 ++rest_of_line;
274 if (*rest_of_line == ';')
275 ++rest_of_line;
276 while (isspace((unsigned char) *rest_of_line))
277 ++rest_of_line;
278 if (*rest_of_line != '\0')
280 found_help = false;
281 found_exit_or_quit = false;
286 * "help" is only a command when the query buffer is empty, but we
287 * emit a one-line message even when it isn't to help confused
288 * users. The text is still added to the query buffer in that
289 * case.
291 if (found_help)
293 if (query_buf->len != 0)
294 #ifndef WIN32
295 puts(_("Use \\? for help or press control-C to clear the input buffer."));
296 #else
297 puts(_("Use \\? for help."));
298 #endif
299 else
301 puts(_("You are using psql, the command-line interface to PostgreSQL."));
302 printf(_("Type: \\copyright for distribution terms\n"
303 " \\h for help with SQL commands\n"
304 " \\? for help with psql commands\n"
305 " \\g or terminate with semicolon to execute query\n"
306 " \\q to quit\n"));
307 free(line);
308 fflush(stdout);
309 continue;
314 * "quit" and "exit" are only commands when the query buffer is
315 * empty, but we emit a one-line message even when it isn't to
316 * help confused users. The text is still added to the query
317 * buffer in that case.
319 if (found_exit_or_quit)
321 if (query_buf->len != 0)
323 if (prompt_status == PROMPT_READY ||
324 prompt_status == PROMPT_CONTINUE ||
325 prompt_status == PROMPT_PAREN)
326 puts(_("Use \\q to quit."));
327 else
328 #ifndef WIN32
329 puts(_("Use control-D to quit."));
330 #else
331 puts(_("Use control-C to quit."));
332 #endif
334 else
336 /* exit app */
337 free(line);
338 fflush(stdout);
339 successResult = EXIT_SUCCESS;
340 break;
345 * If they typed "\q" in a place where "\q" is not active, supply
346 * a hint. The text is still added to the query buffer.
348 if (found_q && query_buf->len != 0 &&
349 prompt_status != PROMPT_READY &&
350 prompt_status != PROMPT_CONTINUE &&
351 prompt_status != PROMPT_PAREN)
352 #ifndef WIN32
353 puts(_("Use control-D to quit."));
354 #else
355 puts(_("Use control-C to quit."));
356 #endif
359 /* echo back if flag is set, unless interactive */
360 if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
362 puts(line);
363 fflush(stdout);
366 /* insert newlines into query buffer between source lines */
367 if (query_buf->len > 0)
369 appendPQExpBufferChar(query_buf, '\n');
370 added_nl_pos = query_buf->len;
372 else
373 added_nl_pos = -1; /* flag we didn't add one */
375 /* Setting this will not have effect until next line. */
376 die_on_error = pset.on_error_stop;
379 * Parse line, looking for command separators.
381 psql_scan_setup(scan_state, line, strlen(line),
382 pset.encoding, standard_strings());
383 success = true;
384 line_saved_in_history = false;
386 while (success || !die_on_error)
388 PsqlScanResult scan_result;
389 promptStatus_t prompt_tmp = prompt_status;
390 size_t pos_in_query;
391 char *tmp_line;
393 pos_in_query = query_buf->len;
394 scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
395 prompt_status = prompt_tmp;
397 if (PQExpBufferBroken(query_buf))
398 pg_fatal("out of memory");
401 * Increase statement line number counter for each linebreak added
402 * to the query buffer by the last psql_scan() call. There only
403 * will be ones to add when navigating to a statement in
404 * readline's history containing newlines.
406 tmp_line = query_buf->data + pos_in_query;
407 while (*tmp_line != '\0')
409 if (*(tmp_line++) == '\n')
410 pset.stmt_lineno++;
413 if (scan_result == PSCAN_EOL)
414 pset.stmt_lineno++;
417 * Send command if semicolon found, or if end of line and we're in
418 * single-line mode.
420 if (scan_result == PSCAN_SEMICOLON ||
421 (scan_result == PSCAN_EOL && pset.singleline))
424 * Save line in history. We use history_buf to accumulate
425 * multi-line queries into a single history entry. Note that
426 * history accumulation works on input lines, so it doesn't
427 * matter whether the query will be ignored due to \if.
429 if (pset.cur_cmd_interactive && !line_saved_in_history)
431 pg_append_history(line, history_buf);
432 pg_send_history(history_buf);
433 line_saved_in_history = true;
436 /* execute query unless we're in an inactive \if branch */
437 if (conditional_active(cond_stack))
439 success = SendQuery(query_buf->data);
440 slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
441 pset.stmt_lineno = 1;
443 /* transfer query to previous_buf by pointer-swapping */
445 PQExpBuffer swap_buf = previous_buf;
447 previous_buf = query_buf;
448 query_buf = swap_buf;
450 resetPQExpBuffer(query_buf);
452 added_nl_pos = -1;
453 /* we need not do psql_scan_reset() here */
455 else
457 /* if interactive, warn about non-executed query */
458 if (pset.cur_cmd_interactive)
459 pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
460 /* fake an OK result for purposes of loop checks */
461 success = true;
462 slashCmdStatus = PSQL_CMD_SEND;
463 pset.stmt_lineno = 1;
464 /* note that query_buf doesn't change state */
467 else if (scan_result == PSCAN_BACKSLASH)
469 /* handle backslash command */
472 * If we added a newline to query_buf, and nothing else has
473 * been inserted in query_buf by the lexer, then strip off the
474 * newline again. This avoids any change to query_buf when a
475 * line contains only a backslash command. Also, in this
476 * situation we force out any previous lines as a separate
477 * history entry; we don't want SQL and backslash commands
478 * intermixed in history if at all possible.
480 if (query_buf->len == added_nl_pos)
482 query_buf->data[--query_buf->len] = '\0';
483 pg_send_history(history_buf);
485 added_nl_pos = -1;
487 /* save backslash command in history */
488 if (pset.cur_cmd_interactive && !line_saved_in_history)
490 pg_append_history(line, history_buf);
491 pg_send_history(history_buf);
492 line_saved_in_history = true;
495 /* execute backslash command */
496 slashCmdStatus = HandleSlashCmds(scan_state,
497 cond_stack,
498 query_buf,
499 previous_buf);
501 success = slashCmdStatus != PSQL_CMD_ERROR;
504 * Resetting stmt_lineno after a backslash command isn't
505 * always appropriate, but it's what we've done historically
506 * and there have been few complaints.
508 pset.stmt_lineno = 1;
510 if (slashCmdStatus == PSQL_CMD_SEND)
512 /* should not see this in inactive branch */
513 Assert(conditional_active(cond_stack));
515 success = SendQuery(query_buf->data);
517 /* transfer query to previous_buf by pointer-swapping */
519 PQExpBuffer swap_buf = previous_buf;
521 previous_buf = query_buf;
522 query_buf = swap_buf;
524 resetPQExpBuffer(query_buf);
526 /* flush any paren nesting info after forced send */
527 psql_scan_reset(scan_state);
529 else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
531 /* should not see this in inactive branch */
532 Assert(conditional_active(cond_stack));
533 /* ensure what came back from editing ends in a newline */
534 if (query_buf->len > 0 &&
535 query_buf->data[query_buf->len - 1] != '\n')
536 appendPQExpBufferChar(query_buf, '\n');
537 /* rescan query_buf as new input */
538 psql_scan_finish(scan_state);
539 free(line);
540 line = pg_strdup(query_buf->data);
541 resetPQExpBuffer(query_buf);
542 /* reset parsing state since we are rescanning whole line */
543 psql_scan_reset(scan_state);
544 psql_scan_setup(scan_state, line, strlen(line),
545 pset.encoding, standard_strings());
546 line_saved_in_history = false;
547 prompt_status = PROMPT_READY;
548 /* we'll want to redisplay after parsing what we have */
549 need_redisplay = true;
551 else if (slashCmdStatus == PSQL_CMD_TERMINATE)
552 break;
555 /* fall out of loop if lexer reached EOL */
556 if (scan_result == PSCAN_INCOMPLETE ||
557 scan_result == PSCAN_EOL)
558 break;
562 * Add line to pending history if we didn't do so already. Then, if
563 * the query buffer is still empty, flush out any unsent history
564 * entry. This means that empty lines (containing only whitespace and
565 * perhaps a dash-dash comment) that precede a query will be recorded
566 * as separate history entries, not as part of that query.
568 if (pset.cur_cmd_interactive)
570 if (!line_saved_in_history)
571 pg_append_history(line, history_buf);
572 if (query_buf->len == 0)
573 pg_send_history(history_buf);
576 psql_scan_finish(scan_state);
577 free(line);
579 if (slashCmdStatus == PSQL_CMD_TERMINATE)
581 successResult = EXIT_SUCCESS;
582 break;
585 if (!pset.cur_cmd_interactive)
587 if (!success && die_on_error)
588 successResult = EXIT_USER;
589 /* Have we lost the db connection? */
590 else if (!pset.db)
591 successResult = EXIT_BADCONN;
593 } /* while !endoffile/session */
596 * If we have a non-semicolon-terminated query at the end of file, we
597 * process it unless the input source is interactive --- in that case it
598 * seems better to go ahead and quit. Also skip if this is an error exit.
600 if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
601 successResult == EXIT_SUCCESS)
603 /* save query in history */
604 /* currently unneeded since we don't use this block if interactive */
605 #ifdef NOT_USED
606 if (pset.cur_cmd_interactive)
607 pg_send_history(history_buf);
608 #endif
610 /* execute query unless we're in an inactive \if branch */
611 if (conditional_active(cond_stack))
613 success = SendQuery(query_buf->data);
615 else
617 if (pset.cur_cmd_interactive)
618 pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
619 success = true;
622 if (!success && die_on_error)
623 successResult = EXIT_USER;
624 else if (pset.db == NULL)
625 successResult = EXIT_BADCONN;
629 * Check for unbalanced \if-\endifs unless user explicitly quit, or the
630 * script is erroring out
632 if (slashCmdStatus != PSQL_CMD_TERMINATE &&
633 successResult != EXIT_USER &&
634 !conditional_stack_empty(cond_stack))
636 pg_log_error("reached EOF without finding closing \\endif(s)");
637 if (die_on_error && !pset.cur_cmd_interactive)
638 successResult = EXIT_USER;
642 * Let's just make real sure the SIGINT handler won't try to use
643 * sigint_interrupt_jmp after we exit this routine. If there is an outer
644 * MainLoop instance, it will reset sigint_interrupt_jmp to point to
645 * itself at the top of its loop, before any further interactive input
646 * happens.
648 sigint_interrupt_enabled = false;
650 destroyPQExpBuffer(query_buf);
651 destroyPQExpBuffer(previous_buf);
652 destroyPQExpBuffer(history_buf);
654 psql_scan_destroy(scan_state);
655 conditional_stack_destroy(cond_stack);
657 pset.cur_cmd_source = prev_cmd_source;
658 pset.cur_cmd_interactive = prev_cmd_interactive;
659 pset.lineno = prev_lineno;
661 return successResult;
662 } /* MainLoop() */