From 0ec0569c3a2ad7148be0a0d1ebb81d5cf8a9270a Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Wed, 3 Jul 2024 15:55:18 +0200 Subject: [PATCH v3 3/3] Have pg_upgrade fail when bad constraints are present --- src/bin/pg_upgrade/check.c | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 27924159d6..3fa1ad8feb 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -27,6 +27,7 @@ static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); +static void check_for_attached_part_idxs(ClusterInfo *cluster); static void check_new_cluster_logical_replication_slots(void); static void check_new_cluster_subscription_configuration(void); static void check_old_cluster_for_valid_slots(bool live_check); @@ -598,6 +599,7 @@ check_and_dump_old_cluster(bool live_check) check_proper_datallowconn(&old_cluster); check_for_prepared_transactions(&old_cluster); check_for_isn_and_int8_passing_mismatch(&old_cluster); + check_for_attached_part_idxs(&old_cluster); if (GET_MAJOR_VERSION(old_cluster.major_version) >= 1700) { @@ -1713,6 +1715,84 @@ check_for_user_defined_encoding_conversions(ClusterInfo *cluster) check_ok(); } +static void +check_for_attached_part_idxs(ClusterInfo *cluster) +{ + FILE *script = NULL; + char output_path[MAXPGPATH]; + + prep_status("Checking for undesirable indexes on partitions"); + + snprintf(output_path, sizeof(output_path), "%s/%s", + log_opts.basedir, + "invalid_partition_indexes.txt"); + + /* + * Find any constraint indexes on partitions that are attached to non- + * constraint indexes on their parent partitioned tables. + */ + for (int dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) + { + PGresult *res; + bool db_used = false; + int ntups; + int i_conoid, + i_conname, + i_tablename; + DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; + PGconn *conn = connectToServer(cluster, active_db->db_name); + + res = executeQueryOrDie(conn, + "SELECT co.oid, co.conname, " + " (SELECT format('%%I.%%I', nspname, relname) " + " FROM pg_catalog.pg_class JOIN pg_catalog.pg_namespace " + " ON (relnamespace = pg_namespace.oid) " + " WHERE pg_class.oid = co.conrelid) AS tablename " + " FROM pg_catalog.pg_constraint co JOIN pg_catalog.pg_class c " + " ON (co.conrelid = c.oid) " + " WHERE c.relispartition and conparentid = 0 AND " + " EXISTS (SELECT 1 FROM pg_catalog.pg_inherits " + " WHERE inhrelid = co.conindid)"); + ntups = PQntuples(res); + i_conoid = PQfnumber(res, "oid"); + i_conname = PQfnumber(res, "conname"); + i_tablename = PQfnumber(res, "tablename"); + for (int rowno = 0; rowno < ntups; rowno++) + { + 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 on table \"%s\"\n", + PQgetvalue(res, rowno, i_conoid), + PQgetvalue(res, rowno, i_conname), + PQgetvalue(res, rowno, i_tablename)); + } + + PQclear(res); + + PQfinish(conn); + } + + if (script) + { + fclose(script); + pg_log(PG_REPORT, "fatal"); + pg_fatal("Your installation contains badly defined indexes on partitions.\n" + "It's no longer allowed to have constraint indexes on partitions\n" + "when their parent tables have non-constraint indexes.\n" + "Please fix or remove these constraints prior to upgrading.\n" + "A list of such constraints is in the file:\n" + " %s", output_path); + } + else + check_ok(); +} + /* * check_new_cluster_logical_replication_slots() * -- 2.39.2