@@ -132,7 +132,8 @@ get_loadable_libraries(void)
132132 PGresult * * ress ;
133133 int totaltups ;
134134 int dbnum ;
135-
135+ bool found_public_plpython_handler = false;
136+
136137 ress = (PGresult * * ) pg_malloc (old_cluster .dbarr .ndbs * sizeof (PGresult * ));
137138 totaltups = 0 ;
138139
@@ -157,9 +158,67 @@ get_loadable_libraries(void)
157158 FirstNormalObjectId );
158159 totaltups += PQntuples (ress [dbnum ]);
159160
161+ /*
162+ * Systems that install plpython before 8.1 have
163+ * plpython_call_handler() defined in the "public" schema, causing
164+ * pg_dumpall to dump it. However that function still references
165+ * "plpython" (no "2"), so it throws an error on restore. This code
166+ * checks for the problem function, reports affected databases to the
167+ * user and explains how to remove them.
168+ * 8.1 git commit: e0dedd0559f005d60c69c9772163e69c204bac69
169+ * http://archives.postgresql.org/pgsql-hackers/2012-03/msg01101.php
170+ * http://archives.postgresql.org/pgsql-bugs/2012-05/msg00206.php
171+ */
172+ if (GET_MAJOR_VERSION (old_cluster .major_version ) < 901 )
173+ {
174+ PGresult * res ;
175+
176+ res = executeQueryOrDie (conn ,
177+ "SELECT 1 "
178+ "FROM pg_catalog.pg_proc JOIN pg_namespace "
179+ " ON pronamespace = pg_namespace.oid "
180+ "WHERE proname = 'plpython_call_handler' AND "
181+ "nspname = 'public' AND "
182+ "prolang = 13 /* C */ AND "
183+ "probin = '$libdir/plpython' AND "
184+ "pg_proc.oid >= %u;" ,
185+ FirstNormalObjectId );
186+ if (PQntuples (res ) > 0 )
187+ {
188+ if (!found_public_plpython_handler )
189+ {
190+ pg_log (PG_WARNING ,
191+ "\nThe old cluster has a \"plpython_call_handler\" function defined\n"
192+ "in the \"public\" schema which is a duplicate of the one defined\n"
193+ "in the \"pg_catalog\" schema. You can confirm this by executing\n"
194+ "in psql:\n"
195+ "\n"
196+ " \\df *.plpython_call_handler\n"
197+ "\n"
198+ "The \"public\" schema version of this function was created by a\n"
199+ "pre-8.1 install of plpython, and must be removed for pg_upgrade\n"
200+ "to complete because it references a now-obsolete \"plpython\"\n"
201+ "shared object file. You can remove the \"public\" schema version\n"
202+ "of this function by running the following command:\n"
203+ "\n"
204+ " DROP FUNCTION public.plpython_call_handler()\n"
205+ "\n"
206+ "in each affected database:\n"
207+ "\n" );
208+ }
209+ pg_log (PG_WARNING , " %s\n" , active_db -> db_name );
210+ found_public_plpython_handler = true;
211+ }
212+ PQclear (res );
213+ }
214+
160215 PQfinish (conn );
161216 }
162217
218+ if (found_public_plpython_handler )
219+ pg_log (PG_FATAL ,
220+ "Remove the problem functions from the old cluster to continue.\n" );
221+
163222 totaltups ++ ; /* reserve for pg_upgrade_support */
164223
165224 /* Allocate what's certainly enough space */
@@ -245,12 +304,6 @@ check_loadable_libraries(void)
245304 * For this case, we could check pg_pltemplate, but that only works
246305 * for languages, and does not help with function shared objects,
247306 * so we just do a general fix.
248- *
249- * Some systems have plpython_call_handler() that references
250- * "plpython" defined in the "public" schema, causing pg_dump to
251- * dump it an generate an error on pg_dumpall restore; not sure
252- * on the cause, see:
253- * http://archives.postgresql.org/pgsql-hackers/2012-03/msg01101.php
254307 */
255308 if (GET_MAJOR_VERSION (old_cluster .major_version ) < 901 &&
256309 strcmp (lib , "$libdir/plpython" ) == 0 )
0 commit comments