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 17:13:01 Functions: 100.0 % 1 1 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 63.8 % 260 166 94 166
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 100.0 % 1 1 1

 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() */
        

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