Skip to content

Commit c1da728

Browse files
committed
Move common pg_dump code related to connections to a new file
ConnectDatabase is used by pg_dumpall, pg_restore and pg_dump so move common code to new file. new file name: connectdb.c Author: Mahendra Singh Thalor <mahi6run@gmail.com>
1 parent ff3a7f0 commit c1da728

File tree

9 files changed

+352
-345
lines changed

9 files changed

+352
-345
lines changed

src/bin/pg_dump/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ OBJS = \
3131
compress_lz4.o \
3232
compress_none.o \
3333
compress_zstd.o \
34+
connectdb.o \
3435
dumputils.o \
3536
filter.o \
3637
parallel.o \
@@ -50,8 +51,8 @@ pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) | submake-libpq submake-libpg
5051
pg_restore: pg_restore.o $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
5152
$(CC) $(CFLAGS) pg_restore.o $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
5253

53-
pg_dumpall: pg_dumpall.o dumputils.o filter.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils
54-
$(CC) $(CFLAGS) pg_dumpall.o dumputils.o filter.o $(WIN32RES) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
54+
pg_dumpall: pg_dumpall.o $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
55+
$(CC) $(CFLAGS) pg_dumpall.o $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
5556

5657
install: all installdirs
5758
$(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X)

src/bin/pg_dump/connectdb.c

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* connectdb.c
4+
* This is a common file connection to the database.
5+
*
6+
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* IDENTIFICATION
10+
* src/bin/pg_dump/connectdb.c
11+
*
12+
*-------------------------------------------------------------------------
13+
*/
14+
15+
#include "postgres_fe.h"
16+
17+
#include "common/connect.h"
18+
#include "common/logging.h"
19+
#include "common/string.h"
20+
#include "connectdb.h"
21+
#include "dumputils.h"
22+
#include "fe_utils/string_utils.h"
23+
24+
static char *constructConnStr(const char **keywords, const char **values);
25+
26+
/*
27+
* ConnectDatabase
28+
*
29+
* Make a database connection with the given parameters. An
30+
* interactive password prompt is automatically issued if required.
31+
*
32+
* If fail_on_error is false, we return NULL without printing any message
33+
* on failure, but preserve any prompted password for the next try.
34+
*
35+
* On success, the 'connstr' is set to a connection string containing
36+
* the options used and 'server_version' is set to version so that caller
37+
* can use them.
38+
*/
39+
PGconn *
40+
ConnectDatabase(const char *dbname, const char *connection_string,
41+
const char *pghost, const char *pgport, const char *pguser,
42+
trivalue prompt_password, bool fail_on_error, const char *progname,
43+
const char **connstr, int *server_version, char *password,
44+
char *override_dbname)
45+
{
46+
PGconn *conn;
47+
bool new_pass;
48+
const char *remoteversion_str;
49+
int my_version;
50+
const char **keywords = NULL;
51+
const char **values = NULL;
52+
PQconninfoOption *conn_opts = NULL;
53+
int server_version_temp;
54+
55+
if (prompt_password == TRI_YES && !password)
56+
password = simple_prompt("Password: ", false);
57+
58+
/*
59+
* Start the connection. Loop until we have a password if requested by
60+
* backend.
61+
*/
62+
do
63+
{
64+
int argcount = 8;
65+
PQconninfoOption *conn_opt;
66+
char *err_msg = NULL;
67+
int i = 0;
68+
69+
free(keywords);
70+
free(values);
71+
PQconninfoFree(conn_opts);
72+
73+
/*
74+
* Merge the connection info inputs given in form of connection string
75+
* and other options. Explicitly discard any dbname value in the
76+
* connection string; otherwise, PQconnectdbParams() would interpret
77+
* that value as being itself a connection string.
78+
*/
79+
if (connection_string)
80+
{
81+
conn_opts = PQconninfoParse(connection_string, &err_msg);
82+
if (conn_opts == NULL)
83+
pg_fatal("%s", err_msg);
84+
85+
for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
86+
{
87+
if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
88+
strcmp(conn_opt->keyword, "dbname") != 0)
89+
argcount++;
90+
}
91+
92+
keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
93+
values = pg_malloc0((argcount + 1) * sizeof(*values));
94+
95+
for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
96+
{
97+
if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
98+
strcmp(conn_opt->keyword, "dbname") != 0)
99+
{
100+
keywords[i] = conn_opt->keyword;
101+
values[i] = conn_opt->val;
102+
i++;
103+
}
104+
}
105+
}
106+
else
107+
{
108+
keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
109+
values = pg_malloc0((argcount + 1) * sizeof(*values));
110+
}
111+
112+
if (pghost)
113+
{
114+
keywords[i] = "host";
115+
values[i] = pghost;
116+
i++;
117+
}
118+
if (pgport)
119+
{
120+
keywords[i] = "port";
121+
values[i] = pgport;
122+
i++;
123+
}
124+
if (pguser)
125+
{
126+
keywords[i] = "user";
127+
values[i] = pguser;
128+
i++;
129+
}
130+
if (password)
131+
{
132+
keywords[i] = "password";
133+
values[i] = password;
134+
i++;
135+
}
136+
if (dbname)
137+
{
138+
keywords[i] = "dbname";
139+
values[i] = dbname;
140+
i++;
141+
}
142+
if (override_dbname)
143+
{
144+
keywords[i] = "dbname";
145+
values[i++] = override_dbname;
146+
}
147+
148+
keywords[i] = "fallback_application_name";
149+
values[i] = progname;
150+
i++;
151+
152+
new_pass = false;
153+
conn = PQconnectdbParams(keywords, values, true);
154+
155+
if (!conn)
156+
pg_fatal("could not connect to database \"%s\"", dbname);
157+
158+
if (PQstatus(conn) == CONNECTION_BAD &&
159+
PQconnectionNeedsPassword(conn) &&
160+
!password &&
161+
prompt_password != TRI_NO)
162+
{
163+
PQfinish(conn);
164+
password = simple_prompt("Password: ", false);
165+
new_pass = true;
166+
}
167+
} while (new_pass);
168+
169+
/* check to see that the backend connection was successfully made */
170+
if (PQstatus(conn) == CONNECTION_BAD)
171+
{
172+
if (fail_on_error)
173+
pg_fatal("%s", PQerrorMessage(conn));
174+
else
175+
{
176+
PQfinish(conn);
177+
178+
free(keywords);
179+
free(values);
180+
PQconninfoFree(conn_opts);
181+
182+
return NULL;
183+
}
184+
}
185+
186+
/*
187+
* Ok, connected successfully. If requested, remember the options used, in
188+
* the form of a connection string.
189+
*/
190+
if (connstr)
191+
*connstr = constructConnStr(keywords, values);
192+
193+
free(keywords);
194+
free(values);
195+
PQconninfoFree(conn_opts);
196+
197+
/* Check version */
198+
remoteversion_str = PQparameterStatus(conn, "server_version");
199+
if (!remoteversion_str)
200+
pg_fatal("could not get server version");
201+
202+
server_version_temp = PQserverVersion(conn);
203+
if (server_version_temp == 0)
204+
pg_fatal("could not parse server version \"%s\"",
205+
remoteversion_str);
206+
207+
/* If requested, then copy server version to out variable. */
208+
if (server_version)
209+
*server_version = server_version_temp;
210+
211+
my_version = PG_VERSION_NUM;
212+
213+
/*
214+
* We allow the server to be back to 9.2, and up to any minor release of
215+
* our own major version. (See also version check in pg_dump.c.)
216+
*/
217+
if (my_version != server_version_temp
218+
&& (server_version_temp < 90200 ||
219+
(server_version_temp / 100) > (my_version / 100)))
220+
{
221+
pg_log_error("aborting because of server version mismatch");
222+
pg_log_error_detail("server version: %s; %s version: %s",
223+
remoteversion_str, progname, PG_VERSION);
224+
exit_nicely(1);
225+
}
226+
227+
PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL));
228+
229+
return conn;
230+
}
231+
232+
/*
233+
* constructConnStr
234+
*
235+
* Construct a connection string from the given keyword/value pairs. It is
236+
* used to pass the connection options to the pg_dump subprocess.
237+
*
238+
* The following parameters are excluded:
239+
* dbname - varies in each pg_dump invocation
240+
* password - it's not secure to pass a password on the command line
241+
* fallback_application_name - we'll let pg_dump set it
242+
*/
243+
static char *
244+
constructConnStr(const char **keywords, const char **values)
245+
{
246+
PQExpBuffer buf = createPQExpBuffer();
247+
char *connstr;
248+
int i;
249+
bool firstkeyword = true;
250+
251+
/* Construct a new connection string in key='value' format. */
252+
for (i = 0; keywords[i] != NULL; i++)
253+
{
254+
if (strcmp(keywords[i], "dbname") == 0 ||
255+
strcmp(keywords[i], "password") == 0 ||
256+
strcmp(keywords[i], "fallback_application_name") == 0)
257+
continue;
258+
259+
if (!firstkeyword)
260+
appendPQExpBufferChar(buf, ' ');
261+
firstkeyword = false;
262+
appendPQExpBuffer(buf, "%s=", keywords[i]);
263+
appendConnStrVal(buf, values[i]);
264+
}
265+
266+
connstr = pg_strdup(buf->data);
267+
destroyPQExpBuffer(buf);
268+
return connstr;
269+
}
270+
271+
/*
272+
* executeQuery
273+
*
274+
* Run a query, return the results, exit program on failure.
275+
*/
276+
PGresult *
277+
executeQuery(PGconn *conn, const char *query)
278+
{
279+
PGresult *res;
280+
281+
pg_log_info("executing %s", query);
282+
283+
res = PQexec(conn, query);
284+
if (!res ||
285+
PQresultStatus(res) != PGRES_TUPLES_OK)
286+
{
287+
pg_log_error("query failed: %s", PQerrorMessage(conn));
288+
pg_log_error_detail("Query was: %s", query);
289+
PQfinish(conn);
290+
exit_nicely(1);
291+
}
292+
293+
return res;
294+
}

src/bin/pg_dump/connectdb.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* connectdb.h
4+
* Common header file for connection to the database.
5+
*
6+
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* IDENTIFICATION
10+
* src/bin/pg_dump/connectdb.h
11+
*
12+
*-------------------------------------------------------------------------
13+
*/
14+
#ifndef CONNECTDB_H
15+
#define CONNECTDB_H
16+
17+
#include "pg_backup.h"
18+
#include "pg_backup_utils.h"
19+
20+
extern PGconn *ConnectDatabase(const char *dbname, const char *connection_string, const char *pghost,
21+
const char *pgport, const char *pguser,
22+
trivalue prompt_password, bool fail_on_error,
23+
const char *progname, const char **connstr, int *server_version,
24+
char *password, char *override_dbname);
25+
extern PGresult *executeQuery(PGconn *conn, const char *query);
26+
#endif /* CONNECTDB_H */

src/bin/pg_dump/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pg_dump_common_sources = files(
66
'compress_lz4.c',
77
'compress_none.c',
88
'compress_zstd.c',
9+
'connectdb.c',
910
'dumputils.c',
1011
'filter.c',
1112
'parallel.c',

src/bin/pg_dump/pg_backup.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,9 +297,9 @@ typedef void (*SetupWorkerPtrType) (Archive *AH);
297297
* Main archiver interface.
298298
*/
299299

300-
extern void ConnectDatabase(Archive *AHX,
301-
const ConnParams *cparams,
302-
bool isReconnect);
300+
extern void ConnectDatabaseAhx(Archive *AHX,
301+
const ConnParams *cparams,
302+
bool isReconnect);
303303
extern void DisconnectDatabase(Archive *AHX);
304304
extern PGconn *GetConnection(Archive *AHX);
305305

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ RestoreArchive(Archive *AHX)
414414
AHX->minRemoteVersion = 0;
415415
AHX->maxRemoteVersion = 9999999;
416416

417-
ConnectDatabase(AHX, &ropt->cparams, false);
417+
ConnectDatabaseAhx(AHX, &ropt->cparams, false);
418418

419419
/*
420420
* If we're talking to the DB directly, don't send comments since they
@@ -4529,7 +4529,7 @@ restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
45294529
/*
45304530
* Now reconnect the single parent connection.
45314531
*/
4532-
ConnectDatabase((Archive *) AH, &ropt->cparams, true);
4532+
ConnectDatabaseAhx((Archive *) AH, &ropt->cparams, true);
45334533

45344534
/* re-establish fixed state */
45354535
_doSetFixedOutputState(AH);
@@ -5146,7 +5146,7 @@ CloneArchive(ArchiveHandle *AH)
51465146
* Connect our new clone object to the database, using the same connection
51475147
* parameters used for the original connection.
51485148
*/
5149-
ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
5149+
ConnectDatabaseAhx((Archive *) clone, &clone->public.ropt->cparams, true);
51505150

51515151
/* re-establish fixed state */
51525152
if (AH->mode == archModeRead)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy