LCOV - code coverage report
Current view: top level - src/bin/psql - common.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 624 862 72.4 %
Date: 2024-11-21 08:14:44 Functions: 35 37 94.6 %
Legend: Lines: hit not hit

          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/common.c
       7             :  */
       8             : #include "postgres_fe.h"
       9             : 
      10             : #include <ctype.h>
      11             : #include <limits.h>
      12             : #include <math.h>
      13             : #include <pwd.h>
      14             : #include <signal.h>
      15             : #ifndef WIN32
      16             : #include <unistd.h>               /* for write() */
      17             : #else
      18             : #include <io.h>                   /* for _write() */
      19             : #include <win32.h>
      20             : #endif
      21             : 
      22             : #include "command.h"
      23             : #include "common.h"
      24             : #include "common/logging.h"
      25             : #include "copy.h"
      26             : #include "crosstabview.h"
      27             : #include "fe_utils/cancel.h"
      28             : #include "fe_utils/mbprint.h"
      29             : #include "fe_utils/string_utils.h"
      30             : #include "portability/instr_time.h"
      31             : #include "settings.h"
      32             : 
      33             : static bool DescribeQuery(const char *query, double *elapsed_msec);
      34             : static int  ExecQueryAndProcessResults(const char *query,
      35             :                                        double *elapsed_msec,
      36             :                                        bool *svpt_gone_p,
      37             :                                        bool is_watch,
      38             :                                        int min_rows,
      39             :                                        const printQueryOpt *opt,
      40             :                                        FILE *printQueryFout);
      41             : static bool command_no_begin(const char *query);
      42             : 
      43             : 
      44             : /*
      45             :  * openQueryOutputFile --- attempt to open a query output file
      46             :  *
      47             :  * fname == NULL selects stdout, else an initial '|' selects a pipe,
      48             :  * else plain file.
      49             :  *
      50             :  * Returns output file pointer into *fout, and is-a-pipe flag into *is_pipe.
      51             :  * Caller is responsible for adjusting SIGPIPE state if it's a pipe.
      52             :  *
      53             :  * On error, reports suitable error message and returns false.
      54             :  */
      55             : bool
      56       18376 : openQueryOutputFile(const char *fname, FILE **fout, bool *is_pipe)
      57             : {
      58       18376 :     if (!fname || fname[0] == '\0')
      59             :     {
      60       18326 :         *fout = stdout;
      61       18326 :         *is_pipe = false;
      62             :     }
      63          50 :     else if (*fname == '|')
      64             :     {
      65           8 :         fflush(NULL);
      66           8 :         *fout = popen(fname + 1, "w");
      67           8 :         *is_pipe = true;
      68             :     }
      69             :     else
      70             :     {
      71          42 :         *fout = fopen(fname, "w");
      72          42 :         *is_pipe = false;
      73             :     }
      74             : 
      75       18376 :     if (*fout == NULL)
      76             :     {
      77           0 :         pg_log_error("%s: %m", fname);
      78           0 :         return false;
      79             :     }
      80             : 
      81       18376 :     return true;
      82             : }
      83             : 
      84             : /*
      85             :  * Check if an output stream for \g needs to be opened, and if yes,
      86             :  * open it and update the caller's gfile_fout and is_pipe state variables.
      87             :  * Return true if OK, false if an error occurred.
      88             :  */
      89             : static bool
      90      128042 : SetupGOutput(FILE **gfile_fout, bool *is_pipe)
      91             : {
      92             :     /* If there is a \g file or program, and it's not already open, open it */
      93      128042 :     if (pset.gfname != NULL && *gfile_fout == NULL)
      94             :     {
      95          32 :         if (openQueryOutputFile(pset.gfname, gfile_fout, is_pipe))
      96             :         {
      97          32 :             if (*is_pipe)
      98           8 :                 disable_sigpipe_trap();
      99             :         }
     100             :         else
     101           0 :             return false;
     102             :     }
     103      128042 :     return true;
     104             : }
     105             : 
     106             : /*
     107             :  * Close the output stream for \g, if we opened it.
     108             :  */
     109             : static void
     110      327568 : CloseGOutput(FILE *gfile_fout, bool is_pipe)
     111             : {
     112      327568 :     if (gfile_fout)
     113             :     {
     114          32 :         if (is_pipe)
     115             :         {
     116           8 :             SetShellResultVariables(pclose(gfile_fout));
     117           8 :             restore_sigpipe_trap();
     118             :         }
     119             :         else
     120          24 :             fclose(gfile_fout);
     121             :     }
     122      327568 : }
     123             : 
     124             : /*
     125             :  * setQFout
     126             :  * -- handler for -o command line option and \o command
     127             :  *
     128             :  * On success, updates pset with the new output file and returns true.
     129             :  * On failure, returns false without changing pset state.
     130             :  */
     131             : bool
     132       18344 : setQFout(const char *fname)
     133             : {
     134             :     FILE       *fout;
     135             :     bool        is_pipe;
     136             : 
     137             :     /* First make sure we can open the new output file/pipe */
     138       18344 :     if (!openQueryOutputFile(fname, &fout, &is_pipe))
     139           0 :         return false;
     140             : 
     141             :     /* Close old file/pipe */
     142       18344 :     if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
     143             :     {
     144          18 :         if (pset.queryFoutPipe)
     145           0 :             SetShellResultVariables(pclose(pset.queryFout));
     146             :         else
     147          18 :             fclose(pset.queryFout);
     148             :     }
     149             : 
     150       18344 :     pset.queryFout = fout;
     151       18344 :     pset.queryFoutPipe = is_pipe;
     152             : 
     153             :     /* Adjust SIGPIPE handling appropriately: ignore signal if is_pipe */
     154       18344 :     set_sigpipe_trap_state(is_pipe);
     155       18344 :     restore_sigpipe_trap();
     156             : 
     157       18344 :     return true;
     158             : }
     159             : 
     160             : 
     161             : /*
     162             :  * Variable-fetching callback for flex lexer
     163             :  *
     164             :  * If the specified variable exists, return its value as a string (malloc'd
     165             :  * and expected to be freed by the caller); else return NULL.
     166             :  *
     167             :  * If "quote" isn't PQUOTE_PLAIN, then return the value suitably quoted and
     168             :  * escaped for the specified quoting requirement.  (Failure in escaping
     169             :  * should lead to printing an error and returning NULL.)
     170             :  *
     171             :  * "passthrough" is the pointer previously given to psql_scan_set_passthrough.
     172             :  * In psql, passthrough points to a ConditionalStack, which we check to
     173             :  * determine whether variable expansion is allowed.
     174             :  */
     175             : char *
     176        3634 : psql_get_variable(const char *varname, PsqlScanQuoteType quote,
     177             :                   void *passthrough)
     178             : {
     179        3634 :     char       *result = NULL;
     180             :     const char *value;
     181             : 
     182             :     /* In an inactive \if branch, suppress all variable substitutions */
     183        3634 :     if (passthrough && !conditional_active((ConditionalStack) passthrough))
     184          72 :         return NULL;
     185             : 
     186        3562 :     value = GetVariable(pset.vars, varname);
     187        3562 :     if (!value)
     188         464 :         return NULL;
     189             : 
     190        3098 :     switch (quote)
     191             :     {
     192        2284 :         case PQUOTE_PLAIN:
     193        2284 :             result = pg_strdup(value);
     194        2284 :             break;
     195         814 :         case PQUOTE_SQL_LITERAL:
     196             :         case PQUOTE_SQL_IDENT:
     197             :             {
     198             :                 /*
     199             :                  * For these cases, we use libpq's quoting functions, which
     200             :                  * assume the string is in the connection's client encoding.
     201             :                  */
     202             :                 char       *escaped_value;
     203             : 
     204         814 :                 if (!pset.db)
     205             :                 {
     206           0 :                     pg_log_error("cannot escape without active connection");
     207           0 :                     return NULL;
     208             :                 }
     209             : 
     210         814 :                 if (quote == PQUOTE_SQL_LITERAL)
     211             :                     escaped_value =
     212         788 :                         PQescapeLiteral(pset.db, value, strlen(value));
     213             :                 else
     214             :                     escaped_value =
     215          26 :                         PQescapeIdentifier(pset.db, value, strlen(value));
     216             : 
     217         814 :                 if (escaped_value == NULL)
     218             :                 {
     219           0 :                     const char *error = PQerrorMessage(pset.db);
     220             : 
     221           0 :                     pg_log_info("%s", error);
     222           0 :                     return NULL;
     223             :                 }
     224             : 
     225             :                 /*
     226             :                  * Rather than complicate the lexer's API with a notion of
     227             :                  * which free() routine to use, just pay the price of an extra
     228             :                  * strdup().
     229             :                  */
     230         814 :                 result = pg_strdup(escaped_value);
     231         814 :                 PQfreemem(escaped_value);
     232         814 :                 break;
     233             :             }
     234           0 :         case PQUOTE_SHELL_ARG:
     235             :             {
     236             :                 /*
     237             :                  * For this we use appendShellStringNoError, which is
     238             :                  * encoding-agnostic, which is fine since the shell probably
     239             :                  * is too.  In any case, the only special character is "'",
     240             :                  * which is not known to appear in valid multibyte characters.
     241             :                  */
     242             :                 PQExpBufferData buf;
     243             : 
     244           0 :                 initPQExpBuffer(&buf);
     245           0 :                 if (!appendShellStringNoError(&buf, value))
     246             :                 {
     247           0 :                     pg_log_error("shell command argument contains a newline or carriage return: \"%s\"",
     248             :                                  value);
     249           0 :                     free(buf.data);
     250           0 :                     return NULL;
     251             :                 }
     252           0 :                 result = buf.data;
     253           0 :                 break;
     254             :             }
     255             : 
     256             :             /* No default: we want a compiler warning for missing cases */
     257             :     }
     258             : 
     259        3098 :     return result;
     260             : }
     261             : 
     262             : 
     263             : /*
     264             :  * for backend Notice messages (INFO, WARNING, etc)
     265             :  */
     266             : void
     267      153388 : NoticeProcessor(void *arg, const char *message)
     268             : {
     269             :     (void) arg;                 /* not used */
     270      153388 :     pg_log_info("%s", message);
     271      153388 : }
     272             : 
     273             : 
     274             : 
     275             : /*
     276             :  * Code to support query cancellation
     277             :  *
     278             :  * Before we start a query, we enable the SIGINT signal catcher to send a
     279             :  * cancel request to the backend.
     280             :  *
     281             :  * SIGINT is supposed to abort all long-running psql operations, not only
     282             :  * database queries.  In most places, this is accomplished by checking
     283             :  * cancel_pressed during long-running loops.  However, that won't work when
     284             :  * blocked on user input (in readline() or fgets()).  In those places, we
     285             :  * set sigint_interrupt_enabled true while blocked, instructing the signal
     286             :  * catcher to longjmp through sigint_interrupt_jmp.  We assume readline and
     287             :  * fgets are coded to handle possible interruption.
     288             :  *
     289             :  * On Windows, currently this does not work, so control-C is less useful
     290             :  * there.
     291             :  */
     292             : volatile sig_atomic_t sigint_interrupt_enabled = false;
     293             : 
     294             : sigjmp_buf  sigint_interrupt_jmp;
     295             : 
     296             : static void
     297           2 : psql_cancel_callback(void)
     298             : {
     299             : #ifndef WIN32
     300             :     /* if we are waiting for input, longjmp out of it */
     301           2 :     if (sigint_interrupt_enabled)
     302             :     {
     303           0 :         sigint_interrupt_enabled = false;
     304           0 :         siglongjmp(sigint_interrupt_jmp, 1);
     305             :     }
     306             : #endif
     307             : 
     308             :     /* else, set cancel flag to stop any long-running loops */
     309           2 :     cancel_pressed = true;
     310           2 : }
     311             : 
     312             : void
     313       18330 : psql_setup_cancel_handler(void)
     314             : {
     315       18330 :     setup_cancel_handler(psql_cancel_callback);
     316       18330 : }
     317             : 
     318             : 
     319             : /* ConnectionUp
     320             :  *
     321             :  * Returns whether our backend connection is still there.
     322             :  */
     323             : static bool
     324      367208 : ConnectionUp(void)
     325             : {
     326      367208 :     return PQstatus(pset.db) != CONNECTION_BAD;
     327             : }
     328             : 
     329             : 
     330             : 
     331             : /* CheckConnection
     332             :  *
     333             :  * Verify that we still have a good connection to the backend, and if not,
     334             :  * see if it can be restored.
     335             :  *
     336             :  * Returns true if either the connection was still there, or it could be
     337             :  * restored successfully; false otherwise.  If, however, there was no
     338             :  * connection and the session is non-interactive, this will exit the program
     339             :  * with a code of EXIT_BADCONN.
     340             :  */
     341             : static bool
     342      367208 : CheckConnection(void)
     343             : {
     344             :     bool        OK;
     345             : 
     346      367208 :     OK = ConnectionUp();
     347      367208 :     if (!OK)
     348             :     {
     349          22 :         if (!pset.cur_cmd_interactive)
     350             :         {
     351          22 :             pg_log_error("connection to server was lost");
     352          22 :             exit(EXIT_BADCONN);
     353             :         }
     354             : 
     355           0 :         fprintf(stderr, _("The connection to the server was lost. Attempting reset: "));
     356           0 :         PQreset(pset.db);
     357           0 :         OK = ConnectionUp();
     358           0 :         if (!OK)
     359             :         {
     360           0 :             fprintf(stderr, _("Failed.\n"));
     361             : 
     362             :             /*
     363             :              * Transition to having no connection; but stash away the failed
     364             :              * connection so that we can still refer to its parameters in a
     365             :              * later \connect attempt.  Keep the state cleanup here in sync
     366             :              * with do_connect().
     367             :              */
     368           0 :             if (pset.dead_conn)
     369           0 :                 PQfinish(pset.dead_conn);
     370           0 :             pset.dead_conn = pset.db;
     371           0 :             pset.db = NULL;
     372           0 :             ResetCancelConn();
     373           0 :             UnsyncVariables();
     374             :         }
     375             :         else
     376             :         {
     377           0 :             fprintf(stderr, _("Succeeded.\n"));
     378             : 
     379             :             /*
     380             :              * Re-sync, just in case anything changed.  Keep this in sync with
     381             :              * do_connect().
     382             :              */
     383           0 :             SyncVariables();
     384           0 :             connection_warnings(false); /* Must be after SyncVariables */
     385             :         }
     386             :     }
     387             : 
     388      367186 :     return OK;
     389             : }
     390             : 
     391             : 
     392             : 
     393             : 
     394             : /*
     395             :  * AcceptResult
     396             :  *
     397             :  * Checks whether a result is valid, giving an error message if necessary;
     398             :  * and ensures that the connection to the backend is still up.
     399             :  *
     400             :  * Returns true for valid result, false for error state.
     401             :  */
     402             : static bool
     403      363892 : AcceptResult(const PGresult *result, bool show_error)
     404             : {
     405             :     bool        OK;
     406             : 
     407      363892 :     if (!result)
     408           0 :         OK = false;
     409             :     else
     410      363892 :         switch (PQresultStatus(result))
     411             :         {
     412      324252 :             case PGRES_COMMAND_OK:
     413             :             case PGRES_TUPLES_OK:
     414             :             case PGRES_TUPLES_CHUNK:
     415             :             case PGRES_EMPTY_QUERY:
     416             :             case PGRES_COPY_IN:
     417             :             case PGRES_COPY_OUT:
     418             :                 /* Fine, do nothing */
     419      324252 :                 OK = true;
     420      324252 :                 break;
     421             : 
     422       39638 :             case PGRES_BAD_RESPONSE:
     423             :             case PGRES_NONFATAL_ERROR:
     424             :             case PGRES_FATAL_ERROR:
     425       39638 :                 OK = false;
     426       39638 :                 break;
     427             : 
     428           2 :             default:
     429           2 :                 OK = false;
     430           2 :                 pg_log_error("unexpected PQresultStatus: %d",
     431             :                              PQresultStatus(result));
     432           2 :                 break;
     433             :         }
     434             : 
     435      363892 :     if (!OK && show_error)
     436             :     {
     437           6 :         const char *error = PQerrorMessage(pset.db);
     438             : 
     439           6 :         if (strlen(error))
     440           6 :             pg_log_info("%s", error);
     441             : 
     442           6 :         CheckConnection();
     443             :     }
     444             : 
     445      363892 :     return OK;
     446             : }
     447             : 
     448             : 
     449             : /*
     450             :  * Set special variables from a query result
     451             :  * - ERROR: true/false, whether an error occurred on this query
     452             :  * - SQLSTATE: code of error, or "00000" if no error, or "" if unknown
     453             :  * - ROW_COUNT: how many rows were returned or affected, or "0"
     454             :  * - LAST_ERROR_SQLSTATE: same for last error
     455             :  * - LAST_ERROR_MESSAGE: message of last error
     456             :  *
     457             :  * Note: current policy is to apply this only to the results of queries
     458             :  * entered by the user, not queries generated by slash commands.
     459             :  */
     460             : static void
     461      327558 : SetResultVariables(PGresult *result, bool success)
     462             : {
     463      327558 :     if (success)
     464             :     {
     465      287632 :         const char *ntuples = PQcmdTuples(result);
     466             : 
     467      287632 :         SetVariable(pset.vars, "ERROR", "false");
     468      287632 :         SetVariable(pset.vars, "SQLSTATE", "00000");
     469      287632 :         SetVariable(pset.vars, "ROW_COUNT", *ntuples ? ntuples : "0");
     470             :     }
     471             :     else
     472             :     {
     473       39926 :         const char *code = PQresultErrorField(result, PG_DIAG_SQLSTATE);
     474       39926 :         const char *mesg = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
     475             : 
     476       39926 :         SetVariable(pset.vars, "ERROR", "true");
     477             : 
     478             :         /*
     479             :          * If there is no SQLSTATE code, use an empty string.  This can happen
     480             :          * for libpq-detected errors (e.g., lost connection, ENOMEM).
     481             :          */
     482       39926 :         if (code == NULL)
     483         104 :             code = "";
     484       39926 :         SetVariable(pset.vars, "SQLSTATE", code);
     485       39926 :         SetVariable(pset.vars, "ROW_COUNT", "0");
     486       39926 :         SetVariable(pset.vars, "LAST_ERROR_SQLSTATE", code);
     487       39926 :         SetVariable(pset.vars, "LAST_ERROR_MESSAGE", mesg ? mesg : "");
     488             :     }
     489      327558 : }
     490             : 
     491             : 
     492             : /*
     493             :  * Set special variables from a shell command result
     494             :  * - SHELL_ERROR: true/false, whether command returned exit code 0
     495             :  * - SHELL_EXIT_CODE: exit code according to shell conventions
     496             :  *
     497             :  * The argument is a wait status as returned by wait(2) or waitpid(2),
     498             :  * which also applies to pclose(3) and system(3).
     499             :  */
     500             : void
     501           8 : SetShellResultVariables(int wait_result)
     502             : {
     503             :     char        buf[32];
     504             : 
     505           8 :     SetVariable(pset.vars, "SHELL_ERROR",
     506             :                 (wait_result == 0) ? "false" : "true");
     507           8 :     snprintf(buf, sizeof(buf), "%d", wait_result_to_exit_code(wait_result));
     508           8 :     SetVariable(pset.vars, "SHELL_EXIT_CODE", buf);
     509           8 : }
     510             : 
     511             : 
     512             : /*
     513             :  * ClearOrSaveResult
     514             :  *
     515             :  * If the result represents an error, remember it for possible display by
     516             :  * \errverbose.  Otherwise, just PQclear() it.
     517             :  *
     518             :  * Note: current policy is to apply this to the results of all queries,
     519             :  * including "back door" queries, for debugging's sake.  It's OK to use
     520             :  * PQclear() directly on results known to not be error results, however.
     521             :  */
     522             : static void
     523      329598 : ClearOrSaveResult(PGresult *result)
     524             : {
     525      329598 :     if (result)
     526             :     {
     527      329054 :         switch (PQresultStatus(result))
     528             :         {
     529       39828 :             case PGRES_NONFATAL_ERROR:
     530             :             case PGRES_FATAL_ERROR:
     531       39828 :                 PQclear(pset.last_error_result);
     532       39828 :                 pset.last_error_result = result;
     533       39828 :                 break;
     534             : 
     535      289226 :             default:
     536      289226 :                 PQclear(result);
     537      289226 :                 break;
     538             :         }
     539         544 :     }
     540      329598 : }
     541             : 
     542             : 
     543             : /*
     544             :  * Consume all results
     545             :  */
     546             : static void
     547           0 : ClearOrSaveAllResults(void)
     548             : {
     549             :     PGresult   *result;
     550             : 
     551           0 :     while ((result = PQgetResult(pset.db)) != NULL)
     552           0 :         ClearOrSaveResult(result);
     553           0 : }
     554             : 
     555             : 
     556             : /*
     557             :  * Print microtiming output.  Always print raw milliseconds; if the interval
     558             :  * is >= 1 second, also break it down into days/hours/minutes/seconds.
     559             :  */
     560             : static void
     561           4 : PrintTiming(double elapsed_msec)
     562             : {
     563             :     double      seconds;
     564             :     double      minutes;
     565             :     double      hours;
     566             :     double      days;
     567             : 
     568           4 :     if (elapsed_msec < 1000.0)
     569             :     {
     570             :         /* This is the traditional (pre-v10) output format */
     571           4 :         printf(_("Time: %.3f ms\n"), elapsed_msec);
     572           4 :         return;
     573             :     }
     574             : 
     575             :     /*
     576             :      * Note: we could print just seconds, in a format like %06.3f, when the
     577             :      * total is less than 1min.  But that's hard to interpret unless we tack
     578             :      * on "s" or otherwise annotate it.  Forcing the display to include
     579             :      * minutes seems like a better solution.
     580             :      */
     581           0 :     seconds = elapsed_msec / 1000.0;
     582           0 :     minutes = floor(seconds / 60.0);
     583           0 :     seconds -= 60.0 * minutes;
     584           0 :     if (minutes < 60.0)
     585             :     {
     586           0 :         printf(_("Time: %.3f ms (%02d:%06.3f)\n"),
     587             :                elapsed_msec, (int) minutes, seconds);
     588           0 :         return;
     589             :     }
     590             : 
     591           0 :     hours = floor(minutes / 60.0);
     592           0 :     minutes -= 60.0 * hours;
     593           0 :     if (hours < 24.0)
     594             :     {
     595           0 :         printf(_("Time: %.3f ms (%02d:%02d:%06.3f)\n"),
     596             :                elapsed_msec, (int) hours, (int) minutes, seconds);
     597           0 :         return;
     598             :     }
     599             : 
     600           0 :     days = floor(hours / 24.0);
     601           0 :     hours -= 24.0 * days;
     602           0 :     printf(_("Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n"),
     603             :            elapsed_msec, days, (int) hours, (int) minutes, seconds);
     604             : }
     605             : 
     606             : 
     607             : /*
     608             :  * PSQLexec
     609             :  *
     610             :  * This is the way to send "backdoor" queries (those not directly entered
     611             :  * by the user). It is subject to -E but not -e.
     612             :  *
     613             :  * Caller is responsible for handling the ensuing processing if a COPY
     614             :  * command is sent.
     615             :  *
     616             :  * Note: we don't bother to check PQclientEncoding; it is assumed that no
     617             :  * caller uses this path to issue "SET CLIENT_ENCODING".
     618             :  */
     619             : PGresult *
     620       34598 : PSQLexec(const char *query)
     621             : {
     622             :     PGresult   *res;
     623             : 
     624       34598 :     if (!pset.db)
     625             :     {
     626           0 :         pg_log_error("You are currently not connected to a database.");
     627           0 :         return NULL;
     628             :     }
     629             : 
     630       34598 :     if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
     631             :     {
     632           0 :         printf(_("/******** QUERY *********/\n"
     633             :                  "%s\n"
     634             :                  "/************************/\n\n"), query);
     635           0 :         fflush(stdout);
     636           0 :         if (pset.logfile)
     637             :         {
     638           0 :             fprintf(pset.logfile,
     639           0 :                     _("/******** QUERY *********/\n"
     640             :                       "%s\n"
     641             :                       "/************************/\n\n"), query);
     642           0 :             fflush(pset.logfile);
     643             :         }
     644             : 
     645           0 :         if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
     646           0 :             return NULL;
     647             :     }
     648             : 
     649       34598 :     SetCancelConn(pset.db);
     650             : 
     651       34598 :     res = PQexec(pset.db, query);
     652             : 
     653       34598 :     ResetCancelConn();
     654             : 
     655       34598 :     if (!AcceptResult(res, true))
     656             :     {
     657           0 :         ClearOrSaveResult(res);
     658           0 :         res = NULL;
     659             :     }
     660             : 
     661       34598 :     return res;
     662             : }
     663             : 
     664             : 
     665             : /*
     666             :  * PSQLexecWatch
     667             :  *
     668             :  * This function is used for \watch command to send the query to
     669             :  * the server and print out the result.
     670             :  *
     671             :  * Returns 1 if the query executed successfully, 0 if it cannot be repeated,
     672             :  * e.g., because of the interrupt, -1 on error.
     673             :  */
     674             : int
     675          36 : PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout, int min_rows)
     676             : {
     677          36 :     bool        timing = pset.timing;
     678          36 :     double      elapsed_msec = 0;
     679             :     int         res;
     680             : 
     681          36 :     if (!pset.db)
     682             :     {
     683           0 :         pg_log_error("You are currently not connected to a database.");
     684           0 :         return 0;
     685             :     }
     686             : 
     687          36 :     SetCancelConn(pset.db);
     688             : 
     689          36 :     res = ExecQueryAndProcessResults(query, &elapsed_msec, NULL, true, min_rows, opt, printQueryFout);
     690             : 
     691          34 :     ResetCancelConn();
     692             : 
     693             :     /* Possible microtiming output */
     694          34 :     if (timing)
     695           0 :         PrintTiming(elapsed_msec);
     696             : 
     697          34 :     return res;
     698             : }
     699             : 
     700             : 
     701             : /*
     702             :  * PrintNotifications: check for asynchronous notifications, and print them out
     703             :  */
     704             : static void
     705      327602 : PrintNotifications(void)
     706             : {
     707             :     PGnotify   *notify;
     708             : 
     709      327602 :     PQconsumeInput(pset.db);
     710      327606 :     while ((notify = PQnotifies(pset.db)) != NULL)
     711             :     {
     712             :         /* for backward compatibility, only show payload if nonempty */
     713           4 :         if (notify->extra[0])
     714           2 :             fprintf(pset.queryFout, _("Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n"),
     715             :                     notify->relname, notify->extra, notify->be_pid);
     716             :         else
     717           2 :             fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
     718             :                     notify->relname, notify->be_pid);
     719           4 :         fflush(pset.queryFout);
     720           4 :         PQfreemem(notify);
     721           4 :         PQconsumeInput(pset.db);
     722             :     }
     723      327602 : }
     724             : 
     725             : 
     726             : /*
     727             :  * PrintQueryTuples: assuming query result is OK, print its tuples
     728             :  *
     729             :  * We use the options given by opt unless that's NULL, in which case
     730             :  * we use pset.popt.
     731             :  *
     732             :  * Output is to printQueryFout unless that's NULL, in which case
     733             :  * we use pset.queryFout.
     734             :  *
     735             :  * Returns true if successful, false otherwise.
     736             :  */
     737             : static bool
     738      127134 : PrintQueryTuples(const PGresult *result, const printQueryOpt *opt,
     739             :                  FILE *printQueryFout)
     740             : {
     741      127134 :     bool        ok = true;
     742      127134 :     FILE       *fout = printQueryFout ? printQueryFout : pset.queryFout;
     743             : 
     744      127134 :     printQuery(result, opt ? opt : &pset.popt, fout, false, pset.logfile);
     745      127134 :     fflush(fout);
     746      127134 :     if (ferror(fout))
     747             :     {
     748           0 :         pg_log_error("could not print result table: %m");
     749           0 :         ok = false;
     750             :     }
     751             : 
     752      127134 :     return ok;
     753             : }
     754             : 
     755             : 
     756             : /*
     757             :  * StoreQueryTuple: assuming query result is OK, save data into variables
     758             :  *
     759             :  * Returns true if successful, false otherwise.
     760             :  */
     761             : static bool
     762         672 : StoreQueryTuple(const PGresult *result)
     763             : {
     764         672 :     bool        success = true;
     765             : 
     766         672 :     if (PQntuples(result) < 1)
     767             :     {
     768          18 :         pg_log_error("no rows returned for \\gset");
     769          18 :         success = false;
     770             :     }
     771         654 :     else if (PQntuples(result) > 1)
     772             :     {
     773          12 :         pg_log_error("more than one row returned for \\gset");
     774          12 :         success = false;
     775             :     }
     776             :     else
     777             :     {
     778             :         int         i;
     779             : 
     780        1434 :         for (i = 0; i < PQnfields(result); i++)
     781             :         {
     782         798 :             char       *colname = PQfname(result, i);
     783             :             char       *varname;
     784             :             char       *value;
     785             : 
     786             :             /* concatenate prefix and column name */
     787         798 :             varname = psprintf("%s%s", pset.gset_prefix, colname);
     788             : 
     789         798 :             if (VariableHasHook(pset.vars, varname))
     790             :             {
     791           6 :                 pg_log_warning("attempt to \\gset into specially treated variable \"%s\" ignored",
     792             :                                varname);
     793           6 :                 continue;
     794             :             }
     795             : 
     796         792 :             if (!PQgetisnull(result, 0, i))
     797         780 :                 value = PQgetvalue(result, 0, i);
     798             :             else
     799             :             {
     800             :                 /* for NULL value, unset rather than set the variable */
     801          12 :                 value = NULL;
     802             :             }
     803             : 
     804         792 :             if (!SetVariable(pset.vars, varname, value))
     805             :             {
     806           6 :                 free(varname);
     807           6 :                 success = false;
     808           6 :                 break;
     809             :             }
     810             : 
     811         786 :             free(varname);
     812             :         }
     813             :     }
     814             : 
     815         672 :     return success;
     816             : }
     817             : 
     818             : 
     819             : /*
     820             :  * ExecQueryTuples: assuming query result is OK, execute each query
     821             :  * result field as a SQL statement
     822             :  *
     823             :  * Returns true if successful, false otherwise.
     824             :  */
     825             : static bool
     826          46 : ExecQueryTuples(const PGresult *result)
     827             : {
     828          46 :     bool        success = true;
     829          46 :     int         nrows = PQntuples(result);
     830          46 :     int         ncolumns = PQnfields(result);
     831             :     int         r,
     832             :                 c;
     833             : 
     834             :     /*
     835             :      * We must turn off gexec_flag to avoid infinite recursion.
     836             :      */
     837          46 :     pset.gexec_flag = false;
     838             : 
     839         472 :     for (r = 0; r < nrows; r++)
     840             :     {
     841         870 :         for (c = 0; c < ncolumns; c++)
     842             :         {
     843         444 :             if (!PQgetisnull(result, r, c))
     844             :             {
     845         438 :                 const char *query = PQgetvalue(result, r, c);
     846             : 
     847             :                 /* Abandon execution if cancel_pressed */
     848         438 :                 if (cancel_pressed)
     849           0 :                     goto loop_exit;
     850             : 
     851             :                 /*
     852             :                  * ECHO_ALL mode should echo these queries, but SendQuery
     853             :                  * assumes that MainLoop did that, so we have to do it here.
     854             :                  */
     855         438 :                 if (pset.echo == PSQL_ECHO_ALL && !pset.singlestep)
     856             :                 {
     857         430 :                     puts(query);
     858         430 :                     fflush(stdout);
     859             :                 }
     860             : 
     861         438 :                 if (!SendQuery(query))
     862             :                 {
     863             :                     /* Error - abandon execution if ON_ERROR_STOP */
     864           6 :                     success = false;
     865           6 :                     if (pset.on_error_stop)
     866           0 :                         goto loop_exit;
     867             :                 }
     868             :             }
     869             :         }
     870             :     }
     871             : 
     872          46 : loop_exit:
     873             : 
     874             :     /*
     875             :      * Restore state.  We know gexec_flag was on, else we'd not be here. (We
     876             :      * also know it'll get turned off at end of command, but that's not ours
     877             :      * to do here.)
     878             :      */
     879          46 :     pset.gexec_flag = true;
     880             : 
     881             :     /* Return true if all queries were successful */
     882          46 :     return success;
     883             : }
     884             : 
     885             : 
     886             : /*
     887             :  * Marshal the COPY data.  Either path will get the
     888             :  * connection out of its COPY state, then call PQresultStatus()
     889             :  * once and report any error.  Return whether all was ok.
     890             :  *
     891             :  * For COPY OUT, direct the output to copystream, or discard if that's NULL.
     892             :  * For COPY IN, use pset.copyStream as data source if it's set,
     893             :  * otherwise cur_cmd_source.
     894             :  *
     895             :  * Update *resultp if further processing is necessary; set to NULL otherwise.
     896             :  * Return a result when queryFout can safely output a result status: on COPY
     897             :  * IN, or on COPY OUT if written to something other than pset.queryFout.
     898             :  * Returning NULL prevents the command status from being printed, which we
     899             :  * want if the status line doesn't get taken as part of the COPY data.
     900             :  */
     901             : static bool
     902        1412 : HandleCopyResult(PGresult **resultp, FILE *copystream)
     903             : {
     904             :     bool        success;
     905             :     PGresult   *copy_result;
     906        1412 :     ExecStatusType result_status = PQresultStatus(*resultp);
     907             : 
     908             :     Assert(result_status == PGRES_COPY_OUT ||
     909             :            result_status == PGRES_COPY_IN);
     910             : 
     911        1412 :     SetCancelConn(pset.db);
     912             : 
     913        1412 :     if (result_status == PGRES_COPY_OUT)
     914             :     {
     915         522 :         success = handleCopyOut(pset.db,
     916             :                                 copystream,
     917             :                                 &copy_result)
     918         522 :             && (copystream != NULL);
     919             : 
     920             :         /*
     921             :          * Suppress status printing if the report would go to the same place
     922             :          * as the COPY data just went.  Note this doesn't prevent error
     923             :          * reporting, since handleCopyOut did that.
     924             :          */
     925         522 :         if (copystream == pset.queryFout)
     926             :         {
     927         496 :             PQclear(copy_result);
     928         496 :             copy_result = NULL;
     929             :         }
     930             :     }
     931             :     else
     932             :     {
     933             :         /* COPY IN */
     934             :         /* Ignore the copystream argument passed to the function */
     935         890 :         copystream = pset.copyStream ? pset.copyStream : pset.cur_cmd_source;
     936         890 :         success = handleCopyIn(pset.db,
     937             :                                copystream,
     938         890 :                                PQbinaryTuples(*resultp),
     939             :                                &copy_result);
     940             :     }
     941        1412 :     ResetCancelConn();
     942             : 
     943             :     /*
     944             :      * Replace the PGRES_COPY_OUT/IN result with COPY command's exit status,
     945             :      * or with NULL if we want to suppress printing anything.
     946             :      */
     947        1412 :     PQclear(*resultp);
     948        1412 :     *resultp = copy_result;
     949             : 
     950        1412 :     return success;
     951             : }
     952             : 
     953             : /*
     954             :  * PrintQueryStatus: report command status as required
     955             :  */
     956             : static void
     957      288768 : PrintQueryStatus(PGresult *result, FILE *printQueryFout)
     958             : {
     959             :     char        buf[16];
     960      288768 :     const char *cmdstatus = PQcmdStatus(result);
     961      288768 :     FILE       *fout = printQueryFout ? printQueryFout : pset.queryFout;
     962             : 
     963             :     /* Do nothing if it's a TUPLES_OK result that isn't from RETURNING */
     964      288768 :     if (PQresultStatus(result) == PGRES_TUPLES_OK)
     965             :     {
     966      128032 :         if (!(strncmp(cmdstatus, "INSERT", 6) == 0 ||
     967      127608 :               strncmp(cmdstatus, "UPDATE", 6) == 0 ||
     968      127208 :               strncmp(cmdstatus, "DELETE", 6) == 0 ||
     969      127026 :               strncmp(cmdstatus, "MERGE", 5) == 0))
     970      126930 :             return;
     971             :     }
     972             : 
     973      161838 :     if (!pset.quiet)
     974             :     {
     975         834 :         if (pset.popt.topt.format == PRINT_HTML)
     976             :         {
     977           0 :             fputs("<p>", fout);
     978           0 :             html_escaped_print(cmdstatus, fout);
     979           0 :             fputs("</p>\n", fout);
     980             :         }
     981             :         else
     982         834 :             fprintf(fout, "%s\n", cmdstatus);
     983         834 :         fflush(fout);
     984             :     }
     985             : 
     986      161838 :     if (pset.logfile)
     987           0 :         fprintf(pset.logfile, "%s\n", cmdstatus);
     988             : 
     989      161838 :     snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(result));
     990      161838 :     SetVariable(pset.vars, "LASTOID", buf);
     991             : }
     992             : 
     993             : 
     994             : /*
     995             :  * PrintQueryResult: print out (or store or execute) query result as required
     996             :  *
     997             :  * last is true if this is the last result of a command string.
     998             :  * opt and printQueryFout are defined as for PrintQueryTuples.
     999             :  * printStatusFout is where to send command status; NULL means pset.queryFout.
    1000             :  *
    1001             :  * Returns true if the query executed successfully, false otherwise.
    1002             :  */
    1003             : static bool
    1004      288852 : PrintQueryResult(PGresult *result, bool last,
    1005             :                  const printQueryOpt *opt, FILE *printQueryFout,
    1006             :                  FILE *printStatusFout)
    1007             : {
    1008             :     bool        success;
    1009             : 
    1010      288852 :     if (!result)
    1011           0 :         return false;
    1012             : 
    1013      288852 :     switch (PQresultStatus(result))
    1014             :     {
    1015      127998 :         case PGRES_TUPLES_OK:
    1016             :             /* store or execute or print the data ... */
    1017      127998 :             if (last && pset.gset_prefix)
    1018         672 :                 success = StoreQueryTuple(result);
    1019      127326 :             else if (last && pset.gexec_flag)
    1020          46 :                 success = ExecQueryTuples(result);
    1021      127280 :             else if (last && pset.crosstab_flag)
    1022         132 :                 success = PrintResultInCrosstab(result);
    1023      127148 :             else if (last || pset.show_all_results)
    1024      127134 :                 success = PrintQueryTuples(result, opt, printQueryFout);
    1025             :             else
    1026          14 :                 success = true;
    1027             : 
    1028             :             /*
    1029             :              * If it's INSERT/UPDATE/DELETE/MERGE RETURNING, also print
    1030             :              * status.
    1031             :              */
    1032      127998 :             if (last || pset.show_all_results)
    1033      127984 :                 PrintQueryStatus(result, printStatusFout);
    1034             : 
    1035      127998 :             break;
    1036             : 
    1037      160736 :         case PGRES_COMMAND_OK:
    1038      160736 :             if (last || pset.show_all_results)
    1039      160736 :                 PrintQueryStatus(result, printStatusFout);
    1040      160736 :             success = true;
    1041      160736 :             break;
    1042             : 
    1043         118 :         case PGRES_EMPTY_QUERY:
    1044         118 :             success = true;
    1045         118 :             break;
    1046             : 
    1047           0 :         case PGRES_COPY_OUT:
    1048             :         case PGRES_COPY_IN:
    1049             :             /* nothing to do here: already processed */
    1050           0 :             success = true;
    1051           0 :             break;
    1052             : 
    1053           0 :         case PGRES_BAD_RESPONSE:
    1054             :         case PGRES_NONFATAL_ERROR:
    1055             :         case PGRES_FATAL_ERROR:
    1056           0 :             success = false;
    1057           0 :             break;
    1058             : 
    1059           0 :         default:
    1060           0 :             success = false;
    1061           0 :             pg_log_error("unexpected PQresultStatus: %d",
    1062             :                          PQresultStatus(result));
    1063           0 :             break;
    1064             :     }
    1065             : 
    1066      288852 :     return success;
    1067             : }
    1068             : 
    1069             : /*
    1070             :  * SendQuery: send the query string to the backend
    1071             :  * (and print out result)
    1072             :  *
    1073             :  * Note: This is the "front door" way to send a query. That is, use it to
    1074             :  * send queries actually entered by the user. These queries will be subject to
    1075             :  * single step mode.
    1076             :  * To send "back door" queries (generated by slash commands, etc.) in a
    1077             :  * controlled way, use PSQLexec().
    1078             :  *
    1079             :  * Returns true if the query executed successfully, false otherwise.
    1080             :  */
    1081             : bool
    1082      327622 : SendQuery(const char *query)
    1083             : {
    1084      327622 :     bool        timing = pset.timing;
    1085             :     PGTransactionStatusType transaction_status;
    1086      327622 :     double      elapsed_msec = 0;
    1087      327622 :     bool        OK = false;
    1088             :     int         i;
    1089      327622 :     bool        on_error_rollback_savepoint = false;
    1090      327622 :     bool        svpt_gone = false;
    1091             : 
    1092      327622 :     if (!pset.db)
    1093             :     {
    1094           0 :         pg_log_error("You are currently not connected to a database.");
    1095           0 :         goto sendquery_cleanup;
    1096             :     }
    1097             : 
    1098      327622 :     if (pset.singlestep)
    1099             :     {
    1100             :         char        buf[3];
    1101             : 
    1102           0 :         fflush(stderr);
    1103           0 :         printf(_("/**(Single step mode: verify command)******************************************/\n"
    1104             :                  "%s\n"
    1105             :                  "/**(press return to proceed or enter x and return to cancel)*******************/\n"),
    1106             :                query);
    1107           0 :         fflush(stdout);
    1108           0 :         if (fgets(buf, sizeof(buf), stdin) != NULL)
    1109           0 :             if (buf[0] == 'x')
    1110           0 :                 goto sendquery_cleanup;
    1111           0 :         if (cancel_pressed)
    1112           0 :             goto sendquery_cleanup;
    1113             :     }
    1114      327622 :     else if (pset.echo == PSQL_ECHO_QUERIES)
    1115             :     {
    1116          30 :         puts(query);
    1117          30 :         fflush(stdout);
    1118             :     }
    1119             : 
    1120      327622 :     if (pset.logfile)
    1121             :     {
    1122           0 :         fprintf(pset.logfile,
    1123           0 :                 _("/******** QUERY *********/\n"
    1124             :                   "%s\n"
    1125             :                   "/************************/\n\n"), query);
    1126           0 :         fflush(pset.logfile);
    1127             :     }
    1128             : 
    1129      327622 :     SetCancelConn(pset.db);
    1130             : 
    1131      327622 :     transaction_status = PQtransactionStatus(pset.db);
    1132             : 
    1133      327622 :     if (transaction_status == PQTRANS_IDLE &&
    1134      299546 :         !pset.autocommit &&
    1135          84 :         !command_no_begin(query))
    1136             :     {
    1137             :         PGresult   *result;
    1138             : 
    1139          72 :         result = PQexec(pset.db, "BEGIN");
    1140          72 :         if (PQresultStatus(result) != PGRES_COMMAND_OK)
    1141             :         {
    1142           0 :             pg_log_info("%s", PQerrorMessage(pset.db));
    1143           0 :             ClearOrSaveResult(result);
    1144           0 :             goto sendquery_cleanup;
    1145             :         }
    1146          72 :         ClearOrSaveResult(result);
    1147          72 :         transaction_status = PQtransactionStatus(pset.db);
    1148             :     }
    1149             : 
    1150      327622 :     if (transaction_status == PQTRANS_INTRANS &&
    1151       27028 :         pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF &&
    1152         156 :         (pset.cur_cmd_interactive ||
    1153         156 :          pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON))
    1154             :     {
    1155             :         PGresult   *result;
    1156             : 
    1157         156 :         result = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");
    1158         156 :         if (PQresultStatus(result) != PGRES_COMMAND_OK)
    1159             :         {
    1160           0 :             pg_log_info("%s", PQerrorMessage(pset.db));
    1161           0 :             ClearOrSaveResult(result);
    1162           0 :             goto sendquery_cleanup;
    1163             :         }
    1164         156 :         ClearOrSaveResult(result);
    1165         156 :         on_error_rollback_savepoint = true;
    1166             :     }
    1167             : 
    1168      327622 :     if (pset.gdesc_flag)
    1169             :     {
    1170             :         /* Describe query's result columns, without executing it */
    1171          68 :         OK = DescribeQuery(query, &elapsed_msec);
    1172             :     }
    1173             :     else
    1174             :     {
    1175             :         /* Default fetch-and-print mode */
    1176      327554 :         OK = (ExecQueryAndProcessResults(query, &elapsed_msec, &svpt_gone, false, 0, NULL, NULL) > 0);
    1177             :     }
    1178             : 
    1179      327602 :     if (!OK && pset.echo == PSQL_ECHO_ERRORS)
    1180           6 :         pg_log_info("STATEMENT:  %s", query);
    1181             : 
    1182             :     /* If we made a temporary savepoint, possibly release/rollback */
    1183      327602 :     if (on_error_rollback_savepoint)
    1184             :     {
    1185         156 :         const char *svptcmd = NULL;
    1186             : 
    1187         156 :         transaction_status = PQtransactionStatus(pset.db);
    1188             : 
    1189         156 :         switch (transaction_status)
    1190             :         {
    1191          42 :             case PQTRANS_INERROR:
    1192             :                 /* We always rollback on an error */
    1193          42 :                 svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
    1194          42 :                 break;
    1195             : 
    1196          42 :             case PQTRANS_IDLE:
    1197             :                 /* If they are no longer in a transaction, then do nothing */
    1198          42 :                 break;
    1199             : 
    1200          72 :             case PQTRANS_INTRANS:
    1201             : 
    1202             :                 /*
    1203             :                  * Release our savepoint, but do nothing if they are messing
    1204             :                  * with savepoints themselves
    1205             :                  */
    1206          72 :                 if (!svpt_gone)
    1207          66 :                     svptcmd = "RELEASE pg_psql_temporary_savepoint";
    1208          72 :                 break;
    1209             : 
    1210           0 :             case PQTRANS_ACTIVE:
    1211             :             case PQTRANS_UNKNOWN:
    1212             :             default:
    1213           0 :                 OK = false;
    1214             :                 /* PQTRANS_UNKNOWN is expected given a broken connection. */
    1215           0 :                 if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp())
    1216           0 :                     pg_log_error("unexpected transaction status (%d)",
    1217             :                                  transaction_status);
    1218           0 :                 break;
    1219             :         }
    1220             : 
    1221         156 :         if (svptcmd)
    1222             :         {
    1223             :             PGresult   *svptres;
    1224             : 
    1225         108 :             svptres = PQexec(pset.db, svptcmd);
    1226         108 :             if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
    1227             :             {
    1228           0 :                 pg_log_info("%s", PQerrorMessage(pset.db));
    1229           0 :                 ClearOrSaveResult(svptres);
    1230           0 :                 OK = false;
    1231             : 
    1232           0 :                 goto sendquery_cleanup;
    1233             :             }
    1234         108 :             PQclear(svptres);
    1235             :         }
    1236             :     }
    1237             : 
    1238             :     /* Possible microtiming output */
    1239      327602 :     if (timing)
    1240           4 :         PrintTiming(elapsed_msec);
    1241             : 
    1242             :     /* check for events that may occur during query execution */
    1243             : 
    1244      327606 :     if (pset.encoding != PQclientEncoding(pset.db) &&
    1245           4 :         PQclientEncoding(pset.db) >= 0)
    1246             :     {
    1247             :         /* track effects of SET CLIENT_ENCODING */
    1248           4 :         pset.encoding = PQclientEncoding(pset.db);
    1249           4 :         pset.popt.topt.encoding = pset.encoding;
    1250           4 :         SetVariable(pset.vars, "ENCODING",
    1251             :                     pg_encoding_to_char(pset.encoding));
    1252             :     }
    1253             : 
    1254      327602 :     PrintNotifications();
    1255             : 
    1256             :     /* perform cleanup that should occur after any attempted query */
    1257             : 
    1258      327602 : sendquery_cleanup:
    1259             : 
    1260             :     /* global cancellation reset */
    1261      327602 :     ResetCancelConn();
    1262             : 
    1263             :     /* reset \g's output-to-filename trigger */
    1264      327602 :     if (pset.gfname)
    1265             :     {
    1266          32 :         free(pset.gfname);
    1267          32 :         pset.gfname = NULL;
    1268             :     }
    1269             : 
    1270             :     /* restore print settings if \g changed them */
    1271      327602 :     if (pset.gsavepopt)
    1272             :     {
    1273          36 :         restorePsetInfo(&pset.popt, pset.gsavepopt);
    1274          36 :         pset.gsavepopt = NULL;
    1275             :     }
    1276             : 
    1277             :     /* clean up after extended protocol queries */
    1278      327602 :     clean_extended_state();
    1279             : 
    1280             :     /* reset \gset trigger */
    1281      327602 :     if (pset.gset_prefix)
    1282             :     {
    1283         672 :         free(pset.gset_prefix);
    1284         672 :         pset.gset_prefix = NULL;
    1285             :     }
    1286             : 
    1287             :     /* reset \gdesc trigger */
    1288      327602 :     pset.gdesc_flag = false;
    1289             : 
    1290             :     /* reset \gexec trigger */
    1291      327602 :     pset.gexec_flag = false;
    1292             : 
    1293             :     /* reset \crosstabview trigger */
    1294      327602 :     pset.crosstab_flag = false;
    1295     1638010 :     for (i = 0; i < lengthof(pset.ctv_args); i++)
    1296             :     {
    1297     1310408 :         pg_free(pset.ctv_args[i]);
    1298     1310408 :         pset.ctv_args[i] = NULL;
    1299             :     }
    1300             : 
    1301      327602 :     return OK;
    1302             : }
    1303             : 
    1304             : 
    1305             : /*
    1306             :  * DescribeQuery: describe the result columns of a query, without executing it
    1307             :  *
    1308             :  * Returns true if the operation executed successfully, false otherwise.
    1309             :  *
    1310             :  * If pset.timing is on, total query time (exclusive of result-printing) is
    1311             :  * stored into *elapsed_msec.
    1312             :  */
    1313             : static bool
    1314          68 : DescribeQuery(const char *query, double *elapsed_msec)
    1315             : {
    1316          68 :     bool        timing = pset.timing;
    1317             :     PGresult   *result;
    1318             :     bool        OK;
    1319             :     instr_time  before,
    1320             :                 after;
    1321             : 
    1322          68 :     *elapsed_msec = 0;
    1323             : 
    1324          68 :     if (timing)
    1325           0 :         INSTR_TIME_SET_CURRENT(before);
    1326             :     else
    1327          68 :         INSTR_TIME_SET_ZERO(before);
    1328             : 
    1329             :     /*
    1330             :      * To parse the query but not execute it, we prepare it, using the unnamed
    1331             :      * prepared statement.  This is invisible to psql users, since there's no
    1332             :      * way to access the unnamed prepared statement from psql user space. The
    1333             :      * next Parse or Query protocol message would overwrite the statement
    1334             :      * anyway.  (So there's no great need to clear it when done, which is a
    1335             :      * good thing because libpq provides no easy way to do that.)
    1336             :      */
    1337          68 :     result = PQprepare(pset.db, "", query, 0, NULL);
    1338          68 :     if (PQresultStatus(result) != PGRES_COMMAND_OK)
    1339             :     {
    1340          14 :         pg_log_info("%s", PQerrorMessage(pset.db));
    1341          14 :         SetResultVariables(result, false);
    1342          14 :         ClearOrSaveResult(result);
    1343          14 :         return false;
    1344             :     }
    1345          54 :     PQclear(result);
    1346             : 
    1347          54 :     result = PQdescribePrepared(pset.db, "");
    1348         108 :     OK = AcceptResult(result, true) &&
    1349          54 :         (PQresultStatus(result) == PGRES_COMMAND_OK);
    1350          54 :     if (OK && result)
    1351             :     {
    1352          54 :         if (PQnfields(result) > 0)
    1353             :         {
    1354             :             PQExpBufferData buf;
    1355             :             int         i;
    1356             : 
    1357          36 :             initPQExpBuffer(&buf);
    1358             : 
    1359          36 :             printfPQExpBuffer(&buf,
    1360             :                               "SELECT name AS \"%s\", pg_catalog.format_type(tp, tpm) AS \"%s\"\n"
    1361             :                               "FROM (VALUES ",
    1362             :                               gettext_noop("Column"),
    1363             :                               gettext_noop("Type"));
    1364             : 
    1365         162 :             for (i = 0; i < PQnfields(result); i++)
    1366             :             {
    1367             :                 const char *name;
    1368             :                 char       *escname;
    1369             : 
    1370         126 :                 if (i > 0)
    1371          90 :                     appendPQExpBufferStr(&buf, ",");
    1372             : 
    1373         126 :                 name = PQfname(result, i);
    1374         126 :                 escname = PQescapeLiteral(pset.db, name, strlen(name));
    1375             : 
    1376         126 :                 if (escname == NULL)
    1377             :                 {
    1378           0 :                     pg_log_info("%s", PQerrorMessage(pset.db));
    1379           0 :                     PQclear(result);
    1380           0 :                     termPQExpBuffer(&buf);
    1381           0 :                     return false;
    1382             :                 }
    1383             : 
    1384         126 :                 appendPQExpBuffer(&buf, "(%s, '%u'::pg_catalog.oid, %d)",
    1385             :                                   escname,
    1386             :                                   PQftype(result, i),
    1387             :                                   PQfmod(result, i));
    1388             : 
    1389         126 :                 PQfreemem(escname);
    1390             :             }
    1391             : 
    1392          36 :             appendPQExpBufferStr(&buf, ") s(name, tp, tpm)");
    1393          36 :             PQclear(result);
    1394             : 
    1395          36 :             result = PQexec(pset.db, buf.data);
    1396          36 :             OK = AcceptResult(result, true);
    1397             : 
    1398          36 :             if (timing)
    1399             :             {
    1400           0 :                 INSTR_TIME_SET_CURRENT(after);
    1401           0 :                 INSTR_TIME_SUBTRACT(after, before);
    1402           0 :                 *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
    1403             :             }
    1404             : 
    1405          36 :             if (OK && result)
    1406          36 :                 OK = PrintQueryResult(result, true, NULL, NULL, NULL);
    1407             : 
    1408          36 :             termPQExpBuffer(&buf);
    1409             :         }
    1410             :         else
    1411          18 :             fprintf(pset.queryFout,
    1412          18 :                     _("The command has no result, or the result has no columns.\n"));
    1413             :     }
    1414             : 
    1415          54 :     SetResultVariables(result, OK);
    1416          54 :     ClearOrSaveResult(result);
    1417             : 
    1418          54 :     return OK;
    1419             : }
    1420             : 
    1421             : 
    1422             : /*
    1423             :  * ExecQueryAndProcessResults: utility function for use by SendQuery()
    1424             :  * and PSQLexecWatch().
    1425             :  *
    1426             :  * Sends query and cycles through PGresult objects.
    1427             :  *
    1428             :  * If our command string contained a COPY FROM STDIN or COPY TO STDOUT, the
    1429             :  * PGresult associated with these commands must be processed by providing an
    1430             :  * input or output stream.  In that event, we'll marshal data for the COPY.
    1431             :  *
    1432             :  * For other commands, the results are processed normally, depending on their
    1433             :  * status.
    1434             :  *
    1435             :  * When invoked from \watch, is_watch is true and min_rows is the value
    1436             :  * of that option, or 0 if it wasn't set.
    1437             :  *
    1438             :  * Returns 1 on complete success, 0 on interrupt and -1 or errors.  Possible
    1439             :  * failure modes include purely client-side problems; check the transaction
    1440             :  * status for the server-side opinion.
    1441             :  *
    1442             :  * Note that on a combined query, failure does not mean that nothing was
    1443             :  * committed.
    1444             :  */
    1445             : static int
    1446      327590 : ExecQueryAndProcessResults(const char *query,
    1447             :                            double *elapsed_msec, bool *svpt_gone_p,
    1448             :                            bool is_watch, int min_rows,
    1449             :                            const printQueryOpt *opt, FILE *printQueryFout)
    1450             : {
    1451      327590 :     bool        timing = pset.timing;
    1452      327590 :     bool        success = false;
    1453      327590 :     bool        return_early = false;
    1454             :     instr_time  before,
    1455             :                 after;
    1456             :     PGresult   *result;
    1457      327590 :     FILE       *gfile_fout = NULL;
    1458      327590 :     bool        gfile_is_pipe = false;
    1459             : 
    1460      327590 :     if (timing)
    1461           4 :         INSTR_TIME_SET_CURRENT(before);
    1462             :     else
    1463      327586 :         INSTR_TIME_SET_ZERO(before);
    1464             : 
    1465      327590 :     switch (pset.send_mode)
    1466             :     {
    1467          18 :         case PSQL_SEND_EXTENDED_CLOSE:
    1468          18 :             success = PQsendClosePrepared(pset.db, pset.stmtName);
    1469          18 :             break;
    1470          30 :         case PSQL_SEND_EXTENDED_PARSE:
    1471          30 :             success = PQsendPrepare(pset.db, pset.stmtName, query, 0, NULL);
    1472          30 :             break;
    1473          58 :         case PSQL_SEND_EXTENDED_QUERY_PARAMS:
    1474             :             Assert(pset.stmtName == NULL);
    1475         116 :             success = PQsendQueryParams(pset.db, query,
    1476             :                                         pset.bind_nparams, NULL,
    1477          58 :                                         (const char *const *) pset.bind_params,
    1478             :                                         NULL, NULL, 0);
    1479          58 :             break;
    1480          66 :         case PSQL_SEND_EXTENDED_QUERY_PREPARED:
    1481             :             Assert(pset.stmtName != NULL);
    1482         132 :             success = PQsendQueryPrepared(pset.db, pset.stmtName,
    1483             :                                           pset.bind_nparams,
    1484          66 :                                           (const char *const *) pset.bind_params,
    1485             :                                           NULL, NULL, 0);
    1486          66 :             break;
    1487      327418 :         case PSQL_SEND_QUERY:
    1488      327418 :             success = PQsendQuery(pset.db, query);
    1489      327418 :             break;
    1490             :     }
    1491             : 
    1492      327590 :     if (!success)
    1493             :     {
    1494           0 :         const char *error = PQerrorMessage(pset.db);
    1495             : 
    1496           0 :         if (strlen(error))
    1497           0 :             pg_log_info("%s", error);
    1498             : 
    1499           0 :         CheckConnection();
    1500             : 
    1501           0 :         return -1;
    1502             :     }
    1503             : 
    1504             :     /*
    1505             :      * Fetch the result in chunks if FETCH_COUNT is set, except when:
    1506             :      *
    1507             :      * * SHOW_ALL_RESULTS is false, since that requires us to complete the
    1508             :      * query before we can tell if its results should be displayed.
    1509             :      *
    1510             :      * * We're doing \crosstab, which likewise needs to see all the rows at
    1511             :      * once.
    1512             :      *
    1513             :      * * We're doing \gexec: we must complete the data fetch to make the
    1514             :      * connection free for issuing the resulting commands.
    1515             :      *
    1516             :      * * We're doing \gset: only one result row is allowed anyway.
    1517             :      *
    1518             :      * * We're doing \watch: users probably don't want us to force use of the
    1519             :      * pager for that, plus chunking could break the min_rows check.
    1520             :      */
    1521      327590 :     if (pset.fetch_count > 0 && pset.show_all_results &&
    1522         110 :         !pset.crosstab_flag && !pset.gexec_flag &&
    1523         104 :         !pset.gset_prefix && !is_watch)
    1524             :     {
    1525          80 :         if (!PQsetChunkedRowsMode(pset.db, pset.fetch_count))
    1526           0 :             pg_log_warning("fetching results in chunked mode failed");
    1527             :     }
    1528             : 
    1529             :     /*
    1530             :      * If SIGINT is sent while the query is processing, the interrupt will be
    1531             :      * consumed.  The user's intention, though, is to cancel the entire watch
    1532             :      * process, so detect a sent cancellation request and exit in this case.
    1533             :      */
    1534      327590 :     if (is_watch && cancel_pressed)
    1535             :     {
    1536           0 :         ClearOrSaveAllResults();
    1537           0 :         return 0;
    1538             :     }
    1539             : 
    1540             :     /* first result */
    1541      327590 :     result = PQgetResult(pset.db);
    1542      327590 :     if (min_rows > 0 && PQntuples(result) < min_rows)
    1543             :     {
    1544           2 :         return_early = true;
    1545             :     }
    1546             : 
    1547      656766 :     while (result != NULL)
    1548             :     {
    1549             :         ExecStatusType result_status;
    1550      329198 :         bool        is_chunked_result = false;
    1551             :         PGresult   *next_result;
    1552             :         bool        last;
    1553             : 
    1554      329198 :         if (!AcceptResult(result, false))
    1555             :         {
    1556             :             /*
    1557             :              * Some error occurred, either a server-side failure or a failure
    1558             :              * to submit the command string.  Record that.
    1559             :              */
    1560       39634 :             const char *error = PQresultErrorMessage(result);
    1561             : 
    1562       39634 :             if (strlen(error))
    1563       39632 :                 pg_log_info("%s", error);
    1564             : 
    1565       39634 :             CheckConnection();
    1566       39612 :             if (!is_watch)
    1567       39610 :                 SetResultVariables(result, false);
    1568             : 
    1569             :             /* keep the result status before clearing it */
    1570       39612 :             result_status = PQresultStatus(result);
    1571       39612 :             ClearOrSaveResult(result);
    1572       39612 :             success = false;
    1573             : 
    1574             :             /*
    1575             :              * switch to next result
    1576             :              */
    1577       39612 :             if (result_status == PGRES_COPY_BOTH ||
    1578       39610 :                 result_status == PGRES_COPY_OUT ||
    1579             :                 result_status == PGRES_COPY_IN)
    1580             : 
    1581             :                 /*
    1582             :                  * For some obscure reason PQgetResult does *not* return a
    1583             :                  * NULL in copy cases despite the result having been cleared,
    1584             :                  * but keeps returning an "empty" result that we have to
    1585             :                  * ignore manually.
    1586             :                  */
    1587           2 :                 result = NULL;
    1588             :             else
    1589       39610 :                 result = PQgetResult(pset.db);
    1590             : 
    1591             :             /*
    1592             :              * Get current timing measure in case an error occurs
    1593             :              */
    1594       39612 :             if (timing)
    1595             :             {
    1596           2 :                 INSTR_TIME_SET_CURRENT(after);
    1597           2 :                 INSTR_TIME_SUBTRACT(after, before);
    1598           2 :                 *elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
    1599             :             }
    1600             : 
    1601       39612 :             continue;
    1602             :         }
    1603      289564 :         else if (svpt_gone_p && !*svpt_gone_p)
    1604             :         {
    1605             :             /*
    1606             :              * Check if the user ran any command that would destroy our
    1607             :              * internal savepoint: If the user did COMMIT AND CHAIN, RELEASE
    1608             :              * or ROLLBACK, our savepoint is gone. If they issued a SAVEPOINT,
    1609             :              * releasing ours would remove theirs.
    1610             :              */
    1611      289470 :             const char *cmd = PQcmdStatus(result);
    1612             : 
    1613      866790 :             *svpt_gone_p = (strcmp(cmd, "COMMIT") == 0 ||
    1614      287850 :                             strcmp(cmd, "SAVEPOINT") == 0 ||
    1615      863880 :                             strcmp(cmd, "RELEASE") == 0 ||
    1616      286560 :                             strcmp(cmd, "ROLLBACK") == 0);
    1617             :         }
    1618             : 
    1619      289564 :         result_status = PQresultStatus(result);
    1620             : 
    1621             :         /* must handle COPY before changing the current result */
    1622             :         Assert(result_status != PGRES_COPY_BOTH);
    1623      289564 :         if (result_status == PGRES_COPY_IN ||
    1624             :             result_status == PGRES_COPY_OUT)
    1625             :         {
    1626        1412 :             FILE       *copy_stream = NULL;
    1627             : 
    1628             :             /*
    1629             :              * For COPY OUT, direct the output to the default place (probably
    1630             :              * a pager pipe) for \watch, or to pset.copyStream for \copy,
    1631             :              * otherwise to pset.gfname if that's set, otherwise to
    1632             :              * pset.queryFout.
    1633             :              */
    1634        1412 :             if (result_status == PGRES_COPY_OUT)
    1635             :             {
    1636         522 :                 if (is_watch)
    1637             :                 {
    1638             :                     /* invoked by \watch */
    1639           0 :                     copy_stream = printQueryFout ? printQueryFout : pset.queryFout;
    1640             :                 }
    1641         522 :                 else if (pset.copyStream)
    1642             :                 {
    1643             :                     /* invoked by \copy */
    1644          54 :                     copy_stream = pset.copyStream;
    1645             :                 }
    1646         468 :                 else if (pset.gfname)
    1647             :                 {
    1648             :                     /* COPY followed by \g filename or \g |program */
    1649          26 :                     success &= SetupGOutput(&gfile_fout, &gfile_is_pipe);
    1650          26 :                     if (gfile_fout)
    1651          26 :                         copy_stream = gfile_fout;
    1652             :                 }
    1653             :                 else
    1654             :                 {
    1655             :                     /* fall back to the generic query output stream */
    1656         442 :                     copy_stream = pset.queryFout;
    1657             :                 }
    1658             :             }
    1659             : 
    1660             :             /*
    1661             :              * Even if the output stream could not be opened, we call
    1662             :              * HandleCopyResult() with a NULL output stream to collect and
    1663             :              * discard the COPY data.
    1664             :              */
    1665        1412 :             success &= HandleCopyResult(&result, copy_stream);
    1666             :         }
    1667             : 
    1668             :         /* If we have a chunked result, collect and print all chunks */
    1669      289564 :         if (result_status == PGRES_TUPLES_CHUNK)
    1670             :         {
    1671          54 :             FILE       *tuples_fout = printQueryFout ? printQueryFout : pset.queryFout;
    1672          54 :             printQueryOpt my_popt = opt ? *opt : pset.popt;
    1673          54 :             int64       total_tuples = 0;
    1674          54 :             bool        is_pager = false;
    1675          54 :             int         flush_error = 0;
    1676             : 
    1677             :             /* initialize print options for partial table output */
    1678          54 :             my_popt.topt.start_table = true;
    1679          54 :             my_popt.topt.stop_table = false;
    1680          54 :             my_popt.topt.prior_records = 0;
    1681             : 
    1682             :             /* open \g file if needed */
    1683          54 :             success &= SetupGOutput(&gfile_fout, &gfile_is_pipe);
    1684          54 :             if (gfile_fout)
    1685           0 :                 tuples_fout = gfile_fout;
    1686             : 
    1687             :             /* force use of pager for any chunked resultset going to stdout */
    1688          54 :             if (success && tuples_fout == stdout)
    1689             :             {
    1690          54 :                 tuples_fout = PageOutput(INT_MAX, &(my_popt.topt));
    1691          54 :                 is_pager = true;
    1692             :             }
    1693             : 
    1694             :             do
    1695             :             {
    1696             :                 /*
    1697             :                  * Display the current chunk of results, unless the output
    1698             :                  * stream stopped working or we got canceled.  We skip use of
    1699             :                  * PrintQueryResult and go directly to printQuery, so that we
    1700             :                  * can pass the correct is_pager value and because we don't
    1701             :                  * want PrintQueryStatus to happen yet.  Above, we rejected
    1702             :                  * use of chunking for all cases in which PrintQueryResult
    1703             :                  * would send the result to someplace other than printQuery.
    1704             :                  */
    1705          78 :                 if (success && !flush_error && !cancel_pressed)
    1706             :                 {
    1707          78 :                     printQuery(result, &my_popt, tuples_fout, is_pager, pset.logfile);
    1708          78 :                     flush_error = fflush(tuples_fout);
    1709             :                 }
    1710             : 
    1711             :                 /* after the first result set, disallow header decoration */
    1712          78 :                 my_popt.topt.start_table = false;
    1713             : 
    1714             :                 /* count tuples before dropping the result */
    1715          78 :                 my_popt.topt.prior_records += PQntuples(result);
    1716          78 :                 total_tuples += PQntuples(result);
    1717             : 
    1718          78 :                 ClearOrSaveResult(result);
    1719             : 
    1720             :                 /* get the next result, loop if it's PGRES_TUPLES_CHUNK */
    1721          78 :                 result = PQgetResult(pset.db);
    1722          78 :             } while (PQresultStatus(result) == PGRES_TUPLES_CHUNK);
    1723             : 
    1724             :             /* We expect an empty PGRES_TUPLES_OK, else there's a problem */
    1725          54 :             if (PQresultStatus(result) == PGRES_TUPLES_OK)
    1726             :             {
    1727             :                 char        buf[32];
    1728             : 
    1729             :                 Assert(PQntuples(result) == 0);
    1730             : 
    1731             :                 /* Display the footer using the empty result */
    1732          48 :                 if (success && !flush_error && !cancel_pressed)
    1733             :                 {
    1734          48 :                     my_popt.topt.stop_table = true;
    1735          48 :                     printQuery(result, &my_popt, tuples_fout, is_pager, pset.logfile);
    1736          48 :                     fflush(tuples_fout);
    1737             :                 }
    1738             : 
    1739          48 :                 if (is_pager)
    1740          48 :                     ClosePager(tuples_fout);
    1741             : 
    1742             :                 /*
    1743             :                  * It's possible the data is from a RETURNING clause, in which
    1744             :                  * case we need to print query status.
    1745             :                  */
    1746          48 :                 PrintQueryStatus(result, printQueryFout);
    1747             : 
    1748             :                 /*
    1749             :                  * We must do a fake SetResultVariables(), since we don't have
    1750             :                  * a PGresult corresponding to the whole query.
    1751             :                  */
    1752          48 :                 SetVariable(pset.vars, "ERROR", "false");
    1753          48 :                 SetVariable(pset.vars, "SQLSTATE", "00000");
    1754          48 :                 snprintf(buf, sizeof(buf), INT64_FORMAT, total_tuples);
    1755          48 :                 SetVariable(pset.vars, "ROW_COUNT", buf);
    1756             :                 /* Prevent SetResultVariables call below */
    1757          48 :                 is_chunked_result = true;
    1758             : 
    1759             :                 /* Clear the empty result so it isn't printed below */
    1760          48 :                 ClearOrSaveResult(result);
    1761          48 :                 result = NULL;
    1762             :             }
    1763             :             else
    1764             :             {
    1765             :                 /* Probably an error report, so close the pager and print it */
    1766           6 :                 if (is_pager)
    1767           6 :                     ClosePager(tuples_fout);
    1768             : 
    1769           6 :                 success &= AcceptResult(result, true);
    1770             :                 /* SetResultVariables and ClearOrSaveResult happen below */
    1771             :             }
    1772             :         }
    1773             : 
    1774             :         /*
    1775             :          * Check PQgetResult() again.  In the typical case of a single-command
    1776             :          * string, it will return NULL.  Otherwise, we'll have other results
    1777             :          * to process.  We need to do that to check whether this is the last.
    1778             :          */
    1779      289564 :         next_result = PQgetResult(pset.db);
    1780      289564 :         last = (next_result == NULL);
    1781             : 
    1782             :         /*
    1783             :          * Update current timing measure.
    1784             :          *
    1785             :          * It will include the display of previous results, if any. This
    1786             :          * cannot be helped because the server goes on processing further
    1787             :          * queries anyway while the previous ones are being displayed. The
    1788             :          * parallel execution of the client display hides the server time when
    1789             :          * it is shorter.
    1790             :          *
    1791             :          * With combined queries, timing must be understood as an upper bound
    1792             :          * of the time spent processing them.
    1793             :          */
    1794      289564 :         if (timing)
    1795             :         {
    1796           2 :             INSTR_TIME_SET_CURRENT(after);
    1797           2 :             INSTR_TIME_SUBTRACT(after, before);
    1798           2 :             *elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
    1799             :         }
    1800             : 
    1801             :         /* this may or may not print something depending on settings */
    1802      289564 :         if (result != NULL)
    1803             :         {
    1804             :             /*
    1805             :              * If results need to be printed into the file specified by \g,
    1806             :              * open it, unless we already did.  Note that when pset.gfname is
    1807             :              * set, the passed-in value of printQueryFout is not used for
    1808             :              * tuple output, but it's still used for status output.
    1809             :              */
    1810      289020 :             FILE       *tuples_fout = printQueryFout;
    1811             : 
    1812      289020 :             if (PQresultStatus(result) == PGRES_TUPLES_OK)
    1813      127962 :                 success &= SetupGOutput(&gfile_fout, &gfile_is_pipe);
    1814      289020 :             if (gfile_fout)
    1815          60 :                 tuples_fout = gfile_fout;
    1816      289020 :             if (success)
    1817      288816 :                 success &= PrintQueryResult(result, last, opt,
    1818             :                                             tuples_fout, printQueryFout);
    1819             :         }
    1820             : 
    1821             :         /* set variables from last result, unless dealt with elsewhere */
    1822      289564 :         if (last && !is_watch && !is_chunked_result)
    1823      287880 :             SetResultVariables(result, success);
    1824             : 
    1825      289564 :         ClearOrSaveResult(result);
    1826      289564 :         result = next_result;
    1827             : 
    1828      289564 :         if (cancel_pressed)
    1829             :         {
    1830             :             /* drop this next result, as well as any others not yet read */
    1831           0 :             ClearOrSaveResult(result);
    1832           0 :             ClearOrSaveAllResults();
    1833           0 :             break;
    1834             :         }
    1835             :     }
    1836             : 
    1837             :     /* close \g file if we opened it */
    1838      327568 :     CloseGOutput(gfile_fout, gfile_is_pipe);
    1839             : 
    1840             :     /* may need this to recover from conn loss during COPY */
    1841      327568 :     if (!CheckConnection())
    1842           0 :         return -1;
    1843             : 
    1844      327568 :     if (cancel_pressed || return_early)
    1845           4 :         return 0;
    1846             : 
    1847      327564 :     return success ? 1 : -1;
    1848             : }
    1849             : 
    1850             : 
    1851             : /*
    1852             :  * Advance the given char pointer over white space and SQL comments.
    1853             :  */
    1854             : static const char *
    1855         108 : skip_white_space(const char *query)
    1856             : {
    1857         108 :     int         cnestlevel = 0; /* slash-star comment nest level */
    1858             : 
    1859         132 :     while (*query)
    1860             :     {
    1861         132 :         int         mblen = PQmblenBounded(query, pset.encoding);
    1862             : 
    1863             :         /*
    1864             :          * Note: we assume the encoding is a superset of ASCII, so that for
    1865             :          * example "query[0] == '/'" is meaningful.  However, we do NOT assume
    1866             :          * that the second and subsequent bytes of a multibyte character
    1867             :          * couldn't look like ASCII characters; so it is critical to advance
    1868             :          * by mblen, not 1, whenever we haven't exactly identified the
    1869             :          * character we are skipping over.
    1870             :          */
    1871         132 :         if (isspace((unsigned char) *query))
    1872          24 :             query += mblen;
    1873         108 :         else if (query[0] == '/' && query[1] == '*')
    1874             :         {
    1875           0 :             cnestlevel++;
    1876           0 :             query += 2;
    1877             :         }
    1878         108 :         else if (cnestlevel > 0 && query[0] == '*' && query[1] == '/')
    1879             :         {
    1880           0 :             cnestlevel--;
    1881           0 :             query += 2;
    1882             :         }
    1883         108 :         else if (cnestlevel == 0 && query[0] == '-' && query[1] == '-')
    1884             :         {
    1885           0 :             query += 2;
    1886             : 
    1887             :             /*
    1888             :              * We have to skip to end of line since any slash-star inside the
    1889             :              * -- comment does NOT start a slash-star comment.
    1890             :              */
    1891           0 :             while (*query)
    1892             :             {
    1893           0 :                 if (*query == '\n')
    1894             :                 {
    1895           0 :                     query++;
    1896           0 :                     break;
    1897             :                 }
    1898           0 :                 query += PQmblenBounded(query, pset.encoding);
    1899             :             }
    1900             :         }
    1901         108 :         else if (cnestlevel > 0)
    1902           0 :             query += mblen;
    1903             :         else
    1904         108 :             break;              /* found first token */
    1905             :     }
    1906             : 
    1907         108 :     return query;
    1908             : }
    1909             : 
    1910             : 
    1911             : /*
    1912             :  * Check whether a command is one of those for which we should NOT start
    1913             :  * a new transaction block (ie, send a preceding BEGIN).
    1914             :  *
    1915             :  * These include the transaction control statements themselves, plus
    1916             :  * certain statements that the backend disallows inside transaction blocks.
    1917             :  */
    1918             : static bool
    1919          84 : command_no_begin(const char *query)
    1920             : {
    1921             :     int         wordlen;
    1922             : 
    1923             :     /*
    1924             :      * First we must advance over any whitespace and comments.
    1925             :      */
    1926          84 :     query = skip_white_space(query);
    1927             : 
    1928             :     /*
    1929             :      * Check word length (since "beginx" is not "begin").
    1930             :      */
    1931          84 :     wordlen = 0;
    1932         564 :     while (isalpha((unsigned char) query[wordlen]))
    1933         480 :         wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    1934             : 
    1935             :     /*
    1936             :      * Transaction control commands.  These should include every keyword that
    1937             :      * gives rise to a TransactionStmt in the backend grammar, except for the
    1938             :      * savepoint-related commands.
    1939             :      *
    1940             :      * (We assume that START must be START TRANSACTION, since there is
    1941             :      * presently no other "START foo" command.)
    1942             :      */
    1943          84 :     if (wordlen == 5 && pg_strncasecmp(query, "abort", 5) == 0)
    1944           0 :         return true;
    1945          84 :     if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0)
    1946          12 :         return true;
    1947          72 :     if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0)
    1948           0 :         return true;
    1949          72 :     if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0)
    1950           0 :         return true;
    1951          72 :     if (wordlen == 3 && pg_strncasecmp(query, "end", 3) == 0)
    1952           0 :         return true;
    1953          72 :     if (wordlen == 8 && pg_strncasecmp(query, "rollback", 8) == 0)
    1954           0 :         return true;
    1955          72 :     if (wordlen == 7 && pg_strncasecmp(query, "prepare", 7) == 0)
    1956             :     {
    1957             :         /* PREPARE TRANSACTION is a TC command, PREPARE foo is not */
    1958           0 :         query += wordlen;
    1959             : 
    1960           0 :         query = skip_white_space(query);
    1961             : 
    1962           0 :         wordlen = 0;
    1963           0 :         while (isalpha((unsigned char) query[wordlen]))
    1964           0 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    1965             : 
    1966           0 :         if (wordlen == 11 && pg_strncasecmp(query, "transaction", 11) == 0)
    1967           0 :             return true;
    1968           0 :         return false;
    1969             :     }
    1970             : 
    1971             :     /*
    1972             :      * Commands not allowed within transactions.  The statements checked for
    1973             :      * here should be exactly those that call PreventInTransactionBlock() in
    1974             :      * the backend.
    1975             :      */
    1976          72 :     if (wordlen == 6 && pg_strncasecmp(query, "vacuum", 6) == 0)
    1977           0 :         return true;
    1978          72 :     if (wordlen == 7 && pg_strncasecmp(query, "cluster", 7) == 0)
    1979             :     {
    1980             :         /* CLUSTER with any arguments is allowed in transactions */
    1981           0 :         query += wordlen;
    1982             : 
    1983           0 :         query = skip_white_space(query);
    1984             : 
    1985           0 :         if (isalpha((unsigned char) query[0]))
    1986           0 :             return false;       /* has additional words */
    1987           0 :         return true;            /* it's CLUSTER without arguments */
    1988             :     }
    1989             : 
    1990          72 :     if (wordlen == 6 && pg_strncasecmp(query, "create", 6) == 0)
    1991             :     {
    1992          12 :         query += wordlen;
    1993             : 
    1994          12 :         query = skip_white_space(query);
    1995             : 
    1996          12 :         wordlen = 0;
    1997          72 :         while (isalpha((unsigned char) query[wordlen]))
    1998          60 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    1999             : 
    2000          12 :         if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
    2001           0 :             return true;
    2002          12 :         if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
    2003           0 :             return true;
    2004             : 
    2005             :         /* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */
    2006          12 :         if (wordlen == 6 && pg_strncasecmp(query, "unique", 6) == 0)
    2007             :         {
    2008           0 :             query += wordlen;
    2009             : 
    2010           0 :             query = skip_white_space(query);
    2011             : 
    2012           0 :             wordlen = 0;
    2013           0 :             while (isalpha((unsigned char) query[wordlen]))
    2014           0 :                 wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2015             :         }
    2016             : 
    2017          12 :         if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
    2018             :         {
    2019           0 :             query += wordlen;
    2020             : 
    2021           0 :             query = skip_white_space(query);
    2022             : 
    2023           0 :             wordlen = 0;
    2024           0 :             while (isalpha((unsigned char) query[wordlen]))
    2025           0 :                 wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2026             : 
    2027           0 :             if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
    2028           0 :                 return true;
    2029             :         }
    2030             : 
    2031          12 :         return false;
    2032             :     }
    2033             : 
    2034          60 :     if (wordlen == 5 && pg_strncasecmp(query, "alter", 5) == 0)
    2035             :     {
    2036           0 :         query += wordlen;
    2037             : 
    2038           0 :         query = skip_white_space(query);
    2039             : 
    2040           0 :         wordlen = 0;
    2041           0 :         while (isalpha((unsigned char) query[wordlen]))
    2042           0 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2043             : 
    2044             :         /* ALTER SYSTEM isn't allowed in xacts */
    2045           0 :         if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
    2046           0 :             return true;
    2047             : 
    2048           0 :         return false;
    2049             :     }
    2050             : 
    2051             :     /*
    2052             :      * Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which
    2053             :      * aren't really valid commands so we don't care much. The other four
    2054             :      * possible matches are correct.
    2055             :      */
    2056          60 :     if ((wordlen == 4 && pg_strncasecmp(query, "drop", 4) == 0) ||
    2057           0 :         (wordlen == 7 && pg_strncasecmp(query, "reindex", 7) == 0))
    2058             :     {
    2059           6 :         query += wordlen;
    2060             : 
    2061           6 :         query = skip_white_space(query);
    2062             : 
    2063           6 :         wordlen = 0;
    2064          36 :         while (isalpha((unsigned char) query[wordlen]))
    2065          30 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2066             : 
    2067           6 :         if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
    2068           0 :             return true;
    2069           6 :         if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
    2070           0 :             return true;
    2071           6 :         if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
    2072           0 :             return true;
    2073          12 :         if (wordlen == 5 && (pg_strncasecmp(query, "index", 5) == 0 ||
    2074           6 :                              pg_strncasecmp(query, "table", 5) == 0))
    2075             :         {
    2076           6 :             query += wordlen;
    2077           6 :             query = skip_white_space(query);
    2078           6 :             wordlen = 0;
    2079          24 :             while (isalpha((unsigned char) query[wordlen]))
    2080          18 :                 wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2081             : 
    2082             :             /*
    2083             :              * REINDEX [ TABLE | INDEX ] CONCURRENTLY are not allowed in
    2084             :              * xacts.
    2085             :              */
    2086           6 :             if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
    2087           0 :                 return true;
    2088             :         }
    2089             : 
    2090             :         /* DROP INDEX CONCURRENTLY isn't allowed in xacts */
    2091           6 :         if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
    2092             :         {
    2093           0 :             query += wordlen;
    2094             : 
    2095           0 :             query = skip_white_space(query);
    2096             : 
    2097           0 :             wordlen = 0;
    2098           0 :             while (isalpha((unsigned char) query[wordlen]))
    2099           0 :                 wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2100             : 
    2101           0 :             if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
    2102           0 :                 return true;
    2103             : 
    2104           0 :             return false;
    2105             :         }
    2106             : 
    2107           6 :         return false;
    2108             :     }
    2109             : 
    2110             :     /* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */
    2111          54 :     if (wordlen == 7 && pg_strncasecmp(query, "discard", 7) == 0)
    2112             :     {
    2113           0 :         query += wordlen;
    2114             : 
    2115           0 :         query = skip_white_space(query);
    2116             : 
    2117           0 :         wordlen = 0;
    2118           0 :         while (isalpha((unsigned char) query[wordlen]))
    2119           0 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2120             : 
    2121           0 :         if (wordlen == 3 && pg_strncasecmp(query, "all", 3) == 0)
    2122           0 :             return true;
    2123           0 :         return false;
    2124             :     }
    2125             : 
    2126          54 :     return false;
    2127             : }
    2128             : 
    2129             : 
    2130             : /*
    2131             :  * Test if the current user is a database superuser.
    2132             :  */
    2133             : bool
    2134         108 : is_superuser(void)
    2135             : {
    2136             :     const char *val;
    2137             : 
    2138         108 :     if (!pset.db)
    2139           0 :         return false;
    2140             : 
    2141         108 :     val = PQparameterStatus(pset.db, "is_superuser");
    2142             : 
    2143         108 :     if (val && strcmp(val, "on") == 0)
    2144         108 :         return true;
    2145             : 
    2146           0 :     return false;
    2147             : }
    2148             : 
    2149             : 
    2150             : /*
    2151             :  * Test if the current session uses standard string literals.
    2152             :  */
    2153             : bool
    2154      626420 : standard_strings(void)
    2155             : {
    2156             :     const char *val;
    2157             : 
    2158      626420 :     if (!pset.db)
    2159           0 :         return false;
    2160             : 
    2161      626420 :     val = PQparameterStatus(pset.db, "standard_conforming_strings");
    2162             : 
    2163      626420 :     if (val && strcmp(val, "on") == 0)
    2164      626228 :         return true;
    2165             : 
    2166         192 :     return false;
    2167             : }
    2168             : 
    2169             : 
    2170             : /*
    2171             :  * Return the session user of the current connection.
    2172             :  */
    2173             : const char *
    2174           0 : session_username(void)
    2175             : {
    2176             :     const char *val;
    2177             : 
    2178           0 :     if (!pset.db)
    2179           0 :         return NULL;
    2180             : 
    2181           0 :     val = PQparameterStatus(pset.db, "session_authorization");
    2182           0 :     if (val)
    2183           0 :         return val;
    2184             :     else
    2185           0 :         return PQuser(pset.db);
    2186             : }
    2187             : 
    2188             : 
    2189             : /* expand_tilde
    2190             :  *
    2191             :  * substitute '~' with HOME or '~username' with username's home dir
    2192             :  *
    2193             :  */
    2194             : void
    2195         184 : expand_tilde(char **filename)
    2196             : {
    2197         184 :     if (!filename || !(*filename))
    2198          18 :         return;
    2199             : 
    2200             :     /*
    2201             :      * WIN32 doesn't use tilde expansion for file names. Also, it uses tilde
    2202             :      * for short versions of long file names, though the tilde is usually
    2203             :      * toward the end, not at the beginning.
    2204             :      */
    2205             : #ifndef WIN32
    2206             : 
    2207             :     /* try tilde expansion */
    2208         166 :     if (**filename == '~')
    2209             :     {
    2210             :         char       *fn;
    2211             :         char        oldp,
    2212             :                    *p;
    2213             :         struct passwd *pw;
    2214             :         char        home[MAXPGPATH];
    2215             : 
    2216           0 :         fn = *filename;
    2217           0 :         *home = '\0';
    2218             : 
    2219           0 :         p = fn + 1;
    2220           0 :         while (*p != '/' && *p != '\0')
    2221           0 :             p++;
    2222             : 
    2223           0 :         oldp = *p;
    2224           0 :         *p = '\0';
    2225             : 
    2226           0 :         if (*(fn + 1) == '\0')
    2227           0 :             get_home_path(home);    /* ~ or ~/ only */
    2228           0 :         else if ((pw = getpwnam(fn + 1)) != NULL)
    2229           0 :             strlcpy(home, pw->pw_dir, sizeof(home)); /* ~user */
    2230             : 
    2231           0 :         *p = oldp;
    2232           0 :         if (strlen(home) != 0)
    2233             :         {
    2234             :             char       *newfn;
    2235             : 
    2236           0 :             newfn = psprintf("%s%s", home, p);
    2237           0 :             free(fn);
    2238           0 :             *filename = newfn;
    2239             :         }
    2240             :     }
    2241             : #endif
    2242             : }
    2243             : 
    2244             : /*
    2245             :  * Checks if connection string starts with either of the valid URI prefix
    2246             :  * designators.
    2247             :  *
    2248             :  * Returns the URI prefix length, 0 if the string doesn't contain a URI prefix.
    2249             :  *
    2250             :  * XXX This is a duplicate of the eponymous libpq function.
    2251             :  */
    2252             : static int
    2253          28 : uri_prefix_length(const char *connstr)
    2254             : {
    2255             :     /* The connection URI must start with either of the following designators: */
    2256             :     static const char uri_designator[] = "postgresql://";
    2257             :     static const char short_uri_designator[] = "postgres://";
    2258             : 
    2259          28 :     if (strncmp(connstr, uri_designator,
    2260             :                 sizeof(uri_designator) - 1) == 0)
    2261           0 :         return sizeof(uri_designator) - 1;
    2262             : 
    2263          28 :     if (strncmp(connstr, short_uri_designator,
    2264             :                 sizeof(short_uri_designator) - 1) == 0)
    2265           0 :         return sizeof(short_uri_designator) - 1;
    2266             : 
    2267          28 :     return 0;
    2268             : }
    2269             : 
    2270             : /*
    2271             :  * Reset state related to extended query protocol
    2272             :  *
    2273             :  * Clean up any state related to bind parameters, statement name and
    2274             :  * PSQL_SEND_MODE.  This needs to be called after processing a query or when
    2275             :  * running a new meta-command that uses the extended query protocol, like
    2276             :  * \parse, \bind, etc.
    2277             :  */
    2278             : void
    2279      327816 : clean_extended_state(void)
    2280             : {
    2281             :     int         i;
    2282             : 
    2283      327816 :     switch (pset.send_mode)
    2284             :     {
    2285          18 :         case PSQL_SEND_EXTENDED_CLOSE:  /* \close */
    2286          18 :             free(pset.stmtName);
    2287          18 :             break;
    2288          30 :         case PSQL_SEND_EXTENDED_PARSE:  /* \parse */
    2289          30 :             free(pset.stmtName);
    2290          30 :             break;
    2291         142 :         case PSQL_SEND_EXTENDED_QUERY_PARAMS:   /* \bind */
    2292             :         case PSQL_SEND_EXTENDED_QUERY_PREPARED: /* \bind_named */
    2293         282 :             for (i = 0; i < pset.bind_nparams; i++)
    2294         140 :                 free(pset.bind_params[i]);
    2295         142 :             free(pset.bind_params);
    2296         142 :             free(pset.stmtName);
    2297         142 :             pset.bind_params = NULL;
    2298         142 :             break;
    2299      327626 :         case PSQL_SEND_QUERY:
    2300      327626 :             break;
    2301             :     }
    2302             : 
    2303      327816 :     pset.stmtName = NULL;
    2304      327816 :     pset.send_mode = PSQL_SEND_QUERY;
    2305      327816 : }
    2306             : 
    2307             : /*
    2308             :  * Recognized connection string either starts with a valid URI prefix or
    2309             :  * contains a "=" in it.
    2310             :  *
    2311             :  * Must be consistent with parse_connection_string: anything for which this
    2312             :  * returns true should at least look like it's parseable by that routine.
    2313             :  *
    2314             :  * XXX This is a duplicate of the eponymous libpq function.
    2315             :  */
    2316             : bool
    2317          28 : recognized_connection_string(const char *connstr)
    2318             : {
    2319          28 :     return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
    2320             : }

Generated by: LCOV version 1.14