]> granicus.if.org Git - postgresql/commitdiff
pg_upgrade: Handle hash index upgrades more smoothly.
authorRobert Haas <rhaas@postgresql.org>
Fri, 19 May 2017 20:49:38 +0000 (16:49 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 19 May 2017 20:49:38 +0000 (16:49 -0400)
Mark any old hash indexes as invalid so that they don't get used, and
create a script to run REINDEX on all of them.  Without this, we'd
still try to use any upgraded hash indexes, but it would fail.

Amit Kapila, reviewed by me.  Per a suggestion from Tom Lane.

Discussion: http://postgr.es/m/CAA4eK1Jidtagm7Q81q-WoegOVgkotv0OxvHOjFxcvFRP4X=mSw@mail.gmail.com

src/bin/pg_upgrade/check.c
src/bin/pg_upgrade/pg_upgrade.h
src/bin/pg_upgrade/version.c

index d52c81e24955a43d18f820ebfe0cff64dd6df6fe..8b9e81eb407521be8bf02142c3d542e372f110e8 100644 (file)
@@ -98,9 +98,16 @@ check_and_dump_old_cluster(bool live_check)
        check_for_reg_data_type_usage(&old_cluster);
        check_for_isn_and_int8_passing_mismatch(&old_cluster);
 
-       /* Pre-PG 10 allowed tables with 'unknown' type columns */
+       /*
+        * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
+        * hash indexes
+        */
        if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906)
+       {
                old_9_6_check_for_unknown_data_type_usage(&old_cluster);
+               if (user_opts.check)
+                       old_9_6_invalidate_hash_indexes(&old_cluster, true);
+       }
 
        /* 9.5 and below should not have roles starting with pg_ */
        if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905)
@@ -176,6 +183,14 @@ issue_warnings(void)
                new_9_0_populate_pg_largeobject_metadata(&new_cluster, false);
                stop_postmaster(false);
        }
+
+       /* Reindex hash indexes for old < 10.0 */
+       if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906)
+       {
+               start_postmaster(&new_cluster, true);
+               old_9_6_invalidate_hash_indexes(&new_cluster, false);
+               stop_postmaster(false);
+       }
 }
 
 
index b78b877903d7e777049a0474924dcb8602243f1f..8fbf8acd7eb1886bab47d409fe9b1ec4622f7a88 100644 (file)
@@ -441,6 +441,8 @@ void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster,
                                                                                 bool check_mode);
 void           old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster);
 void           old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster);
+void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster,
+                                                               bool check_mode);
 
 /* parallel.c */
 void parallel_exec_prog(const char *log_file, const char *opt_log_file,
index a3651aadede0763caca87c56d10bed985f005d03..814eaa522c4dbffb00b9c65a34c3ca67d458bac0 100644 (file)
@@ -287,3 +287,115 @@ old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
        else
                check_ok();
 }
+
+/*
+ * old_9_6_invalidate_hash_indexes()
+ *     9.6 -> 10
+ *     Hash index binary format has changed from 9.6->10.0
+ */
+void
+old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
+{
+       int                     dbnum;
+       FILE       *script = NULL;
+       bool            found = false;
+       char       *output_path = "reindex_hash.sql";
+
+       prep_status("Checking for hash indexes");
+
+       for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
+       {
+               PGresult   *res;
+               bool            db_used = false;
+               int                     ntups;
+               int                     rowno;
+               int                     i_nspname,
+                                       i_relname;
+               DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
+               PGconn     *conn = connectToServer(cluster, active_db->db_name);
+
+               /* find hash indexes */
+               res = executeQueryOrDie(conn,
+                                                               "SELECT n.nspname, c.relname "
+                                                               "FROM   pg_catalog.pg_class c, "
+                                                               "               pg_catalog.pg_index i, "
+                                                               "               pg_catalog.pg_am a, "
+                                                               "               pg_catalog.pg_namespace n "
+                                                               "WHERE  i.indexrelid = c.oid AND "
+                                                               "               c.relam = a.oid AND "
+                                                               "               c.relnamespace = n.oid AND "
+                                                               "               a.amname = 'hash'"
+                       );
+
+               ntups = PQntuples(res);
+               i_nspname = PQfnumber(res, "nspname");
+               i_relname = PQfnumber(res, "relname");
+               for (rowno = 0; rowno < ntups; rowno++)
+               {
+                       found = true;
+                       if (!check_mode)
+                       {
+                               if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
+                                       pg_fatal("could not open file \"%s\": %s\n", output_path,
+                                                        strerror(errno));
+                               if (!db_used)
+                               {
+                                       PQExpBufferData connectbuf;
+
+                                       initPQExpBuffer(&connectbuf);
+                                       appendPsqlMetaConnect(&connectbuf, active_db->db_name);
+                                       fputs(connectbuf.data, script);
+                                       termPQExpBuffer(&connectbuf);
+                                       db_used = true;
+                               }
+                               fprintf(script, "REINDEX INDEX %s.%s;\n",
+                                               quote_identifier(PQgetvalue(res, rowno, i_nspname)),
+                                               quote_identifier(PQgetvalue(res, rowno, i_relname)));
+                       }
+               }
+
+               PQclear(res);
+
+               if (!check_mode && db_used)
+               {
+                       /* mark hash indexes as invalid */
+                       PQclear(executeQueryOrDie(conn,
+                                                                         "UPDATE pg_catalog.pg_index i "
+                                                                         "SET  indisvalid = false "
+                                                                         "FROM pg_catalog.pg_class c, "
+                                                                         "             pg_catalog.pg_am a, "
+                                                                         "             pg_catalog.pg_namespace n "
+                                                                         "WHERE        i.indexrelid = c.oid AND "
+                                                                         "             c.relam = a.oid AND "
+                                                                         "             c.relnamespace = n.oid AND "
+                                                                         "             a.amname = 'hash'"));
+               }
+
+               PQfinish(conn);
+       }
+
+       if (script)
+               fclose(script);
+
+       if (found)
+       {
+               report_status(PG_WARNING, "warning");
+               if (check_mode)
+                       pg_log(PG_WARNING, "\n"
+                                  "Your installation contains hash indexes.  These indexes have different\n"
+                                  "internal formats between your old and new clusters, so they must be\n"
+                                  "reindexed with the REINDEX command.  After upgrading, you will be given\n"
+                                  "REINDEX instructions.\n\n");
+               else
+                       pg_log(PG_WARNING, "\n"
+                                  "Your installation contains hash indexes.  These indexes have different\n"
+                                  "internal formats between your old and new clusters, so they must be\n"
+                                  "reindexed with the REINDEX command.  The file:\n"
+                                  "    %s\n"
+                                  "when executed by psql by the database superuser will recreate all invalid\n"
+                         "indexes; until then, none of these indexes will be used.\n\n",
+                                  output_path);
+       }
+       else
+               check_ok();
+}