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-2025, 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"
26
27/*
28 * Split TABLE[(COLUMNS)] into TABLE and [(COLUMNS)] portions. When you
29 * finish using them, pg_free(*table). *columns is a pointer into "spec",
30 * possibly to its NUL terminator.
31 */
32void
33splitTableColumnsSpec(const char *spec, int encoding,
34 char **table, const char **columns)
35{
36 bool inquotes = false;
37 const char *cp = spec;
38
39 /*
40 * Find the first '(' not identifier-quoted. Based on
41 * dequote_downcase_identifier().
42 */
43 while (*cp && (*cp != '(' || inquotes))
44 {
45 if (*cp == '"')
46 {
47 if (inquotes && cp[1] == '"')
48 cp++; /* pair does not affect quoting */
49 else
50 inquotes = !inquotes;
51 cp++;
52 }
53 else
54 cp += PQmblenBounded(cp, encoding);
55 }
56 *table = pnstrdup(spec, cp - spec);
57 *columns = cp;
58}
59
60/*
61 * Break apart TABLE[(COLUMNS)] of "spec". With the reset_val of search_path
62 * in effect, have regclassin() interpret the TABLE portion. Append to "buf"
63 * the qualified name of TABLE, followed by any (COLUMNS). Exit on failure.
64 * We use this to interpret --table=foo under the search path psql would get,
65 * in advance of "ANALYZE public.foo" under the always-secure search path.
66 */
67void
69 PGconn *conn, bool echo)
70{
71 char *table;
72 const char *columns;
74 PGresult *res;
75 int ntups;
76
77 splitTableColumnsSpec(spec, PQclientEncoding(conn), &table, &columns);
78
79 /*
80 * Query must remain ABSOLUTELY devoid of unqualified names. This would
81 * be unnecessary given a regclassin() variant taking a search_path
82 * argument.
83 */
84 initPQExpBuffer(&sql);
86 "SELECT c.relname, ns.nspname\n"
87 " FROM pg_catalog.pg_class c,"
88 " pg_catalog.pg_namespace ns\n"
89 " WHERE c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n"
90 " AND c.oid OPERATOR(pg_catalog.=) ");
91 appendStringLiteralConn(&sql, table, conn);
92 appendPQExpBufferStr(&sql, "::pg_catalog.regclass;");
93
94 executeCommand(conn, "RESET search_path;", echo);
95
96 /*
97 * One row is a typical result, as is a nonexistent relation ERROR.
98 * regclassin() unconditionally accepts all-digits input as an OID; if no
99 * relation has that OID; this query returns no rows. Catalog corruption
100 * might elicit other row counts.
101 */
102 res = executeQuery(conn, sql.data, echo);
103 ntups = PQntuples(res);
104 if (ntups != 1)
105 {
106 pg_log_error(ngettext("query returned %d row instead of one: %s",
107 "query returned %d rows instead of one: %s",
108 ntups),
109 ntups, sql.data);
110 PQfinish(conn);
111 exit(1);
112 }
114 fmtQualifiedIdEnc(PQgetvalue(res, 0, 1),
115 PQgetvalue(res, 0, 0),
117 appendPQExpBufferStr(buf, columns);
118 PQclear(res);
119 termPQExpBuffer(&sql);
120 pg_free(table);
121
123}
124
125
126/*
127 * Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither.
128 */
129
130/* translator: abbreviation for "yes" */
131#define PG_YESLETTER gettext_noop("y")
132/* translator: abbreviation for "no" */
133#define PG_NOLETTER gettext_noop("n")
134
135bool
137{
138 char prompt[256];
139
140 /*------
141 translator: This is a question followed by the translated options for
142 "yes" and "no". */
143 snprintf(prompt, sizeof(prompt), _("%s (%s/%s) "),
145
146 for (;;)
147 {
148 char *resp;
149
150 resp = simple_prompt(prompt, true);
151
152 if (strcmp(resp, _(PG_YESLETTER)) == 0)
153 {
154 free(resp);
155 return true;
156 }
157 if (strcmp(resp, _(PG_NOLETTER)) == 0)
158 {
159 free(resp);
160 return false;
161 }
162 free(resp);
163
164 printf(_("Please answer \"%s\" or \"%s\".\n"),
166 }
167}
bool yesno_prompt(const char *question)
Definition: common.c:136
void splitTableColumnsSpec(const char *spec, int encoding, char **table, const char **columns)
Definition: common.c:33
void appendQualifiedRelation(PQExpBuffer buf, const char *spec, PGconn *conn, bool echo)
Definition: common.c:68
#define PG_YESLETTER
Definition: common.c:131
#define PG_NOLETTER
Definition: common.c:133
#define ngettext(s, p, n)
Definition: c.h:1152
#define ALWAYS_SECURE_SEARCH_PATH_SQL
Definition: connect.h:25
#define _(x)
Definition: elog.c:90
int PQclientEncoding(const PGconn *conn)
Definition: fe-connect.c:7643
void PQfinish(PGconn *conn)
Definition: fe-connect.c:5224
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
void PQclear(PGresult *res)
Definition: fe-exec.c:721
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
int PQmblenBounded(const char *s, int encoding)
Definition: fe-misc.c:1243
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#define free(a)
Definition: header.h:65
#define question
Definition: indent_codes.h:41
#define pg_log_error(...)
Definition: logging.h:106
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1710
int32 encoding
Definition: pg_database.h:41
static void executeCommand(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1980
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1957
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:239
#define printf(...)
Definition: port.h:245
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
char * simple_prompt(const char *prompt, bool echo)
Definition: sprompt.c:38
PGconn * conn
Definition: streamutil.c:52
const char * fmtQualifiedIdEnc(const char *schema, const char *id, int encoding)
Definition: string_utils.c:263
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
Definition: string_utils.c:446