1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-03 15:22:11 +03:00

vacuumdb: don't prompt for passwords over and over

Having the script prompt for passwords over and over was a preexisting
problem when it processed multiple databases or when it processed
multiple analyze stages, but the parallel mode introduced in commit
a179232047 made it worse.

Fix the annoyance by keeping a copy of the password used by the first
connection that requires one.  Since users can (currently) only have a
single password, there's no need for more complex arrangements (such as
remembering one password per database).

Per bug #13741 reported by Eric Brown.  Patch authored and
cross-reviewed by Haribabu Kommi and Michael Paquier, slightly tweaked
by Álvaro Herrera.

Discussion: http://www.postgresql.org/message-id/20151027193919.931.54948@wrigleys.postgresql.org
Backpatch to 9.5, where parallel vacuumdb was introduced.
This commit is contained in:
Alvaro Herrera
2015-11-12 18:05:23 -03:00
parent 747854f010
commit 5094da99b9
9 changed files with 98 additions and 45 deletions

View File

@@ -43,7 +43,8 @@ static void vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
const char *host, const char *port,
const char *username, enum trivalue prompt_password,
int concurrentCons,
const char *progname, bool echo, bool quiet);
const char *progname, bool echo, bool quiet,
char **password);
static void vacuum_all_databases(vacuumingOptions *vacopts,
bool analyze_in_stages,
@@ -275,6 +276,8 @@ main(int argc, char *argv[])
}
else
{
char *password = NULL;
if (dbname == NULL)
{
if (getenv("PGDATABASE"))
@@ -296,7 +299,8 @@ main(int argc, char *argv[])
&tables,
host, port, username, prompt_password,
concurrentCons,
progname, echo, quiet);
progname, echo, quiet,
&password);
}
}
else
@@ -305,7 +309,10 @@ main(int argc, char *argv[])
&tables,
host, port, username, prompt_password,
concurrentCons,
progname, echo, quiet);
progname, echo, quiet,
&password);
pg_free(password);
}
exit(0);
@@ -323,15 +330,21 @@ main(int argc, char *argv[])
* If concurrentCons is > 1, multiple connections are used to vacuum tables
* in parallel. In this case and if the table list is empty, we first obtain
* a list of tables from the database.
*
* 'password' is both an input and output parameter. If one is not passed,
* then whatever is used in a connection is returned so that caller can
* reuse it in future connections.
*/
static void
vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
int stage,
SimpleStringList *tables,
const char *host, const char *port,
const char *username, enum trivalue prompt_password,
const char *username,
enum trivalue prompt_password,
int concurrentCons,
const char *progname, bool echo, bool quiet)
const char *progname, bool echo, bool quiet,
char **password)
{
PQExpBufferData sql;
PGconn *conn;
@@ -365,8 +378,15 @@ vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
fflush(stdout);
}
conn = connectDatabase(dbname, host, port, username, prompt_password,
progname, false);
conn = connectDatabase(dbname, host, port, username, *password,
prompt_password, progname, false);
/*
* If no password was not specified by caller and the connection required
* one, remember it; this suppresses further password prompts.
*/
if (PQconnectionUsedPassword(conn) && *password == NULL)
*password = pg_strdup(PQpass(conn));
initPQExpBuffer(&sql);
@@ -424,10 +444,20 @@ vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
init_slot(slots, conn);
if (parallel)
{
const char *pqpass;
/*
* If a password was supplied for the initial connection, use it for
* subsequent ones too. (Note that since we're connecting to the same
* database with the same user, there's no need to update the stored
* password any further.)
*/
pqpass = PQpass(conn);
for (i = 1; i < concurrentCons; i++)
{
conn = connectDatabase(dbname, host, port, username, prompt_password,
progname, false);
conn = connectDatabase(dbname, host, port, username, pqpass,
prompt_password, progname, false);
init_slot(slots + i, conn);
}
}
@@ -542,12 +572,23 @@ vacuum_all_databases(vacuumingOptions *vacopts,
PGresult *result;
int stage;
int i;
char *password = NULL;
conn = connectMaintenanceDatabase(maintenance_db, host, port,
username, prompt_password, progname);
result = executeQuery(conn,
"SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;",
progname, echo);
/*
* Remember the password for further connections. If no password was
* required for the maintenance db connection, this gets updated for the
* first connection that does.
*/
if (PQconnectionUsedPassword(conn))
password = pg_strdup(PQpass(conn));
PQfinish(conn);
if (analyze_in_stages)
@@ -572,7 +613,8 @@ vacuum_all_databases(vacuumingOptions *vacopts,
NULL,
host, port, username, prompt_password,
concurrentCons,
progname, echo, quiet);
progname, echo, quiet,
&password);
}
}
}
@@ -588,11 +630,13 @@ vacuum_all_databases(vacuumingOptions *vacopts,
NULL,
host, port, username, prompt_password,
concurrentCons,
progname, echo, quiet);
progname, echo, quiet,
&password);
}
}
PQclear(result);
pg_free(password);
}
/*