4 * server-side function support
6 * Copyright (c) 2010-2011, PostgreSQL Global Development Group
7 * contrib/pg_upgrade/function.c
10 #include "pg_upgrade.h"
12 #include "access/transam.h"
16 * install_db_support_functions()
18 * pg_upgrade requires some support functions that enable it to modify
22 install_db_support_functions(const char *db_name)
24 PGconn *conn = connectToServer(&new_cluster, db_name);
26 /* suppress NOTICE of dropped objects */
27 PQclear(executeQueryOrDie(conn,
28 "SET client_min_messages = warning;"));
29 PQclear(executeQueryOrDie(conn,
30 "DROP SCHEMA IF EXISTS binary_upgrade CASCADE;"));
31 PQclear(executeQueryOrDie(conn,
32 "RESET client_min_messages;"));
34 PQclear(executeQueryOrDie(conn,
35 "CREATE SCHEMA binary_upgrade;"));
37 PQclear(executeQueryOrDie(conn,
38 "CREATE OR REPLACE FUNCTION "
39 " binary_upgrade.set_next_pg_type_oid(OID) "
41 "AS '$libdir/pg_upgrade_support' "
42 "LANGUAGE C STRICT;"));
43 PQclear(executeQueryOrDie(conn,
44 "CREATE OR REPLACE FUNCTION "
45 " binary_upgrade.set_next_array_pg_type_oid(OID) "
47 "AS '$libdir/pg_upgrade_support' "
48 "LANGUAGE C STRICT;"));
49 PQclear(executeQueryOrDie(conn,
50 "CREATE OR REPLACE FUNCTION "
51 " binary_upgrade.set_next_toast_pg_type_oid(OID) "
53 "AS '$libdir/pg_upgrade_support' "
54 "LANGUAGE C STRICT;"));
55 PQclear(executeQueryOrDie(conn,
56 "CREATE OR REPLACE FUNCTION "
57 " binary_upgrade.set_next_heap_pg_class_oid(OID) "
59 "AS '$libdir/pg_upgrade_support' "
60 "LANGUAGE C STRICT;"));
61 PQclear(executeQueryOrDie(conn,
62 "CREATE OR REPLACE FUNCTION "
63 " binary_upgrade.set_next_index_pg_class_oid(OID) "
65 "AS '$libdir/pg_upgrade_support' "
66 "LANGUAGE C STRICT;"));
67 PQclear(executeQueryOrDie(conn,
68 "CREATE OR REPLACE FUNCTION "
69 " binary_upgrade.set_next_toast_pg_class_oid(OID) "
71 "AS '$libdir/pg_upgrade_support' "
72 "LANGUAGE C STRICT;"));
73 PQclear(executeQueryOrDie(conn,
74 "CREATE OR REPLACE FUNCTION "
75 " binary_upgrade.set_next_pg_enum_oid(OID) "
77 "AS '$libdir/pg_upgrade_support' "
78 "LANGUAGE C STRICT;"));
79 PQclear(executeQueryOrDie(conn,
80 "CREATE OR REPLACE FUNCTION "
81 " binary_upgrade.set_next_pg_authid_oid(OID) "
83 "AS '$libdir/pg_upgrade_support' "
84 "LANGUAGE C STRICT;"));
90 uninstall_support_functions(void)
94 prep_status("Removing support functions from new cluster");
96 for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
98 DbInfo *new_db = &new_cluster.dbarr.dbs[dbnum];
99 PGconn *conn = connectToServer(&new_cluster, new_db->db_name);
101 /* suppress NOTICE of dropped objects */
102 PQclear(executeQueryOrDie(conn,
103 "SET client_min_messages = warning;"));
104 PQclear(executeQueryOrDie(conn,
105 "DROP SCHEMA binary_upgrade CASCADE;"));
106 PQclear(executeQueryOrDie(conn,
107 "RESET client_min_messages;"));
115 * get_loadable_libraries()
117 * Fetch the names of all old libraries containing C-language functions.
118 * We will later check that they all exist in the new installation.
121 get_loadable_libraries(void)
128 pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
131 /* Fetch all library names, removing duplicates within each DB */
132 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
134 DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum];
135 PGconn *conn = connectToServer(&old_cluster, active_db->db_name);
137 /* Fetch all libraries referenced in this DB */
138 ress[dbnum] = executeQueryOrDie(conn,
139 "SELECT DISTINCT probin "
140 "FROM pg_catalog.pg_proc "
141 "WHERE prolang = 13 /* C */ AND "
142 " probin IS NOT NULL AND "
144 FirstNormalObjectId);
145 totaltups += PQntuples(ress[dbnum]);
150 /* Allocate what's certainly enough space */
152 os_info.libraries = (char **) pg_malloc(totaltups * sizeof(char *));
154 os_info.libraries = NULL;
157 * Now remove duplicates across DBs. This is pretty inefficient code, but
158 * there probably aren't enough entries to matter.
162 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
164 PGresult *res = ress[dbnum];
168 ntups = PQntuples(res);
169 for (rowno = 0; rowno < ntups; rowno++)
171 char *lib = PQgetvalue(res, rowno, 0);
175 for (n = 0; n < totaltups; n++)
177 if (strcmp(lib, os_info.libraries[n]) == 0)
184 os_info.libraries[totaltups++] = pg_strdup(lib);
190 os_info.num_libraries = totaltups;
197 * check_loadable_libraries()
199 * Check that the new cluster contains all required libraries.
200 * We do this by actually trying to LOAD each one, thereby testing
201 * compatibility as well as presence.
204 check_loadable_libraries(void)
206 PGconn *conn = connectToServer(&new_cluster, "template1");
210 char output_path[MAXPGPATH];
212 prep_status("Checking for presence of required libraries");
214 snprintf(output_path, sizeof(output_path), "%s/loadable_libraries.txt",
217 for (libnum = 0; libnum < os_info.num_libraries; libnum++)
219 char *lib = os_info.libraries[libnum];
220 int llen = strlen(lib);
221 char *cmd = (char *) pg_malloc(8 + 2 * llen + 1);
224 strcpy(cmd, "LOAD '");
225 PQescapeStringConn(conn, cmd + 6, lib, llen, NULL);
228 res = PQexec(conn, cmd);
230 if (PQresultStatus(res) != PGRES_COMMAND_OK)
233 if (script == NULL && (script = fopen(output_path, "w")) == NULL)
234 pg_log(PG_FATAL, "Could not create necessary file: %s\n",
236 fprintf(script, "Failed to load library: %s\n%s\n",
238 PQerrorMessage(conn));
250 pg_log(PG_REPORT, "fatal\n");
252 "| Your installation references loadable libraries that are missing\n"
253 "| from the new installation. You can add these libraries to\n"
254 "| the new installation, or remove the functions using them\n"
255 "| from the old installation. A list of the problem libraries\n"
257 "| \"%s\".\n\n", output_path);