Age Owner TLA Line data Source code
1 : /*
2 : * psql - the PostgreSQL interactive terminal
3 : *
4 : * Copyright (c) 2000-2023, PostgreSQL Global Development Group
5 : *
6 : * src/bin/psql/mainloop.c
7 : */
8 : #include "postgres_fe.h"
9 :
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"
18 :
19 : /* callback functions for our flex lexer */
20 : const PsqlScanCallbacks psqlscan_callbacks = {
21 : psql_get_variable,
22 : };
23 :
24 :
25 : /*
26 : * Main processing loop for reading lines of input
27 : * and sending them to the backend.
28 : *
29 : * This loop is re-entrant. May be called by \i command
30 : * which reads input from a file.
31 : */
32 : int
8482 peter_e 33 CBC 5969 : MainLoop(FILE *source)
34 : {
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;
8439 47 5969 : volatile int successResult = EXIT_SUCCESS;
6321 48 5969 : volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
6989 tgl 49 5969 : volatile promptStatus_t prompt_status = PROMPT_READY;
1234 50 5969 : volatile bool need_redisplay = false;
8397 bruce 51 5969 : volatile int count_eof = 0;
6989 tgl 52 5969 : volatile bool die_on_error = false;
53 : FILE *prev_cmd_source;
54 : bool prev_cmd_interactive;
55 : uint64 prev_lineno;
56 :
57 : /* Save the prior command source */
8486 peter_e 58 5969 : prev_cmd_source = pset.cur_cmd_source;
59 5969 : prev_cmd_interactive = pset.cur_cmd_interactive;
6989 tgl 60 5969 : prev_lineno = pset.lineno;
61 : /* pset.stmt_lineno does not need to be saved and restored */
62 :
63 : /* Establish new source */
8486 peter_e 64 5969 : pset.cur_cmd_source = source;
65 5969 : pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
6989 tgl 66 5969 : pset.lineno = 0;
3141 andres 67 5969 : pset.stmt_lineno = 1;
68 :
69 : /* Create working state */
2578 tgl 70 5969 : scan_state = psql_scan_create(&psqlscan_callbacks);
2201 71 5969 : cond_stack = conditional_stack_create();
72 5969 : psql_scan_set_passthrough(scan_state, (void *) cond_stack);
73 :
8557 bruce 74 5969 : query_buf = createPQExpBuffer();
8397 75 5969 : previous_buf = createPQExpBuffer();
6266 76 5969 : history_buf = createPQExpBuffer();
5247 tgl 77 5969 : if (PQExpBufferBroken(query_buf) ||
78 5969 : PQExpBufferBroken(previous_buf) ||
79 5969 : PQExpBufferBroken(history_buf))
366 tgl 80 UBC 0 : pg_fatal("out of memory");
81 :
82 : /* main loop to get queries and execute them */
7325 bruce 83 CBC 341752 : while (successResult == EXIT_SUCCESS)
84 : {
85 : /*
86 : * Clean up after a previous Control-C
87 : */
8397 88 341731 : if (cancel_pressed)
89 : {
8397 bruce 90 UBC 0 : if (!pset.cur_cmd_interactive)
91 : {
92 : /*
93 : * You get here if you stopped a script with Ctrl-C.
94 : */
95 0 : successResult = EXIT_USER;
96 0 : break;
97 : }
98 :
99 0 : cancel_pressed = false;
100 : }
101 :
102 : /*
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.
106 : */
6143 tgl 107 CBC 341731 : if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
108 : {
109 : /* got here with longjmp */
110 :
111 : /* reset parsing state */
6989 tgl 112 UBC 0 : psql_scan_finish(scan_state);
113 0 : psql_scan_reset(scan_state);
6143 114 0 : resetPQExpBuffer(query_buf);
115 0 : resetPQExpBuffer(history_buf);
6989 116 0 : count_eof = 0;
6321 peter_e 117 0 : slashCmdStatus = PSQL_CMD_UNKNOWN;
6989 tgl 118 0 : prompt_status = PROMPT_READY;
1234 119 0 : need_redisplay = false;
3141 andres 120 0 : pset.stmt_lineno = 1;
6143 tgl 121 0 : cancel_pressed = false;
122 :
8397 bruce 123 0 : if (pset.cur_cmd_interactive)
124 : {
7325 125 0 : putc('\n', stdout);
126 :
127 : /*
128 : * if interactive user is in an \if block, then Ctrl-C will
129 : * exit from the innermost \if.
130 : */
2201 tgl 131 0 : if (!conditional_stack_empty(cond_stack))
132 : {
1469 peter 133 0 : pg_log_error("\\if: escaped");
2201 tgl 134 0 : conditional_stack_pop(cond_stack);
135 : }
136 : }
137 : else
138 : {
8397 bruce 139 0 : successResult = EXIT_USER;
140 0 : break;
141 : }
142 : }
143 :
7018 tgl 144 CBC 341731 : fflush(stdout);
145 :
146 : /*
147 : * get another line
148 : */
6146 149 341731 : if (pset.cur_cmd_interactive)
150 : {
151 : /* May need to reset prompt, eg after \r command */
6989 152 53 : if (query_buf->len == 0)
7188 bruce 153 51 : prompt_status = PROMPT_READY;
154 : /* If query buffer came from \e, redisplay it with a prompt */
1234 tgl 155 53 : if (need_redisplay)
156 : {
1234 tgl 157 UBC 0 : if (query_buf->len > 0)
158 : {
159 0 : fputs(get_prompt(PROMPT_READY, cond_stack), stdout);
160 0 : fputs(query_buf->data, stdout);
161 0 : fflush(stdout);
162 : }
163 0 : need_redisplay = false;
164 : }
165 : /* Now we can fetch a line */
2201 tgl 166 CBC 53 : line = gets_interactive(get_prompt(prompt_status, cond_stack),
167 : query_buf);
168 : }
169 : else
170 : {
7188 bruce 171 341678 : line = gets_fromFile(source);
5611 peter_e 172 341678 : if (!line && ferror(source))
5611 peter_e 173 UBC 0 : successResult = EXIT_FAILURE;
174 : }
175 :
176 : /*
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!)
179 : */
180 :
181 : /* No more input. Time to quit, or \i done */
8554 bruce 182 CBC 341731 : if (line == NULL)
183 : {
8486 peter_e 184 5917 : if (pset.cur_cmd_interactive)
185 : {
186 : /* This tries to mimic bash's IGNOREEOF feature. */
7325 bruce 187 UBC 0 : count_eof++;
188 :
2257 tgl 189 0 : if (count_eof < pset.ignoreeof)
190 : {
6067 191 0 : if (!pset.quiet)
6620 bruce 192 0 : printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
8397 193 0 : continue;
194 : }
195 :
6067 tgl 196 0 : puts(pset.quiet ? "" : "\\q");
197 : }
7188 bruce 198 CBC 5917 : break;
199 : }
200 :
201 335814 : count_eof = 0;
202 :
8397 203 335814 : pset.lineno++;
204 :
205 : /* ignore UTF-8 Unicode byte-order mark */
4887 peter_e 206 335814 : if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
4887 peter_e 207 UBC 0 : memmove(line, line + 3, strlen(line + 3) + 1);
208 :
209 : /* Detect attempts to run custom-format dumps as SQL scripts */
3089 alvherre 210 CBC 335814 : if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
211 5854 : strncmp(line, "PGDMP", 5) == 0)
212 : {
3089 alvherre 213 UBC 0 : free(line);
214 0 : 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 0 : fflush(stdout);
217 0 : successResult = EXIT_FAILURE;
218 0 : break;
219 : }
220 :
221 : /* no further processing of empty lines, unless within a literal */
6989 tgl 222 CBC 335814 : if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
223 : {
8557 bruce 224 59584 : free(line);
225 59584 : continue;
226 : }
227 :
228 : /* Recognize "help", "quit", "exit" only in interactive mode */
1893 229 276230 : if (pset.cur_cmd_interactive)
230 : {
231 43 : char *first_word = line;
232 43 : char *rest_of_line = NULL;
233 43 : bool found_help = false;
234 43 : bool found_exit_or_quit = false;
1882 235 43 : bool found_q = false;
236 :
237 : /*
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.
242 : */
1893 243 43 : if (pg_strncasecmp(first_word, "help", 4) == 0)
244 : {
1893 bruce 245 UBC 0 : rest_of_line = first_word + 4;
246 0 : found_help = true;
247 : }
1893 bruce 248 CBC 43 : else if (pg_strncasecmp(first_word, "exit", 4) == 0 ||
249 43 : pg_strncasecmp(first_word, "quit", 4) == 0)
250 : {
1893 bruce 251 UBC 0 : rest_of_line = first_word + 4;
252 0 : found_exit_or_quit = true;
253 : }
1882 bruce 254 CBC 43 : else if (strncmp(first_word, "\\q", 2) == 0)
255 : {
256 2 : rest_of_line = first_word + 2;
257 2 : found_q = true;
258 : }
259 :
260 : /*
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.
265 : */
1893 266 43 : if (rest_of_line != NULL)
267 : {
268 : /*
269 : * Ignore unless rest of line is whitespace, plus maybe one
270 : * semicolon
271 : */
272 2 : while (isspace((unsigned char) *rest_of_line))
1893 bruce 273 UBC 0 : ++rest_of_line;
1893 bruce 274 CBC 2 : if (*rest_of_line == ';')
1893 bruce 275 UBC 0 : ++rest_of_line;
1893 bruce 276 CBC 2 : while (isspace((unsigned char) *rest_of_line))
1893 bruce 277 UBC 0 : ++rest_of_line;
1893 bruce 278 CBC 2 : if (*rest_of_line != '\0')
279 : {
1893 bruce 280 UBC 0 : found_help = false;
281 0 : found_exit_or_quit = false;
282 : }
283 : }
284 :
285 : /*
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.
290 : */
1893 bruce 291 CBC 43 : if (found_help)
292 : {
1893 bruce 293 UBC 0 : if (query_buf->len != 0)
294 : #ifndef WIN32
295 0 : puts(_("Use \\? for help or press control-C to clear the input buffer."));
296 : #else
297 : puts(_("Use \\? for help."));
298 : #endif
299 : else
300 : {
301 0 : puts(_("You are using psql, the command-line interface to PostgreSQL."));
302 0 : 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 0 : free(line);
308 0 : fflush(stdout);
309 0 : continue;
310 : }
311 : }
312 :
313 : /*
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.
318 : */
1893 bruce 319 CBC 43 : if (found_exit_or_quit)
320 : {
1893 bruce 321 UBC 0 : if (query_buf->len != 0)
322 : {
323 0 : if (prompt_status == PROMPT_READY ||
324 0 : prompt_status == PROMPT_CONTINUE ||
325 0 : prompt_status == PROMPT_PAREN)
326 0 : puts(_("Use \\q to quit."));
327 : else
328 : #ifndef WIN32
329 0 : puts(_("Use control-D to quit."));
330 : #else
331 : puts(_("Use control-C to quit."));
332 : #endif
333 : }
334 : else
335 : {
336 : /* exit app */
337 0 : free(line);
338 0 : fflush(stdout);
339 0 : successResult = EXIT_SUCCESS;
340 0 : break;
341 : }
342 : }
343 :
344 : /*
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.
347 : */
1882 bruce 348 CBC 43 : if (found_q && query_buf->len != 0 &&
1882 bruce 349 UBC 0 : prompt_status != PROMPT_READY &&
350 0 : prompt_status != PROMPT_CONTINUE &&
351 0 : prompt_status != PROMPT_PAREN)
352 : #ifndef WIN32
1809 tgl 353 0 : puts(_("Use control-D to quit."));
354 : #else
355 : puts(_("Use control-C to quit."));
356 : #endif
357 : }
358 :
359 : /* echo back if flag is set, unless interactive */
6067 tgl 360 CBC 276230 : if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
361 : {
8397 bruce 362 265057 : puts(line);
2990 tgl 363 265057 : fflush(stdout);
364 : }
365 :
366 : /* insert newlines into query buffer between source lines */
6989 367 276230 : if (query_buf->len > 0)
368 : {
369 82112 : appendPQExpBufferChar(query_buf, '\n');
370 82112 : added_nl_pos = query_buf->len;
371 : }
372 : else
373 194118 : added_nl_pos = -1; /* flag we didn't add one */
374 :
375 : /* Setting this will not have effect until next line. */
6067 376 276230 : die_on_error = pset.on_error_stop;
377 :
378 : /*
379 : * Parse line, looking for command separators.
380 : */
2578 381 276230 : psql_scan_setup(scan_state, line, strlen(line),
382 276230 : pset.encoding, standard_strings());
8557 bruce 383 276230 : success = true;
6146 tgl 384 276230 : line_saved_in_history = false;
385 :
6989 386 424168 : while (success || !die_on_error)
387 : {
388 : PsqlScanResult scan_result;
389 424147 : promptStatus_t prompt_tmp = prompt_status;
390 : size_t pos_in_query;
391 : char *tmp_line;
392 :
3141 andres 393 424147 : pos_in_query = query_buf->len;
6989 tgl 394 424147 : scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
395 424147 : prompt_status = prompt_tmp;
396 :
5247 397 424147 : if (PQExpBufferBroken(query_buf))
366 tgl 398 UBC 0 : pg_fatal("out of memory");
399 :
400 : /*
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.
405 : */
3141 andres 406 CBC 424147 : tmp_line = query_buf->data + pos_in_query;
407 10277084 : while (*tmp_line != '\0')
408 : {
409 9852937 : if (*(tmp_line++) == '\n')
410 90 : pset.stmt_lineno++;
411 : }
412 :
413 424147 : if (scan_result == PSCAN_EOL)
414 44434 : pset.stmt_lineno++;
415 :
416 : /*
417 : * Send command if semicolon found, or if end of line and we're in
418 : * single-line mode.
419 : */
6989 tgl 420 424147 : if (scan_result == PSCAN_SEMICOLON ||
6067 421 44434 : (scan_result == PSCAN_EOL && pset.singleline))
422 : {
423 : /*
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.
428 : */
6146 429 141788 : if (pset.cur_cmd_interactive && !line_saved_in_history)
430 : {
431 5 : pg_append_history(line, history_buf);
432 5 : pg_send_history(history_buf);
433 5 : line_saved_in_history = true;
434 : }
435 :
436 : /* execute query unless we're in an inactive \if branch */
2201 437 141788 : if (conditional_active(cond_stack))
438 : {
439 141785 : success = SendQuery(query_buf->data);
440 141779 : slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
441 141779 : pset.stmt_lineno = 1;
442 :
443 : /* transfer query to previous_buf by pointer-swapping */
444 : {
445 141779 : PQExpBuffer swap_buf = previous_buf;
446 :
447 141779 : previous_buf = query_buf;
448 141779 : query_buf = swap_buf;
449 : }
450 141779 : resetPQExpBuffer(query_buf);
451 :
452 141779 : added_nl_pos = -1;
453 : /* we need not do psql_scan_reset() here */
454 : }
455 : else
456 : {
457 : /* if interactive, warn about non-executed query */
458 3 : if (pset.cur_cmd_interactive)
1469 peter 459 UBC 0 : 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 */
2201 tgl 461 CBC 3 : success = true;
462 3 : slashCmdStatus = PSQL_CMD_SEND;
463 3 : pset.stmt_lineno = 1;
464 : /* note that query_buf doesn't change state */
465 : }
466 : }
6989 467 282359 : else if (scan_result == PSCAN_BACKSLASH)
468 : {
469 : /* handle backslash command */
470 :
471 : /*
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.
479 : */
480 6181 : if (query_buf->len == added_nl_pos)
481 : {
482 50 : query_buf->data[--query_buf->len] = '\0';
6146 483 50 : pg_send_history(history_buf);
484 : }
6989 485 6181 : added_nl_pos = -1;
486 :
487 : /* save backslash command in history */
6146 488 6181 : if (pset.cur_cmd_interactive && !line_saved_in_history)
489 : {
490 36 : pg_append_history(line, history_buf);
491 36 : pg_send_history(history_buf);
492 36 : line_saved_in_history = true;
493 : }
494 :
495 : /* execute backslash command */
6989 496 6181 : slashCmdStatus = HandleSlashCmds(scan_state,
497 : cond_stack,
498 : query_buf,
499 : previous_buf);
500 :
6321 peter_e 501 6181 : success = slashCmdStatus != PSQL_CMD_ERROR;
502 :
503 : /*
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.
507 : */
2201 tgl 508 6181 : pset.stmt_lineno = 1;
509 :
6321 peter_e 510 6181 : if (slashCmdStatus == PSQL_CMD_SEND)
511 : {
512 : /* should not see this in inactive branch */
2201 tgl 513 494 : Assert(conditional_active(cond_stack));
514 :
8486 peter_e 515 494 : success = SendQuery(query_buf->data);
516 :
517 : /* transfer query to previous_buf by pointer-swapping */
518 : {
5247 tgl 519 494 : PQExpBuffer swap_buf = previous_buf;
520 :
521 494 : previous_buf = query_buf;
522 494 : query_buf = swap_buf;
523 : }
8397 bruce 524 494 : resetPQExpBuffer(query_buf);
525 :
526 : /* flush any paren nesting info after forced send */
6989 tgl 527 494 : psql_scan_reset(scan_state);
528 : }
6146 529 5687 : else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
530 : {
531 : /* should not see this in inactive branch */
2201 tgl 532 UBC 0 : Assert(conditional_active(cond_stack));
533 : /* ensure what came back from editing ends in a newline */
1234 534 0 : if (query_buf->len > 0 &&
535 0 : query_buf->data[query_buf->len - 1] != '\n')
536 0 : appendPQExpBufferChar(query_buf, '\n');
537 : /* rescan query_buf as new input */
6146 538 0 : psql_scan_finish(scan_state);
539 0 : free(line);
540 0 : line = pg_strdup(query_buf->data);
541 0 : resetPQExpBuffer(query_buf);
542 : /* reset parsing state since we are rescanning whole line */
543 0 : psql_scan_reset(scan_state);
2578 544 0 : psql_scan_setup(scan_state, line, strlen(line),
545 0 : pset.encoding, standard_strings());
6146 546 0 : line_saved_in_history = false;
547 0 : prompt_status = PROMPT_READY;
548 : /* we'll want to redisplay after parsing what we have */
1234 549 0 : need_redisplay = true;
550 : }
6146 tgl 551 CBC 5687 : else if (slashCmdStatus == PSQL_CMD_TERMINATE)
552 276203 : break;
553 : }
554 :
555 : /* fall out of loop if lexer reached EOL */
556 424116 : if (scan_result == PSCAN_INCOMPLETE ||
557 : scan_result == PSCAN_EOL)
558 : break;
559 : }
560 :
561 : /*
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.
567 : */
494 568 276224 : if (pset.cur_cmd_interactive)
569 : {
570 43 : if (!line_saved_in_history)
571 2 : pg_append_history(line, history_buf);
572 43 : if (query_buf->len == 0)
573 41 : pg_send_history(history_buf);
574 : }
575 :
6989 576 276224 : psql_scan_finish(scan_state);
8557 bruce 577 276224 : free(line);
578 :
6321 peter_e 579 276224 : if (slashCmdStatus == PSQL_CMD_TERMINATE)
580 : {
6989 tgl 581 25 : successResult = EXIT_SUCCESS;
582 25 : break;
583 : }
584 :
7325 bruce 585 276199 : if (!pset.cur_cmd_interactive)
586 : {
587 276158 : if (!success && die_on_error)
7188 588 21 : successResult = EXIT_USER;
589 : /* Have we lost the db connection? */
7325 590 276137 : else if (!pset.db)
7188 bruce 591 UBC 0 : successResult = EXIT_BADCONN;
592 : }
593 : } /* while !endoffile/session */
594 :
595 : /*
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.
599 : */
8052 tgl 600 CBC 5963 : if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
601 3470 : successResult == EXIT_SUCCESS)
602 : {
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
609 :
610 : /* execute query unless we're in an inactive \if branch */
2201 611 3470 : if (conditional_active(cond_stack))
612 : {
613 3470 : success = SendQuery(query_buf->data);
614 : }
615 : else
616 : {
2201 tgl 617 UBC 0 : if (pset.cur_cmd_interactive)
1469 peter 618 0 : pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
2201 tgl 619 0 : success = true;
620 : }
621 :
8397 bruce 622 CBC 3470 : if (!success && die_on_error)
623 15 : successResult = EXIT_USER;
624 3455 : else if (pset.db == NULL)
8397 bruce 625 UBC 0 : successResult = EXIT_BADCONN;
626 : }
627 :
628 : /*
629 : * Check for unbalanced \if-\endifs unless user explicitly quit, or the
630 : * script is erroring out
631 : */
2201 tgl 632 CBC 5963 : if (slashCmdStatus != PSQL_CMD_TERMINATE &&
633 5938 : successResult != EXIT_USER &&
634 5902 : !conditional_stack_empty(cond_stack))
635 : {
1469 peter 636 UBC 0 : pg_log_error("reached EOF without finding closing \\endif(s)");
2201 tgl 637 0 : if (die_on_error && !pset.cur_cmd_interactive)
638 0 : successResult = EXIT_USER;
639 : }
640 :
641 : /*
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.
647 : */
6143 tgl 648 CBC 5963 : sigint_interrupt_enabled = false;
649 :
8557 bruce 650 5963 : destroyPQExpBuffer(query_buf);
8521 651 5963 : destroyPQExpBuffer(previous_buf);
6266 652 5963 : destroyPQExpBuffer(history_buf);
653 :
6989 tgl 654 5963 : psql_scan_destroy(scan_state);
2201 655 5963 : conditional_stack_destroy(cond_stack);
656 :
8486 peter_e 657 5963 : pset.cur_cmd_source = prev_cmd_source;
658 5963 : pset.cur_cmd_interactive = prev_cmd_interactive;
8397 bruce 659 5963 : pset.lineno = prev_lineno;
660 :
8557 661 5963 : return successResult;
662 : } /* MainLoop() */
|