LCOV - differential code coverage report
Current view: top level - src/bin/psql - mainloop.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB DCB
Current: ba12a202ce1b5581dc0ed149cf3f637d7897ad5d vs 2866d8c7dbfc9d882a7d80fef93fbbe763709932 Lines: 64.0 % 261 167 4 90 2 165 4 2
Current Date: 2026-08-27 14:31:44 +0300 Functions: 100.0 % 1 1 1
Baseline: lcov-20260827-baseline Branches: 62.6 % 214 134 80 134
Baseline Date: 2026-08-27 14:31:58 +0300 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 4 4 4
(30,360] days: 33.3 % 6 2 4 2
(360..) days: 64.1 % 251 161 90 161
Function coverage date bins:
(360..) days: 100.0 % 1 1 1
Branch coverage date bins:
(360..) days: 62.6 % 214 134 80 134

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * psql - the PostgreSQL interactive terminal
                                  3                 :                :  *
                                  4                 :                :  * Copyright (c) 2000-2026, 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
 9718 peter_e@gmx.net            33                 :CBC       10461 : 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;
 9675                            47                 :          10461 :     volatile int successResult = EXIT_SUCCESS;
 7557                            48                 :          10461 :     volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
 8225 tgl@sss.pgh.pa.us          49                 :          10461 :     volatile promptStatus_t prompt_status = PROMPT_READY;
 2470                            50                 :          10461 :     volatile bool need_redisplay = false;
 9633 bruce@momjian.us           51                 :          10461 :     volatile int count_eof = 0;
 8225 tgl@sss.pgh.pa.us          52                 :          10461 :     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 */
 9722 peter_e@gmx.net            58                 :          10461 :     prev_cmd_source = pset.cur_cmd_source;
                                 59                 :          10461 :     prev_cmd_interactive = pset.cur_cmd_interactive;
 8225 tgl@sss.pgh.pa.us          60                 :          10461 :     prev_lineno = pset.lineno;
                                 61                 :                :     /* pset.stmt_lineno does not need to be saved and restored */
                                 62                 :                : 
                                 63                 :                :     /* Establish new source */
 9722 peter_e@gmx.net            64                 :          10461 :     pset.cur_cmd_source = source;
                                 65   [ +  +  +  + ]:          10461 :     pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
 8225 tgl@sss.pgh.pa.us          66                 :          10461 :     pset.lineno = 0;
 4377 andres@anarazel.de         67                 :          10461 :     pset.stmt_lineno = 1;
                                 68                 :                : 
                                 69                 :                :     /* Create working state */
 3814 tgl@sss.pgh.pa.us          70                 :          10461 :     scan_state = psql_scan_create(&psqlscan_callbacks);
 3437                            71                 :          10461 :     cond_stack = conditional_stack_create();
  637 peter@eisentraut.org       72                 :          10461 :     psql_scan_set_passthrough(scan_state, cond_stack);
                                 73                 :                : 
 9793 bruce@momjian.us           74                 :          10461 :     query_buf = createPQExpBuffer();
 9633                            75                 :          10461 :     previous_buf = createPQExpBuffer();
 7502                            76                 :          10461 :     history_buf = createPQExpBuffer();
 6483 tgl@sss.pgh.pa.us          77   [ +  -  +  - ]:          10461 :     if (PQExpBufferBroken(query_buf) ||
                                 78   [ +  -  +  -  :          10461 :         PQExpBufferBroken(previous_buf) ||
                                              +  - ]
                                 79         [ -  + ]:          10461 :         PQExpBufferBroken(history_buf))
 1602 tgl@sss.pgh.pa.us          80                 :UBC           0 :         pg_fatal("out of memory");
                                 81                 :                : 
                                 82                 :                :     /* main loop to get queries and execute them */
 8561 bruce@momjian.us           83         [ +  + ]:CBC      636677 :     while (successResult == EXIT_SUCCESS)
                                 84                 :                :     {
                                 85                 :                :         /*
                                 86                 :                :          * Clean up after a previous Control-C
                                 87                 :                :          */
 9633                            88         [ -  + ]:         636591 :         if (cancel_pressed)
                                 89                 :                :         {
 9633 bruce@momjian.us           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                 :                :          */
 7379 tgl@sss.pgh.pa.us         107         [ -  + ]:CBC      636591 :         if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
                                108                 :                :         {
                                109                 :                :             /* got here with longjmp */
                                110                 :                : 
                                111                 :                :             /* reset parsing state */
 8225 tgl@sss.pgh.pa.us         112                 :UBC           0 :             psql_scan_finish(scan_state);
                                113                 :              0 :             psql_scan_reset(scan_state);
 7379                           114                 :              0 :             resetPQExpBuffer(query_buf);
                                115                 :              0 :             resetPQExpBuffer(history_buf);
 8225                           116                 :              0 :             count_eof = 0;
 7557 peter_e@gmx.net           117                 :              0 :             slashCmdStatus = PSQL_CMD_UNKNOWN;
 8225 tgl@sss.pgh.pa.us         118                 :              0 :             prompt_status = PROMPT_READY;
 2470                           119                 :              0 :             need_redisplay = false;
 4377 andres@anarazel.de        120                 :              0 :             pset.stmt_lineno = 1;
 7379 tgl@sss.pgh.pa.us         121                 :              0 :             cancel_pressed = false;
                                122                 :                : 
 9633 bruce@momjian.us          123         [ #  # ]:              0 :             if (pset.cur_cmd_interactive)
                                124                 :                :             {
 8561                           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                 :                :                  */
 3437 tgl@sss.pgh.pa.us         131         [ #  # ]:              0 :                 if (!conditional_stack_empty(cond_stack))
                                132                 :                :                 {
 2705 peter@eisentraut.org      133                 :              0 :                     pg_log_error("\\if: escaped");
 3437 tgl@sss.pgh.pa.us         134                 :              0 :                     conditional_stack_pop(cond_stack);
                                135                 :                :                 }
                                136                 :                :             }
                                137                 :                :             else
                                138                 :                :             {
 9633 bruce@momjian.us          139                 :              0 :                 successResult = EXIT_USER;
                                140                 :              0 :                 break;
                                141                 :                :             }
                                142                 :                :         }
                                143                 :                : 
 8254 tgl@sss.pgh.pa.us         144                 :CBC      636591 :         fflush(stdout);
                                145                 :                : 
                                146                 :                :         /*
                                147                 :                :          * get another line
                                148                 :                :          */
 7382                           149         [ +  + ]:         636591 :         if (pset.cur_cmd_interactive)
                                150                 :                :         {
                                151                 :                :             /* May need to reset prompt, eg after \r command */
 8225                           152         [ +  + ]:             72 :             if (query_buf->len == 0)
 8424 bruce@momjian.us          153                 :             70 :                 prompt_status = PROMPT_READY;
                                154                 :                :             /* If query buffer came from \e, redisplay it with a prompt */
 2470 tgl@sss.pgh.pa.us         155         [ -  + ]:             72 :             if (need_redisplay)
                                156                 :                :             {
 2470 tgl@sss.pgh.pa.us         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 */
 3437 tgl@sss.pgh.pa.us         166                 :CBC          72 :             line = gets_interactive(get_prompt(prompt_status, cond_stack),
                                167                 :                :                                     query_buf);
                                168                 :                :         }
                                169                 :                :         else
                                170                 :                :         {
 8424 bruce@momjian.us          171                 :         636519 :             line = gets_fromFile(source);
 6847 peter_e@gmx.net           172   [ +  +  -  + ]:         636519 :             if (!line && ferror(source))
 6847 peter_e@gmx.net           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 */
 9790 bruce@momjian.us          182         [ +  + ]:CBC      636591 :         if (line == NULL)
                                183                 :                :         {
 9722 peter_e@gmx.net           184         [ -  + ]:          10131 :             if (pset.cur_cmd_interactive)
                                185                 :                :             {
                                186                 :                :                 /* This tries to mimic bash's IGNOREEOF feature. */
 8561 bruce@momjian.us          187                 :UBC           0 :                 count_eof++;
                                188                 :                : 
 3493 tgl@sss.pgh.pa.us         189         [ #  # ]:              0 :                 if (count_eof < pset.ignoreeof)
                                190                 :                :                 {
 7303                           191         [ #  # ]:              0 :                     if (!pset.quiet)
 7856 bruce@momjian.us          192                 :              0 :                         printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
 9633                           193                 :              0 :                     continue;
                                194                 :                :                 }
                                195                 :                : 
 7303 tgl@sss.pgh.pa.us         196         [ #  # ]:              0 :                 puts(pset.quiet ? "" : "\\q");
                                197                 :                :             }
 8424 bruce@momjian.us          198                 :CBC       10131 :             break;
                                199                 :                :         }
                                200                 :                : 
                                201                 :         626460 :         count_eof = 0;
                                202                 :                : 
 9633                           203                 :         626460 :         pset.lineno++;
                                204                 :                : 
                                205                 :                :         /* ignore UTF-8 Unicode byte-order mark */
 6123 peter_e@gmx.net           206   [ +  +  +  +  :         626460 :         if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
                                              -  + ]
 6123 peter_e@gmx.net           207                 :UBC           0 :             memmove(line, line + 3, strlen(line + 3) + 1);
                                208                 :                : 
                                209                 :                :         /* Detect attempts to run custom-format dumps as SQL scripts */
 4325 alvherre@alvh.no-ip.      210   [ +  +  +  + ]:CBC      626460 :         if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
                                211         [ -  + ]:          10424 :             strncmp(line, "PGDMP", 5) == 0)
                                212                 :                :         {
   57 peter@eisentraut.org      213                 :UNC           0 :             pg_free(line);
 4325 alvherre@alvh.no-ip.      214                 :UBC           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 */
 8225 tgl@sss.pgh.pa.us         222   [ +  +  +  + ]:CBC      626460 :         if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
                                223                 :                :         {
   57 peter@eisentraut.org      224                 :GNC       99843 :             pg_free(line);
 9793 bruce@momjian.us          225                 :CBC       99843 :             continue;
                                226                 :                :         }
                                227                 :                : 
                                228                 :                :         /* Recognize "help", "quit", "exit" only in interactive mode */
 3129                           229         [ +  + ]:         526617 :         if (pset.cur_cmd_interactive)
                                230                 :                :         {
                                231                 :             66 :             char       *first_word = line;
                                232                 :             66 :             char       *rest_of_line = NULL;
                                233                 :             66 :             bool        found_help = false;
                                234                 :             66 :             bool        found_exit_or_quit = false;
 3118                           235                 :             66 :             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                 :                :              */
 3129                           243         [ -  + ]:             66 :             if (pg_strncasecmp(first_word, "help", 4) == 0)
                                244                 :                :             {
 3129 bruce@momjian.us          245                 :UBC           0 :                 rest_of_line = first_word + 4;
                                246                 :              0 :                 found_help = true;
                                247                 :                :             }
 3129 bruce@momjian.us          248         [ +  - ]:CBC          66 :             else if (pg_strncasecmp(first_word, "exit", 4) == 0 ||
                                249         [ -  + ]:             66 :                      pg_strncasecmp(first_word, "quit", 4) == 0)
                                250                 :                :             {
 3129 bruce@momjian.us          251                 :UBC           0 :                 rest_of_line = first_word + 4;
                                252                 :              0 :                 found_exit_or_quit = true;
                                253                 :                :             }
 3118 bruce@momjian.us          254         [ +  + ]:CBC          66 :             else if (strncmp(first_word, "\\q", 2) == 0)
                                255                 :                :             {
                                256                 :              3 :                 rest_of_line = first_word + 2;
                                257                 :              3 :                 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                 :                :              */
 3129                           266         [ +  + ]:             66 :             if (rest_of_line != NULL)
                                267                 :                :             {
                                268                 :                :                 /*
                                269                 :                :                  * Ignore unless rest of line is whitespace, plus maybe one
                                270                 :                :                  * semicolon
                                271                 :                :                  */
                                272         [ -  + ]:              3 :                 while (isspace((unsigned char) *rest_of_line))
 3129 bruce@momjian.us          273                 :UBC           0 :                     ++rest_of_line;
 3129 bruce@momjian.us          274         [ -  + ]:CBC           3 :                 if (*rest_of_line == ';')
 3129 bruce@momjian.us          275                 :UBC           0 :                     ++rest_of_line;
 3129 bruce@momjian.us          276         [ -  + ]:CBC           3 :                 while (isspace((unsigned char) *rest_of_line))
 3129 bruce@momjian.us          277                 :UBC           0 :                     ++rest_of_line;
 3129 bruce@momjian.us          278         [ -  + ]:CBC           3 :                 if (*rest_of_line != '\0')
                                279                 :                :                 {
 3129 bruce@momjian.us          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                 :                :              */
 3129 bruce@momjian.us          291         [ -  + ]:CBC          66 :             if (found_help)
                                292                 :                :             {
 3129 bruce@momjian.us          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"));
   57 peter@eisentraut.org      307                 :UNC           0 :                     pg_free(line);
 3129 bruce@momjian.us          308                 :UBC           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                 :                :              */
 3129 bruce@momjian.us          319         [ -  + ]:CBC          66 :             if (found_exit_or_quit)
                                320                 :                :             {
 3129 bruce@momjian.us          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 */
   57 peter@eisentraut.org      337                 :UNC           0 :                     pg_free(line);
 3129 bruce@momjian.us          338                 :UBC           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                 :                :              */
 3118 bruce@momjian.us          348   [ +  +  -  + ]:CBC          66 :             if (found_q && query_buf->len != 0 &&
 3118 bruce@momjian.us          349         [ #  # ]:UBC           0 :                 prompt_status != PROMPT_READY &&
                                350         [ #  # ]:              0 :                 prompt_status != PROMPT_CONTINUE &&
                                351         [ #  # ]:              0 :                 prompt_status != PROMPT_PAREN)
                                352                 :                : #ifndef WIN32
 3045 tgl@sss.pgh.pa.us         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 */
 7303 tgl@sss.pgh.pa.us         360   [ +  +  +  - ]:CBC      526617 :         if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
                                361                 :                :         {
 9633 bruce@momjian.us          362                 :         460126 :             puts(line);
 4226 tgl@sss.pgh.pa.us         363                 :         460126 :             fflush(stdout);
                                364                 :                :         }
                                365                 :                : 
                                366                 :                :         /* insert newlines into query buffer between source lines */
 8225                           367         [ +  + ]:         526617 :         if (query_buf->len > 0)
                                368                 :                :         {
                                369                 :         167219 :             appendPQExpBufferChar(query_buf, '\n');
                                370                 :         167219 :             added_nl_pos = query_buf->len;
                                371                 :                :         }
                                372                 :                :         else
                                373                 :         359398 :             added_nl_pos = -1;  /* flag we didn't add one */
                                374                 :                : 
                                375                 :                :         /* Setting this will not have effect until next line. */
 7303                           376                 :         526617 :         die_on_error = pset.on_error_stop;
                                377                 :                : 
                                378                 :                :         /*
                                379                 :                :          * Parse line, looking for command separators.
                                380                 :                :          */
 3814                           381                 :         526617 :         psql_scan_setup(scan_state, line, strlen(line),
                                382                 :         526617 :                         pset.encoding, standard_strings());
 9793 bruce@momjian.us          383                 :         526617 :         success = true;
 7382 tgl@sss.pgh.pa.us         384                 :         526617 :         line_saved_in_history = false;
                                385                 :                : 
 8225                           386   [ +  +  +  + ]:         804837 :         while (success || !die_on_error)
                                387                 :                :         {
                                388                 :                :             PsqlScanResult scan_result;
                                389                 :         804751 :             promptStatus_t prompt_tmp = prompt_status;
                                390                 :                :             size_t      pos_in_query;
                                391                 :                :             char       *tmp_line;
                                392                 :                : 
 4377 andres@anarazel.de        393                 :         804751 :             pos_in_query = query_buf->len;
 8225 tgl@sss.pgh.pa.us         394                 :         804751 :             scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
                                395                 :         804751 :             prompt_status = prompt_tmp;
                                396                 :                : 
 6483                           397   [ +  -  -  + ]:         804751 :             if (PQExpBufferBroken(query_buf))
 1602 tgl@sss.pgh.pa.us         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                 :                :              */
 4377 andres@anarazel.de        406                 :CBC      804751 :             tmp_line = query_buf->data + pos_in_query;
                                407         [ +  + ]:       18694580 :             while (*tmp_line != '\0')
                                408                 :                :             {
                                409         [ +  + ]:       17889829 :                 if (*(tmp_line++) == '\n')
                                410                 :            120 :                     pset.stmt_lineno++;
                                411                 :                :             }
                                412                 :                : 
                                413         [ +  + ]:         804751 :             if (scan_result == PSCAN_EOL)
                                414                 :          95514 :                 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                 :                :              */
 8225 tgl@sss.pgh.pa.us         420   [ +  +  +  + ]:         804751 :             if (scan_result == PSCAN_SEMICOLON ||
 7303                           421         [ -  + ]:          95514 :                 (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                 :                :                  */
 7382                           429   [ +  +  +  - ]:         246016 :                 if (pset.cur_cmd_interactive && !line_saved_in_history)
                                430                 :                :                 {
                                431                 :              9 :                     pg_append_history(line, history_buf);
                                432                 :              9 :                     pg_send_history(history_buf);
                                433                 :              9 :                     line_saved_in_history = true;
                                434                 :                :                 }
                                435                 :                : 
                                436                 :                :                 /* execute query unless we're in an inactive \if branch */
 3437                           437         [ +  + ]:         492024 :                 if (conditional_active(cond_stack))
                                438                 :                :                 {
                                439                 :                :                     /* count_copy_from_stdin should be reliable here */
   17                           440                 :         246008 :                     success = SendQuery(query_buf->data,
                                441                 :                :                                         psql_scan_count_copy_from_stdin(scan_state));
 3437                           442         [ +  + ]:         246000 :                     slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
                                443                 :         246000 :                     pset.stmt_lineno = 1;
                                444                 :                : 
                                445                 :                :                     /* transfer query to previous_buf by pointer-swapping */
                                446                 :                :                     {
                                447                 :         246000 :                         PQExpBuffer swap_buf = previous_buf;
                                448                 :                : 
                                449                 :         246000 :                         previous_buf = query_buf;
                                450                 :         246000 :                         query_buf = swap_buf;
                                451                 :                :                     }
                                452                 :         246000 :                     resetPQExpBuffer(query_buf);
                                453                 :                :                     /* reset parsing state, too */
   17                           454                 :         246000 :                     psql_scan_reset(scan_state);
                                455                 :                : 
 3437                           456                 :         246000 :                     added_nl_pos = -1;
                                457                 :                :                 }
                                458                 :                :                 else
                                459                 :                :                 {
                                460                 :                :                     /* if interactive, warn about non-executed query */
                                461         [ -  + ]:              8 :                     if (pset.cur_cmd_interactive)
 2705 peter@eisentraut.org      462                 :UBC           0 :                         pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
                                463                 :                :                     /* fake an OK result for purposes of loop checks */
 3437 tgl@sss.pgh.pa.us         464                 :CBC           8 :                     success = true;
                                465                 :              8 :                     slashCmdStatus = PSQL_CMD_SEND;
                                466                 :              8 :                     pset.stmt_lineno = 1;
                                467                 :                :                     /* note that query_buf doesn't change state */
                                468                 :                :                 }
                                469                 :                :             }
 8225                           470         [ +  + ]:         558735 :             else if (scan_result == PSCAN_BACKSLASH)
                                471                 :                :             {
                                472                 :                :                 /* handle backslash command */
                                473                 :                : 
                                474                 :                :                 /*
                                475                 :                :                  * If we added a newline to query_buf, and nothing else has
                                476                 :                :                  * been inserted in query_buf by the lexer, then strip off the
                                477                 :                :                  * newline again.  This avoids any change to query_buf when a
                                478                 :                :                  * line contains only a backslash command.  Also, in this
                                479                 :                :                  * situation we force out any previous lines as a separate
                                480                 :                :                  * history entry; we don't want SQL and backslash commands
                                481                 :                :                  * intermixed in history if at all possible.
                                482                 :                :                  */
                                483         [ +  + ]:          32448 :                 if (query_buf->len == added_nl_pos)
                                484                 :                :                 {
                                485                 :            180 :                     query_buf->data[--query_buf->len] = '\0';
 7382                           486                 :            180 :                     pg_send_history(history_buf);
                                487                 :                :                 }
 8225                           488                 :          32448 :                 added_nl_pos = -1;
                                489                 :                : 
                                490                 :                :                 /* save backslash command in history */
 7382                           491   [ +  +  +  + ]:          32448 :                 if (pset.cur_cmd_interactive && !line_saved_in_history)
                                492                 :                :                 {
                                493                 :             55 :                     pg_append_history(line, history_buf);
                                494                 :             55 :                     pg_send_history(history_buf);
                                495                 :             55 :                     line_saved_in_history = true;
                                496                 :                :                 }
                                497                 :                : 
                                498                 :                :                 /* execute backslash command */
 8225                           499                 :          32448 :                 slashCmdStatus = HandleSlashCmds(scan_state,
                                500                 :                :                                                  cond_stack,
                                501                 :                :                                                  query_buf,
                                502                 :                :                                                  previous_buf);
                                503                 :                : 
 7557 peter_e@gmx.net           504                 :          32446 :                 success = slashCmdStatus != PSQL_CMD_ERROR;
                                505                 :                : 
                                506                 :                :                 /*
                                507                 :                :                  * Resetting stmt_lineno after a backslash command isn't
                                508                 :                :                  * always appropriate, but it's what we've done historically
                                509                 :                :                  * and there have been few complaints.
                                510                 :                :                  */
 3437 tgl@sss.pgh.pa.us         511                 :          32446 :                 pset.stmt_lineno = 1;
                                512                 :                : 
 7557 peter_e@gmx.net           513         [ +  + ]:          32446 :                 if (slashCmdStatus == PSQL_CMD_SEND)
                                514                 :                :                 {
                                515                 :                :                     /* should not see this in inactive branch */
 3437 tgl@sss.pgh.pa.us         516         [ -  + ]:           2311 :                     Assert(conditional_active(cond_stack));
                                517                 :                : 
   17                           518                 :           2311 :                     success = SendQuery(query_buf->data, -1);
                                519                 :                : 
                                520                 :                :                     /* transfer query to previous_buf by pointer-swapping */
                                521                 :                :                     {
 6483                           522                 :           2307 :                         PQExpBuffer swap_buf = previous_buf;
                                523                 :                : 
                                524                 :           2307 :                         previous_buf = query_buf;
                                525                 :           2307 :                         query_buf = swap_buf;
                                526                 :                :                     }
 9633 bruce@momjian.us          527                 :           2307 :                     resetPQExpBuffer(query_buf);
                                528                 :                :                     /* reset parsing state, too */
 8225 tgl@sss.pgh.pa.us         529                 :           2307 :                     psql_scan_reset(scan_state);
                                530                 :                :                 }
 7382                           531         [ -  + ]:          30135 :                 else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
                                532                 :                :                 {
                                533                 :                :                     /* should not see this in inactive branch */
 3437 tgl@sss.pgh.pa.us         534         [ #  # ]:UBC           0 :                     Assert(conditional_active(cond_stack));
                                535                 :                :                     /* ensure what came back from editing ends in a newline */
 2470                           536         [ #  # ]:              0 :                     if (query_buf->len > 0 &&
                                537         [ #  # ]:              0 :                         query_buf->data[query_buf->len - 1] != '\n')
                                538                 :              0 :                         appendPQExpBufferChar(query_buf, '\n');
                                539                 :                :                     /* rescan query_buf as new input */
 7382                           540                 :              0 :                     psql_scan_finish(scan_state);
   57 peter@eisentraut.org      541                 :UNC           0 :                     pg_free(line);
 7382 tgl@sss.pgh.pa.us         542                 :UBC           0 :                     line = pg_strdup(query_buf->data);
                                543                 :              0 :                     resetPQExpBuffer(query_buf);
                                544                 :                :                     /* reset parsing state since we are rescanning whole line */
                                545                 :              0 :                     psql_scan_reset(scan_state);
 3814                           546                 :              0 :                     psql_scan_setup(scan_state, line, strlen(line),
                                547                 :              0 :                                     pset.encoding, standard_strings());
 7382                           548                 :              0 :                     line_saved_in_history = false;
                                549                 :              0 :                     prompt_status = PROMPT_READY;
                                550                 :                :                     /* we'll want to redisplay after parsing what we have */
 2470                           551                 :              0 :                     need_redisplay = true;
                                552                 :                :                 }
 7382 tgl@sss.pgh.pa.us         553         [ +  + ]:CBC       30135 :                 else if (slashCmdStatus == PSQL_CMD_TERMINATE)
                                554                 :         526517 :                     break;
                                555                 :                :             }
                                556                 :                : 
                                557                 :                :             /* fall out of loop if lexer reached EOL */
                                558   [ +  +  +  + ]:         804507 :             if (scan_result == PSCAN_INCOMPLETE ||
                                559                 :                :                 scan_result == PSCAN_EOL)
                                560                 :                :                 break;
                                561                 :                :         }
                                562                 :                : 
                                563                 :                :         /*
                                564                 :                :          * Add line to pending history if we didn't do so already.  Then, if
                                565                 :                :          * the query buffer is still empty, flush out any unsent history
                                566                 :                :          * entry.  This means that empty lines (containing only whitespace and
                                567                 :                :          * perhaps a dash-dash comment) that precede a query will be recorded
                                568                 :                :          * as separate history entries, not as part of that query.
                                569                 :                :          */
 1730                           570         [ +  + ]:         526603 :         if (pset.cur_cmd_interactive)
                                571                 :                :         {
                                572         [ +  + ]:             66 :             if (!line_saved_in_history)
                                573                 :              2 :                 pg_append_history(line, history_buf);
                                574         [ +  + ]:             66 :             if (query_buf->len == 0)
                                575                 :             64 :                 pg_send_history(history_buf);
                                576                 :                :         }
                                577                 :                : 
 8225                           578                 :         526603 :         psql_scan_finish(scan_state);
   57 peter@eisentraut.org      579                 :GNC      526603 :         pg_free(line);
                                580                 :                : 
 7557 peter_e@gmx.net           581         [ +  + ]:CBC      526603 :         if (slashCmdStatus == PSQL_CMD_TERMINATE)
                                582                 :                :         {
 8225 tgl@sss.pgh.pa.us         583                 :            230 :             successResult = EXIT_SUCCESS;
                                584                 :            230 :             break;
                                585                 :                :         }
                                586                 :                : 
 8561 bruce@momjian.us          587         [ +  + ]:         526373 :         if (!pset.cur_cmd_interactive)
                                588                 :                :         {
                                589   [ +  +  +  + ]:         526310 :             if (!success && die_on_error)
 8424                           590                 :             86 :                 successResult = EXIT_USER;
                                591                 :                :             /* Have we lost the db connection? */
 8561                           592         [ -  + ]:         526224 :             else if (!pset.db)
 8424 bruce@momjian.us          593                 :UBC           0 :                 successResult = EXIT_BADCONN;
                                594                 :                :         }
                                595                 :                :     }                           /* while !endoffile/session */
                                596                 :                : 
                                597                 :                :     /*
                                598                 :                :      * If we have a non-semicolon-terminated query at the end of file, we
                                599                 :                :      * process it unless the input source is interactive --- in that case it
                                600                 :                :      * seems better to go ahead and quit.  Also skip if this is an error exit.
                                601                 :                :      */
 9288 tgl@sss.pgh.pa.us         602   [ +  +  +  - ]:CBC       10447 :     if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
                                603         [ +  - ]:           5712 :         successResult == EXIT_SUCCESS)
                                604                 :                :     {
                                605                 :                :         /* save query in history */
                                606                 :                :         /* currently unneeded since we don't use this block if interactive */
                                607                 :                : #ifdef NOT_USED
                                608                 :                :         if (pset.cur_cmd_interactive)
                                609                 :                :             pg_send_history(history_buf);
                                610                 :                : #endif
                                611                 :                : 
                                612                 :                :         /* execute query unless we're in an inactive \if branch */
 3437                           613         [ +  - ]:           5712 :         if (conditional_active(cond_stack))
                                614                 :                :         {
   17                           615                 :           5712 :             success = SendQuery(query_buf->data,
                                616                 :                :                                 psql_scan_count_copy_from_stdin(scan_state));
                                617                 :                :         }
                                618                 :                :         else
                                619                 :                :         {
 3437 tgl@sss.pgh.pa.us         620         [ #  # ]:UBC           0 :             if (pset.cur_cmd_interactive)
 2705 peter@eisentraut.org      621                 :              0 :                 pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
 3437 tgl@sss.pgh.pa.us         622                 :              0 :             success = true;
                                623                 :                :         }
                                624                 :                : 
 9633 bruce@momjian.us          625   [ +  +  +  - ]:CBC        5711 :         if (!success && die_on_error)
                                626                 :             73 :             successResult = EXIT_USER;
                                627         [ -  + ]:           5638 :         else if (pset.db == NULL)
 9633 bruce@momjian.us          628                 :UBC           0 :             successResult = EXIT_BADCONN;
                                629                 :                :     }
                                630                 :                : 
                                631                 :                :     /*
                                632                 :                :      * Check for unbalanced \if-\endifs unless user explicitly quit, or the
                                633                 :                :      * script is erroring out
                                634                 :                :      */
 3437 tgl@sss.pgh.pa.us         635         [ +  + ]:CBC       10446 :     if (slashCmdStatus != PSQL_CMD_TERMINATE &&
                                636         [ +  + ]:          10216 :         successResult != EXIT_USER &&
                                637         [ -  + ]:          10057 :         !conditional_stack_empty(cond_stack))
                                638                 :                :     {
 2705 peter@eisentraut.org      639                 :UBC           0 :         pg_log_error("reached EOF without finding closing \\endif(s)");
 3437 tgl@sss.pgh.pa.us         640   [ #  #  #  # ]:              0 :         if (die_on_error && !pset.cur_cmd_interactive)
                                641                 :              0 :             successResult = EXIT_USER;
                                642                 :                :     }
                                643                 :                : 
                                644                 :                :     /*
                                645                 :                :      * Let's just make real sure the SIGINT handler won't try to use
                                646                 :                :      * sigint_interrupt_jmp after we exit this routine.  If there is an outer
                                647                 :                :      * MainLoop instance, it will reset sigint_interrupt_jmp to point to
                                648                 :                :      * itself at the top of its loop, before any further interactive input
                                649                 :                :      * happens.
                                650                 :                :      */
 7379 tgl@sss.pgh.pa.us         651                 :CBC       10446 :     sigint_interrupt_enabled = false;
                                652                 :                : 
 9793 bruce@momjian.us          653                 :          10446 :     destroyPQExpBuffer(query_buf);
 9757                           654                 :          10446 :     destroyPQExpBuffer(previous_buf);
 7502                           655                 :          10446 :     destroyPQExpBuffer(history_buf);
                                656                 :                : 
 8225 tgl@sss.pgh.pa.us         657                 :          10446 :     psql_scan_destroy(scan_state);
 3437                           658                 :          10446 :     conditional_stack_destroy(cond_stack);
                                659                 :                : 
 9722 peter_e@gmx.net           660                 :          10446 :     pset.cur_cmd_source = prev_cmd_source;
                                661                 :          10446 :     pset.cur_cmd_interactive = prev_cmd_interactive;
 9633 bruce@momjian.us          662                 :          10446 :     pset.lineno = prev_lineno;
                                663                 :                : 
 9793                           664                 :          10446 :     return successResult;
                                665                 :                : }                               /* MainLoop() */
        

Generated by: LCOV version 2.0-1