In pg_upgrade, disallow migration of 8.3 clusters using contrib/ltree
authorBruce Momjian
Wed, 7 Sep 2011 18:42:36 +0000 (14:42 -0400)
committerBruce Momjian
Wed, 7 Sep 2011 18:42:36 +0000 (14:42 -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 37c38c1b977e79c2437dc17ae9d37b59c1676851..720f1305a5c2b563c9fd4000bd4b83c39e32e729 100644 (file)
@@ -72,6 +72,7 @@ check_old_cluster(migratorContext *ctx, bool live_check,
    {
        old_8_3_check_for_name_data_type_usage(ctx, CLUSTER_OLD);
        old_8_3_check_for_tsquery_usage(ctx, CLUSTER_OLD);
+       old_8_3_check_ltree_usage(ctx, CLUSTER_OLD);
        if (ctx->check)
        {
            old_8_3_rebuild_tsvector_tables(ctx, true, CLUSTER_OLD);
index 41c4b11245ae8e6f1da24004ba2b4f3ddafaf207..7a02fa1946b21fc8c373776124e005c00b4d0439 100644 (file)
@@ -394,6 +394,8 @@ void old_8_3_check_for_name_data_type_usage(migratorContext *ctx,
                                       Cluster whichCluster);
 void old_8_3_check_for_tsquery_usage(migratorContext *ctx,
                                Cluster whichCluster);
+void old_8_3_check_ltree_usage(migratorContext *ctx,
+                               Cluster whichCluster);
 void old_8_3_rebuild_tsvector_tables(migratorContext *ctx,
                                bool check_mode, Cluster whichCluster);
 void old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx,
index 6fcd61b9c4a4933a9d58e930d2759cf266512f11..7e3a7aacec6953b2cb772766f7975c658eb76000 100644 (file)
@@ -203,6 +203,86 @@ old_8_3_check_for_tsquery_usage(migratorContext *ctx, Cluster whichCluster)
 }
 
 
+/*
+ * 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(migratorContext *ctx, Cluster whichCluster)
+{
+   ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
+   &ctx->old : &ctx->new;
+   int         dbnum;
+   FILE       *script = NULL;
+   bool        found = false;
+   char        output_path[MAXPGPATH];
+
+   prep_status(ctx, "Checking for /contrib/ltree");
+
+   snprintf(output_path, sizeof(output_path), "%s/contrib_ltree.txt",
+            ctx->cwd);
+
+   for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+   {
+       PGresult   *res;
+       bool        db_used = false;
+       int         ntups;
+       int         rowno;
+       int         i_nspname,
+                   i_proname;
+       DbInfo     *active_db = &active_cluster->dbarr.dbs[dbnum];
+       PGconn     *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+
+       /* Find any functions coming from contrib/ltree */
+       res = executeQueryOrDie(ctx, 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(ctx, PG_FATAL, "Could not create necessary file:  %s\n", output_path);
+           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 (found)
+   {
+       fclose(script);
+       pg_log(ctx, PG_REPORT, "fatal\n");
+       pg_log(ctx, 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"
+              "| \t%s\n\n", output_path);
+   }
+   else
+       check_ok(ctx);
+}
+
+
 /*
  * old_8_3_rebuild_tsvector_tables()
  * 8.3 -> 8.4
index 31f1c3d1d486fd0edec9f9bc2782e03ae3808a0b..74fba2e8e02e199dd9686591b2b528bf17dcf72e 100644 (file)
@@ -464,6 +464,11 @@ psql --username postgres --file script.sql postgres
    
   
 
+  
+   pg_upgrade will not work if the ltree
+   contrib module is installed in a database.
+  
+
   
    You must drop any such columns and migrate them manually.