LCOV - code coverage report
Current view: top level - src/bin/psql - common.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 593 831 71.4 %
Date: 2024-04-28 13:11:40 Functions: 34 36 94.4 %
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       14358 : openQueryOutputFile(const char *fname, FILE **fout, bool *is_pipe)
      57             : {
      58       14358 :     if (!fname || fname[0] == '\0')
      59             :     {
      60       14314 :         *fout = stdout;
      61       14314 :         *is_pipe = false;
      62             :     }
      63          44 :     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          36 :         *fout = fopen(fname, "w");
      72          36 :         *is_pipe = false;
      73             :     }
      74             : 
      75       14358 :     if (*fout == NULL)
      76             :     {
      77           0 :         pg_log_error("%s: %m", fname);
      78           0 :         return false;
      79             :     }
      80             : 
      81       14358 :     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      122468 : 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      122468 :     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      122468 :     return true;
     104             : }
     105             : 
     106             : /*
     107             :  * Close the output stream for \g, if we opened it.
     108             :  */
     109             : static void
     110      318764 : CloseGOutput(FILE *gfile_fout, bool is_pipe)
     111             : {
     112      318764 :     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      318764 : }
     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       14326 : 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       14326 :     if (!openQueryOutputFile(fname, &fout, &is_pipe))
     139           0 :         return false;
     140             : 
     141             :     /* Close old file/pipe */
     142       14326 :     if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
     143             :     {
     144          12 :         if (pset.queryFoutPipe)
     145           0 :             SetShellResultVariables(pclose(pset.queryFout));
     146             :         else
     147          12 :             fclose(pset.queryFout);
     148             :     }
     149             : 
     150       14326 :     pset.queryFout = fout;
     151       14326 :     pset.queryFoutPipe = is_pipe;
     152             : 
     153             :     /* Adjust SIGPIPE handling appropriately: ignore signal if is_pipe */
     154       14326 :     set_sigpipe_trap_state(is_pipe);
     155       14326 :     restore_sigpipe_trap();
     156             : 
     157       14326 :     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        3552 : psql_get_variable(const char *varname, PsqlScanQuoteType quote,
     177             :                   void *passthrough)
     178             : {
     179        3552 :     char       *result = NULL;
     180             :     const char *value;
     181             : 
     182             :     /* In an inactive \if branch, suppress all variable substitutions */
     183        3552 :     if (passthrough && !conditional_active((ConditionalStack) passthrough))
     184          72 :         return NULL;
     185             : 
     186        3480 :     value = GetVariable(pset.vars, varname);
     187        3480 :     if (!value)
     188         452 :         return NULL;
     189             : 
     190        3028 :     switch (quote)
     191             :     {
     192        2250 :         case PQUOTE_PLAIN:
     193        2250 :             result = pg_strdup(value);
     194        2250 :             break;
     195         778 :         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         778 :                 if (!pset.db)
     205             :                 {
     206           0 :                     pg_log_error("cannot escape without active connection");
     207           0 :                     return NULL;
     208             :                 }
     209             : 
     210         778 :                 if (quote == PQUOTE_SQL_LITERAL)
     211             :                     escaped_value =
     212         752 :                         PQescapeLiteral(pset.db, value, strlen(value));
     213             :                 else
     214             :                     escaped_value =
     215          26 :                         PQescapeIdentifier(pset.db, value, strlen(value));
     216             : 
     217         778 :                 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         778 :                 result = pg_strdup(escaped_value);
     231         778 :                 PQfreemem(escaped_value);
     232         778 :                 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        3028 :     return result;
     260             : }
     261             : 
     262             : 
     263             : /*
     264             :  * for backend Notice messages (INFO, WARNING, etc)
     265             :  */
     266             : void
     267       20538 : NoticeProcessor(void *arg, const char *message)
     268             : {
     269             :     (void) arg;                 /* not used */
     270       20538 :     pg_log_info("%s", message);
     271       20538 : }
     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       14322 : psql_setup_cancel_handler(void)
     314             : {
     315       14322 :     setup_cancel_handler(psql_cancel_callback);
     316       14322 : }
     317             : 
     318             : 
     319             : /* ConnectionUp
     320             :  *
     321             :  * Returns whether our backend connection is still there.
     322             :  */
     323             : static bool
     324      357224 : ConnectionUp(void)
     325             : {
     326      357224 :     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      357224 : CheckConnection(void)
     343             : {
     344             :     bool        OK;
     345             : 
     346      357224 :     OK = ConnectionUp();
     347      357224 :     if (!OK)
     348             :     {
     349          20 :         if (!pset.cur_cmd_interactive)
     350             :         {
     351          20 :             pg_log_error("connection to server was lost");
     352          20 :             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      357204 :     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      353780 : AcceptResult(const PGresult *result, bool show_error)
     404             : {
     405             :     bool        OK;
     406             : 
     407      353780 :     if (!result)
     408           0 :         OK = false;
     409             :     else
     410      353780 :         switch (PQresultStatus(result))
     411             :         {
     412      315320 :             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      315320 :                 OK = true;
     420      315320 :                 break;
     421             : 
     422       38458 :             case PGRES_BAD_RESPONSE:
     423             :             case PGRES_NONFATAL_ERROR:
     424             :             case PGRES_FATAL_ERROR:
     425       38458 :                 OK = false;
     426       38458 :                 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      353780 :     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      353780 :     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      318780 : SetResultVariables(PGresult *result, bool success)
     462             : {
     463      318780 :     if (success)
     464             :     {
     465      280048 :         const char *ntuples = PQcmdTuples(result);
     466             : 
     467      280048 :         SetVariable(pset.vars, "ERROR", "false");
     468      280048 :         SetVariable(pset.vars, "SQLSTATE", "00000");
     469      280048 :         SetVariable(pset.vars, "ROW_COUNT", *ntuples ? ntuples : "0");
     470             :     }
     471             :     else
     472             :     {
     473       38732 :         const char *code = PQresultErrorField(result, PG_DIAG_SQLSTATE);
     474       38732 :         const char *mesg = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
     475             : 
     476       38732 :         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       38732 :         if (code == NULL)
     483         102 :             code = "";
     484       38732 :         SetVariable(pset.vars, "SQLSTATE", code);
     485       38732 :         SetVariable(pset.vars, "ROW_COUNT", "0");
     486       38732 :         SetVariable(pset.vars, "LAST_ERROR_SQLSTATE", code);
     487       38732 :         SetVariable(pset.vars, "LAST_ERROR_MESSAGE", mesg ? mesg : "");
     488             :     }
     489      318780 : }
     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      320706 : ClearOrSaveResult(PGresult *result)
     524             : {
     525      320706 :     if (result)
     526             :     {
     527      320186 :         switch (PQresultStatus(result))
     528             :         {
     529       38632 :             case PGRES_NONFATAL_ERROR:
     530             :             case PGRES_FATAL_ERROR:
     531       38632 :                 PQclear(pset.last_error_result);
     532       38632 :                 pset.last_error_result = result;
     533       38632 :                 break;
     534             : 
     535      281554 :             default:
     536      281554 :                 PQclear(result);
     537      281554 :                 break;
     538             :         }
     539         520 :     }
     540      320706 : }
     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       33380 : PSQLexec(const char *query)
     621             : {
     622             :     PGresult   *res;
     623             : 
     624       33380 :     if (!pset.db)
     625             :     {
     626           0 :         pg_log_error("You are currently not connected to a database.");
     627           0 :         return NULL;
     628             :     }
     629             : 
     630       33380 :     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       33380 :     SetCancelConn(pset.db);
     650             : 
     651       33380 :     res = PQexec(pset.db, query);
     652             : 
     653       33380 :     ResetCancelConn();
     654             : 
     655       33380 :     if (!AcceptResult(res, true))
     656             :     {
     657           0 :         ClearOrSaveResult(res);
     658           0 :         res = NULL;
     659             :     }
     660             : 
     661       33380 :     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           8 : PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout, int min_rows)
     676             : {
     677           8 :     bool        timing = pset.timing;
     678           8 :     double      elapsed_msec = 0;
     679             :     int         res;
     680             : 
     681           8 :     if (!pset.db)
     682             :     {
     683           0 :         pg_log_error("You are currently not connected to a database.");
     684           0 :         return 0;
     685             :     }
     686             : 
     687           8 :     SetCancelConn(pset.db);
     688             : 
     689           8 :     res = ExecQueryAndProcessResults(query, &elapsed_msec, NULL, true, min_rows, opt, printQueryFout);
     690             : 
     691           8 :     ResetCancelConn();
     692             : 
     693             :     /* Possible microtiming output */
     694           8 :     if (timing)
     695           0 :         PrintTiming(elapsed_msec);
     696             : 
     697           8 :     return res;
     698             : }
     699             : 
     700             : 
     701             : /*
     702             :  * PrintNotifications: check for asynchronous notifications, and print them out
     703             :  */
     704             : static void
     705      318824 : PrintNotifications(void)
     706             : {
     707             :     PGnotify   *notify;
     708             : 
     709      318824 :     PQconsumeInput(pset.db);
     710      318828 :     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      318824 : }
     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      121588 : PrintQueryTuples(const PGresult *result, const printQueryOpt *opt,
     739             :                  FILE *printQueryFout)
     740             : {
     741      121588 :     bool        ok = true;
     742      121588 :     FILE       *fout = printQueryFout ? printQueryFout : pset.queryFout;
     743             : 
     744      121588 :     printQuery(result, opt ? opt : &pset.popt, fout, false, pset.logfile);
     745      121588 :     fflush(fout);
     746      121588 :     if (ferror(fout))
     747             :     {
     748           0 :         pg_log_error("could not print result table: %m");
     749           0 :         ok = false;
     750             :     }
     751             : 
     752      121588 :     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         646 : StoreQueryTuple(const PGresult *result)
     763             : {
     764         646 :     bool        success = true;
     765             : 
     766         646 :     if (PQntuples(result) < 1)
     767             :     {
     768          18 :         pg_log_error("no rows returned for \\gset");
     769          18 :         success = false;
     770             :     }
     771         628 :     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        1376 :         for (i = 0; i < PQnfields(result); i++)
     781             :         {
     782         766 :             char       *colname = PQfname(result, i);
     783             :             char       *varname;
     784             :             char       *value;
     785             : 
     786             :             /* concatenate prefix and column name */
     787         766 :             varname = psprintf("%s%s", pset.gset_prefix, colname);
     788             : 
     789         766 :             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         760 :             if (!PQgetisnull(result, 0, i))
     797         748 :                 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         760 :             if (!SetVariable(pset.vars, varname, value))
     805             :             {
     806           6 :                 free(varname);
     807           6 :                 success = false;
     808           6 :                 break;
     809             :             }
     810             : 
     811         754 :             free(varname);
     812             :         }
     813             :     }
     814             : 
     815         646 :     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          44 : ExecQueryTuples(const PGresult *result)
     827             : {
     828          44 :     bool        success = true;
     829          44 :     int         nrows = PQntuples(result);
     830          44 :     int         ncolumns = PQnfields(result);
     831             :     int         r,
     832             :                 c;
     833             : 
     834             :     /*
     835             :      * We must turn off gexec_flag to avoid infinite recursion.
     836             :      */
     837          44 :     pset.gexec_flag = false;
     838             : 
     839         468 :     for (r = 0; r < nrows; r++)
     840             :     {
     841         866 :         for (c = 0; c < ncolumns; c++)
     842             :         {
     843         442 :             if (!PQgetisnull(result, r, c))
     844             :             {
     845         436 :                 const char *query = PQgetvalue(result, r, c);
     846             : 
     847             :                 /* Abandon execution if cancel_pressed */
     848         436 :                 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         436 :                 if (pset.echo == PSQL_ECHO_ALL && !pset.singlestep)
     856             :                 {
     857         430 :                     puts(query);
     858         430 :                     fflush(stdout);
     859             :                 }
     860             : 
     861         436 :                 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          44 : 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          44 :     pset.gexec_flag = true;
     880             : 
     881             :     /* Return true if all queries were successful */
     882          44 :     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        1358 : HandleCopyResult(PGresult **resultp, FILE *copystream)
     903             : {
     904             :     bool        success;
     905             :     PGresult   *copy_result;
     906        1358 :     ExecStatusType result_status = PQresultStatus(*resultp);
     907             : 
     908             :     Assert(result_status == PGRES_COPY_OUT ||
     909             :            result_status == PGRES_COPY_IN);
     910             : 
     911        1358 :     SetCancelConn(pset.db);
     912             : 
     913        1358 :     if (result_status == PGRES_COPY_OUT)
     914             :     {
     915         498 :         success = handleCopyOut(pset.db,
     916             :                                 copystream,
     917             :                                 &copy_result)
     918         498 :             && (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         498 :         if (copystream == pset.queryFout)
     926             :         {
     927         472 :             PQclear(copy_result);
     928         472 :             copy_result = NULL;
     929             :         }
     930             :     }
     931             :     else
     932             :     {
     933             :         /* COPY IN */
     934             :         /* Ignore the copystream argument passed to the function */
     935         860 :         copystream = pset.copyStream ? pset.copyStream : pset.cur_cmd_source;
     936         860 :         success = handleCopyIn(pset.db,
     937             :                                copystream,
     938         860 :                                PQbinaryTuples(*resultp),
     939             :                                &copy_result);
     940             :     }
     941        1358 :     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        1358 :     PQclear(*resultp);
     948        1358 :     *resultp = copy_result;
     949             : 
     950        1358 :     return success;
     951             : }
     952             : 
     953             : /*
     954             :  * PrintQueryStatus: report command status as required
     955             :  */
     956             : static void
     957      281102 : PrintQueryStatus(PGresult *result, FILE *printQueryFout)
     958             : {
     959             :     char        buf[16];
     960      281102 :     const char *cmdstatus = PQcmdStatus(result);
     961      281102 :     FILE       *fout = printQueryFout ? printQueryFout : pset.queryFout;
     962             : 
     963             :     /* Do nothing if it's a TUPLES_OK result that isn't from RETURNING */
     964      281102 :     if (PQresultStatus(result) == PGRES_TUPLES_OK)
     965             :     {
     966      122458 :         if (!(strncmp(cmdstatus, "INSERT", 6) == 0 ||
     967      122034 :               strncmp(cmdstatus, "UPDATE", 6) == 0 ||
     968      121630 :               strncmp(cmdstatus, "DELETE", 6) == 0 ||
     969      121448 :               strncmp(cmdstatus, "MERGE", 5) == 0))
     970      121376 :             return;
     971             :     }
     972             : 
     973      159726 :     if (!pset.quiet)
     974             :     {
     975         832 :         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         832 :             fprintf(fout, "%s\n", cmdstatus);
     983         832 :         fflush(fout);
     984             :     }
     985             : 
     986      159726 :     if (pset.logfile)
     987           0 :         fprintf(pset.logfile, "%s\n", cmdstatus);
     988             : 
     989      159726 :     snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(result));
     990      159726 :     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      281180 : PrintQueryResult(PGresult *result, bool last,
    1005             :                  const printQueryOpt *opt, FILE *printQueryFout,
    1006             :                  FILE *printStatusFout)
    1007             : {
    1008             :     bool        success;
    1009             : 
    1010      281180 :     if (!result)
    1011           0 :         return false;
    1012             : 
    1013      281180 :     switch (PQresultStatus(result))
    1014             :     {
    1015      122424 :         case PGRES_TUPLES_OK:
    1016             :             /* store or execute or print the data ... */
    1017      122424 :             if (last && pset.gset_prefix)
    1018         646 :                 success = StoreQueryTuple(result);
    1019      121778 :             else if (last && pset.gexec_flag)
    1020          44 :                 success = ExecQueryTuples(result);
    1021      121734 :             else if (last && pset.crosstab_flag)
    1022         132 :                 success = PrintResultInCrosstab(result);
    1023      121602 :             else if (last || pset.show_all_results)
    1024      121588 :                 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      122424 :             if (last || pset.show_all_results)
    1033      122410 :                 PrintQueryStatus(result, printStatusFout);
    1034             : 
    1035      122424 :             break;
    1036             : 
    1037      158644 :         case PGRES_COMMAND_OK:
    1038      158644 :             if (last || pset.show_all_results)
    1039      158644 :                 PrintQueryStatus(result, printStatusFout);
    1040      158644 :             success = true;
    1041      158644 :             break;
    1042             : 
    1043         112 :         case PGRES_EMPTY_QUERY:
    1044         112 :             success = true;
    1045         112 :             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      281180 :     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      318844 : SendQuery(const char *query)
    1083             : {
    1084      318844 :     bool        timing = pset.timing;
    1085             :     PGTransactionStatusType transaction_status;
    1086      318844 :     double      elapsed_msec = 0;
    1087      318844 :     bool        OK = false;
    1088             :     int         i;
    1089      318844 :     bool        on_error_rollback_savepoint = false;
    1090      318844 :     bool        svpt_gone = false;
    1091             : 
    1092      318844 :     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      318844 :     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      318844 :     else if (pset.echo == PSQL_ECHO_QUERIES)
    1115             :     {
    1116          30 :         puts(query);
    1117          30 :         fflush(stdout);
    1118             :     }
    1119             : 
    1120      318844 :     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      318844 :     SetCancelConn(pset.db);
    1130             : 
    1131      318844 :     transaction_status = PQtransactionStatus(pset.db);
    1132             : 
    1133      318844 :     if (transaction_status == PQTRANS_IDLE &&
    1134      291612 :         !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      318844 :     if (transaction_status == PQTRANS_INTRANS &&
    1151       26238 :         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      318844 :     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      318776 :         OK = (ExecQueryAndProcessResults(query, &elapsed_msec, &svpt_gone, false, 0, NULL, NULL) > 0);
    1177             :     }
    1178             : 
    1179      318824 :     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      318824 :     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      318824 :     if (timing)
    1240           4 :         PrintTiming(elapsed_msec);
    1241             : 
    1242             :     /* check for events that may occur during query execution */
    1243             : 
    1244      318828 :     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      318824 :     PrintNotifications();
    1255             : 
    1256             :     /* perform cleanup that should occur after any attempted query */
    1257             : 
    1258      318824 : sendquery_cleanup:
    1259             : 
    1260             :     /* global cancellation reset */
    1261      318824 :     ResetCancelConn();
    1262             : 
    1263             :     /* reset \g's output-to-filename trigger */
    1264      318824 :     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      318824 :     if (pset.gsavepopt)
    1272             :     {
    1273          36 :         restorePsetInfo(&pset.popt, pset.gsavepopt);
    1274          36 :         pset.gsavepopt = NULL;
    1275             :     }
    1276             : 
    1277             :     /* clean up after \bind */
    1278      318824 :     if (pset.bind_flag)
    1279             :     {
    1280          60 :         for (i = 0; i < pset.bind_nparams; i++)
    1281          24 :             free(pset.bind_params[i]);
    1282          36 :         free(pset.bind_params);
    1283          36 :         pset.bind_params = NULL;
    1284          36 :         pset.bind_flag = false;
    1285             :     }
    1286             : 
    1287             :     /* reset \gset trigger */
    1288      318824 :     if (pset.gset_prefix)
    1289             :     {
    1290         646 :         free(pset.gset_prefix);
    1291         646 :         pset.gset_prefix = NULL;
    1292             :     }
    1293             : 
    1294             :     /* reset \gdesc trigger */
    1295      318824 :     pset.gdesc_flag = false;
    1296             : 
    1297             :     /* reset \gexec trigger */
    1298      318824 :     pset.gexec_flag = false;
    1299             : 
    1300             :     /* reset \crosstabview trigger */
    1301      318824 :     pset.crosstab_flag = false;
    1302     1594120 :     for (i = 0; i < lengthof(pset.ctv_args); i++)
    1303             :     {
    1304     1275296 :         pg_free(pset.ctv_args[i]);
    1305     1275296 :         pset.ctv_args[i] = NULL;
    1306             :     }
    1307             : 
    1308      318824 :     return OK;
    1309             : }
    1310             : 
    1311             : 
    1312             : /*
    1313             :  * DescribeQuery: describe the result columns of a query, without executing it
    1314             :  *
    1315             :  * Returns true if the operation executed successfully, false otherwise.
    1316             :  *
    1317             :  * If pset.timing is on, total query time (exclusive of result-printing) is
    1318             :  * stored into *elapsed_msec.
    1319             :  */
    1320             : static bool
    1321          68 : DescribeQuery(const char *query, double *elapsed_msec)
    1322             : {
    1323          68 :     bool        timing = pset.timing;
    1324             :     PGresult   *result;
    1325             :     bool        OK;
    1326             :     instr_time  before,
    1327             :                 after;
    1328             : 
    1329          68 :     *elapsed_msec = 0;
    1330             : 
    1331          68 :     if (timing)
    1332           0 :         INSTR_TIME_SET_CURRENT(before);
    1333             :     else
    1334          68 :         INSTR_TIME_SET_ZERO(before);
    1335             : 
    1336             :     /*
    1337             :      * To parse the query but not execute it, we prepare it, using the unnamed
    1338             :      * prepared statement.  This is invisible to psql users, since there's no
    1339             :      * way to access the unnamed prepared statement from psql user space. The
    1340             :      * next Parse or Query protocol message would overwrite the statement
    1341             :      * anyway.  (So there's no great need to clear it when done, which is a
    1342             :      * good thing because libpq provides no easy way to do that.)
    1343             :      */
    1344          68 :     result = PQprepare(pset.db, "", query, 0, NULL);
    1345          68 :     if (PQresultStatus(result) != PGRES_COMMAND_OK)
    1346             :     {
    1347          14 :         pg_log_info("%s", PQerrorMessage(pset.db));
    1348          14 :         SetResultVariables(result, false);
    1349          14 :         ClearOrSaveResult(result);
    1350          14 :         return false;
    1351             :     }
    1352          54 :     PQclear(result);
    1353             : 
    1354          54 :     result = PQdescribePrepared(pset.db, "");
    1355         108 :     OK = AcceptResult(result, true) &&
    1356          54 :         (PQresultStatus(result) == PGRES_COMMAND_OK);
    1357          54 :     if (OK && result)
    1358             :     {
    1359          54 :         if (PQnfields(result) > 0)
    1360             :         {
    1361             :             PQExpBufferData buf;
    1362             :             int         i;
    1363             : 
    1364          36 :             initPQExpBuffer(&buf);
    1365             : 
    1366          36 :             printfPQExpBuffer(&buf,
    1367             :                               "SELECT name AS \"%s\", pg_catalog.format_type(tp, tpm) AS \"%s\"\n"
    1368             :                               "FROM (VALUES ",
    1369             :                               gettext_noop("Column"),
    1370             :                               gettext_noop("Type"));
    1371             : 
    1372         162 :             for (i = 0; i < PQnfields(result); i++)
    1373             :             {
    1374             :                 const char *name;
    1375             :                 char       *escname;
    1376             : 
    1377         126 :                 if (i > 0)
    1378          90 :                     appendPQExpBufferStr(&buf, ",");
    1379             : 
    1380         126 :                 name = PQfname(result, i);
    1381         126 :                 escname = PQescapeLiteral(pset.db, name, strlen(name));
    1382             : 
    1383         126 :                 if (escname == NULL)
    1384             :                 {
    1385           0 :                     pg_log_info("%s", PQerrorMessage(pset.db));
    1386           0 :                     PQclear(result);
    1387           0 :                     termPQExpBuffer(&buf);
    1388           0 :                     return false;
    1389             :                 }
    1390             : 
    1391         126 :                 appendPQExpBuffer(&buf, "(%s, '%u'::pg_catalog.oid, %d)",
    1392             :                                   escname,
    1393             :                                   PQftype(result, i),
    1394             :                                   PQfmod(result, i));
    1395             : 
    1396         126 :                 PQfreemem(escname);
    1397             :             }
    1398             : 
    1399          36 :             appendPQExpBufferStr(&buf, ") s(name, tp, tpm)");
    1400          36 :             PQclear(result);
    1401             : 
    1402          36 :             result = PQexec(pset.db, buf.data);
    1403          36 :             OK = AcceptResult(result, true);
    1404             : 
    1405          36 :             if (timing)
    1406             :             {
    1407           0 :                 INSTR_TIME_SET_CURRENT(after);
    1408           0 :                 INSTR_TIME_SUBTRACT(after, before);
    1409           0 :                 *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
    1410             :             }
    1411             : 
    1412          36 :             if (OK && result)
    1413          36 :                 OK = PrintQueryResult(result, true, NULL, NULL, NULL);
    1414             : 
    1415          36 :             termPQExpBuffer(&buf);
    1416             :         }
    1417             :         else
    1418          18 :             fprintf(pset.queryFout,
    1419          18 :                     _("The command has no result, or the result has no columns.\n"));
    1420             :     }
    1421             : 
    1422          54 :     SetResultVariables(result, OK);
    1423          54 :     ClearOrSaveResult(result);
    1424             : 
    1425          54 :     return OK;
    1426             : }
    1427             : 
    1428             : 
    1429             : /*
    1430             :  * ExecQueryAndProcessResults: utility function for use by SendQuery()
    1431             :  * and PSQLexecWatch().
    1432             :  *
    1433             :  * Sends query and cycles through PGresult objects.
    1434             :  *
    1435             :  * If our command string contained a COPY FROM STDIN or COPY TO STDOUT, the
    1436             :  * PGresult associated with these commands must be processed by providing an
    1437             :  * input or output stream.  In that event, we'll marshal data for the COPY.
    1438             :  *
    1439             :  * For other commands, the results are processed normally, depending on their
    1440             :  * status.
    1441             :  *
    1442             :  * When invoked from \watch, is_watch is true and min_rows is the value
    1443             :  * of that option, or 0 if it wasn't set.
    1444             :  *
    1445             :  * Returns 1 on complete success, 0 on interrupt and -1 or errors.  Possible
    1446             :  * failure modes include purely client-side problems; check the transaction
    1447             :  * status for the server-side opinion.
    1448             :  *
    1449             :  * Note that on a combined query, failure does not mean that nothing was
    1450             :  * committed.
    1451             :  */
    1452             : static int
    1453      318784 : ExecQueryAndProcessResults(const char *query,
    1454             :                            double *elapsed_msec, bool *svpt_gone_p,
    1455             :                            bool is_watch, int min_rows,
    1456             :                            const printQueryOpt *opt, FILE *printQueryFout)
    1457             : {
    1458      318784 :     bool        timing = pset.timing;
    1459             :     bool        success;
    1460      318784 :     bool        return_early = false;
    1461             :     instr_time  before,
    1462             :                 after;
    1463             :     PGresult   *result;
    1464      318784 :     FILE       *gfile_fout = NULL;
    1465      318784 :     bool        gfile_is_pipe = false;
    1466             : 
    1467      318784 :     if (timing)
    1468           4 :         INSTR_TIME_SET_CURRENT(before);
    1469             :     else
    1470      318780 :         INSTR_TIME_SET_ZERO(before);
    1471             : 
    1472      318784 :     if (pset.bind_flag)
    1473          36 :         success = PQsendQueryParams(pset.db, query, pset.bind_nparams, NULL, (const char *const *) pset.bind_params, NULL, NULL, 0);
    1474             :     else
    1475      318748 :         success = PQsendQuery(pset.db, query);
    1476             : 
    1477      318784 :     if (!success)
    1478             :     {
    1479           0 :         const char *error = PQerrorMessage(pset.db);
    1480             : 
    1481           0 :         if (strlen(error))
    1482           0 :             pg_log_info("%s", error);
    1483             : 
    1484           0 :         CheckConnection();
    1485             : 
    1486           0 :         return -1;
    1487             :     }
    1488             : 
    1489             :     /*
    1490             :      * Fetch the result in chunks if FETCH_COUNT is set, except when:
    1491             :      *
    1492             :      * * SHOW_ALL_RESULTS is false, since that requires us to complete the
    1493             :      * query before we can tell if its results should be displayed.
    1494             :      *
    1495             :      * * We're doing \crosstab, which likewise needs to see all the rows at
    1496             :      * once.
    1497             :      *
    1498             :      * * We're doing \gexec: we must complete the data fetch to make the
    1499             :      * connection free for issuing the resulting commands.
    1500             :      *
    1501             :      * * We're doing \gset: only one result row is allowed anyway.
    1502             :      *
    1503             :      * * We're doing \watch: users probably don't want us to force use of the
    1504             :      * pager for that, plus chunking could break the min_rows check.
    1505             :      */
    1506      318784 :     if (pset.fetch_count > 0 && pset.show_all_results &&
    1507         110 :         !pset.crosstab_flag && !pset.gexec_flag &&
    1508         104 :         !pset.gset_prefix && !is_watch)
    1509             :     {
    1510          80 :         if (!PQsetChunkedRowsMode(pset.db, pset.fetch_count))
    1511           0 :             pg_log_warning("fetching results in chunked mode failed");
    1512             :     }
    1513             : 
    1514             :     /*
    1515             :      * If SIGINT is sent while the query is processing, the interrupt will be
    1516             :      * consumed.  The user's intention, though, is to cancel the entire watch
    1517             :      * process, so detect a sent cancellation request and exit in this case.
    1518             :      */
    1519      318784 :     if (is_watch && cancel_pressed)
    1520             :     {
    1521           0 :         ClearOrSaveAllResults();
    1522           0 :         return 0;
    1523             :     }
    1524             : 
    1525             :     /* first result */
    1526      318784 :     result = PQgetResult(pset.db);
    1527      318784 :     if (min_rows > 0 && PQntuples(result) < min_rows)
    1528             :     {
    1529           2 :         return_early = true;
    1530             :     }
    1531             : 
    1532      639068 :     while (result != NULL)
    1533             :     {
    1534             :         ExecStatusType result_status;
    1535      320304 :         bool        is_chunked_result = false;
    1536             :         PGresult   *next_result;
    1537             :         bool        last;
    1538             : 
    1539      320304 :         if (!AcceptResult(result, false))
    1540             :         {
    1541             :             /*
    1542             :              * Some error occurred, either a server-side failure or a failure
    1543             :              * to submit the command string.  Record that.
    1544             :              */
    1545       38454 :             const char *error = PQresultErrorMessage(result);
    1546             : 
    1547       38454 :             if (strlen(error))
    1548       38452 :                 pg_log_info("%s", error);
    1549             : 
    1550       38454 :             CheckConnection();
    1551       38434 :             if (!is_watch)
    1552       38434 :                 SetResultVariables(result, false);
    1553             : 
    1554             :             /* keep the result status before clearing it */
    1555       38434 :             result_status = PQresultStatus(result);
    1556       38434 :             ClearOrSaveResult(result);
    1557       38434 :             success = false;
    1558             : 
    1559             :             /*
    1560             :              * switch to next result
    1561             :              */
    1562       38434 :             if (result_status == PGRES_COPY_BOTH ||
    1563       38432 :                 result_status == PGRES_COPY_OUT ||
    1564             :                 result_status == PGRES_COPY_IN)
    1565             : 
    1566             :                 /*
    1567             :                  * For some obscure reason PQgetResult does *not* return a
    1568             :                  * NULL in copy cases despite the result having been cleared,
    1569             :                  * but keeps returning an "empty" result that we have to
    1570             :                  * ignore manually.
    1571             :                  */
    1572           2 :                 result = NULL;
    1573             :             else
    1574       38432 :                 result = PQgetResult(pset.db);
    1575             : 
    1576             :             /*
    1577             :              * Get current timing measure in case an error occurs
    1578             :              */
    1579       38434 :             if (timing)
    1580             :             {
    1581           2 :                 INSTR_TIME_SET_CURRENT(after);
    1582           2 :                 INSTR_TIME_SUBTRACT(after, before);
    1583           2 :                 *elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
    1584             :             }
    1585             : 
    1586       38434 :             continue;
    1587             :         }
    1588      281850 :         else if (svpt_gone_p && !*svpt_gone_p)
    1589             :         {
    1590             :             /*
    1591             :              * Check if the user ran any command that would destroy our
    1592             :              * internal savepoint: If the user did COMMIT AND CHAIN, RELEASE
    1593             :              * or ROLLBACK, our savepoint is gone. If they issued a SAVEPOINT,
    1594             :              * releasing ours would remove theirs.
    1595             :              */
    1596      281782 :             const char *cmd = PQcmdStatus(result);
    1597             : 
    1598      843774 :             *svpt_gone_p = (strcmp(cmd, "COMMIT") == 0 ||
    1599      280210 :                             strcmp(cmd, "SAVEPOINT") == 0 ||
    1600      840916 :                             strcmp(cmd, "RELEASE") == 0 ||
    1601      278924 :                             strcmp(cmd, "ROLLBACK") == 0);
    1602             :         }
    1603             : 
    1604      281850 :         result_status = PQresultStatus(result);
    1605             : 
    1606             :         /* must handle COPY before changing the current result */
    1607             :         Assert(result_status != PGRES_COPY_BOTH);
    1608      281850 :         if (result_status == PGRES_COPY_IN ||
    1609             :             result_status == PGRES_COPY_OUT)
    1610             :         {
    1611        1358 :             FILE       *copy_stream = NULL;
    1612             : 
    1613             :             /*
    1614             :              * For COPY OUT, direct the output to the default place (probably
    1615             :              * a pager pipe) for \watch, or to pset.copyStream for \copy,
    1616             :              * otherwise to pset.gfname if that's set, otherwise to
    1617             :              * pset.queryFout.
    1618             :              */
    1619        1358 :             if (result_status == PGRES_COPY_OUT)
    1620             :             {
    1621         498 :                 if (is_watch)
    1622             :                 {
    1623             :                     /* invoked by \watch */
    1624           0 :                     copy_stream = printQueryFout ? printQueryFout : pset.queryFout;
    1625             :                 }
    1626         498 :                 else if (pset.copyStream)
    1627             :                 {
    1628             :                     /* invoked by \copy */
    1629          54 :                     copy_stream = pset.copyStream;
    1630             :                 }
    1631         444 :                 else if (pset.gfname)
    1632             :                 {
    1633             :                     /* COPY followed by \g filename or \g |program */
    1634          26 :                     success &= SetupGOutput(&gfile_fout, &gfile_is_pipe);
    1635          26 :                     if (gfile_fout)
    1636          26 :                         copy_stream = gfile_fout;
    1637             :                 }
    1638             :                 else
    1639             :                 {
    1640             :                     /* fall back to the generic query output stream */
    1641         418 :                     copy_stream = pset.queryFout;
    1642             :                 }
    1643             :             }
    1644             : 
    1645             :             /*
    1646             :              * Even if the output stream could not be opened, we call
    1647             :              * HandleCopyResult() with a NULL output stream to collect and
    1648             :              * discard the COPY data.
    1649             :              */
    1650        1358 :             success &= HandleCopyResult(&result, copy_stream);
    1651             :         }
    1652             : 
    1653             :         /* If we have a chunked result, collect and print all chunks */
    1654      281850 :         if (result_status == PGRES_TUPLES_CHUNK)
    1655             :         {
    1656          54 :             FILE       *tuples_fout = printQueryFout ? printQueryFout : pset.queryFout;
    1657          54 :             printQueryOpt my_popt = opt ? *opt : pset.popt;
    1658          54 :             int64       total_tuples = 0;
    1659          54 :             bool        is_pager = false;
    1660          54 :             int         flush_error = 0;
    1661             : 
    1662             :             /* initialize print options for partial table output */
    1663          54 :             my_popt.topt.start_table = true;
    1664          54 :             my_popt.topt.stop_table = false;
    1665          54 :             my_popt.topt.prior_records = 0;
    1666             : 
    1667             :             /* open \g file if needed */
    1668          54 :             success &= SetupGOutput(&gfile_fout, &gfile_is_pipe);
    1669          54 :             if (gfile_fout)
    1670           0 :                 tuples_fout = gfile_fout;
    1671             : 
    1672             :             /* force use of pager for any chunked resultset going to stdout */
    1673          54 :             if (success && tuples_fout == stdout)
    1674             :             {
    1675          54 :                 tuples_fout = PageOutput(INT_MAX, &(my_popt.topt));
    1676          54 :                 is_pager = true;
    1677             :             }
    1678             : 
    1679             :             do
    1680             :             {
    1681             :                 /*
    1682             :                  * Display the current chunk of results, unless the output
    1683             :                  * stream stopped working or we got cancelled.  We skip use of
    1684             :                  * PrintQueryResult and go directly to printQuery, so that we
    1685             :                  * can pass the correct is_pager value and because we don't
    1686             :                  * want PrintQueryStatus to happen yet.  Above, we rejected
    1687             :                  * use of chunking for all cases in which PrintQueryResult
    1688             :                  * would send the result to someplace other than printQuery.
    1689             :                  */
    1690          78 :                 if (success && !flush_error && !cancel_pressed)
    1691             :                 {
    1692          78 :                     printQuery(result, &my_popt, tuples_fout, is_pager, pset.logfile);
    1693          78 :                     flush_error = fflush(tuples_fout);
    1694             :                 }
    1695             : 
    1696             :                 /* after the first result set, disallow header decoration */
    1697          78 :                 my_popt.topt.start_table = false;
    1698             : 
    1699             :                 /* count tuples before dropping the result */
    1700          78 :                 my_popt.topt.prior_records += PQntuples(result);
    1701          78 :                 total_tuples += PQntuples(result);
    1702             : 
    1703          78 :                 ClearOrSaveResult(result);
    1704             : 
    1705             :                 /* get the next result, loop if it's PGRES_TUPLES_CHUNK */
    1706          78 :                 result = PQgetResult(pset.db);
    1707          78 :             } while (PQresultStatus(result) == PGRES_TUPLES_CHUNK);
    1708             : 
    1709             :             /* We expect an empty PGRES_TUPLES_OK, else there's a problem */
    1710          54 :             if (PQresultStatus(result) == PGRES_TUPLES_OK)
    1711             :             {
    1712             :                 char        buf[32];
    1713             : 
    1714             :                 Assert(PQntuples(result) == 0);
    1715             : 
    1716             :                 /* Display the footer using the empty result */
    1717          48 :                 if (success && !flush_error && !cancel_pressed)
    1718             :                 {
    1719          48 :                     my_popt.topt.stop_table = true;
    1720          48 :                     printQuery(result, &my_popt, tuples_fout, is_pager, pset.logfile);
    1721          48 :                     fflush(tuples_fout);
    1722             :                 }
    1723             : 
    1724          48 :                 if (is_pager)
    1725          48 :                     ClosePager(tuples_fout);
    1726             : 
    1727             :                 /*
    1728             :                  * It's possible the data is from a RETURNING clause, in which
    1729             :                  * case we need to print query status.
    1730             :                  */
    1731          48 :                 PrintQueryStatus(result, printQueryFout);
    1732             : 
    1733             :                 /*
    1734             :                  * We must do a fake SetResultVariables(), since we don't have
    1735             :                  * a PGresult corresponding to the whole query.
    1736             :                  */
    1737          48 :                 SetVariable(pset.vars, "ERROR", "false");
    1738          48 :                 SetVariable(pset.vars, "SQLSTATE", "00000");
    1739          48 :                 snprintf(buf, sizeof(buf), INT64_FORMAT, total_tuples);
    1740          48 :                 SetVariable(pset.vars, "ROW_COUNT", buf);
    1741             :                 /* Prevent SetResultVariables call below */
    1742          48 :                 is_chunked_result = true;
    1743             : 
    1744             :                 /* Clear the empty result so it isn't printed below */
    1745          48 :                 ClearOrSaveResult(result);
    1746          48 :                 result = NULL;
    1747             :             }
    1748             :             else
    1749             :             {
    1750             :                 /* Probably an error report, so close the pager and print it */
    1751           6 :                 if (is_pager)
    1752           6 :                     ClosePager(tuples_fout);
    1753             : 
    1754           6 :                 success &= AcceptResult(result, true);
    1755             :                 /* SetResultVariables and ClearOrSaveResult happen below */
    1756             :             }
    1757             :         }
    1758             : 
    1759             :         /*
    1760             :          * Check PQgetResult() again.  In the typical case of a single-command
    1761             :          * string, it will return NULL.  Otherwise, we'll have other results
    1762             :          * to process.  We need to do that to check whether this is the last.
    1763             :          */
    1764      281850 :         next_result = PQgetResult(pset.db);
    1765      281850 :         last = (next_result == NULL);
    1766             : 
    1767             :         /*
    1768             :          * Update current timing measure.
    1769             :          *
    1770             :          * It will include the display of previous results, if any. This
    1771             :          * cannot be helped because the server goes on processing further
    1772             :          * queries anyway while the previous ones are being displayed. The
    1773             :          * parallel execution of the client display hides the server time when
    1774             :          * it is shorter.
    1775             :          *
    1776             :          * With combined queries, timing must be understood as an upper bound
    1777             :          * of the time spent processing them.
    1778             :          */
    1779      281850 :         if (timing)
    1780             :         {
    1781           2 :             INSTR_TIME_SET_CURRENT(after);
    1782           2 :             INSTR_TIME_SUBTRACT(after, before);
    1783           2 :             *elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
    1784             :         }
    1785             : 
    1786             :         /* this may or may not print something depending on settings */
    1787      281850 :         if (result != NULL)
    1788             :         {
    1789             :             /*
    1790             :              * If results need to be printed into the file specified by \g,
    1791             :              * open it, unless we already did.  Note that when pset.gfname is
    1792             :              * set, the passed-in value of printQueryFout is not used for
    1793             :              * tuple output, but it's still used for status output.
    1794             :              */
    1795      281330 :             FILE       *tuples_fout = printQueryFout;
    1796             : 
    1797      281330 :             if (PQresultStatus(result) == PGRES_TUPLES_OK)
    1798      122388 :                 success &= SetupGOutput(&gfile_fout, &gfile_is_pipe);
    1799      281330 :             if (gfile_fout)
    1800          60 :                 tuples_fout = gfile_fout;
    1801      281330 :             if (success)
    1802      281144 :                 success &= PrintQueryResult(result, last, opt,
    1803             :                                             tuples_fout, printQueryFout);
    1804             :         }
    1805             : 
    1806             :         /* set variables from last result, unless dealt with elsewhere */
    1807      281850 :         if (last && !is_watch && !is_chunked_result)
    1808      280278 :             SetResultVariables(result, success);
    1809             : 
    1810      281850 :         ClearOrSaveResult(result);
    1811      281850 :         result = next_result;
    1812             : 
    1813      281850 :         if (cancel_pressed)
    1814             :         {
    1815             :             /* drop this next result, as well as any others not yet read */
    1816           0 :             ClearOrSaveResult(result);
    1817           0 :             ClearOrSaveAllResults();
    1818           0 :             break;
    1819             :         }
    1820             :     }
    1821             : 
    1822             :     /* close \g file if we opened it */
    1823      318764 :     CloseGOutput(gfile_fout, gfile_is_pipe);
    1824             : 
    1825             :     /* may need this to recover from conn loss during COPY */
    1826      318764 :     if (!CheckConnection())
    1827           0 :         return -1;
    1828             : 
    1829      318764 :     if (cancel_pressed || return_early)
    1830           4 :         return 0;
    1831             : 
    1832      318760 :     return success ? 1 : -1;
    1833             : }
    1834             : 
    1835             : 
    1836             : /*
    1837             :  * Advance the given char pointer over white space and SQL comments.
    1838             :  */
    1839             : static const char *
    1840         108 : skip_white_space(const char *query)
    1841             : {
    1842         108 :     int         cnestlevel = 0; /* slash-star comment nest level */
    1843             : 
    1844         132 :     while (*query)
    1845             :     {
    1846         132 :         int         mblen = PQmblenBounded(query, pset.encoding);
    1847             : 
    1848             :         /*
    1849             :          * Note: we assume the encoding is a superset of ASCII, so that for
    1850             :          * example "query[0] == '/'" is meaningful.  However, we do NOT assume
    1851             :          * that the second and subsequent bytes of a multibyte character
    1852             :          * couldn't look like ASCII characters; so it is critical to advance
    1853             :          * by mblen, not 1, whenever we haven't exactly identified the
    1854             :          * character we are skipping over.
    1855             :          */
    1856         132 :         if (isspace((unsigned char) *query))
    1857          24 :             query += mblen;
    1858         108 :         else if (query[0] == '/' && query[1] == '*')
    1859             :         {
    1860           0 :             cnestlevel++;
    1861           0 :             query += 2;
    1862             :         }
    1863         108 :         else if (cnestlevel > 0 && query[0] == '*' && query[1] == '/')
    1864             :         {
    1865           0 :             cnestlevel--;
    1866           0 :             query += 2;
    1867             :         }
    1868         108 :         else if (cnestlevel == 0 && query[0] == '-' && query[1] == '-')
    1869             :         {
    1870           0 :             query += 2;
    1871             : 
    1872             :             /*
    1873             :              * We have to skip to end of line since any slash-star inside the
    1874             :              * -- comment does NOT start a slash-star comment.
    1875             :              */
    1876           0 :             while (*query)
    1877             :             {
    1878           0 :                 if (*query == '\n')
    1879             :                 {
    1880           0 :                     query++;
    1881           0 :                     break;
    1882             :                 }
    1883           0 :                 query += PQmblenBounded(query, pset.encoding);
    1884             :             }
    1885             :         }
    1886         108 :         else if (cnestlevel > 0)
    1887           0 :             query += mblen;
    1888             :         else
    1889         108 :             break;              /* found first token */
    1890             :     }
    1891             : 
    1892         108 :     return query;
    1893             : }
    1894             : 
    1895             : 
    1896             : /*
    1897             :  * Check whether a command is one of those for which we should NOT start
    1898             :  * a new transaction block (ie, send a preceding BEGIN).
    1899             :  *
    1900             :  * These include the transaction control statements themselves, plus
    1901             :  * certain statements that the backend disallows inside transaction blocks.
    1902             :  */
    1903             : static bool
    1904          84 : command_no_begin(const char *query)
    1905             : {
    1906             :     int         wordlen;
    1907             : 
    1908             :     /*
    1909             :      * First we must advance over any whitespace and comments.
    1910             :      */
    1911          84 :     query = skip_white_space(query);
    1912             : 
    1913             :     /*
    1914             :      * Check word length (since "beginx" is not "begin").
    1915             :      */
    1916          84 :     wordlen = 0;
    1917         564 :     while (isalpha((unsigned char) query[wordlen]))
    1918         480 :         wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    1919             : 
    1920             :     /*
    1921             :      * Transaction control commands.  These should include every keyword that
    1922             :      * gives rise to a TransactionStmt in the backend grammar, except for the
    1923             :      * savepoint-related commands.
    1924             :      *
    1925             :      * (We assume that START must be START TRANSACTION, since there is
    1926             :      * presently no other "START foo" command.)
    1927             :      */
    1928          84 :     if (wordlen == 5 && pg_strncasecmp(query, "abort", 5) == 0)
    1929           0 :         return true;
    1930          84 :     if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0)
    1931          12 :         return true;
    1932          72 :     if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0)
    1933           0 :         return true;
    1934          72 :     if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0)
    1935           0 :         return true;
    1936          72 :     if (wordlen == 3 && pg_strncasecmp(query, "end", 3) == 0)
    1937           0 :         return true;
    1938          72 :     if (wordlen == 8 && pg_strncasecmp(query, "rollback", 8) == 0)
    1939           0 :         return true;
    1940          72 :     if (wordlen == 7 && pg_strncasecmp(query, "prepare", 7) == 0)
    1941             :     {
    1942             :         /* PREPARE TRANSACTION is a TC command, PREPARE foo is not */
    1943           0 :         query += wordlen;
    1944             : 
    1945           0 :         query = skip_white_space(query);
    1946             : 
    1947           0 :         wordlen = 0;
    1948           0 :         while (isalpha((unsigned char) query[wordlen]))
    1949           0 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    1950             : 
    1951           0 :         if (wordlen == 11 && pg_strncasecmp(query, "transaction", 11) == 0)
    1952           0 :             return true;
    1953           0 :         return false;
    1954             :     }
    1955             : 
    1956             :     /*
    1957             :      * Commands not allowed within transactions.  The statements checked for
    1958             :      * here should be exactly those that call PreventInTransactionBlock() in
    1959             :      * the backend.
    1960             :      */
    1961          72 :     if (wordlen == 6 && pg_strncasecmp(query, "vacuum", 6) == 0)
    1962           0 :         return true;
    1963          72 :     if (wordlen == 7 && pg_strncasecmp(query, "cluster", 7) == 0)
    1964             :     {
    1965             :         /* CLUSTER with any arguments is allowed in transactions */
    1966           0 :         query += wordlen;
    1967             : 
    1968           0 :         query = skip_white_space(query);
    1969             : 
    1970           0 :         if (isalpha((unsigned char) query[0]))
    1971           0 :             return false;       /* has additional words */
    1972           0 :         return true;            /* it's CLUSTER without arguments */
    1973             :     }
    1974             : 
    1975          72 :     if (wordlen == 6 && pg_strncasecmp(query, "create", 6) == 0)
    1976             :     {
    1977          12 :         query += wordlen;
    1978             : 
    1979          12 :         query = skip_white_space(query);
    1980             : 
    1981          12 :         wordlen = 0;
    1982          72 :         while (isalpha((unsigned char) query[wordlen]))
    1983          60 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    1984             : 
    1985          12 :         if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
    1986           0 :             return true;
    1987          12 :         if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
    1988           0 :             return true;
    1989             : 
    1990             :         /* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */
    1991          12 :         if (wordlen == 6 && pg_strncasecmp(query, "unique", 6) == 0)
    1992             :         {
    1993           0 :             query += wordlen;
    1994             : 
    1995           0 :             query = skip_white_space(query);
    1996             : 
    1997           0 :             wordlen = 0;
    1998           0 :             while (isalpha((unsigned char) query[wordlen]))
    1999           0 :                 wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2000             :         }
    2001             : 
    2002          12 :         if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
    2003             :         {
    2004           0 :             query += wordlen;
    2005             : 
    2006           0 :             query = skip_white_space(query);
    2007             : 
    2008           0 :             wordlen = 0;
    2009           0 :             while (isalpha((unsigned char) query[wordlen]))
    2010           0 :                 wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2011             : 
    2012           0 :             if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
    2013           0 :                 return true;
    2014             :         }
    2015             : 
    2016          12 :         return false;
    2017             :     }
    2018             : 
    2019          60 :     if (wordlen == 5 && pg_strncasecmp(query, "alter", 5) == 0)
    2020             :     {
    2021           0 :         query += wordlen;
    2022             : 
    2023           0 :         query = skip_white_space(query);
    2024             : 
    2025           0 :         wordlen = 0;
    2026           0 :         while (isalpha((unsigned char) query[wordlen]))
    2027           0 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2028             : 
    2029             :         /* ALTER SYSTEM isn't allowed in xacts */
    2030           0 :         if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
    2031           0 :             return true;
    2032             : 
    2033           0 :         return false;
    2034             :     }
    2035             : 
    2036             :     /*
    2037             :      * Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which
    2038             :      * aren't really valid commands so we don't care much. The other four
    2039             :      * possible matches are correct.
    2040             :      */
    2041          60 :     if ((wordlen == 4 && pg_strncasecmp(query, "drop", 4) == 0) ||
    2042           0 :         (wordlen == 7 && pg_strncasecmp(query, "reindex", 7) == 0))
    2043             :     {
    2044           6 :         query += wordlen;
    2045             : 
    2046           6 :         query = skip_white_space(query);
    2047             : 
    2048           6 :         wordlen = 0;
    2049          36 :         while (isalpha((unsigned char) query[wordlen]))
    2050          30 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2051             : 
    2052           6 :         if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
    2053           0 :             return true;
    2054           6 :         if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
    2055           0 :             return true;
    2056           6 :         if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
    2057           0 :             return true;
    2058          12 :         if (wordlen == 5 && (pg_strncasecmp(query, "index", 5) == 0 ||
    2059           6 :                              pg_strncasecmp(query, "table", 5) == 0))
    2060             :         {
    2061           6 :             query += wordlen;
    2062           6 :             query = skip_white_space(query);
    2063           6 :             wordlen = 0;
    2064          24 :             while (isalpha((unsigned char) query[wordlen]))
    2065          18 :                 wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2066             : 
    2067             :             /*
    2068             :              * REINDEX [ TABLE | INDEX ] CONCURRENTLY are not allowed in
    2069             :              * xacts.
    2070             :              */
    2071           6 :             if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
    2072           0 :                 return true;
    2073             :         }
    2074             : 
    2075             :         /* DROP INDEX CONCURRENTLY isn't allowed in xacts */
    2076           6 :         if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
    2077             :         {
    2078           0 :             query += wordlen;
    2079             : 
    2080           0 :             query = skip_white_space(query);
    2081             : 
    2082           0 :             wordlen = 0;
    2083           0 :             while (isalpha((unsigned char) query[wordlen]))
    2084           0 :                 wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2085             : 
    2086           0 :             if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
    2087           0 :                 return true;
    2088             : 
    2089           0 :             return false;
    2090             :         }
    2091             : 
    2092           6 :         return false;
    2093             :     }
    2094             : 
    2095             :     /* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */
    2096          54 :     if (wordlen == 7 && pg_strncasecmp(query, "discard", 7) == 0)
    2097             :     {
    2098           0 :         query += wordlen;
    2099             : 
    2100           0 :         query = skip_white_space(query);
    2101             : 
    2102           0 :         wordlen = 0;
    2103           0 :         while (isalpha((unsigned char) query[wordlen]))
    2104           0 :             wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
    2105             : 
    2106           0 :         if (wordlen == 3 && pg_strncasecmp(query, "all", 3) == 0)
    2107           0 :             return true;
    2108           0 :         return false;
    2109             :     }
    2110             : 
    2111          54 :     return false;
    2112             : }
    2113             : 
    2114             : 
    2115             : /*
    2116             :  * Test if the current user is a database superuser.
    2117             :  */
    2118             : bool
    2119         108 : is_superuser(void)
    2120             : {
    2121             :     const char *val;
    2122             : 
    2123         108 :     if (!pset.db)
    2124           0 :         return false;
    2125             : 
    2126         108 :     val = PQparameterStatus(pset.db, "is_superuser");
    2127             : 
    2128         108 :     if (val && strcmp(val, "on") == 0)
    2129         108 :         return true;
    2130             : 
    2131           0 :     return false;
    2132             : }
    2133             : 
    2134             : 
    2135             : /*
    2136             :  * Test if the current session uses standard string literals.
    2137             :  */
    2138             : bool
    2139      606932 : standard_strings(void)
    2140             : {
    2141             :     const char *val;
    2142             : 
    2143      606932 :     if (!pset.db)
    2144           0 :         return false;
    2145             : 
    2146      606932 :     val = PQparameterStatus(pset.db, "standard_conforming_strings");
    2147             : 
    2148      606932 :     if (val && strcmp(val, "on") == 0)
    2149      606740 :         return true;
    2150             : 
    2151         192 :     return false;
    2152             : }
    2153             : 
    2154             : 
    2155             : /*
    2156             :  * Return the session user of the current connection.
    2157             :  */
    2158             : const char *
    2159           0 : session_username(void)
    2160             : {
    2161             :     const char *val;
    2162             : 
    2163           0 :     if (!pset.db)
    2164           0 :         return NULL;
    2165             : 
    2166           0 :     val = PQparameterStatus(pset.db, "session_authorization");
    2167           0 :     if (val)
    2168           0 :         return val;
    2169             :     else
    2170           0 :         return PQuser(pset.db);
    2171             : }
    2172             : 
    2173             : 
    2174             : /* expand_tilde
    2175             :  *
    2176             :  * substitute '~' with HOME or '~username' with username's home dir
    2177             :  *
    2178             :  */
    2179             : void
    2180         172 : expand_tilde(char **filename)
    2181             : {
    2182         172 :     if (!filename || !(*filename))
    2183          12 :         return;
    2184             : 
    2185             :     /*
    2186             :      * WIN32 doesn't use tilde expansion for file names. Also, it uses tilde
    2187             :      * for short versions of long file names, though the tilde is usually
    2188             :      * toward the end, not at the beginning.
    2189             :      */
    2190             : #ifndef WIN32
    2191             : 
    2192             :     /* try tilde expansion */
    2193         160 :     if (**filename == '~')
    2194             :     {
    2195             :         char       *fn;
    2196             :         char        oldp,
    2197             :                    *p;
    2198             :         struct passwd *pw;
    2199             :         char        home[MAXPGPATH];
    2200             : 
    2201           0 :         fn = *filename;
    2202           0 :         *home = '\0';
    2203             : 
    2204           0 :         p = fn + 1;
    2205           0 :         while (*p != '/' && *p != '\0')
    2206           0 :             p++;
    2207             : 
    2208           0 :         oldp = *p;
    2209           0 :         *p = '\0';
    2210             : 
    2211           0 :         if (*(fn + 1) == '\0')
    2212           0 :             get_home_path(home);    /* ~ or ~/ only */
    2213           0 :         else if ((pw = getpwnam(fn + 1)) != NULL)
    2214           0 :             strlcpy(home, pw->pw_dir, sizeof(home)); /* ~user */
    2215             : 
    2216           0 :         *p = oldp;
    2217           0 :         if (strlen(home) != 0)
    2218             :         {
    2219             :             char       *newfn;
    2220             : 
    2221           0 :             newfn = psprintf("%s%s", home, p);
    2222           0 :             free(fn);
    2223           0 :             *filename = newfn;
    2224             :         }
    2225             :     }
    2226             : #endif
    2227             : }
    2228             : 
    2229             : /*
    2230             :  * Checks if connection string starts with either of the valid URI prefix
    2231             :  * designators.
    2232             :  *
    2233             :  * Returns the URI prefix length, 0 if the string doesn't contain a URI prefix.
    2234             :  *
    2235             :  * XXX This is a duplicate of the eponymous libpq function.
    2236             :  */
    2237             : static int
    2238          28 : uri_prefix_length(const char *connstr)
    2239             : {
    2240             :     /* The connection URI must start with either of the following designators: */
    2241             :     static const char uri_designator[] = "postgresql://";
    2242             :     static const char short_uri_designator[] = "postgres://";
    2243             : 
    2244          28 :     if (strncmp(connstr, uri_designator,
    2245             :                 sizeof(uri_designator) - 1) == 0)
    2246           0 :         return sizeof(uri_designator) - 1;
    2247             : 
    2248          28 :     if (strncmp(connstr, short_uri_designator,
    2249             :                 sizeof(short_uri_designator) - 1) == 0)
    2250           0 :         return sizeof(short_uri_designator) - 1;
    2251             : 
    2252          28 :     return 0;
    2253             : }
    2254             : 
    2255             : /*
    2256             :  * Recognized connection string either starts with a valid URI prefix or
    2257             :  * contains a "=" in it.
    2258             :  *
    2259             :  * Must be consistent with parse_connection_string: anything for which this
    2260             :  * returns true should at least look like it's parseable by that routine.
    2261             :  *
    2262             :  * XXX This is a duplicate of the eponymous libpq function.
    2263             :  */
    2264             : bool
    2265          28 : recognized_connection_string(const char *connstr)
    2266             : {
    2267          28 :     return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
    2268             : }

Generated by: LCOV version 1.14