Skip to content

Commit 97a60fa

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 8b6b374 commit 97a60fa

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
@@ -19,6 +19,7 @@ static void check_is_super_user(ClusterInfo *cluster);
1919
static void check_for_prepared_transactions(ClusterInfo *cluster);
2020
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
2121
static void check_for_reg_data_type_usage(ClusterInfo *cluster);
22+
static void check_for_invalid_indexes(ClusterInfo *cluster);
2223
static void get_bin_version(ClusterInfo *cluster);
2324

2425

@@ -99,6 +100,7 @@ check_old_cluster(bool live_check,
99100
check_is_super_user(&old_cluster);
100101
check_for_prepared_transactions(&old_cluster);
101102
check_for_reg_data_type_usage(&old_cluster);
103+
check_for_invalid_indexes(&old_cluster);
102104
check_for_isn_and_int8_passing_mismatch(&old_cluster);
103105

104106
/* old = PG 8.3 checks? */
@@ -803,6 +805,95 @@ check_for_reg_data_type_usage(ClusterInfo *cluster)
803805
}
804806

805807

808+
/*
809+
* check_for_invalid_indexes()
810+
*
811+
* CREATE INDEX CONCURRENTLY can create invalid indexes if the index build
812+
* fails. These are dumped as valid indexes by pg_dump, but the
813+
* underlying files are still invalid indexes. This checks to make sure
814+
* no invalid indexes exist, either failed index builds or concurrent
815+
* indexes in the process of being created.
816+
*/
817+
static void
818+
check_for_invalid_indexes(ClusterInfo *cluster)
819+
{
820+
int dbnum;
821+
FILE *script = NULL;
822+
bool found = false;
823+
char output_path[MAXPGPATH];
824+
825+
prep_status("Checking for invalid indexes from concurrent index builds");
826+
827+
snprintf(output_path, sizeof(output_path), "invalid_indexes.txt");
828+
829+
for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
830+
{
831+
PGresult *res;
832+
bool db_used = false;
833+
int ntups;
834+
int rowno;
835+
int i_nspname,
836+
i_relname;
837+
DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
838+
PGconn *conn = connectToServer(cluster, active_db->db_name);
839+
840+
res = executeQueryOrDie(conn,
841+
"SELECT n.nspname, c.relname "
842+
"FROM pg_catalog.pg_class c, "
843+
" pg_catalog.pg_namespace n, "
844+
" pg_catalog.pg_index i "
845+
"WHERE (i.indisvalid = false OR "
846+
" i.indisready = false) AND "
847+
" i.indexrelid = c.oid AND "
848+
" c.relnamespace = n.oid AND "
849+
/* we do not migrate these, so skip them */
850+
" n.nspname != 'pg_catalog' AND "
851+
" n.nspname != 'information_schema' AND "
852+
/* indexes do not have toast tables */
853+
" n.nspname != 'pg_toast'");
854+
855+
ntups = PQntuples(res);
856+
i_nspname = PQfnumber(res, "nspname");
857+
i_relname = PQfnumber(res, "relname");
858+
for (rowno = 0; rowno < ntups; rowno++)
859+
{
860+
found = true;
861+
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
862+
pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
863+
output_path, getErrorText(errno));
864+
if (!db_used)
865+
{
866+
fprintf(script, "Database: %s\n", active_db->db_name);
867+
db_used = true;
868+
}
869+
fprintf(script, " %s.%s\n",
870+
PQgetvalue(res, rowno, i_nspname),
871+
PQgetvalue(res, rowno, i_relname));
872+
}
873+
874+
PQclear(res);
875+
876+
PQfinish(conn);
877+
}
878+
879+
if (script)
880+
fclose(script);
881+
882+
if (found)
883+
{
884+
pg_log(PG_REPORT, "fatal\n");
885+
pg_log(PG_FATAL,
886+
"Your installation contains invalid indexes due to failed or\n"
887+
"currently running CREATE INDEX CONCURRENTLY operations. You\n"
888+
"cannot upgrade until these indexes are valid or removed. A\n"
889+
"list of the problem indexes is in the file:\n"
890+
" %s\n\n", output_path);
891+
}
892+
else
893+
check_ok();
894+
}
895+
896+
806897
static void
807898
get_bin_version(ClusterInfo *cluster)
808899
{

0 commit comments

Comments
 (0)