4 * server-side function support
6 * Copyright (c) 2010-2012, PostgreSQL Global Development Group
7 * contrib/pg_upgrade/function.c
12 #include "pg_upgrade.h"
14 #include "access/transam.h"
18 * install_support_functions_in_new_db()
20 * pg_upgrade requires some support functions that enable it to modify
24 install_support_functions_in_new_db(const char *db_name)
26 PGconn *conn = connectToServer(&new_cluster, db_name);
28 /* suppress NOTICE of dropped objects */
29 PQclear(executeQueryOrDie(conn,
30 "SET client_min_messages = warning;"));
31 PQclear(executeQueryOrDie(conn,
32 "DROP SCHEMA IF EXISTS binary_upgrade CASCADE;"));
33 PQclear(executeQueryOrDie(conn,
34 "RESET client_min_messages;"));
36 PQclear(executeQueryOrDie(conn,
37 "CREATE SCHEMA binary_upgrade;"));
39 PQclear(executeQueryOrDie(conn,
40 "CREATE OR REPLACE FUNCTION "
41 "binary_upgrade.set_next_pg_type_oid(OID) "
43 "AS '$libdir/pg_upgrade_support' "
44 "LANGUAGE C STRICT;"));
45 PQclear(executeQueryOrDie(conn,
46 "CREATE OR REPLACE FUNCTION "
47 "binary_upgrade.set_next_array_pg_type_oid(OID) "
49 "AS '$libdir/pg_upgrade_support' "
50 "LANGUAGE C STRICT;"));
51 PQclear(executeQueryOrDie(conn,
52 "CREATE OR REPLACE FUNCTION "
53 "binary_upgrade.set_next_toast_pg_type_oid(OID) "
55 "AS '$libdir/pg_upgrade_support' "
56 "LANGUAGE C STRICT;"));
57 PQclear(executeQueryOrDie(conn,
58 "CREATE OR REPLACE FUNCTION "
59 "binary_upgrade.set_next_heap_pg_class_oid(OID) "
61 "AS '$libdir/pg_upgrade_support' "
62 "LANGUAGE C STRICT;"));
63 PQclear(executeQueryOrDie(conn,
64 "CREATE OR REPLACE FUNCTION "
65 "binary_upgrade.set_next_index_pg_class_oid(OID) "
67 "AS '$libdir/pg_upgrade_support' "
68 "LANGUAGE C STRICT;"));
69 PQclear(executeQueryOrDie(conn,
70 "CREATE OR REPLACE FUNCTION "
71 "binary_upgrade.set_next_toast_pg_class_oid(OID) "
73 "AS '$libdir/pg_upgrade_support' "
74 "LANGUAGE C STRICT;"));
75 PQclear(executeQueryOrDie(conn,
76 "CREATE OR REPLACE FUNCTION "
77 "binary_upgrade.set_next_pg_enum_oid(OID) "
79 "AS '$libdir/pg_upgrade_support' "
80 "LANGUAGE C STRICT;"));
81 PQclear(executeQueryOrDie(conn,
82 "CREATE OR REPLACE FUNCTION "
83 "binary_upgrade.set_next_pg_authid_oid(OID) "
85 "AS '$libdir/pg_upgrade_support' "
86 "LANGUAGE C STRICT;"));
87 PQclear(executeQueryOrDie(conn,
88 "CREATE OR REPLACE FUNCTION "
89 "binary_upgrade.create_empty_extension(text, text, bool, text, oid[], text[], text[]) "
91 "AS '$libdir/pg_upgrade_support' "
98 uninstall_support_functions_from_new_cluster(void)
102 prep_status("Removing support functions from new cluster");
104 for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
106 DbInfo *new_db = &new_cluster.dbarr.dbs[dbnum];
107 PGconn *conn = connectToServer(&new_cluster, new_db->db_name);
109 /* suppress NOTICE of dropped objects */
110 PQclear(executeQueryOrDie(conn,
111 "SET client_min_messages = warning;"));
112 PQclear(executeQueryOrDie(conn,
113 "DROP SCHEMA binary_upgrade CASCADE;"));
114 PQclear(executeQueryOrDie(conn,
115 "RESET client_min_messages;"));
123 * get_loadable_libraries()
125 * Fetch the names of all old libraries containing C-language functions.
126 * We will later check that they all exist in the new installation.
129 get_loadable_libraries(void)
135 ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
138 /* Fetch all library names, removing duplicates within each DB */
139 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
141 DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum];
142 PGconn *conn = connectToServer(&old_cluster, active_db->db_name);
144 /* Fetch all libraries referenced in this DB */
145 ress[dbnum] = executeQueryOrDie(conn,
146 "SELECT DISTINCT probin "
147 "FROM pg_catalog.pg_proc "
148 "WHERE prolang = 13 /* C */ AND "
149 "probin IS NOT NULL AND "
151 FirstNormalObjectId);
152 totaltups += PQntuples(ress[dbnum]);
157 /* Allocate what's certainly enough space */
159 os_info.libraries = (char **) pg_malloc(totaltups * sizeof(char *));
161 os_info.libraries = NULL;
164 * Now remove duplicates across DBs. This is pretty inefficient code, but
165 * there probably aren't enough entries to matter.
169 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
171 PGresult *res = ress[dbnum];
175 ntups = PQntuples(res);
176 for (rowno = 0; rowno < ntups; rowno++)
178 char *lib = PQgetvalue(res, rowno, 0);
182 for (n = 0; n < totaltups; n++)
184 if (strcmp(lib, os_info.libraries[n]) == 0)
191 os_info.libraries[totaltups++] = pg_strdup(lib);
197 os_info.num_libraries = totaltups;
204 * check_loadable_libraries()
206 * Check that the new cluster contains all required libraries.
207 * We do this by actually trying to LOAD each one, thereby testing
208 * compatibility as well as presence.
211 check_loadable_libraries(void)
213 PGconn *conn = connectToServer(&new_cluster, "template1");
217 char output_path[MAXPGPATH];
219 prep_status("Checking for presence of required libraries");
221 snprintf(output_path, sizeof(output_path), "%s/loadable_libraries.txt",
224 for (libnum = 0; libnum < os_info.num_libraries; libnum++)
226 char *lib = os_info.libraries[libnum];
227 int llen = strlen(lib);
228 char cmd[7 + 2 * MAXPGPATH + 1];
232 * In Postgres 9.0, Python 3 support was added, and to do that, a
233 * plpython2u language was created with library name plpython2.so
234 * as a symbolic link to plpython.so. In Postgres 9.1, only the
235 * plpython2.so library was created, and both plpythonu and
236 * plpython2u pointing to it. For this reason, any reference to
237 * library name "plpython" in an old PG <= 9.1 cluster must look
238 * for "plpython2" in the new cluster.
240 * For this case, we could check pg_pltemplate, but that only works
241 * for languages, and does not help with function shared objects,
242 * so we just do a general fix.
244 if (GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
245 strcmp(lib, "$libdir/plpython") == 0)
247 lib = "$libdir/plpython2";
251 strcpy(cmd, "LOAD '");
252 PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
255 res = PQexec(conn, cmd);
257 if (PQresultStatus(res) != PGRES_COMMAND_OK)
260 if (script == NULL && (script = fopen(output_path, "w")) == NULL)
261 pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
262 output_path, getErrorText(errno));
263 fprintf(script, "Could not load library \"%s\"\n%s\n",
265 PQerrorMessage(conn));
276 pg_log(PG_REPORT, "fatal\n");
278 "Your installation references loadable libraries that are missing from the\n"
279 "new installation. You can add these libraries to the new installation,\n"
280 "or remove the functions using them from the old installation. A list of\n"
281 "problem libraries is in the file:\n"
282 " %s\n\n", output_path);