LCOV - differential code coverage report
Current view: top level - src/bin/psql - mainloop.c (source / functions) Coverage Total Hit UBC GBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 63.8 % 260 166 94 166
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 1 1 1
Baseline: 16@8cea358b128 Branches: 63.1 % 214 135 79 1 134
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 63.8 % 260 166 94 166
Function coverage date bins:
(240..) days: 100.0 % 1 1 1
Branch coverage date bins:
(240..) days: 63.1 % 214 135 79 1 134

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * psql - the PostgreSQL interactive terminal
                                  3                 :                :  *
                                  4                 :                :  * Copyright (c) 2000-2024, 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
 8853 peter_e@gmx.net            33                 :CBC        7726 : 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;
 8810                            47                 :           7726 :     volatile int successResult = EXIT_SUCCESS;
 6692                            48                 :           7726 :     volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
 7360 tgl@sss.pgh.pa.us          49                 :           7726 :     volatile promptStatus_t prompt_status = PROMPT_READY;
 1605                            50                 :           7726 :     volatile bool need_redisplay = false;
 8768 bruce@momjian.us           51                 :           7726 :     volatile int count_eof = 0;
 7360 tgl@sss.pgh.pa.us          52                 :           7726 :     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 */
 8857 peter_e@gmx.net            58                 :           7726 :     prev_cmd_source = pset.cur_cmd_source;
                                 59                 :           7726 :     prev_cmd_interactive = pset.cur_cmd_interactive;
 7360 tgl@sss.pgh.pa.us          60                 :           7726 :     prev_lineno = pset.lineno;
                                 61                 :                :     /* pset.stmt_lineno does not need to be saved and restored */
                                 62                 :                : 
                                 63                 :                :     /* Establish new source */
 8857 peter_e@gmx.net            64                 :           7726 :     pset.cur_cmd_source = source;
                                 65   [ +  +  +  + ]:           7726 :     pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
 7360 tgl@sss.pgh.pa.us          66                 :           7726 :     pset.lineno = 0;
 3512 andres@anarazel.de         67                 :           7726 :     pset.stmt_lineno = 1;
                                 68                 :                : 
                                 69                 :                :     /* Create working state */
 2949 tgl@sss.pgh.pa.us          70                 :           7726 :     scan_state = psql_scan_create(&psqlscan_callbacks);
 2572                            71                 :           7726 :     cond_stack = conditional_stack_create();
                                 72                 :           7726 :     psql_scan_set_passthrough(scan_state, (void *) cond_stack);
                                 73                 :                : 
 8928 bruce@momjian.us           74                 :           7726 :     query_buf = createPQExpBuffer();
 8768                            75                 :           7726 :     previous_buf = createPQExpBuffer();
 6637                            76                 :           7726 :     history_buf = createPQExpBuffer();
 5618 tgl@sss.pgh.pa.us          77   [ +  -  +  - ]:           7726 :     if (PQExpBufferBroken(query_buf) ||
                                 78   [ +  -  +  -  :           7726 :         PQExpBufferBroken(previous_buf) ||
                                              +  - ]
                                 79         [ -  + ]:           7726 :         PQExpBufferBroken(history_buf))
  737 tgl@sss.pgh.pa.us          80                 :UBC           0 :         pg_fatal("out of memory");
                                 81                 :                : 
                                 82                 :                :     /* main loop to get queries and execute them */
 7696 bruce@momjian.us           83         [ +  + ]:CBC      375615 :     while (successResult == EXIT_SUCCESS)
                                 84                 :                :     {
                                 85                 :                :         /*
                                 86                 :                :          * Clean up after a previous Control-C
                                 87                 :                :          */
 8768                            88         [ -  + ]:         375577 :         if (cancel_pressed)
                                 89                 :                :         {
 8768 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                 :                :          */
 6514 tgl@sss.pgh.pa.us         107         [ -  + ]:CBC      375577 :         if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
                                108                 :                :         {
                                109                 :                :             /* got here with longjmp */
                                110                 :                : 
                                111                 :                :             /* reset parsing state */
 7360 tgl@sss.pgh.pa.us         112                 :UBC           0 :             psql_scan_finish(scan_state);
                                113                 :              0 :             psql_scan_reset(scan_state);
 6514                           114                 :              0 :             resetPQExpBuffer(query_buf);
                                115                 :              0 :             resetPQExpBuffer(history_buf);
 7360                           116                 :              0 :             count_eof = 0;
 6692 peter_e@gmx.net           117                 :              0 :             slashCmdStatus = PSQL_CMD_UNKNOWN;
 7360 tgl@sss.pgh.pa.us         118                 :              0 :             prompt_status = PROMPT_READY;
 1605                           119                 :              0 :             need_redisplay = false;
 3512 andres@anarazel.de        120                 :              0 :             pset.stmt_lineno = 1;
 6514 tgl@sss.pgh.pa.us         121                 :              0 :             cancel_pressed = false;
                                122                 :                : 
 8768 bruce@momjian.us          123         [ #  # ]:              0 :             if (pset.cur_cmd_interactive)
                                124                 :                :             {
 7696                           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                 :                :                  */
 2572 tgl@sss.pgh.pa.us         131         [ #  # ]:              0 :                 if (!conditional_stack_empty(cond_stack))
                                132                 :                :                 {
 1840 peter@eisentraut.org      133                 :              0 :                     pg_log_error("\\if: escaped");
 2572 tgl@sss.pgh.pa.us         134                 :              0 :                     conditional_stack_pop(cond_stack);
                                135                 :                :                 }
                                136                 :                :             }
                                137                 :                :             else
                                138                 :                :             {
 8768 bruce@momjian.us          139                 :              0 :                 successResult = EXIT_USER;
                                140                 :              0 :                 break;
                                141                 :                :             }
                                142                 :                :         }
                                143                 :                : 
 7389 tgl@sss.pgh.pa.us         144                 :CBC      375577 :         fflush(stdout);
                                145                 :                : 
                                146                 :                :         /*
                                147                 :                :          * get another line
                                148                 :                :          */
 6517                           149         [ +  + ]:         375577 :         if (pset.cur_cmd_interactive)
                                150                 :                :         {
                                151                 :                :             /* May need to reset prompt, eg after \r command */
 7360                           152         [ +  + ]:             54 :             if (query_buf->len == 0)
 7559 bruce@momjian.us          153                 :             52 :                 prompt_status = PROMPT_READY;
                                154                 :                :             /* If query buffer came from \e, redisplay it with a prompt */
 1605 tgl@sss.pgh.pa.us         155         [ -  + ]:             54 :             if (need_redisplay)
                                156                 :                :             {
 1605 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 */
 2572 tgl@sss.pgh.pa.us         166                 :CBC          54 :             line = gets_interactive(get_prompt(prompt_status, cond_stack),
                                167                 :                :                                     query_buf);
                                168                 :                :         }
                                169                 :                :         else
                                170                 :                :         {
 7559 bruce@momjian.us          171                 :         375523 :             line = gets_fromFile(source);
 5982 peter_e@gmx.net           172   [ +  +  -  + ]:         375523 :             if (!line && ferror(source))
 5982 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 */
 8925 bruce@momjian.us          182         [ +  + ]:CBC      375577 :         if (line == NULL)
                                183                 :                :         {
 8857 peter_e@gmx.net           184         [ -  + ]:           7641 :             if (pset.cur_cmd_interactive)
                                185                 :                :             {
                                186                 :                :                 /* This tries to mimic bash's IGNOREEOF feature. */
 7696 bruce@momjian.us          187                 :UBC           0 :                 count_eof++;
                                188                 :                : 
 2628 tgl@sss.pgh.pa.us         189         [ #  # ]:              0 :                 if (count_eof < pset.ignoreeof)
                                190                 :                :                 {
 6438                           191         [ #  # ]:              0 :                     if (!pset.quiet)
 6991 bruce@momjian.us          192                 :              0 :                         printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
 8768                           193                 :              0 :                     continue;
                                194                 :                :                 }
                                195                 :                : 
 6438 tgl@sss.pgh.pa.us         196         [ #  # ]:              0 :                 puts(pset.quiet ? "" : "\\q");
                                197                 :                :             }
 7559 bruce@momjian.us          198                 :CBC        7641 :             break;
                                199                 :                :         }
                                200                 :                : 
                                201                 :         367936 :         count_eof = 0;
                                202                 :                : 
 8768                           203                 :         367936 :         pset.lineno++;
                                204                 :                : 
                                205                 :                :         /* ignore UTF-8 Unicode byte-order mark */
 5258 peter_e@gmx.net           206   [ +  +  +  +  :         367936 :         if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
                                              -  + ]
 5258 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 */
 3460 alvherre@alvh.no-ip.      210   [ +  +  +  + ]:CBC      367936 :         if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
                                211         [ -  + ]:           7432 :             strncmp(line, "PGDMP", 5) == 0)
                                212                 :                :         {
 3460 alvherre@alvh.no-ip.      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 */
 7360 tgl@sss.pgh.pa.us         222   [ +  +  +  + ]:CBC      367936 :         if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
                                223                 :                :         {
 8928 bruce@momjian.us          224                 :          63892 :             free(line);
                                225                 :          63892 :             continue;
                                226                 :                :         }
                                227                 :                : 
                                228                 :                :         /* Recognize "help", "quit", "exit" only in interactive mode */
 2264                           229         [ +  + ]:         304044 :         if (pset.cur_cmd_interactive)
                                230                 :                :         {
                                231                 :             44 :             char       *first_word = line;
                                232                 :             44 :             char       *rest_of_line = NULL;
                                233                 :             44 :             bool        found_help = false;
                                234                 :             44 :             bool        found_exit_or_quit = false;
 2253                           235                 :             44 :             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                 :                :              */
 2264                           243         [ -  + ]:             44 :             if (pg_strncasecmp(first_word, "help", 4) == 0)
                                244                 :                :             {
 2264 bruce@momjian.us          245                 :UBC           0 :                 rest_of_line = first_word + 4;
                                246                 :              0 :                 found_help = true;
                                247                 :                :             }
 2264 bruce@momjian.us          248         [ +  - ]:CBC          44 :             else if (pg_strncasecmp(first_word, "exit", 4) == 0 ||
                                249         [ -  + ]:             44 :                      pg_strncasecmp(first_word, "quit", 4) == 0)
                                250                 :                :             {
 2264 bruce@momjian.us          251                 :UBC           0 :                 rest_of_line = first_word + 4;
                                252                 :              0 :                 found_exit_or_quit = true;
                                253                 :                :             }
 2253 bruce@momjian.us          254         [ +  + ]:CBC          44 :             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                 :                :              */
 2264                           266         [ +  + ]:             44 :             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))
 2264 bruce@momjian.us          273                 :UBC           0 :                     ++rest_of_line;
 2264 bruce@momjian.us          274         [ -  + ]:CBC           2 :                 if (*rest_of_line == ';')
 2264 bruce@momjian.us          275                 :UBC           0 :                     ++rest_of_line;
 2264 bruce@momjian.us          276         [ -  + ]:CBC           2 :                 while (isspace((unsigned char) *rest_of_line))
 2264 bruce@momjian.us          277                 :UBC           0 :                     ++rest_of_line;
 2264 bruce@momjian.us          278         [ -  + ]:CBC           2 :                 if (*rest_of_line != '\0')
                                279                 :                :                 {
 2264 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                 :                :              */
 2264 bruce@momjian.us          291         [ -  + ]:CBC          44 :             if (found_help)
                                292                 :                :             {
 2264 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"));
                                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                 :                :              */
 2264 bruce@momjian.us          319         [ -  + ]:CBC          44 :             if (found_exit_or_quit)
                                320                 :                :             {
 2264 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 */
                                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                 :                :              */
 2253 bruce@momjian.us          348   [ +  +  -  + ]:CBC          44 :             if (found_q && query_buf->len != 0 &&
 2253 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
 2180 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 */
 6438 tgl@sss.pgh.pa.us         360   [ +  +  +  - ]:CBC      304044 :         if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
                                361                 :                :         {
 8768 bruce@momjian.us          362                 :         290265 :             puts(line);
 3361 tgl@sss.pgh.pa.us         363                 :         290265 :             fflush(stdout);
                                364                 :                :         }
                                365                 :                : 
                                366                 :                :         /* insert newlines into query buffer between source lines */
 7360                           367         [ +  + ]:         304044 :         if (query_buf->len > 0)
                                368                 :                :         {
                                369                 :          92028 :             appendPQExpBufferChar(query_buf, '\n');
                                370                 :          92028 :             added_nl_pos = query_buf->len;
                                371                 :                :         }
                                372                 :                :         else
                                373                 :         212016 :             added_nl_pos = -1;  /* flag we didn't add one */
                                374                 :                : 
                                375                 :                :         /* Setting this will not have effect until next line. */
 6438                           376                 :         304044 :         die_on_error = pset.on_error_stop;
                                377                 :                : 
                                378                 :                :         /*
                                379                 :                :          * Parse line, looking for command separators.
                                380                 :                :          */
 2949                           381                 :         304044 :         psql_scan_setup(scan_state, line, strlen(line),
                                382                 :         304044 :                         pset.encoding, standard_strings());
 8928 bruce@momjian.us          383                 :         304044 :         success = true;
 6517 tgl@sss.pgh.pa.us         384                 :         304044 :         line_saved_in_history = false;
                                385                 :                : 
 7360                           386   [ +  +  +  + ]:         464531 :         while (success || !die_on_error)
                                387                 :                :         {
                                388                 :                :             PsqlScanResult scan_result;
                                389                 :         464493 :             promptStatus_t prompt_tmp = prompt_status;
                                390                 :                :             size_t      pos_in_query;
                                391                 :                :             char       *tmp_line;
                                392                 :                : 
 3512 andres@anarazel.de        393                 :         464493 :             pos_in_query = query_buf->len;
 7360 tgl@sss.pgh.pa.us         394                 :         464493 :             scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
                                395                 :         464493 :             prompt_status = prompt_tmp;
                                396                 :                : 
 5618                           397   [ +  -  -  + ]:         464493 :             if (PQExpBufferBroken(query_buf))
  737 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                 :                :              */
 3512 andres@anarazel.de        406                 :CBC      464493 :             tmp_line = query_buf->data + pos_in_query;
                                407         [ +  + ]:       11428249 :             while (*tmp_line != '\0')
                                408                 :                :             {
                                409         [ +  + ]:       10963756 :                 if (*(tmp_line++) == '\n')
                                410                 :             90 :                     pset.stmt_lineno++;
                                411                 :                :             }
                                412                 :                : 
                                413         [ +  + ]:         464493 :             if (scan_result == PSCAN_EOL)
                                414                 :          51047 :                 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                 :                :              */
 7360 tgl@sss.pgh.pa.us         420   [ +  +  +  + ]:         464493 :             if (scan_result == PSCAN_SEMICOLON ||
 6438                           421         [ -  + ]:          51047 :                 (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                 :                :                  */
 6517                           429   [ +  +  +  - ]:         153938 :                 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 */
 2572                           437         [ +  + ]:         307866 :                 if (conditional_active(cond_stack))
                                438                 :                :                 {
                                439                 :         153932 :                     success = SendQuery(query_buf->data);
                                440         [ +  + ]:         153922 :                     slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
                                441                 :         153922 :                     pset.stmt_lineno = 1;
                                442                 :                : 
                                443                 :                :                     /* transfer query to previous_buf by pointer-swapping */
                                444                 :                :                     {
                                445                 :         153922 :                         PQExpBuffer swap_buf = previous_buf;
                                446                 :                : 
                                447                 :         153922 :                         previous_buf = query_buf;
                                448                 :         153922 :                         query_buf = swap_buf;
                                449                 :                :                     }
                                450                 :         153922 :                     resetPQExpBuffer(query_buf);
                                451                 :                : 
                                452                 :         153922 :                     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         [ -  + ]:              6 :                     if (pset.cur_cmd_interactive)
 1840 peter@eisentraut.org      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 */
 2572 tgl@sss.pgh.pa.us         461                 :CBC           6 :                     success = true;
                                462                 :              6 :                     slashCmdStatus = PSQL_CMD_SEND;
                                463                 :              6 :                     pset.stmt_lineno = 1;
                                464                 :                :                     /* note that query_buf doesn't change state */
                                465                 :                :                 }
                                466                 :                :             }
 7360                           467         [ +  + ]:         310555 :             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         [ +  + ]:           6596 :                 if (query_buf->len == added_nl_pos)
                                481                 :                :                 {
                                482                 :             64 :                     query_buf->data[--query_buf->len] = '\0';
 6517                           483                 :             64 :                     pg_send_history(history_buf);
                                484                 :                :                 }
 7360                           485                 :           6596 :                 added_nl_pos = -1;
                                486                 :                : 
                                487                 :                :                 /* save backslash command in history */
 6517                           488   [ +  +  +  + ]:           6596 :                 if (pset.cur_cmd_interactive && !line_saved_in_history)
                                489                 :                :                 {
                                490                 :             37 :                     pg_append_history(line, history_buf);
                                491                 :             37 :                     pg_send_history(history_buf);
                                492                 :             37 :                     line_saved_in_history = true;
                                493                 :                :                 }
                                494                 :                : 
                                495                 :                :                 /* execute backslash command */
 7360                           496                 :           6596 :                 slashCmdStatus = HandleSlashCmds(scan_state,
                                497                 :                :                                                  cond_stack,
                                498                 :                :                                                  query_buf,
                                499                 :                :                                                  previous_buf);
                                500                 :                : 
 6692 peter_e@gmx.net           501                 :           6595 :                 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                 :                :                  */
 2572 tgl@sss.pgh.pa.us         508                 :           6595 :                 pset.stmt_lineno = 1;
                                509                 :                : 
 6692 peter_e@gmx.net           510         [ +  + ]:           6595 :                 if (slashCmdStatus == PSQL_CMD_SEND)
                                511                 :                :                 {
                                512                 :                :                     /* should not see this in inactive branch */
 2572 tgl@sss.pgh.pa.us         513         [ -  + ]:            539 :                     Assert(conditional_active(cond_stack));
                                514                 :                : 
 8857 peter_e@gmx.net           515                 :            539 :                     success = SendQuery(query_buf->data);
                                516                 :                : 
                                517                 :                :                     /* transfer query to previous_buf by pointer-swapping */
                                518                 :                :                     {
 5618 tgl@sss.pgh.pa.us         519                 :            539 :                         PQExpBuffer swap_buf = previous_buf;
                                520                 :                : 
                                521                 :            539 :                         previous_buf = query_buf;
                                522                 :            539 :                         query_buf = swap_buf;
                                523                 :                :                     }
 8768 bruce@momjian.us          524                 :            539 :                     resetPQExpBuffer(query_buf);
                                525                 :                : 
                                526                 :                :                     /* flush any paren nesting info after forced send */
 7360 tgl@sss.pgh.pa.us         527                 :            539 :                     psql_scan_reset(scan_state);
                                528                 :                :                 }
 6517                           529         [ -  + ]:           6056 :                 else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
                                530                 :                :                 {
                                531                 :                :                     /* should not see this in inactive branch */
 2572 tgl@sss.pgh.pa.us         532         [ #  # ]:UBC           0 :                     Assert(conditional_active(cond_stack));
                                533                 :                :                     /* ensure what came back from editing ends in a newline */
 1605                           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 */
 6517                           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);
 2949                           544                 :              0 :                     psql_scan_setup(scan_state, line, strlen(line),
                                545                 :              0 :                                     pset.encoding, standard_strings());
 6517                           546                 :              0 :                     line_saved_in_history = false;
                                547                 :              0 :                     prompt_status = PROMPT_READY;
                                548                 :                :                     /* we'll want to redisplay after parsing what we have */
 1605                           549                 :              0 :                     need_redisplay = true;
                                550                 :                :                 }
 6517 tgl@sss.pgh.pa.us         551         [ +  + ]:CBC        6056 :                 else if (slashCmdStatus == PSQL_CMD_TERMINATE)
                                552                 :         303995 :                     break;
                                553                 :                :             }
                                554                 :                : 
                                555                 :                :             /* fall out of loop if lexer reached EOL */
                                556   [ +  +  +  + ]:         464446 :             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                 :                :          */
  865                           568         [ +  + ]:         304033 :         if (pset.cur_cmd_interactive)
                                569                 :                :         {
                                570         [ +  + ]:             44 :             if (!line_saved_in_history)
                                571                 :              2 :                 pg_append_history(line, history_buf);
                                572         [ +  + ]:             44 :             if (query_buf->len == 0)
                                573                 :             42 :                 pg_send_history(history_buf);
                                574                 :                :         }
                                575                 :                : 
 7360                           576                 :         304033 :         psql_scan_finish(scan_state);
 8928 bruce@momjian.us          577                 :         304033 :         free(line);
                                578                 :                : 
 6692 peter_e@gmx.net           579         [ +  + ]:         304033 :         if (slashCmdStatus == PSQL_CMD_TERMINATE)
                                580                 :                :         {
 7360 tgl@sss.pgh.pa.us         581                 :             36 :             successResult = EXIT_SUCCESS;
                                582                 :             36 :             break;
                                583                 :                :         }
                                584                 :                : 
 7696 bruce@momjian.us          585         [ +  + ]:         303997 :         if (!pset.cur_cmd_interactive)
                                586                 :                :         {
                                587   [ +  +  +  + ]:         303955 :             if (!success && die_on_error)
 7559                           588                 :             38 :                 successResult = EXIT_USER;
                                589                 :                :             /* Have we lost the db connection? */
 7696                           590         [ -  + ]:         303917 :             else if (!pset.db)
 7559 bruce@momjian.us          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                 :                :      */
 8423 tgl@sss.pgh.pa.us         600   [ +  +  +  - ]:CBC        7715 :     if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
                                601         [ +  - ]:           4646 :         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 */
 2572                           611         [ +  - ]:           4646 :         if (conditional_active(cond_stack))
                                612                 :                :         {
                                613                 :           4646 :             success = SendQuery(query_buf->data);
                                614                 :                :         }
                                615                 :                :         else
                                616                 :                :         {
 2572 tgl@sss.pgh.pa.us         617         [ #  # ]:UBC           0 :             if (pset.cur_cmd_interactive)
 1840 peter@eisentraut.org      618                 :              0 :                 pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
 2572 tgl@sss.pgh.pa.us         619                 :              0 :             success = true;
                                620                 :                :         }
                                621                 :                : 
 8768 bruce@momjian.us          622   [ +  +  +  + ]:CBC        4645 :         if (!success && die_on_error)
                                623                 :             20 :             successResult = EXIT_USER;
                                624         [ -  + ]:           4625 :         else if (pset.db == NULL)
 8768 bruce@momjian.us          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                 :                :      */
 2572 tgl@sss.pgh.pa.us         632         [ +  + ]:CBC        7714 :     if (slashCmdStatus != PSQL_CMD_TERMINATE &&
                                633         [ +  + ]:           7678 :         successResult != EXIT_USER &&
                                634         [ -  + ]:           7620 :         !conditional_stack_empty(cond_stack))
                                635                 :                :     {
 1840 peter@eisentraut.org      636                 :UBC           0 :         pg_log_error("reached EOF without finding closing \\endif(s)");
 2572 tgl@sss.pgh.pa.us         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                 :                :      */
 6514 tgl@sss.pgh.pa.us         648                 :CBC        7714 :     sigint_interrupt_enabled = false;
                                649                 :                : 
 8928 bruce@momjian.us          650                 :           7714 :     destroyPQExpBuffer(query_buf);
 8892                           651                 :           7714 :     destroyPQExpBuffer(previous_buf);
 6637                           652                 :           7714 :     destroyPQExpBuffer(history_buf);
                                653                 :                : 
 7360 tgl@sss.pgh.pa.us         654                 :           7714 :     psql_scan_destroy(scan_state);
 2572                           655                 :           7714 :     conditional_stack_destroy(cond_stack);
                                656                 :                : 
 8857 peter_e@gmx.net           657                 :           7714 :     pset.cur_cmd_source = prev_cmd_source;
                                658                 :           7714 :     pset.cur_cmd_interactive = prev_cmd_interactive;
 8768 bruce@momjian.us          659                 :           7714 :     pset.lineno = prev_lineno;
                                660                 :                : 
 8928                           661                 :           7714 :     return successResult;
                                662                 :                : }                               /* MainLoop() */
        

Generated by: LCOV version 2.1-beta2-3-g6141622