00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "postgres_fe.h"
00011
00012 #include "pg_upgrade.h"
00013
00014 #include "access/transam.h"
00015
00016 #define PG_UPGRADE_SUPPORT "$libdir/pg_upgrade_support"
00017
00018
00019
00020
00021
00022
00023
00024 void
00025 install_support_functions_in_new_db(const char *db_name)
00026 {
00027 PGconn *conn = connectToServer(&new_cluster, db_name);
00028
00029
00030 PQclear(executeQueryOrDie(conn,
00031 "SET client_min_messages = warning;"));
00032 PQclear(executeQueryOrDie(conn,
00033 "DROP SCHEMA IF EXISTS binary_upgrade CASCADE;"));
00034 PQclear(executeQueryOrDie(conn,
00035 "RESET client_min_messages;"));
00036
00037 PQclear(executeQueryOrDie(conn,
00038 "CREATE SCHEMA binary_upgrade;"));
00039
00040 PQclear(executeQueryOrDie(conn,
00041 "CREATE OR REPLACE FUNCTION "
00042 "binary_upgrade.set_next_pg_type_oid(OID) "
00043 "RETURNS VOID "
00044 "AS '$libdir/pg_upgrade_support' "
00045 "LANGUAGE C STRICT;"));
00046 PQclear(executeQueryOrDie(conn,
00047 "CREATE OR REPLACE FUNCTION "
00048 "binary_upgrade.set_next_array_pg_type_oid(OID) "
00049 "RETURNS VOID "
00050 "AS '$libdir/pg_upgrade_support' "
00051 "LANGUAGE C STRICT;"));
00052 PQclear(executeQueryOrDie(conn,
00053 "CREATE OR REPLACE FUNCTION "
00054 "binary_upgrade.set_next_toast_pg_type_oid(OID) "
00055 "RETURNS VOID "
00056 "AS '$libdir/pg_upgrade_support' "
00057 "LANGUAGE C STRICT;"));
00058 PQclear(executeQueryOrDie(conn,
00059 "CREATE OR REPLACE FUNCTION "
00060 "binary_upgrade.set_next_heap_pg_class_oid(OID) "
00061 "RETURNS VOID "
00062 "AS '$libdir/pg_upgrade_support' "
00063 "LANGUAGE C STRICT;"));
00064 PQclear(executeQueryOrDie(conn,
00065 "CREATE OR REPLACE FUNCTION "
00066 "binary_upgrade.set_next_index_pg_class_oid(OID) "
00067 "RETURNS VOID "
00068 "AS '$libdir/pg_upgrade_support' "
00069 "LANGUAGE C STRICT;"));
00070 PQclear(executeQueryOrDie(conn,
00071 "CREATE OR REPLACE FUNCTION "
00072 "binary_upgrade.set_next_toast_pg_class_oid(OID) "
00073 "RETURNS VOID "
00074 "AS '$libdir/pg_upgrade_support' "
00075 "LANGUAGE C STRICT;"));
00076 PQclear(executeQueryOrDie(conn,
00077 "CREATE OR REPLACE FUNCTION "
00078 "binary_upgrade.set_next_pg_enum_oid(OID) "
00079 "RETURNS VOID "
00080 "AS '$libdir/pg_upgrade_support' "
00081 "LANGUAGE C STRICT;"));
00082 PQclear(executeQueryOrDie(conn,
00083 "CREATE OR REPLACE FUNCTION "
00084 "binary_upgrade.set_next_pg_authid_oid(OID) "
00085 "RETURNS VOID "
00086 "AS '$libdir/pg_upgrade_support' "
00087 "LANGUAGE C STRICT;"));
00088 PQclear(executeQueryOrDie(conn,
00089 "CREATE OR REPLACE FUNCTION "
00090 "binary_upgrade.create_empty_extension(text, text, bool, text, oid[], text[], text[]) "
00091 "RETURNS VOID "
00092 "AS '$libdir/pg_upgrade_support' "
00093 "LANGUAGE C;"));
00094 PQfinish(conn);
00095 }
00096
00097
00098 void
00099 uninstall_support_functions_from_new_cluster(void)
00100 {
00101 int dbnum;
00102
00103 prep_status("Removing support functions from new cluster");
00104
00105 for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
00106 {
00107 DbInfo *new_db = &new_cluster.dbarr.dbs[dbnum];
00108 PGconn *conn = connectToServer(&new_cluster, new_db->db_name);
00109
00110
00111 PQclear(executeQueryOrDie(conn,
00112 "SET client_min_messages = warning;"));
00113 PQclear(executeQueryOrDie(conn,
00114 "DROP SCHEMA binary_upgrade CASCADE;"));
00115 PQclear(executeQueryOrDie(conn,
00116 "RESET client_min_messages;"));
00117 PQfinish(conn);
00118 }
00119 check_ok();
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129 void
00130 get_loadable_libraries(void)
00131 {
00132 PGresult **ress;
00133 int totaltups;
00134 int dbnum;
00135 bool found_public_plpython_handler = false;
00136
00137 ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
00138 totaltups = 0;
00139
00140
00141 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
00142 {
00143 DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum];
00144 PGconn *conn = connectToServer(&old_cluster, active_db->db_name);
00145
00146
00147
00148
00149
00150
00151
00152 ress[dbnum] = executeQueryOrDie(conn,
00153 "SELECT DISTINCT probin "
00154 "FROM pg_catalog.pg_proc "
00155 "WHERE prolang = 13 /* C */ AND "
00156 "probin IS NOT NULL AND "
00157 "oid >= %u;",
00158 FirstNormalObjectId);
00159 totaltups += PQntuples(ress[dbnum]);
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 if (GET_MAJOR_VERSION(old_cluster.major_version) < 901)
00173 {
00174 PGresult *res;
00175
00176 res = executeQueryOrDie(conn,
00177 "SELECT 1 "
00178 "FROM pg_catalog.pg_proc JOIN pg_namespace "
00179 " ON pronamespace = pg_namespace.oid "
00180 "WHERE proname = 'plpython_call_handler' AND "
00181 "nspname = 'public' AND "
00182 "prolang = 13 /* C */ AND "
00183 "probin = '$libdir/plpython' AND "
00184 "pg_proc.oid >= %u;",
00185 FirstNormalObjectId);
00186 if (PQntuples(res) > 0)
00187 {
00188 if (!found_public_plpython_handler)
00189 {
00190 pg_log(PG_WARNING,
00191 "\nThe old cluster has a \"plpython_call_handler\" function defined\n"
00192 "in the \"public\" schema which is a duplicate of the one defined\n"
00193 "in the \"pg_catalog\" schema. You can confirm this by executing\n"
00194 "in psql:\n"
00195 "\n"
00196 " \\df *.plpython_call_handler\n"
00197 "\n"
00198 "The \"public\" schema version of this function was created by a\n"
00199 "pre-8.1 install of plpython, and must be removed for pg_upgrade\n"
00200 "to complete because it references a now-obsolete \"plpython\"\n"
00201 "shared object file. You can remove the \"public\" schema version\n"
00202 "of this function by running the following command:\n"
00203 "\n"
00204 " DROP FUNCTION public.plpython_call_handler()\n"
00205 "\n"
00206 "in each affected database:\n"
00207 "\n");
00208 }
00209 pg_log(PG_WARNING, " %s\n", active_db->db_name);
00210 found_public_plpython_handler = true;
00211 }
00212 PQclear(res);
00213 }
00214
00215 PQfinish(conn);
00216 }
00217
00218 if (found_public_plpython_handler)
00219 pg_log(PG_FATAL,
00220 "Remove the problem functions from the old cluster to continue.\n");
00221
00222 totaltups++;
00223
00224
00225 os_info.libraries = (char **) pg_malloc(totaltups * sizeof(char *));
00226
00227
00228
00229
00230
00231 totaltups = 0;
00232 os_info.libraries[totaltups++] = pg_strdup(PG_UPGRADE_SUPPORT);
00233
00234 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
00235 {
00236 PGresult *res = ress[dbnum];
00237 int ntups;
00238 int rowno;
00239
00240 ntups = PQntuples(res);
00241 for (rowno = 0; rowno < ntups; rowno++)
00242 {
00243 char *lib = PQgetvalue(res, rowno, 0);
00244 bool dup = false;
00245 int n;
00246
00247 for (n = 0; n < totaltups; n++)
00248 {
00249 if (strcmp(lib, os_info.libraries[n]) == 0)
00250 {
00251 dup = true;
00252 break;
00253 }
00254 }
00255 if (!dup)
00256 os_info.libraries[totaltups++] = pg_strdup(lib);
00257 }
00258
00259 PQclear(res);
00260 }
00261
00262 os_info.num_libraries = totaltups;
00263
00264 pg_free(ress);
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 void
00276 check_loadable_libraries(void)
00277 {
00278 PGconn *conn = connectToServer(&new_cluster, "template1");
00279 int libnum;
00280 FILE *script = NULL;
00281 bool found = false;
00282 char output_path[MAXPGPATH];
00283
00284 prep_status("Checking for presence of required libraries");
00285
00286 snprintf(output_path, sizeof(output_path), "loadable_libraries.txt");
00287
00288 for (libnum = 0; libnum < os_info.num_libraries; libnum++)
00289 {
00290 char *lib = os_info.libraries[libnum];
00291 int llen = strlen(lib);
00292 char cmd[7 + 2 * MAXPGPATH + 1];
00293 PGresult *res;
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 if (GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
00309 strcmp(lib, "$libdir/plpython") == 0)
00310 {
00311 lib = "$libdir/plpython2";
00312 llen = strlen(lib);
00313 }
00314
00315 strcpy(cmd, "LOAD '");
00316 PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
00317 strcat(cmd, "'");
00318
00319 res = PQexec(conn, cmd);
00320
00321 if (PQresultStatus(res) != PGRES_COMMAND_OK)
00322 {
00323 found = true;
00324
00325
00326 if (strcmp(lib, PG_UPGRADE_SUPPORT) == 0)
00327 pg_log(PG_FATAL,
00328 "The pg_upgrade_support module must be created and installed in the new cluster.\n");
00329
00330 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
00331 pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
00332 output_path, getErrorText(errno));
00333 fprintf(script, "Could not load library \"%s\"\n%s\n",
00334 lib,
00335 PQerrorMessage(conn));
00336 }
00337
00338 PQclear(res);
00339 }
00340
00341 PQfinish(conn);
00342
00343 if (found)
00344 {
00345 fclose(script);
00346 pg_log(PG_REPORT, "fatal\n");
00347 pg_log(PG_FATAL,
00348 "Your installation references loadable libraries that are missing from the\n"
00349 "new installation. You can add these libraries to the new installation,\n"
00350 "or remove the functions using them from the old installation. A list of\n"
00351 "problem libraries is in the file:\n"
00352 " %s\n\n", output_path);
00353 }
00354 else
00355 check_ok();
00356 }