Skip to content

Commit 33be41d

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 5840e31 commit 33be41d

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

contrib/pg_upgrade/check.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ static void check_locale_and_encoding(migratorContext *ctx, ControlData *oldctrl
1717
static void check_for_isn_and_int8_passing_mismatch(migratorContext *ctx,
1818
Cluster whichCluster);
1919
static void check_for_reg_data_type_usage(migratorContext *ctx, Cluster whichCluster);
20+
static void check_for_invalid_indexes(migratorContext *ctx, Cluster whichCluster);
2021

2122

2223
/*
@@ -96,6 +97,7 @@ check_old_cluster(migratorContext *ctx, bool live_check,
9697

9798
check_for_reg_data_type_usage(ctx, CLUSTER_OLD);
9899
check_for_isn_and_int8_passing_mismatch(ctx, CLUSTER_OLD);
100+
check_for_invalid_indexes(ctx, CLUSTER_OLD);
99101

100102
/* old = PG 8.3 checks? */
101103
if (GET_MAJOR_VERSION(ctx->old.major_version) <= 803)
@@ -676,3 +678,93 @@ check_for_reg_data_type_usage(migratorContext *ctx, Cluster whichCluster)
676678
else
677679
check_ok(ctx);
678680
}
681+
682+
683+
/*
684+
* check_for_invalid_indexes()
685+
*
686+
* CREATE INDEX CONCURRENTLY can create invalid indexes if the index build
687+
* fails. These are dumped as valid indexes by pg_dump, but the
688+
* underlying files are still invalid indexes. This checks to make sure
689+
* no invalid indexes exist, either failed index builds or concurrent
690+
* indexes in the process of being created.
691+
*/
692+
static void
693+
check_for_invalid_indexes(migratorContext *ctx, Cluster whichCluster)
694+
{
695+
ClusterInfo *cluster = (whichCluster == CLUSTER_OLD) ?
696+
&ctx->old : &ctx->new;
697+
int dbnum;
698+
FILE *script = NULL;
699+
bool found = false;
700+
char output_path[MAXPGPATH];
701+
702+
prep_status(ctx, "Checking for invalid indexes from concurrent index builds");
703+
704+
snprintf(output_path, sizeof(output_path), "invalid_indexes.txt");
705+
706+
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
707+
{
708+
PGresult *res;
709+
bool db_used = false;
710+
int ntups;
711+
int rowno;
712+
int i_nspname,
713+
i_relname;
714+
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
715+
PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
716+
717+
res = executeQueryOrDie(ctx, conn,
718+
"SELECT n.nspname, c.relname "
719+
"FROM pg_catalog.pg_class c, "
720+
" pg_catalog.pg_namespace n, "
721+
" pg_catalog.pg_index i "
722+
"WHERE (i.indisvalid = false OR "
723+
" i.indisready = false) AND "
724+
" i.indexrelid = c.oid AND "
725+
" c.relnamespace = n.oid AND "
726+
/* we do not migrate these, so skip them */
727+
" n.nspname != 'pg_catalog' AND "
728+
" n.nspname != 'information_schema' AND "
729+
/* indexes do not have toast tables */
730+
" n.nspname != 'pg_toast'");
731+
732+
ntups = PQntuples(res);
733+
i_nspname = PQfnumber(res, "nspname");
734+
i_relname = PQfnumber(res, "relname");
735+
for (rowno = 0; rowno < ntups; rowno++)
736+
{
737+
found = true;
738+
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
739+
pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
740+
if (!db_used)
741+
{
742+
fprintf(script, "Database: %s\n", active_db->db_name);
743+
db_used = true;
744+
}
745+
fprintf(script, " %s.%s\n",
746+
PQgetvalue(res, rowno, i_nspname),
747+
PQgetvalue(res, rowno, i_relname));
748+
}
749+
750+
PQclear(res);
751+
752+
PQfinish(conn);
753+
}
754+
755+
if (script)
756+
fclose(script);
757+
758+
if (found)
759+
{
760+
pg_log(ctx, PG_REPORT, "fatal\n");
761+
pg_log(ctx, PG_FATAL,
762+
"Your installation contains invalid indexes due to failed or\n"
763+
"currently running CREATE INDEX CONCURRENTLY operations. You\n"
764+
"cannot upgrade until these indexes are valid or removed. A\n"
765+
"list of the problem indexes is in the file:\n"
766+
" %s\n\n", output_path);
767+
}
768+
else
769+
check_ok(ctx);
770+
}

0 commit comments

Comments
 (0)