PostgreSQL Source Code  git master
common.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <pwd.h>
#include <signal.h>
#include <unistd.h>
#include "command.h"
#include "common.h"
#include "common/logging.h"
#include "copy.h"
#include "crosstabview.h"
#include "fe_utils/cancel.h"
#include "fe_utils/mbprint.h"
#include "fe_utils/string_utils.h"
#include "portability/instr_time.h"
#include "settings.h"
Include dependency graph for common.c:

Go to the source code of this file.

Functions

static bool DescribeQuery (const char *query, double *elapsed_msec)
 
static bool ExecQueryUsingCursor (const char *query, double *elapsed_msec)
 
static int ExecQueryAndProcessResults (const char *query, double *elapsed_msec, bool *svpt_gone_p, bool is_watch, const printQueryOpt *opt, FILE *printQueryFout)
 
static bool command_no_begin (const char *query)
 
static bool is_select_command (const char *query)
 
bool openQueryOutputFile (const char *fname, FILE **fout, bool *is_pipe)
 
bool setQFout (const char *fname)
 
char * psql_get_variable (const char *varname, PsqlScanQuoteType quote, void *passthrough)
 
void NoticeProcessor (void *arg, const char *message)
 
static void psql_cancel_callback (void)
 
void psql_setup_cancel_handler (void)
 
static bool ConnectionUp (void)
 
static bool CheckConnection (void)
 
static bool AcceptResult (const PGresult *result, bool show_error)
 
static void SetResultVariables (PGresult *result, bool success)
 
static void ClearOrSaveResult (PGresult *result)
 
static void ClearOrSaveAllResults (void)
 
static void PrintTiming (double elapsed_msec)
 
PGresultPSQLexec (const char *query)
 
int PSQLexecWatch (const char *query, const printQueryOpt *opt, FILE *printQueryFout)
 
static void PrintNotifications (void)
 
static bool PrintQueryTuples (const PGresult *result, const printQueryOpt *opt, FILE *printQueryFout)
 
static bool StoreQueryTuple (const PGresult *result)
 
static bool ExecQueryTuples (const PGresult *result)
 
static bool HandleCopyResult (PGresult **resultp)
 
static void PrintQueryStatus (PGresult *result, FILE *printQueryFout)
 
static bool PrintQueryResult (PGresult *result, bool last, bool is_watch, const printQueryOpt *opt, FILE *printQueryFout)
 
bool SendQuery (const char *query)
 
static const char * skip_white_space (const char *query)
 
bool is_superuser (void)
 
bool standard_strings (void)
 
const char * session_username (void)
 
void expand_tilde (char **filename)
 
static int uri_prefix_length (const char *connstr)
 
bool recognized_connection_string (const char *connstr)
 

Variables

volatile bool sigint_interrupt_enabled = false
 
sigjmp_buf sigint_interrupt_jmp
 

Function Documentation

◆ AcceptResult()

static bool AcceptResult ( const PGresult result,
bool  show_error 
)
static

Definition at line 359 of file common.c.

360 {
361  bool OK;
362 
363  if (!result)
364  OK = false;
365  else
366  switch (PQresultStatus(result))
367  {
368  case PGRES_COMMAND_OK:
369  case PGRES_TUPLES_OK:
370  case PGRES_EMPTY_QUERY:
371  case PGRES_COPY_IN:
372  case PGRES_COPY_OUT:
373  /* Fine, do nothing */
374  OK = true;
375  break;
376 
377  case PGRES_BAD_RESPONSE:
379  case PGRES_FATAL_ERROR:
380  OK = false;
381  break;
382 
383  default:
384  OK = false;
385  pg_log_error("unexpected PQresultStatus: %d",
386  PQresultStatus(result));
387  break;
388  }
389 
390  if (!OK && show_error)
391  {
392  const char *error = PQerrorMessage(pset.db);
393 
394  if (strlen(error))
395  pg_log_info("%s", error);
396 
397  CheckConnection();
398  }
399 
400  return OK;
401 }
static bool CheckConnection(void)
Definition: common.c:298
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6908
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3270
@ PGRES_COPY_IN
Definition: libpq-fe.h:104
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
@ PGRES_FATAL_ERROR
Definition: libpq-fe.h:108
@ PGRES_COPY_OUT
Definition: libpq-fe.h:103
@ PGRES_EMPTY_QUERY
Definition: libpq-fe.h:96
@ PGRES_BAD_RESPONSE
Definition: libpq-fe.h:105
@ PGRES_NONFATAL_ERROR
Definition: libpq-fe.h:107
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:100
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_info(...)
Definition: logging.h:124
PsqlSettings pset
Definition: startup.c:32
static void error(void)
Definition: sql-dyntest.c:147
PGconn * db
Definition: settings.h:82

References CheckConnection(), _psqlSettings::db, error(), pg_log_error, pg_log_info, PGRES_BAD_RESPONSE, PGRES_COMMAND_OK, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, PGRES_TUPLES_OK, PQerrorMessage(), PQresultStatus(), and pset.

Referenced by DescribeQuery(), ExecQueryAndProcessResults(), ExecQueryUsingCursor(), and PSQLexec().

◆ CheckConnection()

static bool CheckConnection ( void  )
static

Definition at line 298 of file common.c.

299 {
300  bool OK;
301 
302  OK = ConnectionUp();
303  if (!OK)
304  {
306  {
307  pg_log_error("connection to server was lost");
309  }
310 
311  fprintf(stderr, _("The connection to the server was lost. Attempting reset: "));
312  PQreset(pset.db);
313  OK = ConnectionUp();
314  if (!OK)
315  {
316  fprintf(stderr, _("Failed.\n"));
317 
318  /*
319  * Transition to having no connection; but stash away the failed
320  * connection so that we can still refer to its parameters in a
321  * later \connect attempt. Keep the state cleanup here in sync
322  * with do_connect().
323  */
324  if (pset.dead_conn)
326  pset.dead_conn = pset.db;
327  pset.db = NULL;
328  ResetCancelConn();
329  UnsyncVariables();
330  }
331  else
332  {
333  fprintf(stderr, _("Succeeded.\n"));
334 
335  /*
336  * Re-sync, just in case anything changed. Keep this in sync with
337  * do_connect().
338  */
339  SyncVariables();
340  connection_warnings(false); /* Must be after SyncVariables */
341  }
342  }
343 
344  return OK;
345 }
static bool ConnectionUp(void)
Definition: common.c:280
void ResetCancelConn(void)
Definition: cancel.c:107
void UnsyncVariables(void)
Definition: command.c:3780
void SyncVariables(void)
Definition: command.c:3739
void connection_warnings(bool in_startup)
Definition: command.c:3614
#define _(x)
Definition: elog.c:89
void PQreset(PGconn *conn)
Definition: fe-connect.c:4275
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4261
exit(1)
#define fprintf
Definition: port.h:229
#define EXIT_BADCONN
Definition: settings.h:166
PGconn * dead_conn
Definition: settings.h:125
bool cur_cmd_interactive
Definition: settings.h:107

References _, connection_warnings(), ConnectionUp(), _psqlSettings::cur_cmd_interactive, _psqlSettings::db, _psqlSettings::dead_conn, exit(), EXIT_BADCONN, fprintf, pg_log_error, PQfinish(), PQreset(), pset, ResetCancelConn(), SyncVariables(), and UnsyncVariables().

Referenced by AcceptResult(), and ExecQueryAndProcessResults().

◆ ClearOrSaveAllResults()

static void ClearOrSaveAllResults ( void  )
static

Definition at line 483 of file common.c.

484 {
485  PGresult *result;
486 
487  while ((result = PQgetResult(pset.db)) != NULL)
488  ClearOrSaveResult(result);
489 }
static void ClearOrSaveResult(PGresult *result)
Definition: common.c:458
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2082

References ClearOrSaveResult(), _psqlSettings::db, PQgetResult(), and pset.

Referenced by ExecQueryAndProcessResults().

◆ ClearOrSaveResult()

static void ClearOrSaveResult ( PGresult result)
static

Definition at line 458 of file common.c.

459 {
460  if (result)
461  {
462  switch (PQresultStatus(result))
463  {
465  case PGRES_FATAL_ERROR:
468  pset.last_error_result = result;
469  break;
470 
471  default:
472  PQclear(result);
473  break;
474  }
475  }
476 }
void PQclear(PGresult *res)
Definition: fe-exec.c:718
PGresult * last_error_result
Definition: settings.h:89

References _psqlSettings::last_error_result, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, PQclear(), PQresultStatus(), and pset.

Referenced by ClearOrSaveAllResults(), DescribeQuery(), ExecQueryAndProcessResults(), ExecQueryUsingCursor(), PSQLexec(), and SendQuery().

◆ command_no_begin()

static bool command_no_begin ( const char *  query)
static

Definition at line 1955 of file common.c.

1956 {
1957  int wordlen;
1958 
1959  /*
1960  * First we must advance over any whitespace and comments.
1961  */
1962  query = skip_white_space(query);
1963 
1964  /*
1965  * Check word length (since "beginx" is not "begin").
1966  */
1967  wordlen = 0;
1968  while (isalpha((unsigned char) query[wordlen]))
1969  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
1970 
1971  /*
1972  * Transaction control commands. These should include every keyword that
1973  * gives rise to a TransactionStmt in the backend grammar, except for the
1974  * savepoint-related commands.
1975  *
1976  * (We assume that START must be START TRANSACTION, since there is
1977  * presently no other "START foo" command.)
1978  */
1979  if (wordlen == 5 && pg_strncasecmp(query, "abort", 5) == 0)
1980  return true;
1981  if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0)
1982  return true;
1983  if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0)
1984  return true;
1985  if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0)
1986  return true;
1987  if (wordlen == 3 && pg_strncasecmp(query, "end", 3) == 0)
1988  return true;
1989  if (wordlen == 8 && pg_strncasecmp(query, "rollback", 8) == 0)
1990  return true;
1991  if (wordlen == 7 && pg_strncasecmp(query, "prepare", 7) == 0)
1992  {
1993  /* PREPARE TRANSACTION is a TC command, PREPARE foo is not */
1994  query += wordlen;
1995 
1996  query = skip_white_space(query);
1997 
1998  wordlen = 0;
1999  while (isalpha((unsigned char) query[wordlen]))
2000  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2001 
2002  if (wordlen == 11 && pg_strncasecmp(query, "transaction", 11) == 0)
2003  return true;
2004  return false;
2005  }
2006 
2007  /*
2008  * Commands not allowed within transactions. The statements checked for
2009  * here should be exactly those that call PreventInTransactionBlock() in
2010  * the backend.
2011  */
2012  if (wordlen == 6 && pg_strncasecmp(query, "vacuum", 6) == 0)
2013  return true;
2014  if (wordlen == 7 && pg_strncasecmp(query, "cluster", 7) == 0)
2015  {
2016  /* CLUSTER with any arguments is allowed in transactions */
2017  query += wordlen;
2018 
2019  query = skip_white_space(query);
2020 
2021  if (isalpha((unsigned char) query[0]))
2022  return false; /* has additional words */
2023  return true; /* it's CLUSTER without arguments */
2024  }
2025 
2026  if (wordlen == 6 && pg_strncasecmp(query, "create", 6) == 0)
2027  {
2028  query += wordlen;
2029 
2030  query = skip_white_space(query);
2031 
2032  wordlen = 0;
2033  while (isalpha((unsigned char) query[wordlen]))
2034  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2035 
2036  if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
2037  return true;
2038  if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
2039  return true;
2040 
2041  /* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */
2042  if (wordlen == 6 && pg_strncasecmp(query, "unique", 6) == 0)
2043  {
2044  query += wordlen;
2045 
2046  query = skip_white_space(query);
2047 
2048  wordlen = 0;
2049  while (isalpha((unsigned char) query[wordlen]))
2050  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2051  }
2052 
2053  if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
2054  {
2055  query += wordlen;
2056 
2057  query = skip_white_space(query);
2058 
2059  wordlen = 0;
2060  while (isalpha((unsigned char) query[wordlen]))
2061  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2062 
2063  if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
2064  return true;
2065  }
2066 
2067  return false;
2068  }
2069 
2070  if (wordlen == 5 && pg_strncasecmp(query, "alter", 5) == 0)
2071  {
2072  query += wordlen;
2073 
2074  query = skip_white_space(query);
2075 
2076  wordlen = 0;
2077  while (isalpha((unsigned char) query[wordlen]))
2078  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2079 
2080  /* ALTER SYSTEM isn't allowed in xacts */
2081  if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
2082  return true;
2083 
2084  return false;
2085  }
2086 
2087  /*
2088  * Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which
2089  * aren't really valid commands so we don't care much. The other four
2090  * possible matches are correct.
2091  */
2092  if ((wordlen == 4 && pg_strncasecmp(query, "drop", 4) == 0) ||
2093  (wordlen == 7 && pg_strncasecmp(query, "reindex", 7) == 0))
2094  {
2095  query += wordlen;
2096 
2097  query = skip_white_space(query);
2098 
2099  wordlen = 0;
2100  while (isalpha((unsigned char) query[wordlen]))
2101  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2102 
2103  if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
2104  return true;
2105  if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
2106  return true;
2107  if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
2108  return true;
2109  if (wordlen == 5 && (pg_strncasecmp(query, "index", 5) == 0 ||
2110  pg_strncasecmp(query, "table", 5) == 0))
2111  {
2112  query += wordlen;
2113  query = skip_white_space(query);
2114  wordlen = 0;
2115  while (isalpha((unsigned char) query[wordlen]))
2116  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2117 
2118  /*
2119  * REINDEX [ TABLE | INDEX ] CONCURRENTLY are not allowed in
2120  * xacts.
2121  */
2122  if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
2123  return true;
2124  }
2125 
2126  /* DROP INDEX CONCURRENTLY isn't allowed in xacts */
2127  if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
2128  {
2129  query += wordlen;
2130 
2131  query = skip_white_space(query);
2132 
2133  wordlen = 0;
2134  while (isalpha((unsigned char) query[wordlen]))
2135  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2136 
2137  if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
2138  return true;
2139 
2140  return false;
2141  }
2142 
2143  return false;
2144  }
2145 
2146  /* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */
2147  if (wordlen == 7 && pg_strncasecmp(query, "discard", 7) == 0)
2148  {
2149  query += wordlen;
2150 
2151  query = skip_white_space(query);
2152 
2153  wordlen = 0;
2154  while (isalpha((unsigned char) query[wordlen]))
2155  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2156 
2157  if (wordlen == 3 && pg_strncasecmp(query, "all", 3) == 0)
2158  return true;
2159  return false;
2160  }
2161 
2162  return false;
2163 }
static const char * skip_white_space(const char *query)
Definition: common.c:1891
int PQmblenBounded(const char *s, int encoding)
Definition: fe-misc.c:1195
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
int encoding
Definition: settings.h:83

References _psqlSettings::encoding, pg_strncasecmp(), PQmblenBounded(), pset, and skip_white_space().

Referenced by SendQuery().

◆ ConnectionUp()

static bool ConnectionUp ( void  )
static

Definition at line 280 of file common.c.

281 {
282  return PQstatus(pset.db) != CONNECTION_BAD;
283 }
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6855
@ CONNECTION_BAD
Definition: libpq-fe.h:61

References CONNECTION_BAD, _psqlSettings::db, PQstatus(), and pset.

Referenced by CheckConnection(), and SendQuery().

◆ DescribeQuery()

static bool DescribeQuery ( const char *  query,
double *  elapsed_msec 
)
static

Definition at line 1312 of file common.c.

1313 {
1314  bool timing = pset.timing;
1315  PGresult *result;
1316  bool OK;
1318  after;
1319 
1320  *elapsed_msec = 0;
1321 
1322  if (timing)
1324 
1325  /*
1326  * To parse the query but not execute it, we prepare it, using the unnamed
1327  * prepared statement. This is invisible to psql users, since there's no
1328  * way to access the unnamed prepared statement from psql user space. The
1329  * next Parse or Query protocol message would overwrite the statement
1330  * anyway. (So there's no great need to clear it when done, which is a
1331  * good thing because libpq provides no easy way to do that.)
1332  */
1333  result = PQprepare(pset.db, "", query, 0, NULL);
1334  if (PQresultStatus(result) != PGRES_COMMAND_OK)
1335  {
1337  SetResultVariables(result, false);
1338  ClearOrSaveResult(result);
1339  return false;
1340  }
1341  PQclear(result);
1342 
1343  result = PQdescribePrepared(pset.db, "");
1344  OK = AcceptResult(result, true) &&
1345  (PQresultStatus(result) == PGRES_COMMAND_OK);
1346  if (OK && result)
1347  {
1348  if (PQnfields(result) > 0)
1349  {
1351  int i;
1352 
1353  initPQExpBuffer(&buf);
1354 
1356  "SELECT name AS \"%s\", pg_catalog.format_type(tp, tpm) AS \"%s\"\n"
1357  "FROM (VALUES ",
1358  gettext_noop("Column"),
1359  gettext_noop("Type"));
1360 
1361  for (i = 0; i < PQnfields(result); i++)
1362  {
1363  const char *name;
1364  char *escname;
1365 
1366  if (i > 0)
1367  appendPQExpBufferStr(&buf, ",");
1368 
1369  name = PQfname(result, i);
1370  escname = PQescapeLiteral(pset.db, name, strlen(name));
1371 
1372  if (escname == NULL)
1373  {
1375  PQclear(result);
1376  termPQExpBuffer(&buf);
1377  return false;
1378  }
1379 
1380  appendPQExpBuffer(&buf, "(%s, '%u'::pg_catalog.oid, %d)",
1381  escname,
1382  PQftype(result, i),
1383  PQfmod(result, i));
1384 
1385  PQfreemem(escname);
1386  }
1387 
1388  appendPQExpBufferStr(&buf, ") s(name, tp, tpm)");
1389  PQclear(result);
1390 
1391  result = PQexec(pset.db, buf.data);
1392  OK = AcceptResult(result, true);
1393 
1394  if (timing)
1395  {
1396  INSTR_TIME_SET_CURRENT(after);
1397  INSTR_TIME_SUBTRACT(after, before);
1398  *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
1399  }
1400 
1401  if (OK && result)
1402  OK = PrintQueryResult(result, true, false, NULL, NULL);
1403 
1404  termPQExpBuffer(&buf);
1405  }
1406  else
1408  _("The command has no result, or the result has no columns.\n"));
1409  }
1410 
1411  SetResultVariables(result, OK);
1412  ClearOrSaveResult(result);
1413 
1414  return OK;
1415 }
static bool PrintQueryResult(PGresult *result, bool last, bool is_watch, const printQueryOpt *opt, FILE *printQueryFout)
Definition: common.c:995
static void SetResultVariables(PGresult *result, bool success)
Definition: common.c:416
static bool AcceptResult(const PGresult *result, bool show_error)
Definition: common.c:359
#define gettext_noop(x)
Definition: c.h:1194
const char * name
Definition: encode.c:561
void PQfreemem(void *ptr)
Definition: fe-exec.c:3891
PGresult * PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
Definition: fe-exec.c:2317
Oid PQftype(const PGresult *res, int field_num)
Definition: fe-exec.c:3578
PGresult * PQdescribePrepared(PGconn *conn, const char *stmt)
Definition: fe-exec.c:2469
char * PQfname(const PGresult *res, int field_num)
Definition: fe-exec.c:3426
char * PQescapeLiteral(PGconn *conn, const char *str, size_t len)
Definition: fe-exec.c:4166
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2273
int PQfmod(const PGresult *res, int field_num)
Definition: fe-exec.c:3600
int PQnfields(const PGresult *res)
Definition: fe-exec.c:3348
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:170
struct timeval instr_time
Definition: instr_time.h:150
#define INSTR_TIME_GET_MILLISEC(t)
Definition: instr_time.h:202
int i
Definition: isn.c:73
static char * buf
Definition: pg_test_fsync.c:67
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
static int before(chr x, chr y)
Definition: regc_locale.c:492
FILE * queryFout
Definition: settings.h:84

References _, AcceptResult(), appendPQExpBuffer(), appendPQExpBufferStr(), before(), buf, ClearOrSaveResult(), _psqlSettings::db, fprintf, gettext_noop, i, initPQExpBuffer(), INSTR_TIME_GET_MILLISEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, name, pg_log_info, PGRES_COMMAND_OK, PQclear(), PQdescribePrepared(), PQerrorMessage(), PQescapeLiteral(), PQexec(), PQfmod(), PQfname(), PQfreemem(), PQftype(), PQnfields(), PQprepare(), PQresultStatus(), printfPQExpBuffer(), PrintQueryResult(), pset, _psqlSettings::queryFout, SetResultVariables(), termPQExpBuffer(), and _psqlSettings::timing.

Referenced by SendQuery().

◆ ExecQueryAndProcessResults()

static int ExecQueryAndProcessResults ( const char *  query,
double *  elapsed_msec,
bool svpt_gone_p,
bool  is_watch,
const printQueryOpt opt,
FILE *  printQueryFout 
)
static

Definition at line 1440 of file common.c.

1442 {
1443  bool timing = pset.timing;
1444  bool success;
1446  after;
1447  PGresult *result;
1448 
1449  if (timing)
1451 
1452  success = PQsendQuery(pset.db, query);
1453 
1454  if (!success)
1455  {
1456  const char *error = PQerrorMessage(pset.db);
1457 
1458  if (strlen(error))
1459  pg_log_info("%s", error);
1460 
1461  CheckConnection();
1462 
1463  return -1;
1464  }
1465 
1466  /*
1467  * If SIGINT is sent while the query is processing, the interrupt will be
1468  * consumed. The user's intention, though, is to cancel the entire watch
1469  * process, so detect a sent cancellation request and exit in this case.
1470  */
1471  if (is_watch && cancel_pressed)
1472  {
1474  return 0;
1475  }
1476 
1477  /* first result */
1478  result = PQgetResult(pset.db);
1479 
1480  while (result != NULL)
1481  {
1482  ExecStatusType result_status;
1483  PGresult *next_result;
1484  bool last;
1485 
1486  if (!AcceptResult(result, false))
1487  {
1488  /*
1489  * Some error occured, either a server-side failure or a failure
1490  * to submit the command string. Record that.
1491  */
1492  const char *error = PQresultErrorMessage(result);
1493 
1494  if (strlen(error))
1495  pg_log_info("%s", error);
1496 
1497  CheckConnection();
1498  if (!is_watch)
1499  SetResultVariables(result, false);
1500 
1501  /* keep the result status before clearing it */
1502  result_status = PQresultStatus(result);
1503  ClearOrSaveResult(result);
1504  success = false;
1505 
1506  /*
1507  * switch to next result
1508  */
1509  if (result_status == PGRES_COPY_BOTH ||
1510  result_status == PGRES_COPY_OUT ||
1511  result_status == PGRES_COPY_IN)
1512 
1513  /*
1514  * For some obscure reason PQgetResult does *not* return a
1515  * NULL in copy cases despite the result having been cleared,
1516  * but keeps returning an "empty" result that we have to
1517  * ignore manually.
1518  */
1519  result = NULL;
1520  else
1521  result = PQgetResult(pset.db);
1522 
1523  /*
1524  * Get current timing measure in case an error occurs
1525  */
1526  if (timing)
1527  {
1528  INSTR_TIME_SET_CURRENT(after);
1529  INSTR_TIME_SUBTRACT(after, before);
1530  *elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
1531  }
1532 
1533  continue;
1534  }
1535  else if (svpt_gone_p && !*svpt_gone_p)
1536  {
1537  /*
1538  * Check if the user ran any command that would destroy our
1539  * internal savepoint: If the user did COMMIT AND CHAIN, RELEASE
1540  * or ROLLBACK, our savepoint is gone. If they issued a SAVEPOINT,
1541  * releasing ours would remove theirs.
1542  */
1543  const char *cmd = PQcmdStatus(result);
1544 
1545  *svpt_gone_p = (strcmp(cmd, "COMMIT") == 0 ||
1546  strcmp(cmd, "SAVEPOINT") == 0 ||
1547  strcmp(cmd, "RELEASE") == 0 ||
1548  strcmp(cmd, "ROLLBACK") == 0);
1549  }
1550 
1551  result_status = PQresultStatus(result);
1552 
1553  /* must handle COPY before changing the current result */
1554  Assert(result_status != PGRES_COPY_BOTH);
1555  if (result_status == PGRES_COPY_IN ||
1556  result_status == PGRES_COPY_OUT)
1557  {
1558  if (is_watch)
1559  {
1561  pg_log_error("\\watch cannot be used with COPY");
1562  return -1;
1563  }
1564 
1565  success &= HandleCopyResult(&result);
1566  }
1567 
1568  /*
1569  * Check PQgetResult() again. In the typical case of a single-command
1570  * string, it will return NULL. Otherwise, we'll have other results
1571  * to process. We need to do that to check whether this is the last.
1572  */
1573  next_result = PQgetResult(pset.db);
1574  last = (next_result == NULL);
1575 
1576  /*
1577  * Update current timing measure.
1578  *
1579  * It will include the display of previous results, if any. This
1580  * cannot be helped because the server goes on processing further
1581  * queries anyway while the previous ones are being displayed. The
1582  * parallel execution of the client display hides the server time when
1583  * it is shorter.
1584  *
1585  * With combined queries, timing must be understood as an upper bound
1586  * of the time spent processing them.
1587  */
1588  if (timing)
1589  {
1590  INSTR_TIME_SET_CURRENT(after);
1591  INSTR_TIME_SUBTRACT(after, before);
1592  *elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
1593  }
1594 
1595  /* this may or may not print something depending on settings */
1596  if (result != NULL)
1597  success &= PrintQueryResult(result, last, false, opt, printQueryFout);
1598 
1599  /* set variables on last result if all went well */
1600  if (!is_watch && last && success)
1601  SetResultVariables(result, true);
1602 
1603  ClearOrSaveResult(result);
1604  result = next_result;
1605 
1606  if (cancel_pressed)
1607  {
1609  break;
1610  }
1611  }
1612 
1613  /* may need this to recover from conn loss during COPY */
1614  if (!CheckConnection())
1615  return -1;
1616 
1617  return cancel_pressed ? 0 : success ? 1 : -1;
1618 }
static void ClearOrSaveAllResults(void)
Definition: common.c:483
static bool HandleCopyResult(PGresult **resultp)
Definition: common.c:864
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:3286
char * PQcmdStatus(PGresult *res)
Definition: fe-exec.c:3611
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1424
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
static bool success
Definition: initdb.c:169
ExecStatusType
Definition: libpq-fe.h:95
@ PGRES_COPY_BOTH
Definition: libpq-fe.h:109
Assert(fmt[strlen(fmt) - 1] !='\n')

References AcceptResult(), Assert(), before(), cancel_pressed, CheckConnection(), ClearOrSaveAllResults(), ClearOrSaveResult(), _psqlSettings::db, error(), HandleCopyResult(), INSTR_TIME_GET_MILLISEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, pg_log_error, pg_log_info, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PQcmdStatus(), PQerrorMessage(), PQgetResult(), PQresultErrorMessage(), PQresultStatus(), PQsendQuery(), PrintQueryResult(), pset, SetResultVariables(), success, and _psqlSettings::timing.

Referenced by PSQLexecWatch(), and SendQuery().

◆ ExecQueryTuples()

static bool ExecQueryTuples ( const PGresult result)
static

Definition at line 784 of file common.c.

785 {
786  bool success = true;
787  int nrows = PQntuples(result);
788  int ncolumns = PQnfields(result);
789  int r,
790  c;
791 
792  /*
793  * We must turn off gexec_flag to avoid infinite recursion. Note that
794  * this allows ExecQueryUsingCursor to be applied to the individual query
795  * results. SendQuery prevents it from being applied when fetching the
796  * queries-to-execute, because it can't handle recursion either.
797  */
798  pset.gexec_flag = false;
799 
800  for (r = 0; r < nrows; r++)
801  {
802  for (c = 0; c < ncolumns; c++)
803  {
804  if (!PQgetisnull(result, r, c))
805  {
806  const char *query = PQgetvalue(result, r, c);
807 
808  /* Abandon execution if cancel_pressed */
809  if (cancel_pressed)
810  goto loop_exit;
811 
812  /*
813  * ECHO_ALL mode should echo these queries, but SendQuery
814  * assumes that MainLoop did that, so we have to do it here.
815  */
817  {
818  puts(query);
819  fflush(stdout);
820  }
821 
822  if (!SendQuery(query))
823  {
824  /* Error - abandon execution if ON_ERROR_STOP */
825  success = false;
826  if (pset.on_error_stop)
827  goto loop_exit;
828  }
829  }
830  }
831  }
832 
833 loop_exit:
834 
835  /*
836  * Restore state. We know gexec_flag was on, else we'd not be here. (We
837  * also know it'll get turned off at end of command, but that's not ours
838  * to do here.)
839  */
840  pset.gexec_flag = true;
841 
842  /* Return true if all queries were successful */
843  return success;
844 }
bool SendQuery(const char *query)
Definition: common.c:1077
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3340
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3735
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3760
static void const char fflush(stdout)
char * c
@ PSQL_ECHO_ALL
Definition: settings.h:40
bool on_error_stop
Definition: settings.h:133
PSQL_ECHO echo
Definition: settings.h:142
bool singlestep
Definition: settings.h:136
bool gexec_flag
Definition: settings.h:98

References cancel_pressed, _psqlSettings::echo, fflush(), _psqlSettings::gexec_flag, _psqlSettings::on_error_stop, PQgetisnull(), PQgetvalue(), PQnfields(), PQntuples(), pset, PSQL_ECHO_ALL, SendQuery(), _psqlSettings::singlestep, generate_unaccent_rules::stdout, and success.

Referenced by PrintQueryResult().

◆ ExecQueryUsingCursor()

static bool ExecQueryUsingCursor ( const char *  query,
double *  elapsed_msec 
)
static

Definition at line 1632 of file common.c.

1633 {
1634  bool OK = true;
1635  PGresult *result;
1637  printQueryOpt my_popt = pset.popt;
1638  bool timing = pset.timing;
1639  FILE *fout;
1640  bool is_pipe;
1641  bool is_pager = false;
1642  bool started_txn = false;
1643  int64 total_tuples = 0;
1644  int ntuples;
1645  int fetch_count;
1646  char fetch_cmd[64];
1648  after;
1649  int flush_error;
1650 
1651  *elapsed_msec = 0;
1652 
1653  /* initialize print options for partial table output */
1654  my_popt.topt.start_table = true;
1655  my_popt.topt.stop_table = false;
1656  my_popt.topt.prior_records = 0;
1657 
1658  if (timing)
1660 
1661  /* if we're not in a transaction, start one */
1663  {
1664  result = PQexec(pset.db, "BEGIN");
1665  OK = AcceptResult(result, true) &&
1666  (PQresultStatus(result) == PGRES_COMMAND_OK);
1667  ClearOrSaveResult(result);
1668  if (!OK)
1669  return false;
1670  started_txn = true;
1671  }
1672 
1673  /* Send DECLARE CURSOR */
1674  initPQExpBuffer(&buf);
1675  appendPQExpBuffer(&buf, "DECLARE _psql_cursor NO SCROLL CURSOR FOR\n%s",
1676  query);
1677 
1678  result = PQexec(pset.db, buf.data);
1679  OK = AcceptResult(result, true) &&
1680  (PQresultStatus(result) == PGRES_COMMAND_OK);
1681  if (!OK)
1682  SetResultVariables(result, OK);
1683  ClearOrSaveResult(result);
1684  termPQExpBuffer(&buf);
1685  if (!OK)
1686  goto cleanup;
1687 
1688  if (timing)
1689  {
1690  INSTR_TIME_SET_CURRENT(after);
1691  INSTR_TIME_SUBTRACT(after, before);
1692  *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
1693  }
1694 
1695  /*
1696  * In \gset mode, we force the fetch count to be 2, so that we will throw
1697  * the appropriate error if the query returns more than one row.
1698  */
1699  if (pset.gset_prefix)
1700  fetch_count = 2;
1701  else
1702  fetch_count = pset.fetch_count;
1703 
1704  snprintf(fetch_cmd, sizeof(fetch_cmd),
1705  "FETCH FORWARD %d FROM _psql_cursor",
1706  fetch_count);
1707 
1708  /* prepare to write output to \g argument, if any */
1709  if (pset.gfname)
1710  {
1711  if (!openQueryOutputFile(pset.gfname, &fout, &is_pipe))
1712  {
1713  OK = false;
1714  goto cleanup;
1715  }
1716  if (is_pipe)
1718  }
1719  else
1720  {
1721  fout = pset.queryFout;
1722  is_pipe = false; /* doesn't matter */
1723  }
1724 
1725  /* clear any pre-existing error indication on the output stream */
1726  clearerr(fout);
1727 
1728  for (;;)
1729  {
1730  if (timing)
1732 
1733  /* get fetch_count tuples at a time */
1734  result = PQexec(pset.db, fetch_cmd);
1735 
1736  if (timing)
1737  {
1738  INSTR_TIME_SET_CURRENT(after);
1739  INSTR_TIME_SUBTRACT(after, before);
1740  *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
1741  }
1742 
1743  if (PQresultStatus(result) != PGRES_TUPLES_OK)
1744  {
1745  /* shut down pager before printing error message */
1746  if (is_pager)
1747  {
1748  ClosePager(fout);
1749  is_pager = false;
1750  }
1751 
1752  OK = AcceptResult(result, true);
1753  Assert(!OK);
1754  SetResultVariables(result, OK);
1755  ClearOrSaveResult(result);
1756  break;
1757  }
1758 
1759  if (pset.gset_prefix)
1760  {
1761  /* StoreQueryTuple will complain if not exactly one row */
1762  OK = StoreQueryTuple(result);
1763  ClearOrSaveResult(result);
1764  break;
1765  }
1766 
1767  /*
1768  * Note we do not deal with \gdesc, \gexec or \crosstabview modes here
1769  */
1770 
1771  ntuples = PQntuples(result);
1772  total_tuples += ntuples;
1773 
1774  if (ntuples < fetch_count)
1775  {
1776  /* this is the last result set, so allow footer decoration */
1777  my_popt.topt.stop_table = true;
1778  }
1779  else if (fout == stdout && !is_pager)
1780  {
1781  /*
1782  * If query requires multiple result sets, hack to ensure that
1783  * only one pager instance is used for the whole mess
1784  */
1785  fout = PageOutput(INT_MAX, &(my_popt.topt));
1786  is_pager = true;
1787  }
1788 
1789  printQuery(result, &my_popt, fout, is_pager, pset.logfile);
1790 
1791  ClearOrSaveResult(result);
1792 
1793  /* after the first result set, disallow header decoration */
1794  my_popt.topt.start_table = false;
1795  my_popt.topt.prior_records += ntuples;
1796 
1797  /*
1798  * Make sure to flush the output stream, so intermediate results are
1799  * visible to the client immediately. We check the results because if
1800  * the pager dies/exits/etc, there's no sense throwing more data at
1801  * it.
1802  */
1803  flush_error = fflush(fout);
1804 
1805  /*
1806  * Check if we are at the end, if a cancel was pressed, or if there
1807  * were any errors either trying to flush out the results, or more
1808  * generally on the output stream at all. If we hit any errors
1809  * writing things to the stream, we presume $PAGER has disappeared and
1810  * stop bothering to pull down more data.
1811  */
1812  if (ntuples < fetch_count || cancel_pressed || flush_error ||
1813  ferror(fout))
1814  break;
1815  }
1816 
1817  if (pset.gfname)
1818  {
1819  /* close \g argument file/pipe */
1820  if (is_pipe)
1821  {
1822  pclose(fout);
1824  }
1825  else
1826  fclose(fout);
1827  }
1828  else if (is_pager)
1829  {
1830  /* close transient pager */
1831  ClosePager(fout);
1832  }
1833 
1834  if (OK)
1835  {
1836  /*
1837  * We don't have a PGresult here, and even if we did it wouldn't have
1838  * the right row count, so fake SetResultVariables(). In error cases,
1839  * we already set the result variables above.
1840  */
1841  char buf[32];
1842 
1843  SetVariable(pset.vars, "ERROR", "false");
1844  SetVariable(pset.vars, "SQLSTATE", "00000");
1845  snprintf(buf, sizeof(buf), INT64_FORMAT, total_tuples);
1846  SetVariable(pset.vars, "ROW_COUNT", buf);
1847  }
1848 
1849 cleanup:
1850  if (timing)
1852 
1853  /*
1854  * We try to close the cursor on either success or failure, but on failure
1855  * ignore the result (it's probably just a bleat about being in an aborted
1856  * transaction)
1857  */
1858  result = PQexec(pset.db, "CLOSE _psql_cursor");
1859  if (OK)
1860  {
1861  OK = AcceptResult(result, true) &&
1862  (PQresultStatus(result) == PGRES_COMMAND_OK);
1863  ClearOrSaveResult(result);
1864  }
1865  else
1866  PQclear(result);
1867 
1868  if (started_txn)
1869  {
1870  result = PQexec(pset.db, OK ? "COMMIT" : "ROLLBACK");
1871  OK &= AcceptResult(result, true) &&
1872  (PQresultStatus(result) == PGRES_COMMAND_OK);
1873  ClearOrSaveResult(result);
1874  }
1875 
1876  if (timing)
1877  {
1878  INSTR_TIME_SET_CURRENT(after);
1879  INSTR_TIME_SUBTRACT(after, before);
1880  *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
1881  }
1882 
1883  return OK;
1884 }
static bool StoreQueryTuple(const PGresult *result)
Definition: common.c:720
bool openQueryOutputFile(const char *fname, FILE **fout, bool *is_pipe)
Definition: common.c:53
static void cleanup(void)
Definition: bootstrap.c:697
#define INT64_FORMAT
Definition: c.h:483
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:6863
void restore_sigpipe_trap(void)
Definition: print.c:3018
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3490
void ClosePager(FILE *pagerpipe)
Definition: print.c:3096
void disable_sigpipe_trap(void)
Definition: print.c:2995
FILE * PageOutput(int lines, const printTableOpt *topt)
Definition: print.c:3045
@ PQTRANS_IDLE
Definition: libpq-fe.h:118
#define snprintf
Definition: port.h:225
printQueryOpt popt
Definition: settings.h:91
char * gset_prefix
Definition: settings.h:96
VariableSpace vars
Definition: settings.h:118
FILE * logfile
Definition: settings.h:116
char * gfname
Definition: settings.h:93
int fetch_count
Definition: settings.h:139
printTableOpt topt
Definition: print.h:169
bool start_table
Definition: print.h:111
unsigned long prior_records
Definition: print.h:114
bool stop_table
Definition: print.h:112
bool SetVariable(VariableSpace space, const char *name, const char *value)
Definition: variables.c:211

References AcceptResult(), appendPQExpBuffer(), Assert(), before(), buf, cancel_pressed, cleanup(), ClearOrSaveResult(), ClosePager(), _psqlSettings::db, disable_sigpipe_trap(), _psqlSettings::fetch_count, fflush(), _psqlSettings::gfname, _psqlSettings::gset_prefix, initPQExpBuffer(), INSTR_TIME_GET_MILLISEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, INT64_FORMAT, _psqlSettings::logfile, openQueryOutputFile(), PageOutput(), PGRES_COMMAND_OK, PGRES_TUPLES_OK, _psqlSettings::popt, PQclear(), PQexec(), PQntuples(), PQresultStatus(), PQTRANS_IDLE, PQtransactionStatus(), printQuery(), printTableOpt::prior_records, pset, _psqlSettings::queryFout, restore_sigpipe_trap(), SetResultVariables(), SetVariable(), snprintf, printTableOpt::start_table, generate_unaccent_rules::stdout, printTableOpt::stop_table, StoreQueryTuple(), termPQExpBuffer(), _psqlSettings::timing, printQueryOpt::topt, and _psqlSettings::vars.

Referenced by SendQuery().

◆ expand_tilde()

void expand_tilde ( char **  filename)

Definition at line 2268 of file common.c.

2269 {
2270  if (!filename || !(*filename))
2271  return;
2272 
2273  /*
2274  * WIN32 doesn't use tilde expansion for file names. Also, it uses tilde
2275  * for short versions of long file names, though the tilde is usually
2276  * toward the end, not at the beginning.
2277  */
2278 #ifndef WIN32
2279 
2280  /* try tilde expansion */
2281  if (**filename == '~')
2282  {
2283  char *fn;
2284  char oldp,
2285  *p;
2286  struct passwd *pw;
2287  char home[MAXPGPATH];
2288 
2289  fn = *filename;
2290  *home = '\0';
2291 
2292  p = fn + 1;
2293  while (*p != '/' && *p != '\0')
2294  p++;
2295 
2296  oldp = *p;
2297  *p = '\0';
2298 
2299  if (*(fn + 1) == '\0')
2300  get_home_path(home); /* ~ or ~/ only */
2301  else if ((pw = getpwnam(fn + 1)) != NULL)
2302  strlcpy(home, pw->pw_dir, sizeof(home)); /* ~user */
2303 
2304  *p = oldp;
2305  if (strlen(home) != 0)
2306  {
2307  char *newfn;
2308 
2309  newfn = psprintf("%s%s", home, p);
2310  free(fn);
2311  *filename = newfn;
2312  }
2313  }
2314 #endif
2315 }
#define free(a)
Definition: header.h:65
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:94
bool get_home_path(char *ret_path)
Definition: path.c:928
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static void * fn(void *arg)

References filename, fn(), free, get_home_path(), MAXPGPATH, psprintf(), and strlcpy().

Referenced by exec_command_edit(), exec_command_g(), exec_command_include(), exec_command_lo(), exec_command_out(), exec_command_s(), exec_command_write(), initializeInput(), parse_slash_copy(), and process_psqlrc().

◆ HandleCopyResult()

static bool HandleCopyResult ( PGresult **  resultp)
static

Definition at line 864 of file common.c.

865 {
866  bool success;
867  FILE *copystream;
868  PGresult *copy_result;
869  ExecStatusType result_status = PQresultStatus(*resultp);
870 
871  Assert(result_status == PGRES_COPY_OUT ||
872  result_status == PGRES_COPY_IN);
873 
875 
876  if (result_status == PGRES_COPY_OUT)
877  {
878  bool need_close = false;
879  bool is_pipe = false;
880 
881  if (pset.copyStream)
882  {
883  /* invoked by \copy */
884  copystream = pset.copyStream;
885  }
886  else if (pset.gfname)
887  {
888  /* invoked by \g */
890  &copystream, &is_pipe))
891  {
892  need_close = true;
893  if (is_pipe)
895  }
896  else
897  copystream = NULL; /* discard COPY data entirely */
898  }
899  else
900  {
901  /* fall back to the generic query output stream */
902  copystream = pset.queryFout;
903  }
904 
906  copystream,
907  &copy_result)
908  && (copystream != NULL);
909 
910  /*
911  * Suppress status printing if the report would go to the same place
912  * as the COPY data just went. Note this doesn't prevent error
913  * reporting, since handleCopyOut did that.
914  */
915  if (copystream == pset.queryFout)
916  {
917  PQclear(copy_result);
918  copy_result = NULL;
919  }
920 
921  if (need_close)
922  {
923  /* close \g argument file/pipe */
924  if (is_pipe)
925  {
926  pclose(copystream);
928  }
929  else
930  {
931  fclose(copystream);
932  }
933  }
934  }
935  else
936  {
937  /* COPY IN */
940  copystream,
941  PQbinaryTuples(*resultp),
942  &copy_result);
943  }
944  ResetCancelConn();
945 
946  /*
947  * Replace the PGRES_COPY_OUT/IN result with COPY command's exit status,
948  * or with NULL if we want to suppress printing anything.
949  */
950  PQclear(*resultp);
951  *resultp = copy_result;
952 
953  return success;
954 }
bool handleCopyOut(PGconn *conn, FILE *copystream, PGresult **res)
Definition: copy.c:436
bool handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
Definition: copy.c:513
void SetCancelConn(PGconn *conn)
Definition: cancel.c:77
int PQbinaryTuples(const PGresult *res)
Definition: fe-exec.c:3356
FILE * copyStream
Definition: settings.h:87
FILE * cur_cmd_source
Definition: settings.h:105

References Assert(), _psqlSettings::copyStream, _psqlSettings::cur_cmd_source, _psqlSettings::db, disable_sigpipe_trap(), _psqlSettings::gfname, handleCopyIn(), handleCopyOut(), openQueryOutputFile(), PGRES_COPY_IN, PGRES_COPY_OUT, PQbinaryTuples(), PQclear(), PQresultStatus(), pset, _psqlSettings::queryFout, ResetCancelConn(), restore_sigpipe_trap(), SetCancelConn(), and success.

Referenced by ExecQueryAndProcessResults().

◆ is_select_command()

static bool is_select_command ( const char *  query)
static

Definition at line 2170 of file common.c.

2171 {
2172  int wordlen;
2173 
2174  /*
2175  * First advance over any whitespace, comments and left parentheses.
2176  */
2177  for (;;)
2178  {
2179  query = skip_white_space(query);
2180  if (query[0] == '(')
2181  query++;
2182  else
2183  break;
2184  }
2185 
2186  /*
2187  * Check word length (since "selectx" is not "select").
2188  */
2189  wordlen = 0;
2190  while (isalpha((unsigned char) query[wordlen]))
2191  wordlen += PQmblenBounded(&query[wordlen], pset.encoding);
2192 
2193  if (wordlen == 6 && pg_strncasecmp(query, "select", 6) == 0)
2194  return true;
2195 
2196  if (wordlen == 6 && pg_strncasecmp(query, "values", 6) == 0)
2197  return true;
2198 
2199  return false;
2200 }

References _psqlSettings::encoding, pg_strncasecmp(), PQmblenBounded(), pset, and skip_white_space().

Referenced by SendQuery().

◆ is_superuser()

bool is_superuser ( void  )

Definition at line 2207 of file common.c.

2208 {
2209  const char *val;
2210 
2211  if (!pset.db)
2212  return false;
2213 
2214  val = PQparameterStatus(pset.db, "is_superuser");
2215 
2216  if (val && strcmp(val, "on") == 0)
2217  return true;
2218 
2219  return false;
2220 }
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
Definition: fe-connect.c:6873
long val
Definition: informix.c:664

References _psqlSettings::db, PQparameterStatus(), pset, and val.

◆ NoticeProcessor()

void NoticeProcessor ( void *  arg,
const char *  message 
)

Definition at line 223 of file common.c.

224 {
225  (void) arg; /* not used */
226  pg_log_info("%s", message);
227 }
void * arg

References arg, and pg_log_info.

Referenced by do_connect(), and main().

◆ openQueryOutputFile()

bool openQueryOutputFile ( const char *  fname,
FILE **  fout,
bool is_pipe 
)

Definition at line 53 of file common.c.

54 {
55  if (!fname || fname[0] == '\0')
56  {
57  *fout = stdout;
58  *is_pipe = false;
59  }
60  else if (*fname == '|')
61  {
62  *fout = popen(fname + 1, "w");
63  *is_pipe = true;
64  }
65  else
66  {
67  *fout = fopen(fname, "w");
68  *is_pipe = false;
69  }
70 
71  if (*fout == NULL)
72  {
73  pg_log_error("%s: %m", fname);
74  return false;
75  }
76 
77  return true;
78 }

References pg_log_error, and generate_unaccent_rules::stdout.

Referenced by ExecQueryUsingCursor(), HandleCopyResult(), PrintQueryTuples(), and setQFout().

◆ PrintNotifications()

static void PrintNotifications ( void  )
static

Definition at line 641 of file common.c.

642 {
643  PGnotify *notify;
644 
646  while ((notify = PQnotifies(pset.db)) != NULL)
647  {
648  /* for backward compatibility, only show payload if nonempty */
649  if (notify->extra[0])
650  fprintf(pset.queryFout, _("Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n"),
651  notify->relname, notify->extra, notify->be_pid);
652  else
653  fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
654  notify->relname, notify->be_pid);
656  PQfreemem(notify);
658  }
659 }
PGnotify * PQnotifies(PGconn *conn)
Definition: fe-exec.c:2599
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:2004
int be_pid
Definition: libpq-fe.h:190
char * relname
Definition: libpq-fe.h:189
char * extra
Definition: libpq-fe.h:191

References _, pgNotify::be_pid, _psqlSettings::db, pgNotify::extra, fflush(), fprintf, PQconsumeInput(), PQfreemem(), PQnotifies(), pset, _psqlSettings::queryFout, and pgNotify::relname.

Referenced by SendQuery().

◆ PrintQueryResult()

static bool PrintQueryResult ( PGresult result,
bool  last,
bool  is_watch,
const printQueryOpt opt,
FILE *  printQueryFout 
)
static

Definition at line 995 of file common.c.

996 {
997  bool success;
998  const char *cmdstatus;
999 
1000  if (!result)
1001  return false;
1002 
1003  switch (PQresultStatus(result))
1004  {
1005  case PGRES_TUPLES_OK:
1006  /* store or execute or print the data ... */
1007  if (last && pset.gset_prefix)
1008  success = StoreQueryTuple(result);
1009  else if (last && pset.gexec_flag)
1010  success = ExecQueryTuples(result);
1011  else if (last && pset.crosstab_flag)
1012  success = PrintResultInCrosstab(result);
1013  else if (last || pset.show_all_results)
1014  success = PrintQueryTuples(result, opt, printQueryFout);
1015  else
1016  success = true;
1017 
1018  /* if it's INSERT/UPDATE/DELETE RETURNING, also print status */
1019  if (last || pset.show_all_results)
1020  {
1021  cmdstatus = PQcmdStatus(result);
1022  if (strncmp(cmdstatus, "INSERT", 6) == 0 ||
1023  strncmp(cmdstatus, "UPDATE", 6) == 0 ||
1024  strncmp(cmdstatus, "DELETE", 6) == 0)
1025  PrintQueryStatus(result, printQueryFout);
1026  }
1027 
1028  break;
1029 
1030  case PGRES_COMMAND_OK:
1031  if (last || pset.show_all_results)
1032  PrintQueryStatus(result, printQueryFout);
1033  success = true;
1034  break;
1035 
1036  case PGRES_EMPTY_QUERY:
1037  success = true;
1038  break;
1039 
1040  case PGRES_COPY_OUT:
1041  case PGRES_COPY_IN:
1042  /* nothing to do here: already processed */
1043  success = true;
1044  break;
1045 
1046  case PGRES_BAD_RESPONSE:
1047  case PGRES_NONFATAL_ERROR:
1048  case PGRES_FATAL_ERROR:
1049  success = false;
1050  break;
1051 
1052  default:
1053  success = false;
1054  pg_log_error("unexpected PQresultStatus: %d",
1055  PQresultStatus(result));
1056  break;
1057  }
1058 
1059  fflush(printQueryFout ? printQueryFout : pset.queryFout);
1060 
1061  return success;
1062 }
static void PrintQueryStatus(PGresult *result, FILE *printQueryFout)
Definition: common.c:962
static bool ExecQueryTuples(const PGresult *result)
Definition: common.c:784
static bool PrintQueryTuples(const PGresult *result, const printQueryOpt *opt, FILE *printQueryFout)
Definition: common.c:668
bool PrintResultInCrosstab(const PGresult *res)
Definition: crosstabview.c:103
bool show_all_results
Definition: settings.h:151
bool crosstab_flag
Definition: settings.h:99

References _psqlSettings::crosstab_flag, ExecQueryTuples(), fflush(), _psqlSettings::gexec_flag, _psqlSettings::gset_prefix, pg_log_error, PGRES_BAD_RESPONSE, PGRES_COMMAND_OK, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, PGRES_TUPLES_OK, PQcmdStatus(), PQresultStatus(), PrintQueryStatus(), PrintQueryTuples(), PrintResultInCrosstab(), pset, _psqlSettings::queryFout, _psqlSettings::show_all_results, StoreQueryTuple(), and success.

Referenced by DescribeQuery(), and ExecQueryAndProcessResults().

◆ PrintQueryStatus()

static void PrintQueryStatus ( PGresult result,
FILE *  printQueryFout 
)
static

Definition at line 962 of file common.c.

963 {
964  char buf[16];
965  FILE *fout = printQueryFout ? printQueryFout : pset.queryFout;
966 
967  if (!pset.quiet)
968  {
969  if (pset.popt.topt.format == PRINT_HTML)
970  {
971  fputs("<p>", fout);
972  html_escaped_print(PQcmdStatus(result), fout);
973  fputs("</p>\n", fout);
974  }
975  else
976  fprintf(fout, "%s\n", PQcmdStatus(result));
977  }
978 
979  if (pset.logfile)
980  fprintf(pset.logfile, "%s\n", PQcmdStatus(result));
981 
982  snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(result));
983  SetVariable(pset.vars, "LASTOID", buf);
984 }
Oid PQoidValue(const PGresult *res)
Definition: fe-exec.c:3652
void html_escaped_print(const char *in, FILE *fout)
Definition: print.c:1908
@ PRINT_HTML
Definition: print.h:34
enum printFormat format
Definition: print.h:101

References buf, printTableOpt::format, fprintf, html_escaped_print(), _psqlSettings::logfile, _psqlSettings::popt, PQcmdStatus(), PQoidValue(), PRINT_HTML, pset, _psqlSettings::queryFout, _psqlSettings::quiet, SetVariable(), snprintf, printQueryOpt::topt, and _psqlSettings::vars.

Referenced by PrintQueryResult().

◆ PrintQueryTuples()

static bool PrintQueryTuples ( const PGresult result,
const printQueryOpt opt,
FILE *  printQueryFout 
)
static

Definition at line 668 of file common.c.

669 {
670  bool ok = true;
671 
672  /* write output to \g argument, if any */
673  if (pset.gfname)
674  {
675  FILE *fout;
676  bool is_pipe;
677 
678  if (!openQueryOutputFile(pset.gfname, &fout, &is_pipe))
679  return false;
680  if (is_pipe)
682 
683  printQuery(result, &pset.popt, fout, false, pset.logfile);
684  if (ferror(fout))
685  {
686  pg_log_error("could not print result table: %m");
687  ok = false;
688  }
689 
690  if (is_pipe)
691  {
692  pclose(fout);
694  }
695  else
696  fclose(fout);
697  }
698  else
699  {
700  FILE *fout = printQueryFout ? printQueryFout : pset.queryFout;
701 
702  printQuery(result, opt ? opt : &pset.popt, fout, false, pset.logfile);
703  if (ferror(fout))
704  {
705  pg_log_error("could not print result table: %m");
706  ok = false;
707  }
708  }
709 
710  return ok;
711 }

References disable_sigpipe_trap(), _psqlSettings::gfname, _psqlSettings::logfile, openQueryOutputFile(), pg_log_error, _psqlSettings::popt, printQuery(), pset, _psqlSettings::queryFout, and restore_sigpipe_trap().

Referenced by PrintQueryResult().

◆ PrintTiming()

static void PrintTiming ( double  elapsed_msec)
static

Definition at line 497 of file common.c.

498 {
499  double seconds;
500  double minutes;
501  double hours;
502  double days;
503 
504  if (elapsed_msec < 1000.0)
505  {
506  /* This is the traditional (pre-v10) output format */
507  printf(_("Time: %.3f ms\n"), elapsed_msec);
508  return;
509  }
510 
511  /*
512  * Note: we could print just seconds, in a format like %06.3f, when the
513  * total is less than 1min. But that's hard to interpret unless we tack
514  * on "s" or otherwise annotate it. Forcing the display to include
515  * minutes seems like a better solution.
516  */
517  seconds = elapsed_msec / 1000.0;
518  minutes = floor(seconds / 60.0);
519  seconds -= 60.0 * minutes;
520  if (minutes < 60.0)
521  {
522  printf(_("Time: %.3f ms (%02d:%06.3f)\n"),
523  elapsed_msec, (int) minutes, seconds);
524  return;
525  }
526 
527  hours = floor(minutes / 60.0);
528  minutes -= 60.0 * hours;
529  if (hours < 24.0)
530  {
531  printf(_("Time: %.3f ms (%02d:%02d:%06.3f)\n"),
532  elapsed_msec, (int) hours, (int) minutes, seconds);
533  return;
534  }
535 
536  days = floor(hours / 24.0);
537  hours -= 24.0 * days;
538  printf(_("Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n"),
539  elapsed_msec, days, (int) hours, (int) minutes, seconds);
540 }
const char *const days[]
Definition: datetime.c:83
#define printf(...)
Definition: port.h:231

References _, days, and printf.

Referenced by PSQLexecWatch(), and SendQuery().

◆ psql_cancel_callback()

static void psql_cancel_callback ( void  )
static

Definition at line 253 of file common.c.

254 {
255 #ifndef WIN32
256  /* if we are waiting for input, longjmp out of it */
258  {
259  sigint_interrupt_enabled = false;
260  siglongjmp(sigint_interrupt_jmp, 1);
261  }
262 #endif
263 
264  /* else, set cancel flag to stop any long-running loops */
265  cancel_pressed = true;
266 }
sigjmp_buf sigint_interrupt_jmp
Definition: common.c:250
volatile bool sigint_interrupt_enabled
Definition: common.c:248

References cancel_pressed, sigint_interrupt_enabled, and sigint_interrupt_jmp.

Referenced by psql_setup_cancel_handler().

◆ psql_get_variable()

char* psql_get_variable ( const char *  varname,
PsqlScanQuoteType  quote,
void *  passthrough 
)

Definition at line 132 of file common.c.

134 {
135  char *result = NULL;
136  const char *value;
137 
138  /* In an inactive \if branch, suppress all variable substitutions */
139  if (passthrough && !conditional_active((ConditionalStack) passthrough))
140  return NULL;
141 
142  value = GetVariable(pset.vars, varname);
143  if (!value)
144  return NULL;
145 
146  switch (quote)
147  {
148  case PQUOTE_PLAIN:
149  result = pg_strdup(value);
150  break;
151  case PQUOTE_SQL_LITERAL:
152  case PQUOTE_SQL_IDENT:
153  {
154  /*
155  * For these cases, we use libpq's quoting functions, which
156  * assume the string is in the connection's client encoding.
157  */
158  char *escaped_value;
159 
160  if (!pset.db)
161  {
162  pg_log_error("cannot escape without active connection");
163  return NULL;
164  }
165 
166  if (quote == PQUOTE_SQL_LITERAL)
167  escaped_value =
168  PQescapeLiteral(pset.db, value, strlen(value));
169  else
170  escaped_value =
171  PQescapeIdentifier(pset.db, value, strlen(value));
172 
173  if (escaped_value == NULL)
174  {
175  const char *error = PQerrorMessage(pset.db);
176 
177  pg_log_info("%s", error);
178  return NULL;
179  }
180 
181  /*
182  * Rather than complicate the lexer's API with a notion of
183  * which free() routine to use, just pay the price of an extra
184  * strdup().
185  */
186  result = pg_strdup(escaped_value);
187  PQfreemem(escaped_value);
188  break;
189  }
190  case PQUOTE_SHELL_ARG:
191  {
192  /*
193  * For this we use appendShellStringNoError, which is
194  * encoding-agnostic, which is fine since the shell probably
195  * is too. In any case, the only special character is "'",
196  * which is not known to appear in valid multibyte characters.
197  */
199 
202  {
203  pg_log_error("shell command argument contains a newline or carriage return: \"%s\"",
204  value);
205  free(buf.data);
206  return NULL;
207  }
208  result = buf.data;
209  break;
210  }
211 
212  /* No default: we want a compiler warning for missing cases */
213  }
214 
215  return result;
216 }
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:140
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
Definition: fe-exec.c:4172
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static struct @151 value
@ PQUOTE_SQL_LITERAL
Definition: psqlscan.h:55
@ PQUOTE_PLAIN
Definition: psqlscan.h:54
@ PQUOTE_SHELL_ARG
Definition: psqlscan.h:57
@ PQUOTE_SQL_IDENT
Definition: psqlscan.h:56
bool appendShellStringNoError(PQExpBuffer buf, const char *str)
Definition: string_utils.c:441
const char * GetVariable(VariableSpace space, const char *name)
Definition: variables.c:71

References appendShellStringNoError(), buf, conditional_active(), _psqlSettings::db, error(), free, GetVariable(), initPQExpBuffer(), pg_log_error, pg_log_info, pg_strdup(), PQerrorMessage(), PQescapeIdentifier(), PQescapeLiteral(), PQfreemem(), PQUOTE_PLAIN, PQUOTE_SHELL_ARG, PQUOTE_SQL_IDENT, PQUOTE_SQL_LITERAL, pset, value, and _psqlSettings::vars.

◆ psql_setup_cancel_handler()

void psql_setup_cancel_handler ( void  )

Definition at line 269 of file common.c.

270 {
272 }
static void setup_cancel_handler(void)
Definition: parallel.c:610
static void psql_cancel_callback(void)
Definition: common.c:253

References psql_cancel_callback(), and setup_cancel_handler().

Referenced by main().

◆ PSQLexec()

PGresult* PSQLexec ( const char *  query)

Definition at line 556 of file common.c.

557 {
558  PGresult *res;
559 
560  if (!pset.db)
561  {
562  pg_log_error("You are currently not connected to a database.");
563  return NULL;
564  }
565 
567  {
568  printf(_("********* QUERY **********\n"
569  "%s\n"
570  "**************************\n\n"), query);
571  fflush(stdout);
572  if (pset.logfile)
573  {
575  _("********* QUERY **********\n"
576  "%s\n"
577  "**************************\n\n"), query);
579  }
580 
582  return NULL;
583  }
584 
586 
587  res = PQexec(pset.db, query);
588 
589  ResetCancelConn();
590 
591  if (!AcceptResult(res, true))
592  {
594  res = NULL;
595  }
596 
597  return res;
598 }
@ PSQL_ECHO_HIDDEN_NOEXEC
Definition: settings.h:47
@ PSQL_ECHO_HIDDEN_OFF
Definition: settings.h:45
PSQL_ECHO_HIDDEN echo_hidden
Definition: settings.h:143

References _, AcceptResult(), ClearOrSaveResult(), _psqlSettings::db, _psqlSettings::echo_hidden, fflush(), fprintf, _psqlSettings::logfile, pg_log_error, PQexec(), printf, pset, PSQL_ECHO_HIDDEN_NOEXEC, PSQL_ECHO_HIDDEN_OFF, res, ResetCancelConn(), SetCancelConn(), and generate_unaccent_rules::stdout.

Referenced by add_tablespace_footer(), addFooterToPublicationDesc(), describeAccessMethods(), describeAggregates(), describeConfigurationParameters(), describeFunctions(), describeOneTableDetails(), describeOneTSConfig(), describeOneTSParser(), describeOperators(), describePublications(), describeRoles(), describeSubscriptions(), describeTableDetails(), describeTablespaces(), describeTypes(), do_lo_import(), exec_command_password(), fail_lo_xact(), finish_lo_xact(), listAllDbs(), listCasts(), listCollations(), listConversions(), listDbRoleSettings(), listDefaultACLs(), listDomains(), listEventTriggers(), listExtendedStats(), listExtensionContents(), listExtensions(), listForeignDataWrappers(), listForeignServers(), listForeignTables(), listLanguages(), listLargeObjects(), listOneExtensionContents(), listOperatorClasses(), listOperatorFamilies(), listOpFamilyFunctions(), listOpFamilyOperators(), listPartitionedTables(), listPublications(), listSchemas(), listTables(), listTSConfigs(), listTSConfigsVerbose(), listTSDictionaries(), listTSParsers(), listTSParsersVerbose(), listTSTemplates(), listUserMappings(), main(), objectDescription(), permissionsList(), and start_lo_xact().

◆ PSQLexecWatch()

int PSQLexecWatch ( const char *  query,
const printQueryOpt opt,
FILE *  printQueryFout 
)

Definition at line 611 of file common.c.

612 {
613  bool timing = pset.timing;
614  double elapsed_msec = 0;
615  int res;
616 
617  if (!pset.db)
618  {
619  pg_log_error("You are currently not connected to a database.");
620  return 0;
621  }
622 
624 
625  res = ExecQueryAndProcessResults(query, &elapsed_msec, NULL, true, opt, printQueryFout);
626 
627  ResetCancelConn();
628 
629  /* Possible microtiming output */
630  if (timing)
631  PrintTiming(elapsed_msec);
632 
633  return res;
634 }
static int ExecQueryAndProcessResults(const char *query, double *elapsed_msec, bool *svpt_gone_p, bool is_watch, const printQueryOpt *opt, FILE *printQueryFout)
Definition: common.c:1440
static void PrintTiming(double elapsed_msec)
Definition: common.c:497

References _psqlSettings::db, ExecQueryAndProcessResults(), pg_log_error, PrintTiming(), pset, res, ResetCancelConn(), SetCancelConn(), and _psqlSettings::timing.

Referenced by do_watch().

◆ recognized_connection_string()

static bool recognized_connection_string ( const char *  connstr)

Definition at line 2353 of file common.c.

2354 {
2355  return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
2356 }
static int uri_prefix_length(const char *connstr)
Definition: common.c:2326
static char * connstr
Definition: pg_dumpall.c:63

References connstr, and uri_prefix_length().

Referenced by do_connect().

◆ SendQuery()

bool SendQuery ( const char *  query)

Definition at line 1077 of file common.c.

1078 {
1079  bool timing = pset.timing;
1080  PGTransactionStatusType transaction_status;
1081  double elapsed_msec = 0;
1082  bool OK = false;
1083  int i;
1084  bool on_error_rollback_savepoint = false;
1085  bool svpt_gone = false;
1086 
1087  if (!pset.db)
1088  {
1089  pg_log_error("You are currently not connected to a database.");
1090  goto sendquery_cleanup;
1091  }
1092 
1093  if (pset.singlestep)
1094  {
1095  char buf[3];
1096 
1097  fflush(stderr);
1098  printf(_("***(Single step mode: verify command)*******************************************\n"
1099  "%s\n"
1100  "***(press return to proceed or enter x and return to cancel)********************\n"),
1101  query);
1102  fflush(stdout);
1103  if (fgets(buf, sizeof(buf), stdin) != NULL)
1104  if (buf[0] == 'x')
1105  goto sendquery_cleanup;
1106  if (cancel_pressed)
1107  goto sendquery_cleanup;
1108  }
1109  else if (pset.echo == PSQL_ECHO_QUERIES)
1110  {
1111  puts(query);
1112  fflush(stdout);
1113  }
1114 
1115  if (pset.logfile)
1116  {
1118  _("********* QUERY **********\n"
1119  "%s\n"
1120  "**************************\n\n"), query);
1121  fflush(pset.logfile);
1122  }
1123 
1125 
1126  transaction_status = PQtransactionStatus(pset.db);
1127 
1128  if (transaction_status == PQTRANS_IDLE &&
1129  !pset.autocommit &&
1130  !command_no_begin(query))
1131  {
1132  PGresult *result;
1133 
1134  result = PQexec(pset.db, "BEGIN");
1135  if (PQresultStatus(result) != PGRES_COMMAND_OK)
1136  {
1138  ClearOrSaveResult(result);
1139  goto sendquery_cleanup;
1140  }
1141  ClearOrSaveResult(result);
1142  transaction_status = PQtransactionStatus(pset.db);
1143  }
1144 
1145  if (transaction_status == PQTRANS_INTRANS &&
1149  {
1150  PGresult *result;
1151 
1152  result = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");
1153  if (PQresultStatus(result) != PGRES_COMMAND_OK)
1154  {
1156  ClearOrSaveResult(result);
1157  goto sendquery_cleanup;
1158  }
1159  ClearOrSaveResult(result);
1160  on_error_rollback_savepoint = true;
1161  }
1162 
1163  if (pset.gdesc_flag)
1164  {
1165  /* Describe query's result columns, without executing it */
1166  OK = DescribeQuery(query, &elapsed_msec);
1167  }
1168  else if (pset.fetch_count <= 0 || pset.gexec_flag ||
1170  {
1171  /* Default fetch-it-all-and-print mode */
1172  OK = (ExecQueryAndProcessResults(query, &elapsed_msec, &svpt_gone, false, NULL, NULL) >= 0);
1173  }
1174  else
1175  {
1176  /* Fetch-in-segments mode */
1177  OK = ExecQueryUsingCursor(query, &elapsed_msec);
1178  }
1179 
1180  if (!OK && pset.echo == PSQL_ECHO_ERRORS)
1181  pg_log_info("STATEMENT: %s", query);
1182 
1183  /* If we made a temporary savepoint, possibly release/rollback */
1184  if (on_error_rollback_savepoint)
1185  {
1186  const char *svptcmd = NULL;
1187 
1188  transaction_status = PQtransactionStatus(pset.db);
1189 
1190  switch (transaction_status)
1191  {
1192  case PQTRANS_INERROR:
1193  /* We always rollback on an error */
1194  svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
1195  break;
1196 
1197  case PQTRANS_IDLE:
1198  /* If they are no longer in a transaction, then do nothing */
1199  break;
1200 
1201  case PQTRANS_INTRANS:
1202 
1203  /*
1204  * Release our savepoint, but do nothing if they are messing
1205  * with savepoints themselves
1206  */
1207  if (!svpt_gone)
1208  svptcmd = "RELEASE pg_psql_temporary_savepoint";
1209  break;
1210 
1211  case PQTRANS_ACTIVE:
1212  case PQTRANS_UNKNOWN:
1213  default:
1214  OK = false;
1215  /* PQTRANS_UNKNOWN is expected given a broken connection. */
1216  if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp())
1217  pg_log_error("unexpected transaction status (%d)",
1218  transaction_status);
1219  break;
1220  }
1221 
1222  if (svptcmd)
1223  {
1224  PGresult *svptres;
1225 
1226  svptres = PQexec(pset.db, svptcmd);
1227  if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
1228  {
1230  ClearOrSaveResult(svptres);
1231  OK = false;
1232 
1233  goto sendquery_cleanup;
1234  }
1235  PQclear(svptres);
1236  }
1237  }
1238 
1239  /* Possible microtiming output */
1240  if (timing)
1241  PrintTiming(elapsed_msec);
1242 
1243  /* check for events that may occur during query execution */
1244 
1245  if (pset.encoding != PQclientEncoding(pset.db) &&
1246  PQclientEncoding(pset.db) >= 0)
1247  {
1248  /* track effects of SET CLIENT_ENCODING */
1251  SetVariable(pset.vars, "ENCODING",
1253  }
1254 
1256 
1257  /* perform cleanup that should occur after any attempted query */
1258 
1259 sendquery_cleanup:
1260 
1261  /* global cancellation reset */
1262  ResetCancelConn();
1263 
1264  /* reset \g's output-to-filename trigger */
1265  if (pset.gfname)
1266  {
1267  free(pset.gfname);
1268  pset.gfname = NULL;
1269  }
1270 
1271  /* restore print settings if \g changed them */
1272  if (pset.gsavepopt)
1273  {
1275  pset.gsavepopt = NULL;
1276  }
1277 
1278  /* reset \gset trigger */
1279  if (pset.gset_prefix)
1280  {
1282  pset.gset_prefix = NULL;
1283  }
1284 
1285  /* reset \gdesc trigger */
1286  pset.gdesc_flag = false;
1287 
1288  /* reset \gexec trigger */
1289  pset.gexec_flag = false;
1290 
1291  /* reset \crosstabview trigger */
1292  pset.crosstab_flag = false;
1293  for (i = 0; i < lengthof(pset.ctv_args); i++)
1294  {
1295  pg_free(pset.ctv_args[i]);
1296  pset.ctv_args[i] = NULL;
1297  }
1298 
1299  return OK;
1300 }
static bool DescribeQuery(const char *query, double *elapsed_msec)
Definition: common.c:1312
static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec)
Definition: common.c:1632
static void PrintNotifications(void)
Definition: common.c:641
static bool is_select_command(const char *query)
Definition: common.c:2170
static bool command_no_begin(const char *query)
Definition: common.c:1955
#define lengthof(array)
Definition: c.h:734
void restorePsetInfo(printQueryOpt *popt, printQueryOpt *save)
Definition: command.c:4778
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
int PQclientEncoding(const PGconn *conn)
Definition: fe-connect.c:6985
void pg_free(void *ptr)
Definition: fe_memutils.c:105
PGTransactionStatusType
Definition: libpq-fe.h:117
@ PQTRANS_INTRANS
Definition: libpq-fe.h:120
@ PQTRANS_ACTIVE
Definition: libpq-fe.h:119
@ PQTRANS_UNKNOWN
Definition: libpq-fe.h:122
@ PQTRANS_INERROR
Definition: libpq-fe.h:121
@ PSQL_ERROR_ROLLBACK_ON
Definition: settings.h:54
@ PSQL_ERROR_ROLLBACK_OFF
Definition: settings.h:52
@ PSQL_ECHO_ERRORS
Definition: settings.h:39
@ PSQL_ECHO_QUERIES
Definition: settings.h:38
PSQL_ERROR_ROLLBACK on_error_rollback
Definition: settings.h:144
bool autocommit
Definition: settings.h:132
char * ctv_args[4]
Definition: settings.h:100
printQueryOpt * gsavepopt
Definition: settings.h:94
bool gdesc_flag
Definition: settings.h:97
int encoding
Definition: print.h:122

References _, _psqlSettings::autocommit, buf, cancel_pressed, ClearOrSaveResult(), command_no_begin(), ConnectionUp(), _psqlSettings::crosstab_flag, _psqlSettings::ctv_args, _psqlSettings::cur_cmd_interactive, _psqlSettings::db, DescribeQuery(), _psqlSettings::echo, _psqlSettings::encoding, printTableOpt::encoding, ExecQueryAndProcessResults(), ExecQueryUsingCursor(), _psqlSettings::fetch_count, fflush(), fprintf, free, _psqlSettings::gdesc_flag, _psqlSettings::gexec_flag, _psqlSettings::gfname, _psqlSettings::gsavepopt, _psqlSettings::gset_prefix, i, is_select_command(), lengthof, _psqlSettings::logfile, _psqlSettings::on_error_rollback, pg_encoding_to_char(), pg_free(), pg_log_error, pg_log_info, PGRES_COMMAND_OK, _psqlSettings::popt, PQclear(), PQclientEncoding(), PQerrorMessage(), PQexec(), PQresultStatus(), PQTRANS_ACTIVE, PQTRANS_IDLE, PQTRANS_INERROR, PQTRANS_INTRANS, PQTRANS_UNKNOWN, PQtransactionStatus(), printf, PrintNotifications(), PrintTiming(), pset, PSQL_ECHO_ERRORS, PSQL_ECHO_QUERIES, PSQL_ERROR_ROLLBACK_OFF, PSQL_ERROR_ROLLBACK_ON, ResetCancelConn(), restorePsetInfo(), SetCancelConn(), SetVariable(), _psqlSettings::singlestep, generate_unaccent_rules::stdout, _psqlSettings::timing, printQueryOpt::topt, and _psqlSettings::vars.

Referenced by do_copy(), ExecQueryTuples(), main(), and MainLoop().

◆ session_username()

const char* session_username ( void  )

Definition at line 2247 of file common.c.

2248 {
2249  const char *val;
2250 
2251  if (!pset.db)
2252  return NULL;
2253 
2254  val = PQparameterStatus(pset.db, "session_authorization");
2255  if (val)
2256  return val;
2257  else
2258  return PQuser(pset.db);
2259 }
char * PQuser(const PGconn *conn)
Definition: fe-connect.c:6762

References _psqlSettings::db, PQparameterStatus(), PQuser(), pset, and val.

Referenced by get_prompt().

◆ setQFout()

bool setQFout ( const char *  fname)

Definition at line 88 of file common.c.

89 {
90  FILE *fout;
91  bool is_pipe;
92 
93  /* First make sure we can open the new output file/pipe */
94  if (!openQueryOutputFile(fname, &fout, &is_pipe))
95  return false;
96 
97  /* Close old file/pipe */
98  if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
99  {
100  if (pset.queryFoutPipe)
101  pclose(pset.queryFout);
102  else
103  fclose(pset.queryFout);
104  }
105 
106  pset.queryFout = fout;
107  pset.queryFoutPipe = is_pipe;
108 
109  /* Adjust SIGPIPE handling appropriately: ignore signal if is_pipe */
110  set_sigpipe_trap_state(is_pipe);
112 
113  return true;
114 }
void set_sigpipe_trap_state(bool ignore)
Definition: print.c:3031
bool queryFoutPipe
Definition: settings.h:85

References openQueryOutputFile(), pset, _psqlSettings::queryFout, _psqlSettings::queryFoutPipe, restore_sigpipe_trap(), set_sigpipe_trap_state(), and generate_unaccent_rules::stdout.

Referenced by exec_command_out(), main(), and parse_psql_options().

◆ SetResultVariables()

static void SetResultVariables ( PGresult result,
bool  success 
)
static

Definition at line 416 of file common.c.

417 {
418  if (success)
419  {
420  const char *ntuples = PQcmdTuples(result);
421 
422  SetVariable(pset.vars, "ERROR", "false");
423  SetVariable(pset.vars, "SQLSTATE", "00000");
424  SetVariable(pset.vars, "ROW_COUNT", *ntuples ? ntuples : "0");
425  }
426  else
427  {
428  const char *code = PQresultErrorField(result, PG_DIAG_SQLSTATE);
429  const char *mesg = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
430 
431  SetVariable(pset.vars, "ERROR", "true");
432 
433  /*
434  * If there is no SQLSTATE code, use an empty string. This can happen
435  * for libpq-detected errors (e.g., lost connection, ENOMEM).
436  */
437  if (code == NULL)
438  code = "";
439  SetVariable(pset.vars, "SQLSTATE", code);
440  SetVariable(pset.vars, "ROW_COUNT", "0");
441  SetVariable(pset.vars, "LAST_ERROR_SQLSTATE", code);
442  SetVariable(pset.vars, "LAST_ERROR_MESSAGE", mesg ? mesg : "");
443  }
444 }
char * PQcmdTuples(PGresult *res)
Definition: fe-exec.c:3681
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3325
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58

References PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SQLSTATE, PQcmdTuples(), PQresultErrorField(), pset, SetVariable(), success, and _psqlSettings::vars.

Referenced by DescribeQuery(), ExecQueryAndProcessResults(), and ExecQueryUsingCursor().

◆ skip_white_space()

static const char* skip_white_space ( const char *  query)
static

Definition at line 1891 of file common.c.

1892 {
1893  int cnestlevel = 0; /* slash-star comment nest level */
1894 
1895  while (*query)
1896  {
1897  int mblen = PQmblenBounded(query, pset.encoding);
1898 
1899  /*
1900  * Note: we assume the encoding is a superset of ASCII, so that for
1901  * example "query[0] == '/'" is meaningful. However, we do NOT assume
1902  * that the second and subsequent bytes of a multibyte character
1903  * couldn't look like ASCII characters; so it is critical to advance
1904  * by mblen, not 1, whenever we haven't exactly identified the
1905  * character we are skipping over.
1906  */
1907  if (isspace((unsigned char) *query))
1908  query += mblen;
1909  else if (query[0] == '/' && query[1] == '*')
1910  {
1911  cnestlevel++;
1912  query += 2;
1913  }
1914  else if (cnestlevel > 0 && query[0] == '*' && query[1] == '/')
1915  {
1916  cnestlevel--;
1917  query += 2;
1918  }
1919  else if (cnestlevel == 0 && query[0] == '-' && query[1] == '-')
1920  {
1921  query += 2;
1922 
1923  /*
1924  * We have to skip to end of line since any slash-star inside the
1925  * -- comment does NOT start a slash-star comment.
1926  */
1927  while (*query)
1928  {
1929  if (*query == '\n')
1930  {
1931  query++;
1932  break;
1933  }
1934  query += PQmblenBounded(query, pset.encoding);
1935  }
1936  }
1937  else if (cnestlevel > 0)
1938  query += mblen;
1939  else
1940  break; /* found first token */
1941  }
1942 
1943  return query;
1944 }

References _psqlSettings::encoding, PQmblenBounded(), and pset.

Referenced by command_no_begin(), and is_select_command().

◆ standard_strings()

bool standard_strings ( void  )

Definition at line 2227 of file common.c.

2228 {
2229  const char *val;
2230 
2231  if (!pset.db)
2232  return false;
2233 
2234  val = PQparameterStatus(pset.db, "standard_conforming_strings");
2235 
2236  if (val && strcmp(val, "on") == 0)
2237  return true;
2238 
2239  return false;
2240 }

References _psqlSettings::db, PQparameterStatus(), pset, and val.

Referenced by get_create_object_cmd(), main(), MainLoop(), and parse_slash_copy().

◆ StoreQueryTuple()

static bool StoreQueryTuple ( const PGresult result)
static

Definition at line 720 of file common.c.

721 {
722  bool success = true;
723 
724  if (PQntuples(result) < 1)
725  {
726  pg_log_error("no rows returned for \\gset");
727  success = false;
728  }
729  else if (PQntuples(result) > 1)
730  {
731  pg_log_error("more than one row returned for \\gset");
732  success = false;
733  }
734  else
735  {
736  int i;
737 
738  for (i = 0; i < PQnfields(result); i++)
739  {
740  char *colname = PQfname(result, i);
741  char *varname;
742  char *value;
743 
744  /* concatenate prefix and column name */
745  varname = psprintf("%s%s", pset.gset_prefix, colname);
746 
747  if (VariableHasHook(pset.vars, varname))
748  {
749  pg_log_warning("attempt to \\gset into specially treated variable \"%s\" ignored",
750  varname);
751  continue;
752  }
753 
754  if (!PQgetisnull(result, 0, i))
755  value = PQgetvalue(result, 0, i);
756  else
757  {
758  /* for NULL value, unset rather than set the variable */
759  value = NULL;
760  }
761 
762  if (!SetVariable(pset.vars, varname, value))
763  {
764  free(varname);
765  success = false;
766  break;
767  }
768 
769  free(varname);
770  }
771  }
772 
773  return success;
774 }
#define pg_log_warning(...)
Definition: pgfnames.c:24
bool VariableHasHook(VariableSpace space, const char *name)
Definition: variables.c:368

References free, _psqlSettings::gset_prefix, i, pg_log_error, pg_log_warning, PQfname(), PQgetisnull(), PQgetvalue(), PQnfields(), PQntuples(), pset, psprintf(), SetVariable(), success, value, VariableHasHook(), and _psqlSettings::vars.

Referenced by ExecQueryUsingCursor(), and PrintQueryResult().

◆ uri_prefix_length()

static int uri_prefix_length ( const char *  connstr)
static

Definition at line 2326 of file common.c.

2327 {
2328  /* The connection URI must start with either of the following designators: */
2329  static const char uri_designator[] = "postgresql://";
2330  static const char short_uri_designator[] = "postgres://";
2331 
2332  if (strncmp(connstr, uri_designator,
2333  sizeof(uri_designator) - 1) == 0)
2334  return sizeof(uri_designator) - 1;
2335 
2336  if (strncmp(connstr, short_uri_designator,
2337  sizeof(short_uri_designator) - 1) == 0)
2338  return sizeof(short_uri_designator) - 1;
2339 
2340  return 0;
2341 }
static const char short_uri_designator[]
Definition: fe-connect.c:372
static const char uri_designator[]
Definition: fe-connect.c:371

References connstr, short_uri_designator, and uri_designator.

Referenced by recognized_connection_string().

Variable Documentation

◆ sigint_interrupt_enabled

◆ sigint_interrupt_jmp

sigjmp_buf sigint_interrupt_jmp