mirror of
https://github.com/postgres/postgres.git
synced 2025-05-21 00:02:53 -04:00
Add -d option to pg_dumpall, for specifying a connection string.
Like with pg_basebackup and pg_receivexlog, it's a bit strange to call the option -d/--dbname, when in fact you cannot pass a database name in it. Original patch by Amit Kapila, heavily modified by me.
This commit is contained in:
parent
691e595dd9
commit
3dee636e04
@ -405,6 +405,25 @@ PostgreSQL documentation
|
|||||||
The following command-line options control the database connection parameters.
|
The following command-line options control the database connection parameters.
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-d <replaceable class="parameter">connstr</replaceable></option></term>
|
||||||
|
<term><option>--dbname=<replaceable class="parameter">connstr</replaceable></option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Specifies parameters used to connect to the server, as a connection
|
||||||
|
string. See <xref linkend="libpq-connstring"> for more information.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The option is called <literal>--dbname</> for consistency with other
|
||||||
|
client applications, but because <application>pg_dumpall</application>
|
||||||
|
needs to connect to many databases, database name in the connection
|
||||||
|
string will be ignored. Use <literal>-l</literal> option to specify
|
||||||
|
the name of the database used to dump global objects and to discover
|
||||||
|
what other databases should be dumped.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-h <replaceable>host</replaceable></option></term>
|
<term><option>-h <replaceable>host</replaceable></option></term>
|
||||||
<term><option>--host=<replaceable>host</replaceable></option></term>
|
<term><option>--host=<replaceable>host</replaceable></option></term>
|
||||||
|
@ -56,13 +56,15 @@ static int runPgDump(const char *dbname);
|
|||||||
static void buildShSecLabels(PGconn *conn, const char *catalog_name,
|
static void buildShSecLabels(PGconn *conn, const char *catalog_name,
|
||||||
uint32 objectId, PQExpBuffer buffer,
|
uint32 objectId, PQExpBuffer buffer,
|
||||||
const char *target, const char *objname);
|
const char *target, const char *objname);
|
||||||
static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
static PGconn *connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport,
|
||||||
const char *pguser, enum trivalue prompt_password, bool fail_on_error);
|
const char *pguser, enum trivalue prompt_password, bool fail_on_error);
|
||||||
|
static char *constructConnStr(const char **keywords, const char **values);
|
||||||
static PGresult *executeQuery(PGconn *conn, const char *query);
|
static PGresult *executeQuery(PGconn *conn, const char *query);
|
||||||
static void executeCommand(PGconn *conn, const char *query);
|
static void executeCommand(PGconn *conn, const char *query);
|
||||||
|
|
||||||
static char pg_dump_bin[MAXPGPATH];
|
static char pg_dump_bin[MAXPGPATH];
|
||||||
static PQExpBuffer pgdumpopts;
|
static PQExpBuffer pgdumpopts;
|
||||||
|
static char *connstr = "";
|
||||||
static bool skip_acls = false;
|
static bool skip_acls = false;
|
||||||
static bool verbose = false;
|
static bool verbose = false;
|
||||||
|
|
||||||
@ -91,6 +93,7 @@ main(int argc, char *argv[])
|
|||||||
{"globals-only", no_argument, NULL, 'g'},
|
{"globals-only", no_argument, NULL, 'g'},
|
||||||
{"host", required_argument, NULL, 'h'},
|
{"host", required_argument, NULL, 'h'},
|
||||||
{"ignore-version", no_argument, NULL, 'i'},
|
{"ignore-version", no_argument, NULL, 'i'},
|
||||||
|
{"dbname", required_argument, NULL, 'd'},
|
||||||
{"database", required_argument, NULL, 'l'},
|
{"database", required_argument, NULL, 'l'},
|
||||||
{"oids", no_argument, NULL, 'o'},
|
{"oids", no_argument, NULL, 'o'},
|
||||||
{"no-owner", no_argument, NULL, 'O'},
|
{"no-owner", no_argument, NULL, 'O'},
|
||||||
@ -188,7 +191,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
pgdumpopts = createPQExpBuffer();
|
pgdumpopts = createPQExpBuffer();
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "acf:gh:il:oOp:rsS:tU:vwWx", long_options, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, "acd:f:gh:i:l:oOp:rsS:tU:vwWx", long_options, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -201,6 +204,10 @@ main(int argc, char *argv[])
|
|||||||
output_clean = true;
|
output_clean = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
connstr = pg_strdup(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
filename = pg_strdup(optarg);
|
filename = pg_strdup(optarg);
|
||||||
appendPQExpBuffer(pgdumpopts, " -f ");
|
appendPQExpBuffer(pgdumpopts, " -f ");
|
||||||
@ -213,8 +220,6 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
pghost = pg_strdup(optarg);
|
pghost = pg_strdup(optarg);
|
||||||
appendPQExpBuffer(pgdumpopts, " -h ");
|
|
||||||
doShellQuoting(pgdumpopts, pghost);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
@ -235,8 +240,6 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
pgport = pg_strdup(optarg);
|
pgport = pg_strdup(optarg);
|
||||||
appendPQExpBuffer(pgdumpopts, " -p ");
|
|
||||||
doShellQuoting(pgdumpopts, pgport);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
@ -258,8 +261,6 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
pguser = pg_strdup(optarg);
|
pguser = pg_strdup(optarg);
|
||||||
appendPQExpBuffer(pgdumpopts, " -U ");
|
|
||||||
doShellQuoting(pgdumpopts, pguser);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -370,7 +371,7 @@ main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
if (pgdb)
|
if (pgdb)
|
||||||
{
|
{
|
||||||
conn = connectDatabase(pgdb, pghost, pgport, pguser,
|
conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser,
|
||||||
prompt_password, false);
|
prompt_password, false);
|
||||||
|
|
||||||
if (!conn)
|
if (!conn)
|
||||||
@ -382,10 +383,10 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
conn = connectDatabase("postgres", pghost, pgport, pguser,
|
conn = connectDatabase("postgres", connstr, pghost, pgport, pguser,
|
||||||
prompt_password, false);
|
prompt_password, false);
|
||||||
if (!conn)
|
if (!conn)
|
||||||
conn = connectDatabase("template1", pghost, pgport, pguser,
|
conn = connectDatabase("template1", connstr, pghost, pgport, pguser,
|
||||||
prompt_password, true);
|
prompt_password, true);
|
||||||
|
|
||||||
if (!conn)
|
if (!conn)
|
||||||
@ -568,6 +569,7 @@ help(void)
|
|||||||
" ALTER OWNER commands to set ownership\n"));
|
" ALTER OWNER commands to set ownership\n"));
|
||||||
|
|
||||||
printf(_("\nConnection options:\n"));
|
printf(_("\nConnection options:\n"));
|
||||||
|
printf(_(" -d, --dbname=CONNSTR connect using connection string\n"));
|
||||||
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
|
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
|
||||||
printf(_(" -l, --database=DBNAME alternative default database\n"));
|
printf(_(" -l, --database=DBNAME alternative default database\n"));
|
||||||
printf(_(" -p, --port=PORT database server port number\n"));
|
printf(_(" -p, --port=PORT database server port number\n"));
|
||||||
@ -1630,7 +1632,7 @@ dumpDatabases(PGconn *conn)
|
|||||||
static int
|
static int
|
||||||
runPgDump(const char *dbname)
|
runPgDump(const char *dbname)
|
||||||
{
|
{
|
||||||
PQExpBuffer connstr = createPQExpBuffer();
|
PQExpBuffer connstrbuf = createPQExpBuffer();
|
||||||
PQExpBuffer cmd = createPQExpBuffer();
|
PQExpBuffer cmd = createPQExpBuffer();
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -1647,16 +1649,13 @@ runPgDump(const char *dbname)
|
|||||||
appendPQExpBuffer(cmd, " -Fp ");
|
appendPQExpBuffer(cmd, " -Fp ");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct a connection string from the database name, like
|
* Append the database name to the already-constructed stem of connection
|
||||||
* dbname='<database name>'. pg_dump would usually also accept the
|
* string.
|
||||||
* database name as is, but if it contains any = characters, it would
|
|
||||||
* incorrectly treat it as a connection string.
|
|
||||||
*/
|
*/
|
||||||
appendPQExpBuffer(connstr, "dbname='");
|
appendPQExpBuffer(connstrbuf, "%s dbname=", connstr);
|
||||||
doConnStrQuoting(connstr, dbname);
|
doConnStrQuoting(connstrbuf, dbname);
|
||||||
appendPQExpBuffer(connstr, "'");
|
|
||||||
|
|
||||||
doShellQuoting(cmd, connstr->data);
|
doShellQuoting(cmd, connstrbuf->data);
|
||||||
|
|
||||||
appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE);
|
appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE);
|
||||||
|
|
||||||
@ -1669,7 +1668,7 @@ runPgDump(const char *dbname)
|
|||||||
ret = system(cmd->data);
|
ret = system(cmd->data);
|
||||||
|
|
||||||
destroyPQExpBuffer(cmd);
|
destroyPQExpBuffer(cmd);
|
||||||
destroyPQExpBuffer(connstr);
|
destroyPQExpBuffer(connstrbuf);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1703,16 +1702,23 @@ buildShSecLabels(PGconn *conn, const char *catalog_name, uint32 objectId,
|
|||||||
*
|
*
|
||||||
* If fail_on_error is false, we return NULL without printing any message
|
* If fail_on_error is false, we return NULL without printing any message
|
||||||
* on failure, but preserve any prompted password for the next try.
|
* on failure, but preserve any prompted password for the next try.
|
||||||
|
*
|
||||||
|
* On success, the global variable 'connstr' is set to a connection string
|
||||||
|
* containing the options used.
|
||||||
*/
|
*/
|
||||||
static PGconn *
|
static PGconn *
|
||||||
connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
connectDatabase(const char *dbname, const char *connection_string,
|
||||||
const char *pguser, enum trivalue prompt_password, bool fail_on_error)
|
const char *pghost, const char *pgport, const char *pguser,
|
||||||
|
enum trivalue prompt_password, bool fail_on_error)
|
||||||
{
|
{
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
bool new_pass;
|
bool new_pass;
|
||||||
const char *remoteversion_str;
|
const char *remoteversion_str;
|
||||||
int my_version;
|
int my_version;
|
||||||
static char *password = NULL;
|
static char *password = NULL;
|
||||||
|
const char **keywords = NULL;
|
||||||
|
const char **values = NULL;
|
||||||
|
PQconninfoOption *conn_opts = NULL;
|
||||||
|
|
||||||
if (prompt_password == TRI_YES && !password)
|
if (prompt_password == TRI_YES && !password)
|
||||||
password = simple_prompt("Password: ", 100, false);
|
password = simple_prompt("Password: ", 100, false);
|
||||||
@ -1723,31 +1729,93 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
|||||||
*/
|
*/
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
#define PARAMS_ARRAY_SIZE 7
|
int argcount = 6;
|
||||||
const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
|
PQconninfoOption *conn_opt;
|
||||||
const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
|
char *err_msg = NULL;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
keywords[0] = "host";
|
if (keywords)
|
||||||
values[0] = pghost;
|
free(keywords);
|
||||||
keywords[1] = "port";
|
if (values)
|
||||||
values[1] = pgport;
|
free(values);
|
||||||
keywords[2] = "user";
|
if (conn_opts)
|
||||||
values[2] = pguser;
|
PQconninfoFree(conn_opts);
|
||||||
keywords[3] = "password";
|
|
||||||
values[3] = password;
|
/*
|
||||||
keywords[4] = "dbname";
|
* Merge the connection info inputs given in form of connection string
|
||||||
values[4] = dbname;
|
* and other options.
|
||||||
keywords[5] = "fallback_application_name";
|
*/
|
||||||
values[5] = progname;
|
if (connection_string)
|
||||||
keywords[6] = NULL;
|
{
|
||||||
values[6] = NULL;
|
conn_opts = PQconninfoParse(connection_string, &err_msg);
|
||||||
|
if (conn_opts == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: %s\n", progname, err_msg);
|
||||||
|
exit_nicely(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
|
||||||
|
{
|
||||||
|
if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
|
||||||
|
argcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
|
||||||
|
values = pg_malloc0((argcount + 1) * sizeof(*values));
|
||||||
|
|
||||||
|
for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
|
||||||
|
{
|
||||||
|
if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
|
||||||
|
{
|
||||||
|
keywords[i] = conn_opt->keyword;
|
||||||
|
values[i] = conn_opt->val;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
|
||||||
|
values = pg_malloc0((argcount + 1) * sizeof(*values));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pghost)
|
||||||
|
{
|
||||||
|
keywords[i] = "host";
|
||||||
|
values[i] = pghost;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (pgport)
|
||||||
|
{
|
||||||
|
keywords[i] = "port";
|
||||||
|
values[i] = pgport;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (pguser)
|
||||||
|
{
|
||||||
|
keywords[i] = "user";
|
||||||
|
values[i] = pguser;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (password)
|
||||||
|
{
|
||||||
|
keywords[i] = "password";
|
||||||
|
values[i] = password;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (dbname)
|
||||||
|
{
|
||||||
|
keywords[i] = "dbname";
|
||||||
|
values[i] = dbname;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
keywords[i] = "fallback_application_name";
|
||||||
|
values[i] = progname;
|
||||||
|
i++;
|
||||||
|
|
||||||
new_pass = false;
|
new_pass = false;
|
||||||
conn = PQconnectdbParams(keywords, values, true);
|
conn = PQconnectdbParams(keywords, values, true);
|
||||||
|
|
||||||
free(keywords);
|
|
||||||
free(values);
|
|
||||||
|
|
||||||
if (!conn)
|
if (!conn)
|
||||||
{
|
{
|
||||||
fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
|
fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
|
||||||
@ -1779,10 +1847,26 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
|
||||||
|
free(keywords);
|
||||||
|
free(values);
|
||||||
|
PQconninfoFree(conn_opts);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ok, connected successfully. Remember the options used, in the form of
|
||||||
|
* a connection string.
|
||||||
|
*/
|
||||||
|
connstr = constructConnStr(keywords, values);
|
||||||
|
|
||||||
|
free(keywords);
|
||||||
|
free(values);
|
||||||
|
PQconninfoFree(conn_opts);
|
||||||
|
|
||||||
|
/* Check version */
|
||||||
remoteversion_str = PQparameterStatus(conn, "server_version");
|
remoteversion_str = PQparameterStatus(conn, "server_version");
|
||||||
if (!remoteversion_str)
|
if (!remoteversion_str)
|
||||||
{
|
{
|
||||||
@ -1829,6 +1913,43 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------
|
||||||
|
* Construct a connection string from the given keyword/value pairs. It is
|
||||||
|
* used to pass the connection options to the pg_dump subprocess.
|
||||||
|
*
|
||||||
|
* The following parameters are excluded:
|
||||||
|
* dbname - varies in each pg_dump invocation
|
||||||
|
* password - it's not secure to pass a password on the command line
|
||||||
|
* fallback_application_name - we'll let pg_dump set it
|
||||||
|
* ----------
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
constructConnStr(const char **keywords, const char **values)
|
||||||
|
{
|
||||||
|
PQExpBuffer buf = createPQExpBuffer();
|
||||||
|
char *connstr;
|
||||||
|
int i;
|
||||||
|
bool firstkeyword = true;
|
||||||
|
|
||||||
|
/* Construct a new connection string in key='value' format. */
|
||||||
|
for (i = 0; keywords[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(keywords[i], "dbname") == 0 ||
|
||||||
|
strcmp(keywords[i], "password") == 0 ||
|
||||||
|
strcmp(keywords[i], "fallback_application_name") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!firstkeyword)
|
||||||
|
appendPQExpBufferChar(buf, ' ');
|
||||||
|
firstkeyword = false;
|
||||||
|
appendPQExpBuffer(buf, "%s=", keywords[i]);
|
||||||
|
doConnStrQuoting(buf, values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
connstr = pg_strdup(buf->data);
|
||||||
|
destroyPQExpBuffer(buf);
|
||||||
|
return connstr;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run a query, return the results, exit program on failure.
|
* Run a query, return the results, exit program on failure.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user