From 3cd66a2e1bbe3fc7a90c96962c158475f715245d Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 28 Aug 2024 15:35:31 -0500 Subject: [PATCH v10 11/11] Use pg_upgrade's parallel framework for encoding conversion check. Reviewed-by: FIXME Discussion: https://postgr.es/m/20240516211638.GA1688936%40nathanxps13 --- src/bin/pg_upgrade/check.c | 120 ++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 56 deletions(-) diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index dff440b29a..01ab3d0694 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -1684,81 +1684,89 @@ check_for_pg_role_prefix(ClusterInfo *cluster) } /* - * Verify that no user-defined encoding conversions exist. + * Callback function for processing results of query for + * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query + * returned any rows (i.e., the check failed), write the details to the report + * file. */ static void -check_for_user_defined_encoding_conversions(ClusterInfo *cluster) +process_user_defined_encoding_conversions(DbInfo *dbinfo, PGresult *res, void *arg) { - int dbnum; - FILE *script = NULL; - char output_path[MAXPGPATH]; + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + bool db_used = false; + int ntups = PQntuples(res); + int i_conoid = PQfnumber(res, "conoid"); + int i_conname = PQfnumber(res, "conname"); + int i_nspname = PQfnumber(res, "nspname"); - prep_status("Checking for user-defined encoding conversions"); + AssertVariableIsOfType(&process_user_defined_encoding_conversions, + UpgradeTaskProcessCB); - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - "encoding_conversions.txt"); + if (!ntups) + return; - /* Find any user defined encoding conversions */ - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) + for (int rowno = 0; rowno < ntups; rowno++) { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_conoid, - i_conname, - i_nspname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* - * The query below hardcodes FirstNormalObjectId as 16384 rather than - * interpolating that C #define into the query because, if that - * #define is ever changed, the cutoff we want to use is the value - * used by pre-version 14 servers, not that of some future version. - */ - res = executeQueryOrDie(conn, - "SELECT c.oid as conoid, c.conname, n.nspname " - "FROM pg_catalog.pg_conversion c, " - " pg_catalog.pg_namespace n " - "WHERE c.connamespace = n.oid AND " - " c.oid >= 16384"); - ntups = PQntuples(res); - i_conoid = PQfnumber(res, "conoid"); - i_conname = PQfnumber(res, "conname"); - i_nspname = PQfnumber(res, "nspname"); - for (rowno = 0; rowno < ntups; rowno++) + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + if (!db_used) { - if (script == NULL && - (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - fprintf(script, "In database: %s\n", active_db->db_name); - db_used = true; - } - fprintf(script, " (oid=%s) %s.%s\n", - PQgetvalue(res, rowno, i_conoid), - PQgetvalue(res, rowno, i_nspname), - PQgetvalue(res, rowno, i_conname)); + fprintf(report->file, "In database: %s\n", dbinfo->db_name); + db_used = true; } + fprintf(report->file, " (oid=%s) %s.%s\n", + PQgetvalue(res, rowno, i_conoid), + PQgetvalue(res, rowno, i_nspname), + PQgetvalue(res, rowno, i_conname)); + } +} - PQclear(res); +/* + * Verify that no user-defined encoding conversions exist. + */ +static void +check_for_user_defined_encoding_conversions(ClusterInfo *cluster) +{ + UpgradeTaskReport report; + UpgradeTask *task = upgrade_task_create(); + const char *query; - PQfinish(conn); - } + prep_status("Checking for user-defined encoding conversions"); - if (script) + report.file = NULL; + snprintf(report.path, sizeof(report.path), "%s/%s", + log_opts.basedir, + "encoding_conversions.txt"); + + /* + * The query below hardcodes FirstNormalObjectId as 16384 rather than + * interpolating that C #define into the query because, if that #define is + * ever changed, the cutoff we want to use is the value used by + * pre-version 14 servers, not that of some future version. + */ + query = "SELECT c.oid as conoid, c.conname, n.nspname " + "FROM pg_catalog.pg_conversion c, " + " pg_catalog.pg_namespace n " + "WHERE c.connamespace = n.oid AND " + " c.oid >= 16384"; + + upgrade_task_add_step(task, query, + process_user_defined_encoding_conversions, + true, &report); + upgrade_task_run(task, cluster); + upgrade_task_free(task); + + if (report.file) { - fclose(script); + fclose(report.file); pg_log(PG_REPORT, "fatal"); pg_fatal("Your installation contains user-defined encoding conversions.\n" "The conversion function parameters changed in PostgreSQL version 14\n" "so this cluster cannot currently be upgraded. You can remove the\n" "encoding conversions in the old cluster and restart the upgrade.\n" "A list of user-defined encoding conversions is in the file:\n" - " %s", output_path); + " %s", report.path); } else check_ok(); -- 2.39.3 (Apple Git-146)