Skip to content

Commit c880cf2

Browse files
pg_upgrade: Parallelize encoding conversion check.
This commit makes use of the new task framework in pg_upgrade to parallelize the check for incompatible user-defined encoding conversions, i.e., those defined on servers older than v14. This step will now process multiple databases concurrently when pg_upgrade's --jobs option is provided a value greater than 1. Reviewed-by: Daniel Gustafsson, Ilya Gladyshev Discussion: https://postgr.es/m/20240516211638.GA1688936%40nathanxps13
1 parent f93f5f7 commit c880cf2

File tree

1 file changed

+64
-56
lines changed

1 file changed

+64
-56
lines changed

src/bin/pg_upgrade/check.c

Lines changed: 64 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,81 +1684,89 @@ check_for_pg_role_prefix(ClusterInfo *cluster)
16841684
}
16851685

16861686
/*
1687-
* Verify that no user-defined encoding conversions exist.
1687+
* Callback function for processing results of query for
1688+
* check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query
1689+
* returned any rows (i.e., the check failed), write the details to the report
1690+
* file.
16881691
*/
16891692
static void
1690-
check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
1693+
process_user_defined_encoding_conversions(DbInfo *dbinfo, PGresult *res, void *arg)
16911694
{
1692-
int dbnum;
1693-
FILE *script = NULL;
1694-
char output_path[MAXPGPATH];
1695+
UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
1696+
bool db_used = false;
1697+
int ntups = PQntuples(res);
1698+
int i_conoid = PQfnumber(res, "conoid");
1699+
int i_conname = PQfnumber(res, "conname");
1700+
int i_nspname = PQfnumber(res, "nspname");
16951701

1696-
prep_status("Checking for user-defined encoding conversions");
1702+
AssertVariableIsOfType(&process_user_defined_encoding_conversions,
1703+
UpgradeTaskProcessCB);
16971704

1698-
snprintf(output_path, sizeof(output_path), "%s/%s",
1699-
log_opts.basedir,
1700-
"encoding_conversions.txt");
1705+
if (!ntups)
1706+
return;
17011707

1702-
/* Find any user defined encoding conversions */
1703-
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
1708+
for (int rowno = 0; rowno < ntups; rowno++)
17041709
{
1705-
PGresult *res;
1706-
bool db_used = false;
1707-
int ntups;
1708-
int rowno;
1709-
int i_conoid,
1710-
i_conname,
1711-
i_nspname;
1712-
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
1713-
PGconn *conn = connectToServer(cluster, active_db->db_name);
1714-
1715-
/*
1716-
* The query below hardcodes FirstNormalObjectId as 16384 rather than
1717-
* interpolating that C #define into the query because, if that
1718-
* #define is ever changed, the cutoff we want to use is the value
1719-
* used by pre-version 14 servers, not that of some future version.
1720-
*/
1721-
res = executeQueryOrDie(conn,
1722-
"SELECT c.oid as conoid, c.conname, n.nspname "
1723-
"FROM pg_catalog.pg_conversion c, "
1724-
" pg_catalog.pg_namespace n "
1725-
"WHERE c.connamespace = n.oid AND "
1726-
" c.oid >= 16384");
1727-
ntups = PQntuples(res);
1728-
i_conoid = PQfnumber(res, "conoid");
1729-
i_conname = PQfnumber(res, "conname");
1730-
i_nspname = PQfnumber(res, "nspname");
1731-
for (rowno = 0; rowno < ntups; rowno++)
1710+
if (report->file == NULL &&
1711+
(report->file = fopen_priv(report->path, "w")) == NULL)
1712+
pg_fatal("could not open file \"%s\": %m", report->path);
1713+
if (!db_used)
17321714
{
1733-
if (script == NULL &&
1734-
(script = fopen_priv(output_path, "w")) == NULL)
1735-
pg_fatal("could not open file \"%s\": %m", output_path);
1736-
if (!db_used)
1737-
{
1738-
fprintf(script, "In database: %s\n", active_db->db_name);
1739-
db_used = true;
1740-
}
1741-
fprintf(script, " (oid=%s) %s.%s\n",
1742-
PQgetvalue(res, rowno, i_conoid),
1743-
PQgetvalue(res, rowno, i_nspname),
1744-
PQgetvalue(res, rowno, i_conname));
1715+
fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1716+
db_used = true;
17451717
}
1718+
fprintf(report->file, " (oid=%s) %s.%s\n",
1719+
PQgetvalue(res, rowno, i_conoid),
1720+
PQgetvalue(res, rowno, i_nspname),
1721+
PQgetvalue(res, rowno, i_conname));
1722+
}
1723+
}
17461724

1747-
PQclear(res);
1725+
/*
1726+
* Verify that no user-defined encoding conversions exist.
1727+
*/
1728+
static void
1729+
check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
1730+
{
1731+
UpgradeTaskReport report;
1732+
UpgradeTask *task = upgrade_task_create();
1733+
const char *query;
17481734

1749-
PQfinish(conn);
1750-
}
1735+
prep_status("Checking for user-defined encoding conversions");
17511736

1752-
if (script)
1737+
report.file = NULL;
1738+
snprintf(report.path, sizeof(report.path), "%s/%s",
1739+
log_opts.basedir,
1740+
"encoding_conversions.txt");
1741+
1742+
/*
1743+
* The query below hardcodes FirstNormalObjectId as 16384 rather than
1744+
* interpolating that C #define into the query because, if that #define is
1745+
* ever changed, the cutoff we want to use is the value used by
1746+
* pre-version 14 servers, not that of some future version.
1747+
*/
1748+
query = "SELECT c.oid as conoid, c.conname, n.nspname "
1749+
"FROM pg_catalog.pg_conversion c, "
1750+
" pg_catalog.pg_namespace n "
1751+
"WHERE c.connamespace = n.oid AND "
1752+
" c.oid >= 16384";
1753+
1754+
upgrade_task_add_step(task, query,
1755+
process_user_defined_encoding_conversions,
1756+
true, &report);
1757+
upgrade_task_run(task, cluster);
1758+
upgrade_task_free(task);
1759+
1760+
if (report.file)
17531761
{
1754-
fclose(script);
1762+
fclose(report.file);
17551763
pg_log(PG_REPORT, "fatal");
17561764
pg_fatal("Your installation contains user-defined encoding conversions.\n"
17571765
"The conversion function parameters changed in PostgreSQL version 14\n"
17581766
"so this cluster cannot currently be upgraded. You can remove the\n"
17591767
"encoding conversions in the old cluster and restart the upgrade.\n"
17601768
"A list of user-defined encoding conversions is in the file:\n"
1761-
" %s", output_path);
1769+
" %s", report.path);
17621770
}
17631771
else
17641772
check_ok();

0 commit comments

Comments
 (0)