PostgreSQL Source Code  git master
common.c File Reference
#include "postgres_fe.h"
#include <signal.h>
#include <unistd.h>
#include "common.h"
#include "common/connect.h"
#include "common/logging.h"
#include "common/string.h"
#include "fe_utils/cancel.h"
#include "fe_utils/string_utils.h"
Include dependency graph for common.c:

Go to the source code of this file.

Macros

#define ERRCODE_UNDEFINED_TABLE   "42P01"
 
#define PG_YESLETTER   gettext_noop("y")
 
#define PG_NOLETTER   gettext_noop("n")
 

Functions

void handle_help_version_opts (int argc, char *argv[], const char *fixed_progname, help_handler hlp)
 
PGconnconnectDatabase (const ConnParams *cparams, const char *progname, bool echo, bool fail_ok, bool allow_password_reuse)
 
PGconnconnectMaintenanceDatabase (ConnParams *cparams, const char *progname, bool echo)
 
void disconnectDatabase (PGconn *conn)
 
PGresultexecuteQuery (PGconn *conn, const char *query, bool echo)
 
void executeCommand (PGconn *conn, const char *query, bool echo)
 
bool executeMaintenanceCommand (PGconn *conn, const char *query, bool echo)
 
bool consumeQueryResult (PGconn *conn)
 
bool processQueryResult (PGconn *conn, PGresult *result)
 
void splitTableColumnsSpec (const char *spec, int encoding, char **table, const char **columns)
 
void appendQualifiedRelation (PQExpBuffer buf, const char *spec, PGconn *conn, bool echo)
 
bool yesno_prompt (const char *question)
 

Macro Definition Documentation

◆ ERRCODE_UNDEFINED_TABLE

#define ERRCODE_UNDEFINED_TABLE   "42P01"

Definition at line 27 of file common.c.

Referenced by processQueryResult().

◆ PG_NOLETTER

#define PG_NOLETTER   gettext_noop("n")

Definition at line 450 of file common.c.

Referenced by yesno_prompt().

◆ PG_YESLETTER

#define PG_YESLETTER   gettext_noop("y")

Definition at line 448 of file common.c.

Referenced by yesno_prompt().

Function Documentation

◆ appendQualifiedRelation()

void appendQualifiedRelation ( PQExpBuffer  buf,
const char *  spec,
PGconn conn,
bool  echo 
)

Definition at line 386 of file common.c.

References ALWAYS_SECURE_SEARCH_PATH_SQL, appendPQExpBufferStr(), appendStringLiteralConn(), PQExpBufferData::data, executeCommand(), executeQuery(), fmtQualifiedId(), initPQExpBuffer(), ngettext, pg_free(), pg_log_error, PQclear(), PQclientEncoding(), PQfinish(), PQgetvalue(), PQntuples(), splitTableColumnsSpec(), and termPQExpBuffer().

Referenced by cluster_one_database(), and run_reindex_command().

388 {
389  char *table;
390  const char *columns;
391  PQExpBufferData sql;
392  PGresult *res;
393  int ntups;
394 
395  splitTableColumnsSpec(spec, PQclientEncoding(conn), &table, &columns);
396 
397  /*
398  * Query must remain ABSOLUTELY devoid of unqualified names. This would
399  * be unnecessary given a regclassin() variant taking a search_path
400  * argument.
401  */
402  initPQExpBuffer(&sql);
404  "SELECT c.relname, ns.nspname\n"
405  " FROM pg_catalog.pg_class c,"
406  " pg_catalog.pg_namespace ns\n"
407  " WHERE c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n"
408  " AND c.oid OPERATOR(pg_catalog.=) ");
409  appendStringLiteralConn(&sql, table, conn);
410  appendPQExpBufferStr(&sql, "::pg_catalog.regclass;");
411 
412  executeCommand(conn, "RESET search_path;", echo);
413 
414  /*
415  * One row is a typical result, as is a nonexistent relation ERROR.
416  * regclassin() unconditionally accepts all-digits input as an OID; if no
417  * relation has that OID; this query returns no rows. Catalog corruption
418  * might elicit other row counts.
419  */
420  res = executeQuery(conn, sql.data, echo);
421  ntups = PQntuples(res);
422  if (ntups != 1)
423  {
424  pg_log_error(ngettext("query returned %d row instead of one: %s",
425  "query returned %d rows instead of one: %s",
426  ntups),
427  ntups, sql.data);
428  PQfinish(conn);
429  exit(1);
430  }
432  fmtQualifiedId(PQgetvalue(res, 0, 1),
433  PQgetvalue(res, 0, 0)));
434  appendPQExpBufferStr(buf, columns);
435  PQclear(res);
436  termPQExpBuffer(&sql);
437  pg_free(table);
438 
440 }
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3163
PGresult * executeQuery(PGconn *conn, const char *query, bool echo)
Definition: common.c:221
void executeCommand(PGconn *conn, const char *query, bool echo)
Definition: common.c:246
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:80
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
int PQclientEncoding(const PGconn *conn)
Definition: fe-connect.c:6729
#define ngettext(s, p, n)
Definition: c.h:1124
void PQclear(PGresult *res)
Definition: fe-exec.c:694
const char * fmtQualifiedId(const char *schema, const char *id)
Definition: string_utils.c:145
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#define ALWAYS_SECURE_SEARCH_PATH_SQL
Definition: connect.h:25
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
Definition: string_utils.c:293
void splitTableColumnsSpec(const char *spec, int encoding, char **table, const char **columns)
Definition: common.c:351
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ connectDatabase()

PGconn* connectDatabase ( const ConnParams cparams,
const char *  progname,
bool  echo,
bool  fail_ok,
bool  allow_password_reuse 
)

Definition at line 65 of file common.c.

References ALWAYS_SECURE_SEARCH_PATH_SQL, Assert, conn, CONNECTION_BAD, _connParams::dbname, executeQuery(), free, i, lengthof, _connParams::override_dbname, password, pg_log_error, _connParams::pghost, _connParams::pgport, _connParams::pguser, PQclear(), PQconnectdbParams(), PQconnectionNeedsPassword(), PQerrorMessage(), PQfinish(), PQstatus(), progname, _connParams::prompt_password, simple_prompt(), TRI_NO, TRI_YES, and values.

Referenced by connectMaintenanceDatabase().

67 {
68  PGconn *conn;
69  bool new_pass;
70  static char *password = NULL;
71 
72  /* Callers must supply at least dbname; other params can be NULL */
73  Assert(cparams->dbname);
74 
75  if (!allow_password_reuse && password)
76  {
77  free(password);
78  password = NULL;
79  }
80 
81  if (cparams->prompt_password == TRI_YES && password == NULL)
82  password = simple_prompt("Password: ", false);
83 
84  /*
85  * Start the connection. Loop until we have a password if requested by
86  * backend.
87  */
88  do
89  {
90  const char *keywords[8];
91  const char *values[8];
92  int i = 0;
93 
94  /*
95  * If dbname is a connstring, its entries can override the other
96  * values obtained from cparams; but in turn, override_dbname can
97  * override the dbname component of it.
98  */
99  keywords[i] = "host";
100  values[i++] = cparams->pghost;
101  keywords[i] = "port";
102  values[i++] = cparams->pgport;
103  keywords[i] = "user";
104  values[i++] = cparams->pguser;
105  keywords[i] = "password";
106  values[i++] = password;
107  keywords[i] = "dbname";
108  values[i++] = cparams->dbname;
109  if (cparams->override_dbname)
110  {
111  keywords[i] = "dbname";
112  values[i++] = cparams->override_dbname;
113  }
114  keywords[i] = "fallback_application_name";
115  values[i++] = progname;
116  keywords[i] = NULL;
117  values[i++] = NULL;
118  Assert(i <= lengthof(keywords));
119 
120  new_pass = false;
121  conn = PQconnectdbParams(keywords, values, true);
122 
123  if (!conn)
124  {
125  pg_log_error("could not connect to database %s: out of memory",
126  cparams->dbname);
127  exit(1);
128  }
129 
130  /*
131  * No luck? Trying asking (again) for a password.
132  */
133  if (PQstatus(conn) == CONNECTION_BAD &&
135  cparams->prompt_password != TRI_NO)
136  {
137  PQfinish(conn);
138  if (password)
139  free(password);
140  password = simple_prompt("Password: ", false);
141  new_pass = true;
142  }
143  } while (new_pass);
144 
145  /* check to see that the backend connection was successfully made */
146  if (PQstatus(conn) == CONNECTION_BAD)
147  {
148  if (fail_ok)
149  {
150  PQfinish(conn);
151  return NULL;
152  }
153  pg_log_error("could not connect to database %s: %s",
154  cparams->dbname, PQerrorMessage(conn));
155  exit(1);
156  }
157 
158  /* Start strict; callers may override this. */
160 
161  return conn;
162 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6669
char * pgport
Definition: pg_backup.h:66
PGresult * executeQuery(PGconn *conn, const char *query, bool echo)
Definition: common.c:221
#define pg_log_error(...)
Definition: logging.h:80
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
char * simple_prompt(const char *prompt, bool echo)
Definition: sprompt.c:38
#define lengthof(array)
Definition: c.h:676
const char * progname
Definition: pg_standby.c:36
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:647
char * dbname
Definition: pg_backup.h:65
PGconn * conn
Definition: streamutil.c:54
static char * password
Definition: streamutil.c:53
char * override_dbname
Definition: pg_backup.h:72
char * pghost
Definition: pg_backup.h:67
enum trivalue prompt_password
Definition: common.h:32
void PQclear(PGresult *res)
Definition: fe-exec.c:694
#define free(a)
Definition: header.h:65
#define Assert(condition)
Definition: c.h:746
#define ALWAYS_SECURE_SEARCH_PATH_SQL
Definition: connect.h:25
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int PQconnectionNeedsPassword(const PGconn *conn)
Definition: fe-connect.c:6703
int i
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6616
const char * pguser
Definition: common.h:31

◆ connectMaintenanceDatabase()

PGconn* connectMaintenanceDatabase ( ConnParams cparams,
const char *  progname,
bool  echo 
)

Definition at line 173 of file common.c.

References conn, connectDatabase(), and _connParams::dbname.

Referenced by cluster_all_databases(), main(), reindex_all_databases(), and vacuum_all_databases().

175 {
176  PGconn *conn;
177 
178  /* If a maintenance database name was specified, just connect to it. */
179  if (cparams->dbname)
180  return connectDatabase(cparams, progname, echo, false, false);
181 
182  /* Otherwise, try postgres first and then template1. */
183  cparams->dbname = "postgres";
184  conn = connectDatabase(cparams, progname, echo, true, false);
185  if (!conn)
186  {
187  cparams->dbname = "template1";
188  conn = connectDatabase(cparams, progname, echo, false, false);
189  }
190  return conn;
191 }
PGconn * connectDatabase(const ConnParams *cparams, const char *progname, bool echo, bool fail_ok, bool allow_password_reuse)
Definition: common.c:65
const char * progname
Definition: pg_standby.c:36
char * dbname
Definition: pg_backup.h:65
PGconn * conn
Definition: streamutil.c:54

◆ consumeQueryResult()

bool consumeQueryResult ( PGconn conn)

Definition at line 299 of file common.c.

References PQgetResult(), processQueryResult(), ResetCancelConn(), and SetCancelConn().

Referenced by ParallelSlotsWaitCompletion().

300 {
301  bool ok = true;
302  PGresult *result;
303 
304  SetCancelConn(conn);
305  while ((result = PQgetResult(conn)) != NULL)
306  {
307  if (!processQueryResult(conn, result))
308  ok = false;
309  }
310  ResetCancelConn();
311  return ok;
312 }
bool processQueryResult(PGconn *conn, PGresult *result)
Definition: common.c:320
void ResetCancelConn(void)
Definition: cancel.c:100
void SetCancelConn(PGconn *conn)
Definition: cancel.c:70
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1778

◆ disconnectDatabase()

void disconnectDatabase ( PGconn conn)

Definition at line 197 of file common.c.

References Assert, PQcancel(), PQfinish(), PQfreeCancel(), PQgetCancel(), PQTRANS_ACTIVE, and PQtransactionStatus().

Referenced by ParallelSlotsTerminate().

198 {
199  char errbuf[256];
200 
201  Assert(conn != NULL);
202 
203  if (PQtransactionStatus(conn) == PQTRANS_ACTIVE)
204  {
205  PGcancel *cancel;
206 
207  if ((cancel = PQgetCancel(conn)))
208  {
209  (void) PQcancel(cancel, errbuf, sizeof(errbuf));
210  PQfreeCancel(cancel);
211  }
212  }
213 
214  PQfinish(conn);
215 }
void PQfreeCancel(PGcancel *cancel)
Definition: fe-connect.c:4318
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
PGcancel * PQgetCancel(PGconn *conn)
Definition: fe-connect.c:4295
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:6624
#define Assert(condition)
Definition: c.h:746
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
Definition: fe-connect.c:4450

◆ executeCommand()

void executeCommand ( PGconn conn,
const char *  query,
bool  echo 
)

Definition at line 246 of file common.c.

References pg_log_error, pg_log_info, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQexec(), PQfinish(), PQresultStatus(), and printf.

Referenced by appendQualifiedRelation().

247 {
248  PGresult *res;
249 
250  if (echo)
251  printf("%s\n", query);
252 
253  res = PQexec(conn, query);
254  if (!res ||
256  {
257  pg_log_error("query failed: %s", PQerrorMessage(conn));
258  pg_log_info("query was: %s", query);
259  PQfinish(conn);
260  exit(1);
261  }
262 
263  PQclear(res);
264 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6669
#define pg_log_error(...)
Definition: logging.h:80
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
#define printf(...)
Definition: port.h:221
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2692
void PQclear(PGresult *res)
Definition: fe-exec.c:694
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1939
#define pg_log_info(...)
Definition: logging.h:88

◆ executeMaintenanceCommand()

bool executeMaintenanceCommand ( PGconn conn,
const char *  query,
bool  echo 
)

Definition at line 273 of file common.c.

References PGRES_COMMAND_OK, PQclear(), PQexec(), PQresultStatus(), printf, ResetCancelConn(), and SetCancelConn().

Referenced by cluster_one_database(), and run_reindex_command().

274 {
275  PGresult *res;
276  bool r;
277 
278  if (echo)
279  printf("%s\n", query);
280 
281  SetCancelConn(conn);
282  res = PQexec(conn, query);
283  ResetCancelConn();
284 
285  r = (res && PQresultStatus(res) == PGRES_COMMAND_OK);
286 
287  if (res)
288  PQclear(res);
289 
290  return r;
291 }
void ResetCancelConn(void)
Definition: cancel.c:100
#define printf(...)
Definition: port.h:221
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2692
void SetCancelConn(PGconn *conn)
Definition: cancel.c:70
void PQclear(PGresult *res)
Definition: fe-exec.c:694
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1939

◆ executeQuery()

PGresult* executeQuery ( PGconn conn,
const char *  query,
bool  echo 
)

Definition at line 221 of file common.c.

References pg_log_error, pg_log_info, PGRES_TUPLES_OK, PQerrorMessage(), PQexec(), PQfinish(), PQresultStatus(), and printf.

Referenced by appendQualifiedRelation(), and connectDatabase().

222 {
223  PGresult *res;
224 
225  if (echo)
226  printf("%s\n", query);
227 
228  res = PQexec(conn, query);
229  if (!res ||
231  {
232  pg_log_error("query failed: %s", PQerrorMessage(conn));
233  pg_log_info("query was: %s", query);
234  PQfinish(conn);
235  exit(1);
236  }
237 
238  return res;
239 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6669
#define pg_log_error(...)
Definition: logging.h:80
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
#define printf(...)
Definition: port.h:221
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2692
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1939
#define pg_log_info(...)
Definition: logging.h:88

◆ handle_help_version_opts()

void handle_help_version_opts ( int  argc,
char *  argv[],
const char *  fixed_progname,
help_handler  hlp 
)

Definition at line 34 of file common.c.

References get_progname(), and printf.

Referenced by main().

36 {
37  if (argc > 1)
38  {
39  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
40  {
41  hlp(get_progname(argv[0]));
42  exit(0);
43  }
44  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
45  {
46  printf("%s (PostgreSQL) " PG_VERSION "\n", fixed_progname);
47  exit(0);
48  }
49  }
50 }
const char * get_progname(const char *argv0)
Definition: path.c:453
#define printf(...)
Definition: port.h:221

◆ processQueryResult()

bool processQueryResult ( PGconn conn,
PGresult result 
)

Definition at line 320 of file common.c.

References ERRCODE_UNDEFINED_TABLE, PG_DIAG_SQLSTATE, pg_log_error, PGRES_COMMAND_OK, PQclear(), PQdb(), PQerrorMessage(), PQresultErrorField(), and PQresultStatus().

Referenced by consumeQueryResult(), and ParallelSlotsGetIdle().

321 {
322  /*
323  * If it's an error, report it. Errors about a missing table are harmless
324  * so we continue processing; but die for other errors.
325  */
326  if (PQresultStatus(result) != PGRES_COMMAND_OK)
327  {
328  char *sqlState = PQresultErrorField(result, PG_DIAG_SQLSTATE);
329 
330  pg_log_error("processing of database \"%s\" failed: %s",
331  PQdb(conn), PQerrorMessage(conn));
332 
333  if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) != 0)
334  {
335  PQclear(result);
336  return false;
337  }
338  }
339 
340  PQclear(result);
341  return true;
342 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6669
#define pg_log_error(...)
Definition: logging.h:80
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2692
#define ERRCODE_UNDEFINED_TABLE
Definition: common.c:27
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6519
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2754

◆ splitTableColumnsSpec()

void splitTableColumnsSpec ( const char *  spec,
int  encoding,
char **  table,
const char **  columns 
)

Definition at line 351 of file common.c.

References pnstrdup(), and PQmblen().

Referenced by appendQualifiedRelation(), and vacuum_one_database().

353 {
354  bool inquotes = false;
355  const char *cp = spec;
356 
357  /*
358  * Find the first '(' not identifier-quoted. Based on
359  * dequote_downcase_identifier().
360  */
361  while (*cp && (*cp != '(' || inquotes))
362  {
363  if (*cp == '"')
364  {
365  if (inquotes && cp[1] == '"')
366  cp++; /* pair does not affect quoting */
367  else
368  inquotes = !inquotes;
369  cp++;
370  }
371  else
372  cp += PQmblen(cp, encoding);
373  }
374  *table = pnstrdup(spec, cp - spec);
375  *columns = cp;
376 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1198
int32 encoding
Definition: pg_database.h:41
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1231

◆ yesno_prompt()

bool yesno_prompt ( const char *  question)

Definition at line 453 of file common.c.

References _, free, PG_NOLETTER, PG_YESLETTER, printf, simple_prompt(), and snprintf.

Referenced by main().

454 {
455  char prompt[256];
456 
457  /*------
458  translator: This is a question followed by the translated options for
459  "yes" and "no". */
460  snprintf(prompt, sizeof(prompt), _("%s (%s/%s) "),
461  _(question), _(PG_YESLETTER), _(PG_NOLETTER));
462 
463  for (;;)
464  {
465  char *resp;
466 
467  resp = simple_prompt(prompt, true);
468 
469  if (strcmp(resp, _(PG_YESLETTER)) == 0)
470  {
471  free(resp);
472  return true;
473  }
474  if (strcmp(resp, _(PG_NOLETTER)) == 0)
475  {
476  free(resp);
477  return false;
478  }
479  free(resp);
480 
481  printf(_("Please answer \"%s\" or \"%s\".\n"),
483  }
484 }
#define PG_YESLETTER
Definition: common.c:448
#define printf(...)
Definition: port.h:221
char * simple_prompt(const char *prompt, bool echo)
Definition: sprompt.c:38
#define PG_NOLETTER
Definition: common.c:450
#define free(a)
Definition: header.h:65
#define snprintf
Definition: port.h:215
#define _(x)
Definition: elog.c:88