diff options
author | Michael Paquier <michael@paquier.xyz> | 2019-07-19 09:31:58 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2019-07-19 09:31:58 +0900 |
commit | 5f3840370b63fdf17f704a285623ccc233fa8d4f (patch) | |
tree | 194f7e1322dc8fb871b853e516a13e12e96a81de /src/bin/scripts/common.c | |
parent | b538c90b1bded5464787e2b8e4431302d24eb601 (diff) |
Refactor parallelization processing code in src/bin/scripts/
The existing facility of vacuumdb to handle parallel connections into a
given database with an authentication set is moved to a common file in
src/bin/scripts/, named scripts_parallel.c. This introduces a set of
routines to initialize, wait and terminate a set of connections,
simplifying a bit the code of vacuumdb on the way. More routines
related to result handling and database connection are moved to
common.c.
The initial plan is to use that for reindexdb, but it could be applied
to other tools like clusterdb.
While on it, clean up a set of variables "progname" which were defined
as routine arguments for error messages. Since most of the callers have
switched to pg_log_error() and such there is no need for this variable.
Author: Julien Rouhaud
Reviewed-by: Michael Paquier, Álvaro Herrera
Discussion: https://postgr.es/m/CAOBaU_YrnH_Jqo46NhaJ7uRBiWWEcS40VNRQxgFbqYo9kApUsg@mail.gmail.com
Diffstat (limited to 'src/bin/scripts/common.c')
-rw-r--r-- | src/bin/scripts/common.c | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c index 296029d8093..1b38a1da494 100644 --- a/src/bin/scripts/common.c +++ b/src/bin/scripts/common.c @@ -22,6 +22,8 @@ #include "fe_utils/connect.h" #include "fe_utils/string_utils.h" +#define ERRCODE_UNDEFINED_TABLE "42P01" + static PGcancel *volatile cancelConn = NULL; bool CancelRequested = false; @@ -146,8 +148,7 @@ connectDatabase(const char *dbname, const char *pghost, exit(1); } - PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, - progname, echo)); + PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo)); return conn; } @@ -179,10 +180,34 @@ connectMaintenanceDatabase(const char *maintenance_db, } /* + * Disconnect the given connection, canceling any statement if one is active. + */ +void +disconnectDatabase(PGconn *conn) +{ + char errbuf[256]; + + Assert(conn != NULL); + + if (PQtransactionStatus(conn) == PQTRANS_ACTIVE) + { + PGcancel *cancel; + + if ((cancel = PQgetCancel(conn))) + { + (void) PQcancel(cancel, errbuf, sizeof(errbuf)); + PQfreeCancel(cancel); + } + } + + PQfinish(conn); +} + +/* * Run a query, return the results, exit program on failure. */ PGresult * -executeQuery(PGconn *conn, const char *query, const char *progname, bool echo) +executeQuery(PGconn *conn, const char *query, bool echo) { PGresult *res; @@ -207,8 +232,7 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo) * As above for a SQL command (which returns nothing). */ void -executeCommand(PGconn *conn, const char *query, - const char *progname, bool echo) +executeCommand(PGconn *conn, const char *query, bool echo) { PGresult *res; @@ -255,6 +279,57 @@ executeMaintenanceCommand(PGconn *conn, const char *query, bool echo) return r; } +/* + * Consume all the results generated for the given connection until + * nothing remains. If at least one error is encountered, return false. + * Note that this will block if the connection is busy. + */ +bool +consumeQueryResult(PGconn *conn) +{ + bool ok = true; + PGresult *result; + + SetCancelConn(conn); + while ((result = PQgetResult(conn)) != NULL) + { + if (!processQueryResult(conn, result)) + ok = false; + } + ResetCancelConn(); + return ok; +} + +/* + * Process (and delete) a query result. Returns true if there's no error, + * false otherwise -- but errors about trying to work on a missing relation + * are reported and subsequently ignored. + */ +bool +processQueryResult(PGconn *conn, PGresult *result) +{ + /* + * If it's an error, report it. Errors about a missing table are harmless + * so we continue processing; but die for other errors. + */ + if (PQresultStatus(result) != PGRES_COMMAND_OK) + { + char *sqlState = PQresultErrorField(result, PG_DIAG_SQLSTATE); + + pg_log_error("processing of database \"%s\" failed: %s", + PQdb(conn), PQerrorMessage(conn)); + + if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) != 0) + { + PQclear(result); + return false; + } + } + + PQclear(result); + return true; +} + /* * Split TABLE[(COLUMNS)] into TABLE and [(COLUMNS)] portions. When you @@ -299,7 +374,7 @@ splitTableColumnsSpec(const char *spec, int encoding, */ void appendQualifiedRelation(PQExpBuffer buf, const char *spec, - PGconn *conn, const char *progname, bool echo) + PGconn *conn, bool echo) { char *table; const char *columns; @@ -324,7 +399,7 @@ appendQualifiedRelation(PQExpBuffer buf, const char *spec, appendStringLiteralConn(&sql, table, conn); appendPQExpBufferStr(&sql, "::pg_catalog.regclass;"); - executeCommand(conn, "RESET search_path;", progname, echo); + executeCommand(conn, "RESET search_path;", echo); /* * One row is a typical result, as is a nonexistent relation ERROR. @@ -332,7 +407,7 @@ appendQualifiedRelation(PQExpBuffer buf, const char *spec, * relation has that OID; this query returns no rows. Catalog corruption * might elicit other row counts. */ - res = executeQuery(conn, sql.data, progname, echo); + res = executeQuery(conn, sql.data, echo); ntups = PQntuples(res); if (ntups != 1) { @@ -351,8 +426,7 @@ appendQualifiedRelation(PQExpBuffer buf, const char *spec, termPQExpBuffer(&sql); pg_free(table); - PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, - progname, echo)); + PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo)); } |