LCOV - differential code coverage report
Current view: top level - src/bin/psql - common.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 70.9 % 907 643 4 71 141 48 63 389 18 173 153 396 3
Current Date: 2023-04-08 17:13:01 Functions: 94.4 % 36 34 2 32 2 2 33
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 62.5 % 8 5 3 5
Legend: Lines: hit not hit (60,120] days: 100.0 % 3 3 3
(120,180] days: 100.0 % 10 10 9 1
(180,240] days: 81.6 % 49 40 1 1 7 1 27 12 3 28
(240..) days: 69.9 % 837 585 70 134 48 62 362 1 160 148 362
Function coverage date bins:
[..60] days: 100.0 % 1 1 1
(180,240] days: 100.0 % 4 4 4
(240..) days: 45.3 % 64 29 2 28 1 2 31

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

Generated by: LCOV version v1.16-55-g56c0a2a