Skip to content

Commit 7443580

Browse files
committed
Fix pg_upgrade for invalid indexes
All versions of pg_upgrade upgraded invalid indexes caused by CREATE INDEX CONCURRENTLY failures and marked them as valid. The patch adds a check to all pg_upgrade versions and throws an error during upgrade or --check. Backpatch to 9.2, 9.1, 9.0. Patch slightly adjusted.
1 parent fb565f8 commit 7443580

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

contrib/pg_upgrade/check.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ static void check_is_super_user(ClusterInfo *cluster);
2020
static void check_for_prepared_transactions(ClusterInfo *cluster);
2121
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
2222
static void check_for_reg_data_type_usage(ClusterInfo *cluster);
23+
static void check_for_invalid_indexes(ClusterInfo *cluster);
2324
static void get_bin_version(ClusterInfo *cluster);
2425
static char *get_canonical_locale_name(int category, const char *locale);
2526

@@ -97,6 +98,7 @@ check_old_cluster(bool live_check, char **sequence_script_file_name)
9798
check_is_super_user(&old_cluster);
9899
check_for_prepared_transactions(&old_cluster);
99100
check_for_reg_data_type_usage(&old_cluster);
101+
check_for_invalid_indexes(&old_cluster);
100102
check_for_isn_and_int8_passing_mismatch(&old_cluster);
101103

102104
/* old = PG 8.3 checks? */
@@ -927,6 +929,95 @@ check_for_reg_data_type_usage(ClusterInfo *cluster)
927929
}
928930

929931

932+
/*
933+
* check_for_invalid_indexes()
934+
*
935+
* CREATE INDEX CONCURRENTLY can create invalid indexes if the index build
936+
* fails. These are dumped as valid indexes by pg_dump, but the
937+
* underlying files are still invalid indexes. This checks to make sure
938+
* no invalid indexes exist, either failed index builds or concurrent
939+
* indexes in the process of being created.
940+
*/
941+
static void
942+
check_for_invalid_indexes(ClusterInfo *cluster)
943+
{
944+
int dbnum;
945+
FILE *script = NULL;
946+
bool found = false;
947+
char output_path[MAXPGPATH];
948+
949+
prep_status("Checking for invalid indexes from concurrent index builds");
950+
951+
snprintf(output_path, sizeof(output_path), "invalid_indexes.txt");
952+
953+
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
954+
{
955+
PGresult *res;
956+
bool db_used = false;
957+
int ntups;
958+
int rowno;
959+
int i_nspname,
960+
i_relname;
961+
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
962+
PGconn *conn = connectToServer(cluster, active_db->db_name);
963+
964+
res = executeQueryOrDie(conn,
965+
"SELECT n.nspname, c.relname "
966+
"FROM pg_catalog.pg_class c, "
967+
" pg_catalog.pg_namespace n, "
968+
" pg_catalog.pg_index i "
969+
"WHERE (i.indisvalid = false OR "
970+
" i.indisready = false) AND "
971+
" i.indexrelid = c.oid AND "
972+
" c.relnamespace = n.oid AND "
973+
/* we do not migrate these, so skip them */
974+
" n.nspname != 'pg_catalog' AND "
975+
" n.nspname != 'information_schema' AND "
976+
/* indexes do not have toast tables */
977+
" n.nspname != 'pg_toast'");
978+
979+
ntups = PQntuples(res);
980+
i_nspname = PQfnumber(res, "nspname");
981+
i_relname = PQfnumber(res, "relname");
982+
for (rowno = 0; rowno < ntups; rowno++)
983+
{
984+
found = true;
985+
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
986+
pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
987+
output_path, getErrorText(errno));
988+
if (!db_used)
989+
{
990+
fprintf(script, "Database: %s\n", active_db->db_name);
991+
db_used = true;
992+
}
993+
fprintf(script, " %s.%s\n",
994+
PQgetvalue(res, rowno, i_nspname),
995+
PQgetvalue(res, rowno, i_relname));
996+
}
997+
998+
PQclear(res);
999+
1000+
PQfinish(conn);
1001+
}
1002+
1003+
if (script)
1004+
fclose(script);
1005+
1006+
if (found)
1007+
{
1008+
pg_log(PG_REPORT, "fatal\n");
1009+
pg_log(PG_FATAL,
1010+
"Your installation contains invalid indexes due to failed or\n"
1011+
"currently running CREATE INDEX CONCURRENTLY operations. You\n"
1012+
"cannot upgrade until these indexes are valid or removed. A\n"
1013+
"list of the problem indexes is in the file:\n"
1014+
" %s\n\n", output_path);
1015+
}
1016+
else
1017+
check_ok();
1018+
}
1019+
1020+
9301021
static void
9311022
get_bin_version(ClusterInfo *cluster)
9321023
{

0 commit comments

Comments
 (0)