diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2015-11-12 18:05:23 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2015-11-12 18:05:23 -0300 |
commit | 5094da99b901df42580b6e7494d036ee4be9eb81 (patch) | |
tree | f879bf36a6d9c73811447fb114788ac7a12bb350 /src/bin/scripts/vacuumdb.c | |
parent | 747854f010b168c4f076cf44b61b100b0fe20866 (diff) | |
download | postgresql-5094da99b901df42580b6e7494d036ee4be9eb81.tar.gz postgresql-5094da99b901df42580b6e7494d036ee4be9eb81.zip |
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.
Diffstat (limited to 'src/bin/scripts/vacuumdb.c')
-rw-r--r-- | src/bin/scripts/vacuumdb.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c index 4ce27b78c54..6c67263f3c6 100644 --- a/src/bin/scripts/vacuumdb.c +++ b/src/bin/scripts/vacuumdb.c @@ -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); } /* |