LCOV - code coverage report
Current view: top level - src/bin/psql - mainloop.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 128 245 52.2 %
Date: 2019-06-18 07:06:57 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * psql - the PostgreSQL interactive terminal
       3             :  *
       4             :  * Copyright (c) 2000-2019, PostgreSQL Global Development Group
       5             :  *
       6             :  * src/bin/psql/mainloop.c
       7             :  */
       8             : #include "postgres_fe.h"
       9             : #include "mainloop.h"
      10             : 
      11             : #include "command.h"
      12             : #include "common.h"
      13             : #include "input.h"
      14             : #include "prompt.h"
      15             : #include "settings.h"
      16             : 
      17             : #include "common/logging.h"
      18             : #include "mb/pg_wchar.h"
      19             : 
      20             : 
      21             : /* callback functions for our flex lexer */
      22             : const PsqlScanCallbacks psqlscan_callbacks = {
      23             :     psql_get_variable,
      24             : };
      25             : 
      26             : 
      27             : /*
      28             :  * Main processing loop for reading lines of input
      29             :  *  and sending them to the backend.
      30             :  *
      31             :  * This loop is re-entrant. May be called by \i command
      32             :  *  which reads input from a file.
      33             :  */
      34             : int
      35        2698 : MainLoop(FILE *source)
      36             : {
      37             :     PsqlScanState scan_state;   /* lexer working state */
      38             :     ConditionalStack cond_stack;    /* \if status stack */
      39             :     volatile PQExpBuffer query_buf; /* buffer for query being accumulated */
      40             :     volatile PQExpBuffer previous_buf;  /* if there isn't anything in the new
      41             :                                          * buffer yet, use this one for \e,
      42             :                                          * etc. */
      43             :     PQExpBuffer history_buf;    /* earlier lines of a multi-line command, not
      44             :                                  * yet saved to readline history */
      45             :     char       *line;           /* current line of input */
      46             :     int         added_nl_pos;
      47             :     bool        success;
      48             :     bool        line_saved_in_history;
      49        2698 :     volatile int successResult = EXIT_SUCCESS;
      50        2698 :     volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
      51        2698 :     volatile promptStatus_t prompt_status = PROMPT_READY;
      52        2698 :     volatile int count_eof = 0;
      53        2698 :     volatile bool die_on_error = false;
      54             :     FILE       *prev_cmd_source;
      55             :     bool        prev_cmd_interactive;
      56             :     uint64      prev_lineno;
      57             : 
      58             :     /* Save the prior command source */
      59        2698 :     prev_cmd_source = pset.cur_cmd_source;
      60        2698 :     prev_cmd_interactive = pset.cur_cmd_interactive;
      61        2698 :     prev_lineno = pset.lineno;
      62             :     /* pset.stmt_lineno does not need to be saved and restored */
      63             : 
      64             :     /* Establish new source */
      65        2698 :     pset.cur_cmd_source = source;
      66        2698 :     pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
      67        2698 :     pset.lineno = 0;
      68        2698 :     pset.stmt_lineno = 1;
      69             : 
      70             :     /* Create working state */
      71        2698 :     scan_state = psql_scan_create(&psqlscan_callbacks);
      72        2698 :     cond_stack = conditional_stack_create();
      73        2698 :     psql_scan_set_passthrough(scan_state, (void *) cond_stack);
      74             : 
      75        2698 :     query_buf = createPQExpBuffer();
      76        2698 :     previous_buf = createPQExpBuffer();
      77        2698 :     history_buf = createPQExpBuffer();
      78        5396 :     if (PQExpBufferBroken(query_buf) ||
      79        5396 :         PQExpBufferBroken(previous_buf) ||
      80        2698 :         PQExpBufferBroken(history_buf))
      81             :     {
      82           0 :         pg_log_error("out of memory");
      83           0 :         exit(EXIT_FAILURE);
      84             :     }
      85             : 
      86             :     /* main loop to get queries and execute them */
      87      347196 :     while (successResult == EXIT_SUCCESS)
      88             :     {
      89             :         /*
      90             :          * Clean up after a previous Control-C
      91             :          */
      92      344486 :         if (cancel_pressed)
      93             :         {
      94           0 :             if (!pset.cur_cmd_interactive)
      95             :             {
      96             :                 /*
      97             :                  * You get here if you stopped a script with Ctrl-C.
      98             :                  */
      99           0 :                 successResult = EXIT_USER;
     100           0 :                 break;
     101             :             }
     102             : 
     103           0 :             cancel_pressed = false;
     104             :         }
     105             : 
     106             :         /*
     107             :          * Establish longjmp destination for exiting from wait-for-input. We
     108             :          * must re-do this each time through the loop for safety, since the
     109             :          * jmpbuf might get changed during command execution.
     110             :          */
     111      344486 :         if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
     112             :         {
     113             :             /* got here with longjmp */
     114             : 
     115             :             /* reset parsing state */
     116           0 :             psql_scan_finish(scan_state);
     117           0 :             psql_scan_reset(scan_state);
     118           0 :             resetPQExpBuffer(query_buf);
     119           0 :             resetPQExpBuffer(history_buf);
     120           0 :             count_eof = 0;
     121           0 :             slashCmdStatus = PSQL_CMD_UNKNOWN;
     122           0 :             prompt_status = PROMPT_READY;
     123           0 :             pset.stmt_lineno = 1;
     124           0 :             cancel_pressed = false;
     125             : 
     126           0 :             if (pset.cur_cmd_interactive)
     127             :             {
     128           0 :                 putc('\n', stdout);
     129             : 
     130             :                 /*
     131             :                  * if interactive user is in an \if block, then Ctrl-C will
     132             :                  * exit from the innermost \if.
     133             :                  */
     134           0 :                 if (!conditional_stack_empty(cond_stack))
     135             :                 {
     136           0 :                     pg_log_error("\\if: escaped");
     137           0 :                     conditional_stack_pop(cond_stack);
     138             :                 }
     139             :             }
     140             :             else
     141             :             {
     142           0 :                 successResult = EXIT_USER;
     143           0 :                 break;
     144             :             }
     145             :         }
     146             : 
     147      344486 :         fflush(stdout);
     148             : 
     149             :         /*
     150             :          * get another line
     151             :          */
     152      344486 :         if (pset.cur_cmd_interactive)
     153             :         {
     154             :             /* May need to reset prompt, eg after \r command */
     155           0 :             if (query_buf->len == 0)
     156           0 :                 prompt_status = PROMPT_READY;
     157           0 :             line = gets_interactive(get_prompt(prompt_status, cond_stack),
     158             :                                     query_buf);
     159             :         }
     160             :         else
     161             :         {
     162      344486 :             line = gets_fromFile(source);
     163      344486 :             if (!line && ferror(source))
     164           0 :                 successResult = EXIT_FAILURE;
     165             :         }
     166             : 
     167             :         /*
     168             :          * query_buf holds query already accumulated.  line is the malloc'd
     169             :          * new line of input (note it must be freed before looping around!)
     170             :          */
     171             : 
     172             :         /* No more input.  Time to quit, or \i done */
     173      344486 :         if (line == NULL)
     174             :         {
     175        2680 :             if (pset.cur_cmd_interactive)
     176             :             {
     177             :                 /* This tries to mimic bash's IGNOREEOF feature. */
     178           0 :                 count_eof++;
     179             : 
     180           0 :                 if (count_eof < pset.ignoreeof)
     181             :                 {
     182           0 :                     if (!pset.quiet)
     183           0 :                         printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
     184           0 :                     continue;
     185             :                 }
     186             : 
     187           0 :                 puts(pset.quiet ? "" : "\\q");
     188             :             }
     189        2680 :             break;
     190             :         }
     191             : 
     192      341806 :         count_eof = 0;
     193             : 
     194      341806 :         pset.lineno++;
     195             : 
     196             :         /* ignore UTF-8 Unicode byte-order mark */
     197      341806 :         if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
     198           0 :             memmove(line, line + 3, strlen(line + 3) + 1);
     199             : 
     200             :         /* Detect attempts to run custom-format dumps as SQL scripts */
     201      344346 :         if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
     202        2540 :             strncmp(line, "PGDMP", 5) == 0)
     203             :         {
     204           0 :             free(line);
     205           0 :             puts(_("The input is a PostgreSQL custom-format dump.\n"
     206             :                    "Use the pg_restore command-line client to restore this dump to a database.\n"));
     207           0 :             fflush(stdout);
     208           0 :             successResult = EXIT_FAILURE;
     209           0 :             break;
     210             :         }
     211             : 
     212             :         /* no further processing of empty lines, unless within a literal */
     213      341806 :         if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
     214             :         {
     215       63550 :             free(line);
     216       63550 :             continue;
     217             :         }
     218             : 
     219             :         /* Recognize "help", "quit", "exit" only in interactive mode */
     220      278256 :         if (pset.cur_cmd_interactive)
     221             :         {
     222           0 :             char       *first_word = line;
     223           0 :             char       *rest_of_line = NULL;
     224           0 :             bool        found_help = false;
     225           0 :             bool        found_exit_or_quit = false;
     226           0 :             bool        found_q = false;
     227             : 
     228             :             /* Search for the words we recognize;  must be first word */
     229           0 :             if (pg_strncasecmp(first_word, "help", 4) == 0)
     230             :             {
     231           0 :                 rest_of_line = first_word + 4;
     232           0 :                 found_help = true;
     233             :             }
     234           0 :             else if (pg_strncasecmp(first_word, "exit", 4) == 0 ||
     235           0 :                      pg_strncasecmp(first_word, "quit", 4) == 0)
     236             :             {
     237           0 :                 rest_of_line = first_word + 4;
     238           0 :                 found_exit_or_quit = true;
     239             :             }
     240             : 
     241           0 :             else if (strncmp(first_word, "\\q", 2) == 0)
     242             :             {
     243           0 :                 rest_of_line = first_word + 2;
     244           0 :                 found_q = true;
     245             :             }
     246             : 
     247             :             /*
     248             :              * If we found a command word, check whether the rest of the line
     249             :              * contains only whitespace plus maybe one semicolon.  If not,
     250             :              * ignore the command word after all.  These commands are only for
     251             :              * compatibility with other SQL clients and are not documented.
     252             :              */
     253           0 :             if (rest_of_line != NULL)
     254             :             {
     255             :                 /*
     256             :                  * Ignore unless rest of line is whitespace, plus maybe one
     257             :                  * semicolon
     258             :                  */
     259           0 :                 while (isspace((unsigned char) *rest_of_line))
     260           0 :                     ++rest_of_line;
     261           0 :                 if (*rest_of_line == ';')
     262           0 :                     ++rest_of_line;
     263           0 :                 while (isspace((unsigned char) *rest_of_line))
     264           0 :                     ++rest_of_line;
     265           0 :                 if (*rest_of_line != '\0')
     266             :                 {
     267           0 :                     found_help = false;
     268           0 :                     found_exit_or_quit = false;
     269             :                 }
     270             :             }
     271             : 
     272             :             /*
     273             :              * "help" is only a command when the query buffer is empty, but we
     274             :              * emit a one-line message even when it isn't to help confused
     275             :              * users.  The text is still added to the query buffer in that
     276             :              * case.
     277             :              */
     278           0 :             if (found_help)
     279             :             {
     280           0 :                 if (query_buf->len != 0)
     281             : #ifndef WIN32
     282           0 :                     puts(_("Use \\? for help or press control-C to clear the input buffer."));
     283             : #else
     284             :                     puts(_("Use \\? for help."));
     285             : #endif
     286             :                 else
     287             :                 {
     288           0 :                     puts(_("You are using psql, the command-line interface to PostgreSQL."));
     289           0 :                     printf(_("Type:  \\copyright for distribution terms\n"
     290             :                              "       \\h for help with SQL commands\n"
     291             :                              "       \\? for help with psql commands\n"
     292             :                              "       \\g or terminate with semicolon to execute query\n"
     293             :                              "       \\q to quit\n"));
     294           0 :                     free(line);
     295           0 :                     fflush(stdout);
     296           0 :                     continue;
     297             :                 }
     298             :             }
     299             : 
     300             :             /*
     301             :              * "quit" and "exit" are only commands when the query buffer is
     302             :              * empty, but we emit a one-line message even when it isn't to
     303             :              * help confused users.  The text is still added to the query
     304             :              * buffer in that case.
     305             :              */
     306           0 :             if (found_exit_or_quit)
     307             :             {
     308           0 :                 if (query_buf->len != 0)
     309             :                 {
     310           0 :                     if (prompt_status == PROMPT_READY ||
     311           0 :                         prompt_status == PROMPT_CONTINUE ||
     312           0 :                         prompt_status == PROMPT_PAREN)
     313           0 :                         puts(_("Use \\q to quit."));
     314             :                     else
     315             : #ifndef WIN32
     316           0 :                         puts(_("Use control-D to quit."));
     317             : #else
     318             :                         puts(_("Use control-C to quit."));
     319             : #endif
     320             :                 }
     321             :                 else
     322             :                 {
     323             :                     /* exit app */
     324           0 :                     free(line);
     325           0 :                     fflush(stdout);
     326           0 :                     successResult = EXIT_SUCCESS;
     327           0 :                     break;
     328             :                 }
     329             :             }
     330             : 
     331             :             /*
     332             :              * If they typed "\q" in a place where "\q" is not active, supply
     333             :              * a hint.  The text is still added to the query buffer.
     334             :              */
     335           0 :             if (found_q && query_buf->len != 0 &&
     336           0 :                 prompt_status != PROMPT_READY &&
     337           0 :                 prompt_status != PROMPT_CONTINUE &&
     338           0 :                 prompt_status != PROMPT_PAREN)
     339             : #ifndef WIN32
     340           0 :                 puts(_("Use control-D to quit."));
     341             : #else
     342             :                 puts(_("Use control-C to quit."));
     343             : #endif
     344             :         }
     345             : 
     346             :         /* echo back if flag is set, unless interactive */
     347      278256 :         if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
     348             :         {
     349      274028 :             puts(line);
     350      274028 :             fflush(stdout);
     351             :         }
     352             : 
     353             :         /* insert newlines into query buffer between source lines */
     354      278256 :         if (query_buf->len > 0)
     355             :         {
     356       85174 :             appendPQExpBufferChar(query_buf, '\n');
     357       85174 :             added_nl_pos = query_buf->len;
     358             :         }
     359             :         else
     360      193082 :             added_nl_pos = -1;  /* flag we didn't add one */
     361             : 
     362             :         /* Setting this will not have effect until next line. */
     363      278256 :         die_on_error = pset.on_error_stop;
     364             : 
     365             :         /*
     366             :          * Parse line, looking for command separators.
     367             :          */
     368      278256 :         psql_scan_setup(scan_state, line, strlen(line),
     369      278256 :                         pset.encoding, standard_strings());
     370      278256 :         success = true;
     371      278256 :         line_saved_in_history = false;
     372             : 
     373      705924 :         while (success || !die_on_error)
     374             :         {
     375             :             PsqlScanResult scan_result;
     376      427656 :             promptStatus_t prompt_tmp = prompt_status;
     377             :             size_t      pos_in_query;
     378             :             char       *tmp_line;
     379             : 
     380      427656 :             pos_in_query = query_buf->len;
     381      427656 :             scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
     382      427656 :             prompt_status = prompt_tmp;
     383             : 
     384      427656 :             if (PQExpBufferBroken(query_buf))
     385             :             {
     386           0 :                 pg_log_error("out of memory");
     387           0 :                 exit(EXIT_FAILURE);
     388             :             }
     389             : 
     390             :             /*
     391             :              * Increase statement line number counter for each linebreak added
     392             :              * to the query buffer by the last psql_scan() call. There only
     393             :              * will be ones to add when navigating to a statement in
     394             :              * readline's history containing newlines.
     395             :              */
     396      427656 :             tmp_line = query_buf->data + pos_in_query;
     397    10681490 :             while (*tmp_line != '\0')
     398             :             {
     399     9826178 :                 if (*(tmp_line++) == '\n')
     400           0 :                     pset.stmt_lineno++;
     401             :             }
     402             : 
     403      427656 :             if (scan_result == PSCAN_EOL)
     404       40258 :                 pset.stmt_lineno++;
     405             : 
     406             :             /*
     407             :              * Send command if semicolon found, or if end of line and we're in
     408             :              * single-line mode.
     409             :              */
     410      427656 :             if (scan_result == PSCAN_SEMICOLON ||
     411       40258 :                 (scan_result == PSCAN_EOL && pset.singleline))
     412             :             {
     413             :                 /*
     414             :                  * Save line in history.  We use history_buf to accumulate
     415             :                  * multi-line queries into a single history entry.  Note that
     416             :                  * history accumulation works on input lines, so it doesn't
     417             :                  * matter whether the query will be ignored due to \if.
     418             :                  */
     419      144582 :                 if (pset.cur_cmd_interactive && !line_saved_in_history)
     420             :                 {
     421           0 :                     pg_append_history(line, history_buf);
     422           0 :                     pg_send_history(history_buf);
     423           0 :                     line_saved_in_history = true;
     424             :                 }
     425             : 
     426             :                 /* execute query unless we're in an inactive \if branch */
     427      289158 :                 if (conditional_active(cond_stack))
     428             :                 {
     429      144578 :                     success = SendQuery(query_buf->data);
     430      144572 :                     slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
     431      144572 :                     pset.stmt_lineno = 1;
     432             : 
     433             :                     /* transfer query to previous_buf by pointer-swapping */
     434             :                     {
     435      144572 :                         PQExpBuffer swap_buf = previous_buf;
     436             : 
     437      144572 :                         previous_buf = query_buf;
     438      144572 :                         query_buf = swap_buf;
     439             :                     }
     440      144572 :                     resetPQExpBuffer(query_buf);
     441             : 
     442      144572 :                     added_nl_pos = -1;
     443             :                     /* we need not do psql_scan_reset() here */
     444             :                 }
     445             :                 else
     446             :                 {
     447             :                     /* if interactive, warn about non-executed query */
     448           4 :                     if (pset.cur_cmd_interactive)
     449           0 :                         pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
     450             :                     /* fake an OK result for purposes of loop checks */
     451           4 :                     success = true;
     452           4 :                     slashCmdStatus = PSQL_CMD_SEND;
     453           4 :                     pset.stmt_lineno = 1;
     454             :                     /* note that query_buf doesn't change state */
     455             :                 }
     456             :             }
     457      283074 :             else if (scan_result == PSCAN_BACKSLASH)
     458             :             {
     459             :                 /* handle backslash command */
     460             : 
     461             :                 /*
     462             :                  * If we added a newline to query_buf, and nothing else has
     463             :                  * been inserted in query_buf by the lexer, then strip off the
     464             :                  * newline again.  This avoids any change to query_buf when a
     465             :                  * line contains only a backslash command.  Also, in this
     466             :                  * situation we force out any previous lines as a separate
     467             :                  * history entry; we don't want SQL and backslash commands
     468             :                  * intermixed in history if at all possible.
     469             :                  */
     470        4836 :                 if (query_buf->len == added_nl_pos)
     471             :                 {
     472          60 :                     query_buf->data[--query_buf->len] = '\0';
     473          60 :                     pg_send_history(history_buf);
     474             :                 }
     475        4836 :                 added_nl_pos = -1;
     476             : 
     477             :                 /* save backslash command in history */
     478        4836 :                 if (pset.cur_cmd_interactive && !line_saved_in_history)
     479             :                 {
     480           0 :                     pg_append_history(line, history_buf);
     481           0 :                     pg_send_history(history_buf);
     482           0 :                     line_saved_in_history = true;
     483             :                 }
     484             : 
     485             :                 /* execute backslash command */
     486        4836 :                 slashCmdStatus = HandleSlashCmds(scan_state,
     487             :                                                  cond_stack,
     488             :                                                  query_buf,
     489             :                                                  previous_buf);
     490             : 
     491        4836 :                 success = slashCmdStatus != PSQL_CMD_ERROR;
     492             : 
     493             :                 /*
     494             :                  * Resetting stmt_lineno after a backslash command isn't
     495             :                  * always appropriate, but it's what we've done historically
     496             :                  * and there have been few complaints.
     497             :                  */
     498        4836 :                 pset.stmt_lineno = 1;
     499             : 
     500        4836 :                 if (slashCmdStatus == PSQL_CMD_SEND)
     501             :                 {
     502             :                     /* should not see this in inactive branch */
     503             :                     Assert(conditional_active(cond_stack));
     504             : 
     505         298 :                     success = SendQuery(query_buf->data);
     506             : 
     507             :                     /* transfer query to previous_buf by pointer-swapping */
     508             :                     {
     509         298 :                         PQExpBuffer swap_buf = previous_buf;
     510             : 
     511         298 :                         previous_buf = query_buf;
     512         298 :                         query_buf = swap_buf;
     513             :                     }
     514         298 :                     resetPQExpBuffer(query_buf);
     515             : 
     516             :                     /* flush any paren nesting info after forced send */
     517         298 :                     psql_scan_reset(scan_state);
     518             :                 }
     519        4538 :                 else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
     520             :                 {
     521             :                     /* should not see this in inactive branch */
     522             :                     Assert(conditional_active(cond_stack));
     523             :                     /* rescan query_buf as new input */
     524           0 :                     psql_scan_finish(scan_state);
     525           0 :                     free(line);
     526           0 :                     line = pg_strdup(query_buf->data);
     527           0 :                     resetPQExpBuffer(query_buf);
     528             :                     /* reset parsing state since we are rescanning whole line */
     529           0 :                     psql_scan_reset(scan_state);
     530           0 :                     psql_scan_setup(scan_state, line, strlen(line),
     531           0 :                                     pset.encoding, standard_strings());
     532           0 :                     line_saved_in_history = false;
     533           0 :                     prompt_status = PROMPT_READY;
     534             :                 }
     535        4538 :                 else if (slashCmdStatus == PSQL_CMD_TERMINATE)
     536      278238 :                     break;
     537             :             }
     538             : 
     539             :             /* fall out of loop if lexer reached EOL */
     540      427650 :             if (scan_result == PSCAN_INCOMPLETE ||
     541             :                 scan_result == PSCAN_EOL)
     542             :                 break;
     543             :         }
     544             : 
     545             :         /* Add line to pending history if we didn't execute anything yet */
     546      278250 :         if (pset.cur_cmd_interactive && !line_saved_in_history)
     547           0 :             pg_append_history(line, history_buf);
     548             : 
     549      278250 :         psql_scan_finish(scan_state);
     550      278250 :         free(line);
     551             : 
     552      278250 :         if (slashCmdStatus == PSQL_CMD_TERMINATE)
     553             :         {
     554           0 :             successResult = EXIT_SUCCESS;
     555           0 :             break;
     556             :         }
     557             : 
     558      278250 :         if (!pset.cur_cmd_interactive)
     559             :         {
     560      278250 :             if (!success && die_on_error)
     561          12 :                 successResult = EXIT_USER;
     562             :             /* Have we lost the db connection? */
     563      278238 :             else if (!pset.db)
     564           0 :                 successResult = EXIT_BADCONN;
     565             :         }
     566             :     }                           /* while !endoffile/session */
     567             : 
     568             :     /*
     569             :      * If we have a non-semicolon-terminated query at the end of file, we
     570             :      * process it unless the input source is interactive --- in that case it
     571             :      * seems better to go ahead and quit.  Also skip if this is an error exit.
     572             :      */
     573        3536 :     if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
     574         844 :         successResult == EXIT_SUCCESS)
     575             :     {
     576             :         /* save query in history */
     577             :         /* currently unneeded since we don't use this block if interactive */
     578             : #ifdef NOT_USED
     579             :         if (pset.cur_cmd_interactive)
     580             :             pg_send_history(history_buf);
     581             : #endif
     582             : 
     583             :         /* execute query unless we're in an inactive \if branch */
     584         844 :         if (conditional_active(cond_stack))
     585             :         {
     586         844 :             success = SendQuery(query_buf->data);
     587             :         }
     588             :         else
     589             :         {
     590           0 :             if (pset.cur_cmd_interactive)
     591           0 :                 pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
     592           0 :             success = true;
     593             :         }
     594             : 
     595         844 :         if (!success && die_on_error)
     596          14 :             successResult = EXIT_USER;
     597         830 :         else if (pset.db == NULL)
     598           0 :             successResult = EXIT_BADCONN;
     599             :     }
     600             : 
     601             :     /*
     602             :      * Check for unbalanced \if-\endifs unless user explicitly quit, or the
     603             :      * script is erroring out
     604             :      */
     605        5384 :     if (slashCmdStatus != PSQL_CMD_TERMINATE &&
     606        5358 :         successResult != EXIT_USER &&
     607        2666 :         !conditional_stack_empty(cond_stack))
     608             :     {
     609           0 :         pg_log_error("reached EOF without finding closing \\endif(s)");
     610           0 :         if (die_on_error && !pset.cur_cmd_interactive)
     611           0 :             successResult = EXIT_USER;
     612             :     }
     613             : 
     614             :     /*
     615             :      * Let's just make real sure the SIGINT handler won't try to use
     616             :      * sigint_interrupt_jmp after we exit this routine.  If there is an outer
     617             :      * MainLoop instance, it will reset sigint_interrupt_jmp to point to
     618             :      * itself at the top of its loop, before any further interactive input
     619             :      * happens.
     620             :      */
     621        2692 :     sigint_interrupt_enabled = false;
     622             : 
     623        2692 :     destroyPQExpBuffer(query_buf);
     624        2692 :     destroyPQExpBuffer(previous_buf);
     625        2692 :     destroyPQExpBuffer(history_buf);
     626             : 
     627        2692 :     psql_scan_destroy(scan_state);
     628        2692 :     conditional_stack_destroy(cond_stack);
     629             : 
     630        2692 :     pset.cur_cmd_source = prev_cmd_source;
     631        2692 :     pset.cur_cmd_interactive = prev_cmd_interactive;
     632        2692 :     pset.lineno = prev_lineno;
     633             : 
     634        2692 :     return successResult;
     635             : }                               /* MainLoop() */

Generated by: LCOV version 1.13