]> granicus.if.org Git - postgresql/commitdiff
In pg_upgrade, disallow migration of 8.3 clusters using contrib/ltree
authorBruce Momjian <bruce@momjian.us>
Wed, 7 Sep 2011 18:42:36 +0000 (14:42 -0400)
committerBruce Momjian <bruce@momjian.us>
Wed, 7 Sep 2011 18:43:07 +0000 (14:43 -0400)
because its internal format was changed in 8.4.

Backpatch to 9.0 and 9.1.

Report by depesz, diagnosis by Tom.

contrib/pg_upgrade/check.c
contrib/pg_upgrade/pg_upgrade.h
contrib/pg_upgrade/version_old_8_3.c
doc/src/sgml/pgupgrade.sgml

index aae408e408eae6199e3427e0b3b44eebde97363a..419628c3a448d43864ee3bd9e01dec534b76bfc6 100644 (file)
@@ -77,6 +77,7 @@ check_old_cluster(bool live_check,
        {
                old_8_3_check_for_name_data_type_usage(&old_cluster);
                old_8_3_check_for_tsquery_usage(&old_cluster);
+               old_8_3_check_ltree_usage(&old_cluster);
                if (user_opts.check)
                {
                        old_8_3_rebuild_tsvector_tables(&old_cluster, true);
index 613ddbd03ff2b6e59e99f2f053377a8dd7e75f40..898541b770b6890679f42afe45feb12b7eea4d19 100644 (file)
@@ -390,6 +390,7 @@ void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster,
 
 void           old_8_3_check_for_name_data_type_usage(ClusterInfo *cluster);
 void           old_8_3_check_for_tsquery_usage(ClusterInfo *cluster);
+void           old_8_3_check_ltree_usage(ClusterInfo *cluster);
 void           old_8_3_rebuild_tsvector_tables(ClusterInfo *cluster, bool check_mode);
 void           old_8_3_invalidate_hash_gin_indexes(ClusterInfo *cluster, bool check_mode);
 void old_8_3_invalidate_bpchar_pattern_ops_indexes(ClusterInfo *cluster,
index 69046def1fd739f7cd44ef6b312da240005095be..ffb79adc91a129157feb411dd813600c7546f751 100644 (file)
@@ -201,6 +201,87 @@ old_8_3_check_for_tsquery_usage(ClusterInfo *cluster)
 }
 
 
+/*
+ *     old_8_3_check_ltree_usage()
+ *     8.3 -> 8.4
+ *     The internal ltree structure was changed in 8.4 so upgrading is impossible.
+ */
+void
+old_8_3_check_ltree_usage(ClusterInfo *cluster)
+{
+       int                     dbnum;
+       FILE       *script = NULL;
+       bool            found = false;
+       char            output_path[MAXPGPATH];
+
+       prep_status("Checking for contrib/ltree");
+
+       snprintf(output_path, sizeof(output_path), "%s/contrib_ltree.txt",
+                        os_info.cwd);
+
+       for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
+       {
+               PGresult   *res;
+               bool            db_used = false;
+               int                     ntups;
+               int                     rowno;
+               int                     i_nspname,
+                                       i_proname;
+               DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
+               PGconn     *conn = connectToServer(cluster, active_db->db_name);
+
+               /* Find any functions coming from contrib/ltree */
+               res = executeQueryOrDie(conn,
+                                                               "SELECT n.nspname, p.proname "
+                                                               "FROM   pg_catalog.pg_proc p, "
+                                                               "               pg_catalog.pg_namespace n "
+                                                               "WHERE  p.pronamespace = n.oid AND "
+                                                               "               p.probin = '$libdir/ltree'");
+
+               ntups = PQntuples(res);
+               i_nspname = PQfnumber(res, "nspname");
+               i_proname = PQfnumber(res, "proname");
+               for (rowno = 0; rowno < ntups; rowno++)
+               {
+                       found = true;
+                       if (script == NULL && (script = fopen(output_path, "w")) == NULL)
+                               pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
+                                          output_path, getErrorText(errno));
+                       if (!db_used)
+                       {
+                               fprintf(script, "Database: %s\n", active_db->db_name);
+                               db_used = true;
+                       }
+                       fprintf(script, "  %s.%s\n",
+                                       PQgetvalue(res, rowno, i_nspname),
+                                       PQgetvalue(res, rowno, i_proname));
+               }
+
+               PQclear(res);
+
+               PQfinish(conn);
+       }
+
+       if (script)
+               fclose(script);
+
+       if (found)
+       {
+               pg_log(PG_REPORT, "fatal\n");
+               pg_log(PG_FATAL,
+                          "Your installation contains the \"ltree\" data type.  This data type\n"
+                          "changed its internal storage format between your old and new clusters so this\n"
+                          "cluster cannot currently be upgraded.  You can manually upgrade databases\n"
+                          "that use \"contrib/ltree\" facilities and remove \"contrib/ltree\" from the old\n"
+                          "cluster and restart the upgrade.  A list of the problem functions is in the\n"
+                          "file:\n"
+                          "    %s\n\n", output_path);
+       }
+       else
+               check_ok();
+}
+
+
 /*
  * old_8_3_rebuild_tsvector_tables()
  *     8.3 -> 8.4
index 8ea9c270120a5077de951b37127a16caace08b29..3a6dbfd65acaf2b3f5156b1f813bdf9796d37ecf 100644 (file)
@@ -485,6 +485,11 @@ psql --username postgres --file script.sql postgres
    You must drop any such columns and upgrade them manually.
   </para>
 
+  <para>
+   pg_upgrade will not work if the <filename>ltree</>
+   contrib module is installed in a database.
+  </para>
+
   <para>
    pg_upgrade will require a table rebuild if:
    <itemizedlist>