@@ -20,6 +20,7 @@ static void check_is_super_user(ClusterInfo *cluster);
20
20
static void check_for_prepared_transactions (ClusterInfo * cluster );
21
21
static void check_for_isn_and_int8_passing_mismatch (ClusterInfo * cluster );
22
22
static void check_for_reg_data_type_usage (ClusterInfo * cluster );
23
+ static void check_for_invalid_indexes (ClusterInfo * cluster );
23
24
static void get_bin_version (ClusterInfo * cluster );
24
25
static char * get_canonical_locale_name (int category , const char * locale );
25
26
@@ -97,6 +98,7 @@ check_old_cluster(bool live_check, char **sequence_script_file_name)
97
98
check_is_super_user (& old_cluster );
98
99
check_for_prepared_transactions (& old_cluster );
99
100
check_for_reg_data_type_usage (& old_cluster );
101
+ check_for_invalid_indexes (& old_cluster );
100
102
check_for_isn_and_int8_passing_mismatch (& old_cluster );
101
103
102
104
/* old = PG 8.3 checks? */
@@ -927,6 +929,95 @@ check_for_reg_data_type_usage(ClusterInfo *cluster)
927
929
}
928
930
929
931
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
+
930
1021
static void
931
1022
get_bin_version (ClusterInfo * cluster )
932
1023
{
0 commit comments