@@ -20,6 +20,7 @@ static void check_is_super_user(ClusterInfo *cluster);
2020static void check_for_prepared_transactions (ClusterInfo * cluster );
2121static void check_for_isn_and_int8_passing_mismatch (ClusterInfo * cluster );
2222static void check_for_reg_data_type_usage (ClusterInfo * cluster );
23+ static void check_for_invalid_indexes (ClusterInfo * cluster );
2324static void get_bin_version (ClusterInfo * cluster );
2425static 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)
9798check_is_super_user (& old_cluster );
9899check_for_prepared_transactions (& old_cluster );
99100check_for_reg_data_type_usage (& old_cluster );
101+ check_for_invalid_indexes (& old_cluster );
100102check_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+ "FROMpg_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+
9301021static void
9311022get_bin_version (ClusterInfo * cluster )
9321023{