1077 lines
38 KiB
Diff
1077 lines
38 KiB
Diff
From 27d64ec8da4c0813c5cb0956e74b332d1db67bc7 Mon Sep 17 00:00:00 2001
|
|
From: Tom Lane <tgl@sss.pgh.pa.us>
|
|
Date: Mon, 19 Oct 2020 19:03:47 -0400
|
|
Subject: [PATCH 2/2] Fix connection string handling in src/bin/scripts/
|
|
programs.
|
|
|
|
When told to process all databases, clusterdb, reindexdb, and vacuumdb
|
|
would reconnect by replacing their --maintenance-db parameter with the
|
|
name of the target database. If that parameter is a connstring (which
|
|
has been allowed for a long time, though we failed to document that
|
|
before this patch), we'd lose any other options it might specify, for
|
|
example SSL or GSS parameters, possibly resulting in failure to connect.
|
|
Thus, this is the same bug as commit a45bc8a4f fixed in pg_dump and
|
|
pg_restore. We can fix it in the same way, by using libpq's rules for
|
|
handling multiple "dbname" parameters to add the target database name
|
|
separately. I chose to apply the same refactoring approach as in that
|
|
patch, with a struct to handle the command line parameters that need to
|
|
be passed through to connectDatabase. (Maybe someday we can unify the
|
|
very similar functions here and in pg_dump/pg_restore.)
|
|
|
|
Per Peter Eisentraut's comments on bug #16604. Back-patch to all
|
|
supported branches.
|
|
|
|
Discussion: https://postgr.es/m/16604-933f4b8791227b15@postgresql.org
|
|
---
|
|
doc/src/sgml/ref/clusterdb.sgml | 20 +++++---
|
|
doc/src/sgml/ref/createdb.sgml | 3 ++
|
|
doc/src/sgml/ref/dropdb.sgml | 3 ++
|
|
doc/src/sgml/ref/reindexdb.sgml | 20 +++++---
|
|
doc/src/sgml/ref/vacuumdb.sgml | 20 +++++---
|
|
src/bin/scripts/clusterdb.c | 67 +++++++++++--------------
|
|
src/bin/scripts/common.c | 89 ++++++++++++++++++++-------------
|
|
src/bin/scripts/common.h | 26 +++++++---
|
|
src/bin/scripts/createdb.c | 11 +++-
|
|
src/bin/scripts/createuser.c | 11 +++-
|
|
src/bin/scripts/dropdb.c | 12 +++--
|
|
src/bin/scripts/dropuser.c | 13 +++--
|
|
src/bin/scripts/reindexdb.c | 85 +++++++++++++++----------------
|
|
src/bin/scripts/vacuumdb.c | 70 +++++++++++---------------
|
|
14 files changed, 254 insertions(+), 196 deletions(-)
|
|
|
|
diff --git a/doc/src/sgml/ref/clusterdb.sgml b/doc/src/sgml/ref/clusterdb.sgml
|
|
index 67582fd6e6..e3e2c0cff7 100644
|
|
--- a/doc/src/sgml/ref/clusterdb.sgml
|
|
+++ b/doc/src/sgml/ref/clusterdb.sgml
|
|
@@ -90,9 +90,9 @@ PostgreSQL documentation
|
|
<term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></></term>
|
|
<listitem>
|
|
<para>
|
|
- Specifies the name of the database to be clustered.
|
|
- If this is not specified and <option>-a</option> (or
|
|
- <option>--all</option>) is not used, the database name is read
|
|
+ Specifies the name of the database to be clustered,
|
|
+ when <option>-a</option>/<option>--all</option> is not used.
|
|
+ If this is not specified, the database name is read
|
|
from the environment variable <envar>PGDATABASE</envar>. If
|
|
that is not set, the user name specified for the connection is
|
|
used.
|
|
@@ -246,10 +246,16 @@ PostgreSQL documentation
|
|
<term><option>--maintenance-db=<replaceable class="parameter">dbname</replaceable></></term>
|
|
<listitem>
|
|
<para>
|
|
- Specifies the name of the database to connect to discover what other
|
|
- databases should be clustered. If not specified, the
|
|
- <literal>postgres</literal> database will be used,
|
|
- and if that does not exist, <literal>template1</literal> will be used.
|
|
+ Specifies the name of the database to connect to to discover which
|
|
+ databases should be clustered,
|
|
+ when <option>-a</option>/<option>--all</option> is used.
|
|
+ If not specified, the <literal>postgres</literal> database will be used,
|
|
+ or if that does not exist, <literal>template1</literal> will be used.
|
|
+ This can be a <link linkend="libpq-connstring">connection
|
|
+ string</link>. If so, connection string parameters will override any
|
|
+ conflicting command line options. Also, connection string parameters
|
|
+ other than the database name itself will be re-used when connecting
|
|
+ to other databases.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
diff --git a/doc/src/sgml/ref/createdb.sgml b/doc/src/sgml/ref/createdb.sgml
|
|
index 9fc4c16a81..7bb46a0fb2 100644
|
|
--- a/doc/src/sgml/ref/createdb.sgml
|
|
+++ b/doc/src/sgml/ref/createdb.sgml
|
|
@@ -286,6 +286,9 @@ PostgreSQL documentation
|
|
database will be used; if that does not exist (or if it is the name
|
|
of the new database being created), <literal>template1</literal> will
|
|
be used.
|
|
+ This can be a <link linkend="libpq-connstring">connection
|
|
+ string</link>. If so, connection string parameters will override any
|
|
+ conflicting command line options.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
diff --git a/doc/src/sgml/ref/dropdb.sgml b/doc/src/sgml/ref/dropdb.sgml
|
|
index 16c49e7928..0d7170d665 100644
|
|
--- a/doc/src/sgml/ref/dropdb.sgml
|
|
+++ b/doc/src/sgml/ref/dropdb.sgml
|
|
@@ -205,6 +205,9 @@ PostgreSQL documentation
|
|
target database. If not specified, the <literal>postgres</literal>
|
|
database will be used; if that does not exist (or is the database
|
|
being dropped), <literal>template1</literal> will be used.
|
|
+ This can be a <link linkend="libpq-connstring">connection
|
|
+ string</link>. If so, connection string parameters will override any
|
|
+ conflicting command line options.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml
|
|
index e4721d8113..202e45e6ae 100644
|
|
--- a/doc/src/sgml/ref/reindexdb.sgml
|
|
+++ b/doc/src/sgml/ref/reindexdb.sgml
|
|
@@ -123,9 +123,9 @@ PostgreSQL documentation
|
|
<term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></></term>
|
|
<listitem>
|
|
<para>
|
|
- Specifies the name of the database to be reindexed.
|
|
- If this is not specified and <option>-a</option> (or
|
|
- <option>--all</option>) is not used, the database name is read
|
|
+ Specifies the name of the database to be reindexed,
|
|
+ when <option>-a</option>/<option>--all</option> is not used.
|
|
+ If this is not specified, the database name is read
|
|
from the environment variable <envar>PGDATABASE</envar>. If
|
|
that is not set, the user name specified for the connection is
|
|
used.
|
|
@@ -314,10 +314,16 @@ PostgreSQL documentation
|
|
<term><option>--maintenance-db=<replaceable class="parameter">dbname</replaceable></></term>
|
|
<listitem>
|
|
<para>
|
|
- Specifies the name of the database to connect to discover what other
|
|
- databases should be reindexed. If not specified, the
|
|
- <literal>postgres</literal> database will be used,
|
|
- and if that does not exist, <literal>template1</literal> will be used.
|
|
+ Specifies the name of the database to connect to to discover which
|
|
+ databases should be reindexed,
|
|
+ when <option>-a</option>/<option>--all</option> is used.
|
|
+ If not specified, the <literal>postgres</literal> database will be used,
|
|
+ or if that does not exist, <literal>template1</literal> will be used.
|
|
+ This can be a <link linkend="libpq-connstring">connection
|
|
+ string</link>. If so, connection string parameters will override any
|
|
+ conflicting command line options. Also, connection string parameters
|
|
+ other than the database name itself will be re-used when connecting
|
|
+ to other databases.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml
|
|
index 4f6fa0d708..64a9f2dba3 100644
|
|
--- a/doc/src/sgml/ref/vacuumdb.sgml
|
|
+++ b/doc/src/sgml/ref/vacuumdb.sgml
|
|
@@ -92,9 +92,9 @@ PostgreSQL documentation
|
|
<term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></option></term>
|
|
<listitem>
|
|
<para>
|
|
- Specifies the name of the database to be cleaned or analyzed.
|
|
- If this is not specified and <option>-a</option> (or
|
|
- <option>--all</option>) is not used, the database name is read
|
|
+ Specifies the name of the database to be cleaned or analyzed,
|
|
+ when <option>-a</option>/<option>--all</option> is not used.
|
|
+ If this is not specified, the database name is read
|
|
from the environment variable <envar>PGDATABASE</envar>. If
|
|
that is not set, the user name specified for the connection is
|
|
used.
|
|
@@ -339,10 +339,16 @@ PostgreSQL documentation
|
|
<term><option>--maintenance-db=<replaceable class="parameter">dbname</replaceable></></term>
|
|
<listitem>
|
|
<para>
|
|
- Specifies the name of the database to connect to discover what other
|
|
- databases should be vacuumed. If not specified, the
|
|
- <literal>postgres</literal> database will be used,
|
|
- and if that does not exist, <literal>template1</literal> will be used.
|
|
+ Specifies the name of the database to connect to to discover which
|
|
+ databases should be vacuumed,
|
|
+ when <option>-a</option>/<option>--all</option> is used.
|
|
+ If not specified, the <literal>postgres</literal> database will be used,
|
|
+ or if that does not exist, <literal>template1</literal> will be used.
|
|
+ This can be a <link linkend="libpq-connstring">connection
|
|
+ string</link>. If so, connection string parameters will override any
|
|
+ conflicting command line options. Also, connection string parameters
|
|
+ other than the database name itself will be re-used when connecting
|
|
+ to other databases.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
diff --git a/src/bin/scripts/clusterdb.c b/src/bin/scripts/clusterdb.c
|
|
index c48b0cb08f..e53cc92405 100644
|
|
--- a/src/bin/scripts/clusterdb.c
|
|
+++ b/src/bin/scripts/clusterdb.c
|
|
@@ -15,15 +15,10 @@
|
|
#include "fe_utils/string_utils.h"
|
|
|
|
|
|
-static void cluster_one_database(const char *dbname, bool verbose, const char *table,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
- const char *progname, bool echo);
|
|
-static void cluster_all_databases(bool verbose, const char *maintenance_db,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
- const char *progname, bool echo, bool quiet);
|
|
-
|
|
+static void cluster_one_database(const ConnParams *cparams, const char *table,
|
|
+ const char *progname, bool verbose, bool echo);
|
|
+static void cluster_all_databases(ConnParams *cparams, const char *progname,
|
|
+ bool verbose, bool echo, bool quiet);
|
|
static void help(const char *progname);
|
|
|
|
|
|
@@ -56,6 +51,7 @@ main(int argc, char *argv[])
|
|
char *port = NULL;
|
|
char *username = NULL;
|
|
enum trivalue prompt_password = TRI_DEFAULT;
|
|
+ ConnParams cparams;
|
|
bool echo = false;
|
|
bool quiet = false;
|
|
bool alldb = false;
|
|
@@ -131,6 +127,13 @@ main(int argc, char *argv[])
|
|
exit(1);
|
|
}
|
|
|
|
+ /* fill cparams except for dbname, which is set below */
|
|
+ cparams.pghost = host;
|
|
+ cparams.pgport = port;
|
|
+ cparams.pguser = username;
|
|
+ cparams.prompt_password = prompt_password;
|
|
+ cparams.override_dbname = NULL;
|
|
+
|
|
setup_cancel_handler();
|
|
|
|
if (alldb)
|
|
@@ -149,8 +152,9 @@ main(int argc, char *argv[])
|
|
exit(1);
|
|
}
|
|
|
|
- cluster_all_databases(verbose, maintenance_db, host, port, username, prompt_password,
|
|
- progname, echo, quiet);
|
|
+ cparams.dbname = maintenance_db;
|
|
+
|
|
+ cluster_all_databases(&cparams, progname, verbose, echo, quiet);
|
|
}
|
|
else
|
|
{
|
|
@@ -164,21 +168,21 @@ main(int argc, char *argv[])
|
|
dbname = get_user_name_or_exit(progname);
|
|
}
|
|
|
|
+ cparams.dbname = dbname;
|
|
+
|
|
if (tables.head != NULL)
|
|
{
|
|
SimpleStringListCell *cell;
|
|
|
|
for (cell = tables.head; cell; cell = cell->next)
|
|
{
|
|
- cluster_one_database(dbname, verbose, cell->val,
|
|
- host, port, username, prompt_password,
|
|
- progname, echo);
|
|
+ cluster_one_database(&cparams, cell->val,
|
|
+ progname, verbose, echo);
|
|
}
|
|
}
|
|
else
|
|
- cluster_one_database(dbname, verbose, NULL,
|
|
- host, port, username, prompt_password,
|
|
- progname, echo);
|
|
+ cluster_one_database(&cparams, NULL,
|
|
+ progname, verbose, echo);
|
|
}
|
|
|
|
exit(0);
|
|
@@ -186,17 +190,14 @@ main(int argc, char *argv[])
|
|
|
|
|
|
static void
|
|
-cluster_one_database(const char *dbname, bool verbose, const char *table,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
- const char *progname, bool echo)
|
|
+cluster_one_database(const ConnParams *cparams, const char *table,
|
|
+ const char *progname, bool verbose, bool echo)
|
|
{
|
|
PQExpBufferData sql;
|
|
|
|
PGconn *conn;
|
|
|
|
- conn = connectDatabase(dbname, host, port, username, prompt_password,
|
|
- progname, echo, false, false);
|
|
+ conn = connectDatabase(cparams, progname, echo, false, false);
|
|
|
|
initPQExpBuffer(&sql);
|
|
|
|
@@ -227,22 +228,17 @@ cluster_one_database(const char *dbname, bool verbose, const char *table,
|
|
|
|
|
|
static void
|
|
-cluster_all_databases(bool verbose, const char *maintenance_db,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
- const char *progname, bool echo, bool quiet)
|
|
+cluster_all_databases(ConnParams *cparams, const char *progname,
|
|
+ bool verbose, bool echo, bool quiet)
|
|
{
|
|
PGconn *conn;
|
|
PGresult *result;
|
|
- PQExpBufferData connstr;
|
|
int i;
|
|
|
|
- conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
|
|
- prompt_password, progname, echo);
|
|
+ conn = connectMaintenanceDatabase(cparams, progname, echo);
|
|
result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
|
|
PQfinish(conn);
|
|
|
|
- initPQExpBuffer(&connstr);
|
|
for (i = 0; i < PQntuples(result); i++)
|
|
{
|
|
char *dbname = PQgetvalue(result, i, 0);
|
|
@@ -253,15 +249,10 @@ cluster_all_databases(bool verbose, const char *maintenance_db,
|
|
fflush(stdout);
|
|
}
|
|
|
|
- resetPQExpBuffer(&connstr);
|
|
- appendPQExpBuffer(&connstr, "dbname=");
|
|
- appendConnStrVal(&connstr, dbname);
|
|
+ cparams->override_dbname = dbname;
|
|
|
|
- cluster_one_database(connstr.data, verbose, NULL,
|
|
- host, port, username, prompt_password,
|
|
- progname, echo);
|
|
+ cluster_one_database(cparams, NULL, progname, verbose, echo);
|
|
}
|
|
- termPQExpBuffer(&connstr);
|
|
|
|
PQclear(result);
|
|
}
|
|
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c
|
|
index 5088c4c48e..ad70ca4ff9 100644
|
|
--- a/src/bin/scripts/common.c
|
|
+++ b/src/bin/scripts/common.c
|
|
@@ -57,7 +57,7 @@ handle_help_version_opts(int argc, char *argv[],
|
|
* Make a database connection with the given parameters.
|
|
*
|
|
* An interactive password prompt is automatically issued if needed and
|
|
- * allowed by prompt_password.
|
|
+ * allowed by cparams->prompt_password.
|
|
*
|
|
* If allow_password_reuse is true, we will try to re-use any password
|
|
* given during previous calls to this routine. (Callers should not pass
|
|
@@ -65,9 +65,7 @@ handle_help_version_opts(int argc, char *argv[],
|
|
* as before, else we might create password exposure hazards.)
|
|
*/
|
|
PGconn *
|
|
-connectDatabase(const char *dbname, const char *pghost,
|
|
- const char *pgport, const char *pguser,
|
|
- enum trivalue prompt_password, const char *progname,
|
|
+connectDatabase(const ConnParams *cparams, const char *progname,
|
|
bool echo, bool fail_ok, bool allow_password_reuse)
|
|
{
|
|
PGconn *conn;
|
|
@@ -75,10 +73,13 @@ connectDatabase(const char *dbname, const char *pghost,
|
|
static bool have_password = false;
|
|
static char password[100];
|
|
|
|
+ /* Callers must supply at least dbname; other params can be NULL */
|
|
+ Assert(cparams->dbname);
|
|
+
|
|
if (!allow_password_reuse)
|
|
have_password = false;
|
|
|
|
- if (!have_password && prompt_password == TRI_YES)
|
|
+ if (cparams->prompt_password == TRI_YES && !have_password)
|
|
{
|
|
simple_prompt("Password: ", password, sizeof(password), false);
|
|
have_password = true;
|
|
@@ -90,23 +91,35 @@ connectDatabase(const char *dbname, const char *pghost,
|
|
*/
|
|
do
|
|
{
|
|
- const char *keywords[7];
|
|
- const char *values[7];
|
|
-
|
|
- keywords[0] = "host";
|
|
- values[0] = pghost;
|
|
- keywords[1] = "port";
|
|
- values[1] = pgport;
|
|
- keywords[2] = "user";
|
|
- values[2] = pguser;
|
|
- keywords[3] = "password";
|
|
- values[3] = have_password ? password : NULL;
|
|
- keywords[4] = "dbname";
|
|
- values[4] = dbname;
|
|
- keywords[5] = "fallback_application_name";
|
|
- values[5] = progname;
|
|
- keywords[6] = NULL;
|
|
- values[6] = NULL;
|
|
+ const char *keywords[8];
|
|
+ const char *values[8];
|
|
+ int i = 0;
|
|
+
|
|
+ /*
|
|
+ * If dbname is a connstring, its entries can override the other
|
|
+ * values obtained from cparams; but in turn, override_dbname can
|
|
+ * override the dbname component of it.
|
|
+ */
|
|
+ keywords[i] = "host";
|
|
+ values[i++] = cparams->pghost;
|
|
+ keywords[i] = "port";
|
|
+ values[i++] = cparams->pgport;
|
|
+ keywords[i] = "user";
|
|
+ values[i++] = cparams->pguser;
|
|
+ keywords[i] = "password";
|
|
+ values[i++] = have_password ? password : NULL;
|
|
+ keywords[i] = "dbname";
|
|
+ values[i++] = cparams->dbname;
|
|
+ if (cparams->override_dbname)
|
|
+ {
|
|
+ keywords[i] = "dbname";
|
|
+ values[i++] = cparams->override_dbname;
|
|
+ }
|
|
+ keywords[i] = "fallback_application_name";
|
|
+ values[i++] = progname;
|
|
+ keywords[i] = NULL;
|
|
+ values[i++] = NULL;
|
|
+ Assert(i <= lengthof(keywords));
|
|
|
|
new_pass = false;
|
|
conn = PQconnectdbParams(keywords, values, true);
|
|
@@ -114,7 +127,7 @@ connectDatabase(const char *dbname, const char *pghost,
|
|
if (!conn)
|
|
{
|
|
fprintf(stderr, _("%s: could not connect to database %s: out of memory\n"),
|
|
- progname, dbname);
|
|
+ progname, cparams->dbname);
|
|
exit(1);
|
|
}
|
|
|
|
@@ -123,7 +136,7 @@ connectDatabase(const char *dbname, const char *pghost,
|
|
*/
|
|
if (PQstatus(conn) == CONNECTION_BAD &&
|
|
PQconnectionNeedsPassword(conn) &&
|
|
- prompt_password != TRI_NO)
|
|
+ cparams->prompt_password != TRI_NO)
|
|
{
|
|
PQfinish(conn);
|
|
simple_prompt("Password: ", password, sizeof(password), false);
|
|
@@ -141,10 +154,11 @@ connectDatabase(const char *dbname, const char *pghost,
|
|
return NULL;
|
|
}
|
|
fprintf(stderr, _("%s: could not connect to database %s: %s"),
|
|
- progname, dbname, PQerrorMessage(conn));
|
|
+ progname, cparams->dbname, PQerrorMessage(conn));
|
|
exit(1);
|
|
}
|
|
|
|
+ /* Start strict; callers may override this. */
|
|
PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL,
|
|
progname, echo));
|
|
|
|
@@ -153,27 +167,30 @@ connectDatabase(const char *dbname, const char *pghost,
|
|
|
|
/*
|
|
* Try to connect to the appropriate maintenance database.
|
|
+ *
|
|
+ * This differs from connectDatabase only in that it has a rule for
|
|
+ * inserting a default "dbname" if none was given (which is why cparams
|
|
+ * is not const). Note that cparams->dbname should typically come from
|
|
+ * a --maintenance-db command line parameter.
|
|
*/
|
|
PGconn *
|
|
-connectMaintenanceDatabase(const char *maintenance_db,
|
|
- const char *pghost, const char *pgport,
|
|
- const char *pguser, enum trivalue prompt_password,
|
|
+connectMaintenanceDatabase(ConnParams *cparams,
|
|
const char *progname, bool echo)
|
|
{
|
|
PGconn *conn;
|
|
|
|
/* If a maintenance database name was specified, just connect to it. */
|
|
- if (maintenance_db)
|
|
- return connectDatabase(maintenance_db, pghost, pgport, pguser,
|
|
- prompt_password, progname, echo, false, false);
|
|
+ if (cparams->dbname)
|
|
+ return connectDatabase(cparams, progname, echo, false, false);
|
|
|
|
/* Otherwise, try postgres first and then template1. */
|
|
- conn = connectDatabase("postgres", pghost, pgport, pguser, prompt_password,
|
|
- progname, echo, true, false);
|
|
+ cparams->dbname = "postgres";
|
|
+ conn = connectDatabase(cparams, progname, echo, true, false);
|
|
if (!conn)
|
|
- conn = connectDatabase("template1", pghost, pgport, pguser,
|
|
- prompt_password, progname, echo, false, false);
|
|
-
|
|
+ {
|
|
+ cparams->dbname = "template1";
|
|
+ conn = connectDatabase(cparams, progname, echo, false, false);
|
|
+ }
|
|
return conn;
|
|
}
|
|
|
|
diff --git a/src/bin/scripts/common.h b/src/bin/scripts/common.h
|
|
index 085e3b7cf6..b94c3e907f 100644
|
|
--- a/src/bin/scripts/common.h
|
|
+++ b/src/bin/scripts/common.h
|
|
@@ -23,20 +23,32 @@ enum trivalue
|
|
|
|
extern bool CancelRequested;
|
|
|
|
+/* Parameters needed by connectDatabase/connectMaintenanceDatabase */
|
|
+typedef struct _connParams
|
|
+{
|
|
+ /* These fields record the actual command line parameters */
|
|
+ const char *dbname; /* this may be a connstring! */
|
|
+ const char *pghost;
|
|
+ const char *pgport;
|
|
+ const char *pguser;
|
|
+ enum trivalue prompt_password;
|
|
+ /* If not NULL, this overrides the dbname obtained from command line */
|
|
+ /* (but *only* the DB name, not anything else in the connstring) */
|
|
+ const char *override_dbname;
|
|
+} ConnParams;
|
|
+
|
|
typedef void (*help_handler) (const char *progname);
|
|
|
|
extern void handle_help_version_opts(int argc, char *argv[],
|
|
const char *fixed_progname,
|
|
help_handler hlp);
|
|
|
|
-extern PGconn *connectDatabase(const char *dbname, const char *pghost,
|
|
- const char *pgport, const char *pguser,
|
|
- enum trivalue prompt_password, const char *progname,
|
|
- bool echo, bool fail_ok, bool allow_password_reuse);
|
|
+extern PGconn *connectDatabase(const ConnParams *cparams,
|
|
+ const char *progname,
|
|
+ bool echo, bool fail_ok,
|
|
+ bool allow_password_reuse);
|
|
|
|
-extern PGconn *connectMaintenanceDatabase(const char *maintenance_db,
|
|
- const char *pghost, const char *pgport,
|
|
- const char *pguser, enum trivalue prompt_password,
|
|
+extern PGconn *connectMaintenanceDatabase(ConnParams *cparams,
|
|
const char *progname, bool echo);
|
|
|
|
extern PGresult *executeQuery(PGconn *conn, const char *query,
|
|
diff --git a/src/bin/scripts/createdb.c b/src/bin/scripts/createdb.c
|
|
index 45d26ecb8c..f1be5745fb 100644
|
|
--- a/src/bin/scripts/createdb.c
|
|
+++ b/src/bin/scripts/createdb.c
|
|
@@ -50,6 +50,7 @@ main(int argc, char *argv[])
|
|
char *port = NULL;
|
|
char *username = NULL;
|
|
enum trivalue prompt_password = TRI_DEFAULT;
|
|
+ ConnParams cparams;
|
|
bool echo = false;
|
|
char *owner = NULL;
|
|
char *tablespace = NULL;
|
|
@@ -181,8 +182,14 @@ main(int argc, char *argv[])
|
|
if (maintenance_db == NULL && strcmp(dbname, "postgres") == 0)
|
|
maintenance_db = "template1";
|
|
|
|
- conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
|
|
- prompt_password, progname, echo);
|
|
+ cparams.dbname = maintenance_db;
|
|
+ cparams.pghost = host;
|
|
+ cparams.pgport = port;
|
|
+ cparams.pguser = username;
|
|
+ cparams.prompt_password = prompt_password;
|
|
+ cparams.override_dbname = NULL;
|
|
+
|
|
+ conn = connectMaintenanceDatabase(&cparams, progname, echo);
|
|
|
|
initPQExpBuffer(&sql);
|
|
|
|
diff --git a/src/bin/scripts/createuser.c b/src/bin/scripts/createuser.c
|
|
index edadd136a6..b1585d7e56 100644
|
|
--- a/src/bin/scripts/createuser.c
|
|
+++ b/src/bin/scripts/createuser.c
|
|
@@ -60,6 +60,7 @@ main(int argc, char *argv[])
|
|
char *username = NULL;
|
|
SimpleStringList roles = {NULL, NULL};
|
|
enum trivalue prompt_password = TRI_DEFAULT;
|
|
+ ConnParams cparams;
|
|
bool echo = false;
|
|
bool interactive = false;
|
|
char *conn_limit = NULL;
|
|
@@ -251,8 +252,14 @@ main(int argc, char *argv[])
|
|
if (login == 0)
|
|
login = TRI_YES;
|
|
|
|
- conn = connectDatabase("postgres", host, port, username, prompt_password,
|
|
- progname, echo, false, false);
|
|
+ cparams.dbname = NULL; /* this program lacks any dbname option... */
|
|
+ cparams.pghost = host;
|
|
+ cparams.pgport = port;
|
|
+ cparams.pguser = username;
|
|
+ cparams.prompt_password = prompt_password;
|
|
+ cparams.override_dbname = NULL;
|
|
+
|
|
+ conn = connectMaintenanceDatabase(&cparams, progname, echo);
|
|
|
|
initPQExpBuffer(&sql);
|
|
|
|
diff --git a/src/bin/scripts/dropdb.c b/src/bin/scripts/dropdb.c
|
|
index 614110179e..3f14a365ee 100644
|
|
--- a/src/bin/scripts/dropdb.c
|
|
+++ b/src/bin/scripts/dropdb.c
|
|
@@ -46,6 +46,7 @@ main(int argc, char *argv[])
|
|
char *port = NULL;
|
|
char *username = NULL;
|
|
enum trivalue prompt_password = TRI_DEFAULT;
|
|
+ ConnParams cparams;
|
|
bool echo = false;
|
|
bool interactive = false;
|
|
|
|
@@ -128,9 +129,14 @@ main(int argc, char *argv[])
|
|
if (maintenance_db == NULL && strcmp(dbname, "postgres") == 0)
|
|
maintenance_db = "template1";
|
|
|
|
- conn = connectMaintenanceDatabase(maintenance_db,
|
|
- host, port, username, prompt_password,
|
|
- progname, echo);
|
|
+ cparams.dbname = maintenance_db;
|
|
+ cparams.pghost = host;
|
|
+ cparams.pgport = port;
|
|
+ cparams.pguser = username;
|
|
+ cparams.prompt_password = prompt_password;
|
|
+ cparams.override_dbname = NULL;
|
|
+
|
|
+ conn = connectMaintenanceDatabase(&cparams, progname, echo);
|
|
|
|
if (echo)
|
|
printf("%s\n", sql.data);
|
|
diff --git a/src/bin/scripts/dropuser.c b/src/bin/scripts/dropuser.c
|
|
index ad400c3518..1dd5ad20fd 100644
|
|
--- a/src/bin/scripts/dropuser.c
|
|
+++ b/src/bin/scripts/dropuser.c
|
|
@@ -44,6 +44,7 @@ main(int argc, char *argv[])
|
|
char *port = NULL;
|
|
char *username = NULL;
|
|
enum trivalue prompt_password = TRI_DEFAULT;
|
|
+ ConnParams cparams;
|
|
bool echo = false;
|
|
bool interactive = false;
|
|
char dropuser_buf[128];
|
|
@@ -129,13 +130,19 @@ main(int argc, char *argv[])
|
|
exit(0);
|
|
}
|
|
|
|
+ cparams.dbname = NULL; /* this program lacks any dbname option... */
|
|
+ cparams.pghost = host;
|
|
+ cparams.pgport = port;
|
|
+ cparams.pguser = username;
|
|
+ cparams.prompt_password = prompt_password;
|
|
+ cparams.override_dbname = NULL;
|
|
+
|
|
+ conn = connectMaintenanceDatabase(&cparams, progname, echo);
|
|
+
|
|
initPQExpBuffer(&sql);
|
|
appendPQExpBuffer(&sql, "DROP ROLE %s%s;",
|
|
(if_exists ? "IF EXISTS " : ""), fmtId(dropuser));
|
|
|
|
- conn = connectDatabase("postgres", host, port, username, prompt_password,
|
|
- progname, echo, false, false);
|
|
-
|
|
if (echo)
|
|
printf("%s\n", sql.data);
|
|
result = PQexec(conn, sql.data);
|
|
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
|
|
index cdfb115641..48074afe79 100644
|
|
--- a/src/bin/scripts/reindexdb.c
|
|
+++ b/src/bin/scripts/reindexdb.c
|
|
@@ -15,19 +15,14 @@
|
|
#include "fe_utils/string_utils.h"
|
|
|
|
|
|
-static void reindex_one_database(const char *name, const char *dbname,
|
|
- const char *type, const char *host,
|
|
- const char *port, const char *username,
|
|
- enum trivalue prompt_password, const char *progname,
|
|
+static void reindex_one_database(const ConnParams *cparams,
|
|
+ const char *type, const char *name,
|
|
+ const char *progname,
|
|
bool echo, bool verbose);
|
|
-static void reindex_all_databases(const char *maintenance_db,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
+static void reindex_all_databases(ConnParams *cparams,
|
|
const char *progname, bool echo,
|
|
bool quiet, bool verbose);
|
|
-static void reindex_system_catalogs(const char *dbname,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
+static void reindex_system_catalogs(const ConnParams *cparams,
|
|
const char *progname, bool echo, bool verbose);
|
|
static void help(const char *progname);
|
|
|
|
@@ -63,6 +58,7 @@ main(int argc, char *argv[])
|
|
const char *port = NULL;
|
|
const char *username = NULL;
|
|
enum trivalue prompt_password = TRI_DEFAULT;
|
|
+ ConnParams cparams;
|
|
bool syscatalog = false;
|
|
bool alldb = false;
|
|
bool echo = false;
|
|
@@ -151,6 +147,13 @@ main(int argc, char *argv[])
|
|
exit(1);
|
|
}
|
|
|
|
+ /* fill cparams except for dbname, which is set below */
|
|
+ cparams.pghost = host;
|
|
+ cparams.pgport = port;
|
|
+ cparams.pguser = username;
|
|
+ cparams.prompt_password = prompt_password;
|
|
+ cparams.override_dbname = NULL;
|
|
+
|
|
setup_cancel_handler();
|
|
|
|
if (alldb)
|
|
@@ -181,8 +184,10 @@ main(int argc, char *argv[])
|
|
exit(1);
|
|
}
|
|
|
|
- reindex_all_databases(maintenance_db, host, port, username,
|
|
- prompt_password, progname, echo, quiet, verbose);
|
|
+ cparams.dbname = maintenance_db;
|
|
+
|
|
+ reindex_all_databases(&cparams,
|
|
+ progname, echo, quiet, verbose);
|
|
}
|
|
else if (syscatalog)
|
|
{
|
|
@@ -212,7 +217,9 @@ main(int argc, char *argv[])
|
|
dbname = get_user_name_or_exit(progname);
|
|
}
|
|
|
|
- reindex_system_catalogs(dbname, host, port, username, prompt_password,
|
|
+ cparams.dbname = dbname;
|
|
+
|
|
+ reindex_system_catalogs(&cparams,
|
|
progname, echo, verbose);
|
|
}
|
|
else
|
|
@@ -227,14 +234,16 @@ main(int argc, char *argv[])
|
|
dbname = get_user_name_or_exit(progname);
|
|
}
|
|
|
|
+ cparams.dbname = dbname;
|
|
+
|
|
if (schemas.head != NULL)
|
|
{
|
|
SimpleStringListCell *cell;
|
|
|
|
for (cell = schemas.head; cell; cell = cell->next)
|
|
{
|
|
- reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
|
|
- username, prompt_password, progname, echo, verbose);
|
|
+ reindex_one_database(&cparams, "SCHEMA", cell->val,
|
|
+ progname, echo, verbose);
|
|
}
|
|
}
|
|
|
|
@@ -244,8 +253,8 @@ main(int argc, char *argv[])
|
|
|
|
for (cell = indexes.head; cell; cell = cell->next)
|
|
{
|
|
- reindex_one_database(cell->val, dbname, "INDEX", host, port,
|
|
- username, prompt_password, progname, echo, verbose);
|
|
+ reindex_one_database(&cparams, "INDEX", cell->val,
|
|
+ progname, echo, verbose);
|
|
}
|
|
}
|
|
if (tables.head != NULL)
|
|
@@ -254,8 +263,8 @@ main(int argc, char *argv[])
|
|
|
|
for (cell = tables.head; cell; cell = cell->next)
|
|
{
|
|
- reindex_one_database(cell->val, dbname, "TABLE", host, port,
|
|
- username, prompt_password, progname, echo, verbose);
|
|
+ reindex_one_database(&cparams, "TABLE", cell->val,
|
|
+ progname, echo, verbose);
|
|
}
|
|
}
|
|
|
|
@@ -264,25 +273,24 @@ main(int argc, char *argv[])
|
|
* specified
|
|
*/
|
|
if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
|
|
- reindex_one_database(NULL, dbname, "DATABASE", host, port,
|
|
- username, prompt_password, progname, echo, verbose);
|
|
+ reindex_one_database(&cparams, "DATABASE", NULL,
|
|
+ progname, echo, verbose);
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
static void
|
|
-reindex_one_database(const char *name, const char *dbname, const char *type,
|
|
- const char *host, const char *port, const char *username,
|
|
- enum trivalue prompt_password, const char *progname, bool echo,
|
|
- bool verbose)
|
|
+reindex_one_database(const ConnParams *cparams,
|
|
+ const char *type, const char *name,
|
|
+ const char *progname,
|
|
+ bool echo, bool verbose)
|
|
{
|
|
PQExpBufferData sql;
|
|
|
|
PGconn *conn;
|
|
|
|
- conn = connectDatabase(dbname, host, port, username, prompt_password,
|
|
- progname, echo, false, false);
|
|
+ conn = connectDatabase(cparams, progname, echo, false, false);
|
|
|
|
initPQExpBuffer(&sql);
|
|
|
|
@@ -325,22 +333,17 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
|
|
}
|
|
|
|
static void
|
|
-reindex_all_databases(const char *maintenance_db,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
+reindex_all_databases(ConnParams *cparams,
|
|
const char *progname, bool echo, bool quiet, bool verbose)
|
|
{
|
|
PGconn *conn;
|
|
PGresult *result;
|
|
- PQExpBufferData connstr;
|
|
int i;
|
|
|
|
- conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
|
|
- prompt_password, progname, echo);
|
|
+ conn = connectMaintenanceDatabase(cparams, progname, echo);
|
|
result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
|
|
PQfinish(conn);
|
|
|
|
- initPQExpBuffer(&connstr);
|
|
for (i = 0; i < PQntuples(result); i++)
|
|
{
|
|
char *dbname = PQgetvalue(result, i, 0);
|
|
@@ -351,29 +354,23 @@ reindex_all_databases(const char *maintenance_db,
|
|
fflush(stdout);
|
|
}
|
|
|
|
- resetPQExpBuffer(&connstr);
|
|
- appendPQExpBuffer(&connstr, "dbname=");
|
|
- appendConnStrVal(&connstr, dbname);
|
|
+ cparams->override_dbname = dbname;
|
|
|
|
- reindex_one_database(NULL, connstr.data, "DATABASE", host,
|
|
- port, username, prompt_password,
|
|
+ reindex_one_database(cparams, "DATABASE", NULL,
|
|
progname, echo, verbose);
|
|
}
|
|
- termPQExpBuffer(&connstr);
|
|
|
|
PQclear(result);
|
|
}
|
|
|
|
static void
|
|
-reindex_system_catalogs(const char *dbname, const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
+reindex_system_catalogs(const ConnParams *cparams,
|
|
const char *progname, bool echo, bool verbose)
|
|
{
|
|
PGconn *conn;
|
|
PQExpBufferData sql;
|
|
|
|
- conn = connectDatabase(dbname, host, port, username, prompt_password,
|
|
- progname, echo, false, false);
|
|
+ conn = connectDatabase(cparams, progname, echo, false, false);
|
|
|
|
initPQExpBuffer(&sql);
|
|
|
|
diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c
|
|
index 4ac765244a..40b1fbc5a3 100644
|
|
--- a/src/bin/scripts/vacuumdb.c
|
|
+++ b/src/bin/scripts/vacuumdb.c
|
|
@@ -43,19 +43,16 @@ typedef struct vacuumingOptions
|
|
} vacuumingOptions;
|
|
|
|
|
|
-static void vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
|
|
+static void vacuum_one_database(const ConnParams *cparams,
|
|
+ vacuumingOptions *vacopts,
|
|
int stage,
|
|
SimpleStringList *tables,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
int concurrentCons,
|
|
const char *progname, bool echo, bool quiet);
|
|
|
|
-static void vacuum_all_databases(vacuumingOptions *vacopts,
|
|
+static void vacuum_all_databases(ConnParams *cparams,
|
|
+ vacuumingOptions *vacopts,
|
|
bool analyze_in_stages,
|
|
- const char *maintenance_db,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
int concurrentCons,
|
|
const char *progname, bool echo, bool quiet);
|
|
|
|
@@ -122,6 +119,7 @@ main(int argc, char *argv[])
|
|
char *port = NULL;
|
|
char *username = NULL;
|
|
enum trivalue prompt_password = TRI_DEFAULT;
|
|
+ ConnParams cparams;
|
|
bool echo = false;
|
|
bool quiet = false;
|
|
vacuumingOptions vacopts;
|
|
@@ -248,6 +246,13 @@ main(int argc, char *argv[])
|
|
/* allow 'and_analyze' with 'analyze_only' */
|
|
}
|
|
|
|
+ /* fill cparams except for dbname, which is set below */
|
|
+ cparams.pghost = host;
|
|
+ cparams.pgport = port;
|
|
+ cparams.pguser = username;
|
|
+ cparams.prompt_password = prompt_password;
|
|
+ cparams.override_dbname = NULL;
|
|
+
|
|
setup_cancel_handler();
|
|
|
|
/* Avoid opening extra connections. */
|
|
@@ -269,10 +274,10 @@ main(int argc, char *argv[])
|
|
exit(1);
|
|
}
|
|
|
|
- vacuum_all_databases(&vacopts,
|
|
+ cparams.dbname = maintenance_db;
|
|
+
|
|
+ vacuum_all_databases(&cparams, &vacopts,
|
|
analyze_in_stages,
|
|
- maintenance_db,
|
|
- host, port, username, prompt_password,
|
|
concurrentCons,
|
|
progname, echo, quiet);
|
|
}
|
|
@@ -288,25 +293,25 @@ main(int argc, char *argv[])
|
|
dbname = get_user_name_or_exit(progname);
|
|
}
|
|
|
|
+ cparams.dbname = dbname;
|
|
+
|
|
if (analyze_in_stages)
|
|
{
|
|
int stage;
|
|
|
|
for (stage = 0; stage < ANALYZE_NUM_STAGES; stage++)
|
|
{
|
|
- vacuum_one_database(dbname, &vacopts,
|
|
+ vacuum_one_database(&cparams, &vacopts,
|
|
stage,
|
|
&tables,
|
|
- host, port, username, prompt_password,
|
|
concurrentCons,
|
|
progname, echo, quiet);
|
|
}
|
|
}
|
|
else
|
|
- vacuum_one_database(dbname, &vacopts,
|
|
+ vacuum_one_database(&cparams, &vacopts,
|
|
ANALYZE_NO_STAGE,
|
|
&tables,
|
|
- host, port, username, prompt_password,
|
|
concurrentCons,
|
|
progname, echo, quiet);
|
|
}
|
|
@@ -328,11 +333,10 @@ main(int argc, char *argv[])
|
|
* a list of tables from the database.
|
|
*/
|
|
static void
|
|
-vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
|
|
+vacuum_one_database(const ConnParams *cparams,
|
|
+ vacuumingOptions *vacopts,
|
|
int stage,
|
|
SimpleStringList *tables,
|
|
- const char *host, const char *port,
|
|
- const char *username, enum trivalue prompt_password,
|
|
int concurrentCons,
|
|
const char *progname, bool echo, bool quiet)
|
|
{
|
|
@@ -358,8 +362,7 @@ vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
|
|
Assert(stage == ANALYZE_NO_STAGE ||
|
|
(stage >= 0 && stage < ANALYZE_NUM_STAGES));
|
|
|
|
- conn = connectDatabase(dbname, host, port, username, prompt_password,
|
|
- progname, echo, false, true);
|
|
+ conn = connectDatabase(cparams, progname, echo, false, true);
|
|
|
|
if (!quiet)
|
|
{
|
|
@@ -435,8 +438,7 @@ vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
|
|
{
|
|
for (i = 1; i < concurrentCons; i++)
|
|
{
|
|
- conn = connectDatabase(dbname, host, port, username, prompt_password,
|
|
- progname, echo, false, true);
|
|
+ conn = connectDatabase(cparams, progname, echo, false, true);
|
|
|
|
/*
|
|
* Fail and exit immediately if trying to use a socket in an
|
|
@@ -556,28 +558,23 @@ finish:
|
|
* quickly everywhere before generating more detailed ones.
|
|
*/
|
|
static void
|
|
-vacuum_all_databases(vacuumingOptions *vacopts,
|
|
+vacuum_all_databases(ConnParams *cparams,
|
|
+ vacuumingOptions *vacopts,
|
|
bool analyze_in_stages,
|
|
- const char *maintenance_db, const char *host,
|
|
- const char *port, const char *username,
|
|
- enum trivalue prompt_password,
|
|
int concurrentCons,
|
|
const char *progname, bool echo, bool quiet)
|
|
{
|
|
PGconn *conn;
|
|
PGresult *result;
|
|
- PQExpBufferData connstr;
|
|
int stage;
|
|
int i;
|
|
|
|
- conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
|
|
- prompt_password, progname, echo);
|
|
+ conn = connectMaintenanceDatabase(cparams, progname, echo);
|
|
result = executeQuery(conn,
|
|
"SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;",
|
|
progname, echo);
|
|
PQfinish(conn);
|
|
|
|
- initPQExpBuffer(&connstr);
|
|
if (analyze_in_stages)
|
|
{
|
|
/*
|
|
@@ -592,14 +589,11 @@ vacuum_all_databases(vacuumingOptions *vacopts,
|
|
{
|
|
for (i = 0; i < PQntuples(result); i++)
|
|
{
|
|
- resetPQExpBuffer(&connstr);
|
|
- appendPQExpBuffer(&connstr, "dbname=");
|
|
- appendConnStrVal(&connstr, PQgetvalue(result, i, 0));
|
|
+ cparams->override_dbname = PQgetvalue(result, i, 0);
|
|
|
|
- vacuum_one_database(connstr.data, vacopts,
|
|
+ vacuum_one_database(cparams, vacopts,
|
|
stage,
|
|
NULL,
|
|
- host, port, username, prompt_password,
|
|
concurrentCons,
|
|
progname, echo, quiet);
|
|
}
|
|
@@ -609,19 +603,15 @@ vacuum_all_databases(vacuumingOptions *vacopts,
|
|
{
|
|
for (i = 0; i < PQntuples(result); i++)
|
|
{
|
|
- resetPQExpBuffer(&connstr);
|
|
- appendPQExpBuffer(&connstr, "dbname=");
|
|
- appendConnStrVal(&connstr, PQgetvalue(result, i, 0));
|
|
+ cparams->override_dbname = PQgetvalue(result, i, 0);
|
|
|
|
- vacuum_one_database(connstr.data, vacopts,
|
|
+ vacuum_one_database(cparams, vacopts,
|
|
ANALYZE_NO_STAGE,
|
|
NULL,
|
|
- host, port, username, prompt_password,
|
|
concurrentCons,
|
|
progname, echo, quiet);
|
|
}
|
|
}
|
|
- termPQExpBuffer(&connstr);
|
|
|
|
PQclear(result);
|
|
}
|
|
--
|
|
2.23.0
|
|
|