LCOV - differential code coverage report
Current view: top level - src/bin/psql - mainloop.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 63.8 % 260 166 94 166
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 1 1 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           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
      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;
      47            5969 :     volatile int successResult = EXIT_SUCCESS;
      48            5969 :     volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
      49            5969 :     volatile promptStatus_t prompt_status = PROMPT_READY;
      50            5969 :     volatile bool need_redisplay = false;
      51            5969 :     volatile int count_eof = 0;
      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 */
      58            5969 :     prev_cmd_source = pset.cur_cmd_source;
      59            5969 :     prev_cmd_interactive = pset.cur_cmd_interactive;
      60            5969 :     prev_lineno = pset.lineno;
      61                 :     /* pset.stmt_lineno does not need to be saved and restored */
      62                 : 
      63                 :     /* Establish new source */
      64            5969 :     pset.cur_cmd_source = source;
      65            5969 :     pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
      66            5969 :     pset.lineno = 0;
      67            5969 :     pset.stmt_lineno = 1;
      68                 : 
      69                 :     /* Create working state */
      70            5969 :     scan_state = psql_scan_create(&psqlscan_callbacks);
      71            5969 :     cond_stack = conditional_stack_create();
      72            5969 :     psql_scan_set_passthrough(scan_state, (void *) cond_stack);
      73                 : 
      74            5969 :     query_buf = createPQExpBuffer();
      75            5969 :     previous_buf = createPQExpBuffer();
      76            5969 :     history_buf = createPQExpBuffer();
      77            5969 :     if (PQExpBufferBroken(query_buf) ||
      78            5969 :         PQExpBufferBroken(previous_buf) ||
      79            5969 :         PQExpBufferBroken(history_buf))
      80 UBC           0 :         pg_fatal("out of memory");
      81                 : 
      82                 :     /* main loop to get queries and execute them */
      83 CBC      341752 :     while (successResult == EXIT_SUCCESS)
      84                 :     {
      85                 :         /*
      86                 :          * Clean up after a previous Control-C
      87                 :          */
      88          341731 :         if (cancel_pressed)
      89                 :         {
      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                 :          */
     107 CBC      341731 :         if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
     108                 :         {
     109                 :             /* got here with longjmp */
     110                 : 
     111                 :             /* reset parsing state */
     112 UBC           0 :             psql_scan_finish(scan_state);
     113               0 :             psql_scan_reset(scan_state);
     114               0 :             resetPQExpBuffer(query_buf);
     115               0 :             resetPQExpBuffer(history_buf);
     116               0 :             count_eof = 0;
     117               0 :             slashCmdStatus = PSQL_CMD_UNKNOWN;
     118               0 :             prompt_status = PROMPT_READY;
     119               0 :             need_redisplay = false;
     120               0 :             pset.stmt_lineno = 1;
     121               0 :             cancel_pressed = false;
     122                 : 
     123               0 :             if (pset.cur_cmd_interactive)
     124                 :             {
     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                 :                  */
     131               0 :                 if (!conditional_stack_empty(cond_stack))
     132                 :                 {
     133               0 :                     pg_log_error("\\if: escaped");
     134               0 :                     conditional_stack_pop(cond_stack);
     135                 :                 }
     136                 :             }
     137                 :             else
     138                 :             {
     139               0 :                 successResult = EXIT_USER;
     140               0 :                 break;
     141                 :             }
     142                 :         }
     143                 : 
     144 CBC      341731 :         fflush(stdout);
     145                 : 
     146                 :         /*
     147                 :          * get another line
     148                 :          */
     149          341731 :         if (pset.cur_cmd_interactive)
     150                 :         {
     151                 :             /* May need to reset prompt, eg after \r command */
     152              53 :             if (query_buf->len == 0)
     153              51 :                 prompt_status = PROMPT_READY;
     154                 :             /* If query buffer came from \e, redisplay it with a prompt */
     155              53 :             if (need_redisplay)
     156                 :             {
     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 */
     166 CBC          53 :             line = gets_interactive(get_prompt(prompt_status, cond_stack),
     167                 :                                     query_buf);
     168                 :         }
     169                 :         else
     170                 :         {
     171          341678 :             line = gets_fromFile(source);
     172          341678 :             if (!line && ferror(source))
     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 */
     182 CBC      341731 :         if (line == NULL)
     183                 :         {
     184            5917 :             if (pset.cur_cmd_interactive)
     185                 :             {
     186                 :                 /* This tries to mimic bash's IGNOREEOF feature. */
     187 UBC           0 :                 count_eof++;
     188                 : 
     189               0 :                 if (count_eof < pset.ignoreeof)
     190                 :                 {
     191               0 :                     if (!pset.quiet)
     192               0 :                         printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
     193               0 :                     continue;
     194                 :                 }
     195                 : 
     196               0 :                 puts(pset.quiet ? "" : "\\q");
     197                 :             }
     198 CBC        5917 :             break;
     199                 :         }
     200                 : 
     201          335814 :         count_eof = 0;
     202                 : 
     203          335814 :         pset.lineno++;
     204                 : 
     205                 :         /* ignore UTF-8 Unicode byte-order mark */
     206          335814 :         if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
     207 UBC           0 :             memmove(line, line + 3, strlen(line + 3) + 1);
     208                 : 
     209                 :         /* Detect attempts to run custom-format dumps as SQL scripts */
     210 CBC      335814 :         if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
     211            5854 :             strncmp(line, "PGDMP", 5) == 0)
     212                 :         {
     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 */
     222 CBC      335814 :         if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
     223                 :         {
     224           59584 :             free(line);
     225           59584 :             continue;
     226                 :         }
     227                 : 
     228                 :         /* Recognize "help", "quit", "exit" only in interactive mode */
     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;
     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                 :              */
     243              43 :             if (pg_strncasecmp(first_word, "help", 4) == 0)
     244                 :             {
     245 UBC           0 :                 rest_of_line = first_word + 4;
     246               0 :                 found_help = true;
     247                 :             }
     248 CBC          43 :             else if (pg_strncasecmp(first_word, "exit", 4) == 0 ||
     249              43 :                      pg_strncasecmp(first_word, "quit", 4) == 0)
     250                 :             {
     251 UBC           0 :                 rest_of_line = first_word + 4;
     252               0 :                 found_exit_or_quit = true;
     253                 :             }
     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                 :              */
     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))
     273 UBC           0 :                     ++rest_of_line;
     274 CBC           2 :                 if (*rest_of_line == ';')
     275 UBC           0 :                     ++rest_of_line;
     276 CBC           2 :                 while (isspace((unsigned char) *rest_of_line))
     277 UBC           0 :                     ++rest_of_line;
     278 CBC           2 :                 if (*rest_of_line != '\0')
     279                 :                 {
     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                 :              */
     291 CBC          43 :             if (found_help)
     292                 :             {
     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                 :              */
     319 CBC          43 :             if (found_exit_or_quit)
     320                 :             {
     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                 :              */
     348 CBC          43 :             if (found_q && query_buf->len != 0 &&
     349 UBC           0 :                 prompt_status != PROMPT_READY &&
     350               0 :                 prompt_status != PROMPT_CONTINUE &&
     351               0 :                 prompt_status != PROMPT_PAREN)
     352                 : #ifndef WIN32
     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 */
     360 CBC      276230 :         if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
     361                 :         {
     362          265057 :             puts(line);
     363          265057 :             fflush(stdout);
     364                 :         }
     365                 : 
     366                 :         /* insert newlines into query buffer between source lines */
     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. */
     376          276230 :         die_on_error = pset.on_error_stop;
     377                 : 
     378                 :         /*
     379                 :          * Parse line, looking for command separators.
     380                 :          */
     381          276230 :         psql_scan_setup(scan_state, line, strlen(line),
     382          276230 :                         pset.encoding, standard_strings());
     383          276230 :         success = true;
     384          276230 :         line_saved_in_history = false;
     385                 : 
     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                 : 
     393          424147 :             pos_in_query = query_buf->len;
     394          424147 :             scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
     395          424147 :             prompt_status = prompt_tmp;
     396                 : 
     397          424147 :             if (PQExpBufferBroken(query_buf))
     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                 :              */
     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                 :              */
     420          424147 :             if (scan_result == PSCAN_SEMICOLON ||
     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                 :                  */
     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 */
     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)
     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 */
     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                 :             }
     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';
     483              50 :                     pg_send_history(history_buf);
     484                 :                 }
     485            6181 :                 added_nl_pos = -1;
     486                 : 
     487                 :                 /* save backslash command in history */
     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 */
     496            6181 :                 slashCmdStatus = HandleSlashCmds(scan_state,
     497                 :                                                  cond_stack,
     498                 :                                                  query_buf,
     499                 :                                                  previous_buf);
     500                 : 
     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                 :                  */
     508            6181 :                 pset.stmt_lineno = 1;
     509                 : 
     510            6181 :                 if (slashCmdStatus == PSQL_CMD_SEND)
     511                 :                 {
     512                 :                     /* should not see this in inactive branch */
     513             494 :                     Assert(conditional_active(cond_stack));
     514                 : 
     515             494 :                     success = SendQuery(query_buf->data);
     516                 : 
     517                 :                     /* transfer query to previous_buf by pointer-swapping */
     518                 :                     {
     519             494 :                         PQExpBuffer swap_buf = previous_buf;
     520                 : 
     521             494 :                         previous_buf = query_buf;
     522             494 :                         query_buf = swap_buf;
     523                 :                     }
     524             494 :                     resetPQExpBuffer(query_buf);
     525                 : 
     526                 :                     /* flush any paren nesting info after forced send */
     527             494 :                     psql_scan_reset(scan_state);
     528                 :                 }
     529            5687 :                 else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
     530                 :                 {
     531                 :                     /* should not see this in inactive branch */
     532 UBC           0 :                     Assert(conditional_active(cond_stack));
     533                 :                     /* ensure what came back from editing ends in a newline */
     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 */
     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);
     544               0 :                     psql_scan_setup(scan_state, line, strlen(line),
     545               0 :                                     pset.encoding, standard_strings());
     546               0 :                     line_saved_in_history = false;
     547               0 :                     prompt_status = PROMPT_READY;
     548                 :                     /* we'll want to redisplay after parsing what we have */
     549               0 :                     need_redisplay = true;
     550                 :                 }
     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                 :          */
     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                 : 
     576          276224 :         psql_scan_finish(scan_state);
     577          276224 :         free(line);
     578                 : 
     579          276224 :         if (slashCmdStatus == PSQL_CMD_TERMINATE)
     580                 :         {
     581              25 :             successResult = EXIT_SUCCESS;
     582              25 :             break;
     583                 :         }
     584                 : 
     585          276199 :         if (!pset.cur_cmd_interactive)
     586                 :         {
     587          276158 :             if (!success && die_on_error)
     588              21 :                 successResult = EXIT_USER;
     589                 :             /* Have we lost the db connection? */
     590          276137 :             else if (!pset.db)
     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                 :      */
     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 */
     611            3470 :         if (conditional_active(cond_stack))
     612                 :         {
     613            3470 :             success = SendQuery(query_buf->data);
     614                 :         }
     615                 :         else
     616                 :         {
     617 UBC           0 :             if (pset.cur_cmd_interactive)
     618               0 :                 pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
     619               0 :             success = true;
     620                 :         }
     621                 : 
     622 CBC        3470 :         if (!success && die_on_error)
     623              15 :             successResult = EXIT_USER;
     624            3455 :         else if (pset.db == NULL)
     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                 :      */
     632 CBC        5963 :     if (slashCmdStatus != PSQL_CMD_TERMINATE &&
     633            5938 :         successResult != EXIT_USER &&
     634            5902 :         !conditional_stack_empty(cond_stack))
     635                 :     {
     636 UBC           0 :         pg_log_error("reached EOF without finding closing \\endif(s)");
     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                 :      */
     648 CBC        5963 :     sigint_interrupt_enabled = false;
     649                 : 
     650            5963 :     destroyPQExpBuffer(query_buf);
     651            5963 :     destroyPQExpBuffer(previous_buf);
     652            5963 :     destroyPQExpBuffer(history_buf);
     653                 : 
     654            5963 :     psql_scan_destroy(scan_state);
     655            5963 :     conditional_stack_destroy(cond_stack);
     656                 : 
     657            5963 :     pset.cur_cmd_source = prev_cmd_source;
     658            5963 :     pset.cur_cmd_interactive = prev_cmd_interactive;
     659            5963 :     pset.lineno = prev_lineno;
     660                 : 
     661            5963 :     return successResult;
     662                 : }                               /* MainLoop() */
        

Generated by: LCOV version v1.16-55-g56c0a2a