PostgreSQL Source Code  git master
common.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * common.c
4  * Common support routines for bin/scripts/
5  *
6  *
7  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * src/bin/scripts/common.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres_fe.h"
16 
17 #include <signal.h>
18 #include <unistd.h>
19 
20 #include "common.h"
21 #include "common/connect.h"
22 #include "common/logging.h"
23 #include "common/string.h"
24 #include "fe_utils/cancel.h"
25 #include "fe_utils/string_utils.h"
26 
27 #define ERRCODE_UNDEFINED_TABLE "42P01"
28 
29 /*
30  * Provide strictly harmonized handling of --help and --version
31  * options.
32  */
33 void
34 handle_help_version_opts(int argc, char *argv[],
35  const char *fixed_progname, help_handler hlp)
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 }
51 
52 
53 /*
54  * Make a database connection with the given parameters.
55  *
56  * An interactive password prompt is automatically issued if needed and
57  * allowed by cparams->prompt_password.
58  *
59  * If allow_password_reuse is true, we will try to re-use any password
60  * given during previous calls to this routine. (Callers should not pass
61  * allow_password_reuse=true unless reconnecting to the same database+user
62  * as before, else we might create password exposure hazards.)
63  */
64 PGconn *
65 connectDatabase(const ConnParams *cparams, const char *progname,
66  bool echo, bool fail_ok, bool allow_password_reuse)
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("%s", PQerrorMessage(conn));
154  exit(1);
155  }
156 
157  /* Start strict; callers may override this. */
159 
160  return conn;
161 }
162 
163 /*
164  * Try to connect to the appropriate maintenance database.
165  *
166  * This differs from connectDatabase only in that it has a rule for
167  * inserting a default "dbname" if none was given (which is why cparams
168  * is not const). Note that cparams->dbname should typically come from
169  * a --maintenance-db command line parameter.
170  */
171 PGconn *
173  const char *progname, bool echo)
174 {
175  PGconn *conn;
176 
177  /* If a maintenance database name was specified, just connect to it. */
178  if (cparams->dbname)
179  return connectDatabase(cparams, progname, echo, false, false);
180 
181  /* Otherwise, try postgres first and then template1. */
182  cparams->dbname = "postgres";
183  conn = connectDatabase(cparams, progname, echo, true, false);
184  if (!conn)
185  {
186  cparams->dbname = "template1";
187  conn = connectDatabase(cparams, progname, echo, false, false);
188  }
189  return conn;
190 }
191 
192 /*
193  * Disconnect the given connection, canceling any statement if one is active.
194  */
195 void
197 {
198  char errbuf[256];
199 
200  Assert(conn != NULL);
201 
202  if (PQtransactionStatus(conn) == PQTRANS_ACTIVE)
203  {
204  PGcancel *cancel;
205 
206  if ((cancel = PQgetCancel(conn)))
207  {
208  (void) PQcancel(cancel, errbuf, sizeof(errbuf));
209  PQfreeCancel(cancel);
210  }
211  }
212 
213  PQfinish(conn);
214 }
215 
216 /*
217  * Run a query, return the results, exit program on failure.
218  */
219 PGresult *
220 executeQuery(PGconn *conn, const char *query, bool echo)
221 {
222  PGresult *res;
223 
224  if (echo)
225  printf("%s\n", query);
226 
227  res = PQexec(conn, query);
228  if (!res ||
230  {
231  pg_log_error("query failed: %s", PQerrorMessage(conn));
232  pg_log_info("query was: %s", query);
233  PQfinish(conn);
234  exit(1);
235  }
236 
237  return res;
238 }
239 
240 
241 /*
242  * As above for a SQL command (which returns nothing).
243  */
244 void
245 executeCommand(PGconn *conn, const char *query, bool echo)
246 {
247  PGresult *res;
248 
249  if (echo)
250  printf("%s\n", query);
251 
252  res = PQexec(conn, query);
253  if (!res ||
255  {
256  pg_log_error("query failed: %s", PQerrorMessage(conn));
257  pg_log_info("query was: %s", query);
258  PQfinish(conn);
259  exit(1);
260  }
261 
262  PQclear(res);
263 }
264 
265 
266 /*
267  * As above for a SQL maintenance command (returns command success).
268  * Command is executed with a cancel handler set, so Ctrl-C can
269  * interrupt it.
270  */
271 bool
272 executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
273 {
274  PGresult *res;
275  bool r;
276 
277  if (echo)
278  printf("%s\n", query);
279 
280  SetCancelConn(conn);
281  res = PQexec(conn, query);
282  ResetCancelConn();
283 
284  r = (res && PQresultStatus(res) == PGRES_COMMAND_OK);
285 
286  if (res)
287  PQclear(res);
288 
289  return r;
290 }
291 
292 /*
293  * Consume all the results generated for the given connection until
294  * nothing remains. If at least one error is encountered, return false.
295  * Note that this will block if the connection is busy.
296  */
297 bool
299 {
300  bool ok = true;
301  PGresult *result;
302 
303  SetCancelConn(conn);
304  while ((result = PQgetResult(conn)) != NULL)
305  {
306  if (!processQueryResult(conn, result))
307  ok = false;
308  }
309  ResetCancelConn();
310  return ok;
311 }
312 
313 /*
314  * Process (and delete) a query result. Returns true if there's no error,
315  * false otherwise -- but errors about trying to work on a missing relation
316  * are reported and subsequently ignored.
317  */
318 bool
320 {
321  /*
322  * If it's an error, report it. Errors about a missing table are harmless
323  * so we continue processing; but die for other errors.
324  */
325  if (PQresultStatus(result) != PGRES_COMMAND_OK)
326  {
327  char *sqlState = PQresultErrorField(result, PG_DIAG_SQLSTATE);
328 
329  pg_log_error("processing of database \"%s\" failed: %s",
330  PQdb(conn), PQerrorMessage(conn));
331 
332  if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) != 0)
333  {
334  PQclear(result);
335  return false;
336  }
337  }
338 
339  PQclear(result);
340  return true;
341 }
342 
343 
344 /*
345  * Split TABLE[(COLUMNS)] into TABLE and [(COLUMNS)] portions. When you
346  * finish using them, pg_free(*table). *columns is a pointer into "spec",
347  * possibly to its NUL terminator.
348  */
349 void
350 splitTableColumnsSpec(const char *spec, int encoding,
351  char **table, const char **columns)
352 {
353  bool inquotes = false;
354  const char *cp = spec;
355 
356  /*
357  * Find the first '(' not identifier-quoted. Based on
358  * dequote_downcase_identifier().
359  */
360  while (*cp && (*cp != '(' || inquotes))
361  {
362  if (*cp == '"')
363  {
364  if (inquotes && cp[1] == '"')
365  cp++; /* pair does not affect quoting */
366  else
367  inquotes = !inquotes;
368  cp++;
369  }
370  else
371  cp += PQmblen(cp, encoding);
372  }
373  *table = pnstrdup(spec, cp - spec);
374  *columns = cp;
375 }
376 
377 /*
378  * Break apart TABLE[(COLUMNS)] of "spec". With the reset_val of search_path
379  * in effect, have regclassin() interpret the TABLE portion. Append to "buf"
380  * the qualified name of TABLE, followed by any (COLUMNS). Exit on failure.
381  * We use this to interpret --table=foo under the search path psql would get,
382  * in advance of "ANALYZE public.foo" under the always-secure search path.
383  */
384 void
386  PGconn *conn, bool echo)
387 {
388  char *table;
389  const char *columns;
390  PQExpBufferData sql;
391  PGresult *res;
392  int ntups;
393 
394  splitTableColumnsSpec(spec, PQclientEncoding(conn), &table, &columns);
395 
396  /*
397  * Query must remain ABSOLUTELY devoid of unqualified names. This would
398  * be unnecessary given a regclassin() variant taking a search_path
399  * argument.
400  */
401  initPQExpBuffer(&sql);
403  "SELECT c.relname, ns.nspname\n"
404  " FROM pg_catalog.pg_class c,"
405  " pg_catalog.pg_namespace ns\n"
406  " WHERE c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n"
407  " AND c.oid OPERATOR(pg_catalog.=) ");
408  appendStringLiteralConn(&sql, table, conn);
409  appendPQExpBufferStr(&sql, "::pg_catalog.regclass;");
410 
411  executeCommand(conn, "RESET search_path;", echo);
412 
413  /*
414  * One row is a typical result, as is a nonexistent relation ERROR.
415  * regclassin() unconditionally accepts all-digits input as an OID; if no
416  * relation has that OID; this query returns no rows. Catalog corruption
417  * might elicit other row counts.
418  */
419  res = executeQuery(conn, sql.data, echo);
420  ntups = PQntuples(res);
421  if (ntups != 1)
422  {
423  pg_log_error(ngettext("query returned %d row instead of one: %s",
424  "query returned %d rows instead of one: %s",
425  ntups),
426  ntups, sql.data);
427  PQfinish(conn);
428  exit(1);
429  }
431  fmtQualifiedId(PQgetvalue(res, 0, 1),
432  PQgetvalue(res, 0, 0)));
433  appendPQExpBufferStr(buf, columns);
434  PQclear(res);
435  termPQExpBuffer(&sql);
436  pg_free(table);
437 
439 }
440 
441 
442 /*
443  * Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither.
444  */
445 
446 /* translator: abbreviation for "yes" */
447 #define PG_YESLETTER gettext_noop("y")
448 /* translator: abbreviation for "no" */
449 #define PG_NOLETTER gettext_noop("n")
450 
451 bool
452 yesno_prompt(const char *question)
453 {
454  char prompt[256];
455 
456  /*------
457  translator: This is a question followed by the translated options for
458  "yes" and "no". */
459  snprintf(prompt, sizeof(prompt), _("%s (%s/%s) "),
460  _(question), _(PG_YESLETTER), _(PG_NOLETTER));
461 
462  for (;;)
463  {
464  char *resp;
465 
466  resp = simple_prompt(prompt, true);
467 
468  if (strcmp(resp, _(PG_YESLETTER)) == 0)
469  {
470  free(resp);
471  return true;
472  }
473  if (strcmp(resp, _(PG_NOLETTER)) == 0)
474  {
475  free(resp);
476  return false;
477  }
478  free(resp);
479 
480  printf(_("Please answer \"%s\" or \"%s\".\n"),
482  }
483 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6626
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1198
#define PG_YESLETTER
Definition: common.c:447
bool yesno_prompt(const char *question)
Definition: common.c:452
char * pgport
Definition: pg_backup.h:66
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3122
PGresult * executeQuery(PGconn *conn, const char *query, bool echo)
Definition: common.c:220
void executeCommand(PGconn *conn, const char *query, bool echo)
Definition: common.c:245
bool processQueryResult(PGconn *conn, PGresult *result)
Definition: common.c:319
const char * get_progname(const char *argv0)
Definition: path.c:453
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:80
void ResetCancelConn(void)
Definition: cancel.c:100
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
void PQfreeCancel(PGcancel *cancel)
Definition: fe-connect.c:4265
bool consumeQueryResult(PGconn *conn)
Definition: common.c:298
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4121
#define printf(...)
Definition: port.h:221
char * simple_prompt(const char *prompt, bool echo)
Definition: sprompt.c:38
PGconn * connectDatabase(const ConnParams *cparams, const char *progname, bool echo, bool fail_ok, bool allow_password_reuse)
Definition: common.c:65
#define lengthof(array)
Definition: c.h:722
#define PG_NOLETTER
Definition: common.c:449
const char * progname
Definition: pg_standby.c:36
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2728
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
int PQclientEncoding(const PGconn *conn)
Definition: fe-connect.c:6686
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2651
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 * buf
Definition: pg_test_fsync.c:68
bool executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
Definition: common.c:272
PGcancel * PQgetCancel(PGconn *conn)
Definition: fe-connect.c:4242
void SetCancelConn(PGconn *conn)
Definition: cancel.c:70
static char * password
Definition: streamutil.c:53
PGconn * connectMaintenanceDatabase(ConnParams *cparams, const char *progname, bool echo)
Definition: common.c:172
char * override_dbname
Definition: pg_backup.h:72
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
Definition: common.c:34
char * pghost
Definition: pg_backup.h:67
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:6581
enum trivalue prompt_password
Definition: common.h:32
#define ngettext(s, p, n)
Definition: c.h:1170
void disconnectDatabase(PGconn *conn)
Definition: common.c:196
#define ERRCODE_UNDEFINED_TABLE
Definition: common.c:27
void PQclear(PGresult *res)
Definition: fe-exec.c:676
void(* help_handler)(const char *progname)
Definition: common.h:38
#define free(a)
Definition: header.h:65
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6476
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2713
#define Assert(condition)
Definition: c.h:792
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
int32 encoding
Definition: pg_database.h:41
void appendQualifiedRelation(PQExpBuffer buf, const char *spec, PGconn *conn, bool echo)
Definition: common.c:385
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
Definition: fe-connect.c:4397
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
Definition: string_utils.c:293
int PQconnectionNeedsPassword(const PGconn *conn)
Definition: fe-connect.c:6660
void splitTableColumnsSpec(const char *spec, int encoding, char **table, const char **columns)
Definition: common.c:350
int i
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1907
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6573
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1231
#define snprintf
Definition: port.h:215
#define _(x)
Definition: elog.c:89
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1746
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
#define pg_log_info(...)
Definition: logging.h:88
const char * pguser
Definition: common.h:31