00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "postgres_fe.h"
00011
00012 #include "pg_upgrade.h"
00013
00014
00015 static void set_locale_and_encoding(ClusterInfo *cluster);
00016 static void check_new_cluster_is_empty(void);
00017 static void check_locale_and_encoding(ControlData *oldctrl,
00018 ControlData *newctrl);
00019 static void check_is_super_user(ClusterInfo *cluster);
00020 static void check_for_prepared_transactions(ClusterInfo *cluster);
00021 static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
00022 static void check_for_reg_data_type_usage(ClusterInfo *cluster);
00023 static void get_bin_version(ClusterInfo *cluster);
00024 static char *get_canonical_locale_name(int category, const char *locale);
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 static char *
00035 fix_path_separator(char *path)
00036 {
00037 #ifdef WIN32
00038
00039 char *result;
00040 char *c;
00041
00042 result = pg_strdup(path);
00043
00044 for (c = result; *c != '\0'; c++)
00045 if (*c == '/')
00046 *c = '\\';
00047
00048 return result;
00049
00050 #else
00051
00052 return path;
00053
00054 #endif
00055 }
00056
00057 void
00058 output_check_banner(bool live_check)
00059 {
00060 if (user_opts.check && live_check)
00061 {
00062 pg_log(PG_REPORT, "Performing Consistency Checks on Old Live Server\n");
00063 pg_log(PG_REPORT, "------------------------------------------------\n");
00064 }
00065 else
00066 {
00067 pg_log(PG_REPORT, "Performing Consistency Checks\n");
00068 pg_log(PG_REPORT, "-----------------------------\n");
00069 }
00070 }
00071
00072
00073 void
00074 check_and_dump_old_cluster(bool live_check, char **sequence_script_file_name)
00075 {
00076
00077
00078 if (!live_check)
00079 start_postmaster(&old_cluster, true);
00080
00081 set_locale_and_encoding(&old_cluster);
00082
00083 get_pg_database_relfilenode(&old_cluster);
00084
00085
00086 get_db_and_rel_infos(&old_cluster);
00087
00088 init_tablespaces();
00089
00090 get_loadable_libraries();
00091
00092
00093
00094
00095
00096 check_is_super_user(&old_cluster);
00097 check_for_prepared_transactions(&old_cluster);
00098 check_for_reg_data_type_usage(&old_cluster);
00099 check_for_isn_and_int8_passing_mismatch(&old_cluster);
00100
00101
00102 if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
00103 {
00104 old_8_3_check_for_name_data_type_usage(&old_cluster);
00105 old_8_3_check_for_tsquery_usage(&old_cluster);
00106 old_8_3_check_ltree_usage(&old_cluster);
00107 if (user_opts.check)
00108 {
00109 old_8_3_rebuild_tsvector_tables(&old_cluster, true);
00110 old_8_3_invalidate_hash_gin_indexes(&old_cluster, true);
00111 old_8_3_invalidate_bpchar_pattern_ops_indexes(&old_cluster, true);
00112 }
00113 else
00114
00115
00116
00117
00118
00119
00120 *sequence_script_file_name =
00121 old_8_3_create_sequence_script(&old_cluster);
00122 }
00123
00124
00125 if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
00126 new_9_0_populate_pg_largeobject_metadata(&old_cluster, true);
00127
00128
00129
00130
00131
00132 if (!user_opts.check)
00133 generate_old_dump();
00134
00135 if (!live_check)
00136 stop_postmaster(false);
00137 }
00138
00139
00140 void
00141 check_new_cluster(void)
00142 {
00143 set_locale_and_encoding(&new_cluster);
00144
00145 check_locale_and_encoding(&old_cluster.controldata, &new_cluster.controldata);
00146
00147 get_db_and_rel_infos(&new_cluster);
00148
00149 check_new_cluster_is_empty();
00150
00151 check_loadable_libraries();
00152
00153 if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
00154 check_hard_link();
00155
00156 check_is_super_user(&new_cluster);
00157
00158
00159
00160
00161
00162 if (old_cluster.install_role_oid != new_cluster.install_role_oid)
00163 pg_log(PG_FATAL,
00164 "Old and new cluster install users have different values for pg_authid.oid.\n");
00165
00166
00167
00168
00169
00170
00171 if (new_cluster.role_count != 1)
00172 pg_log(PG_FATAL, "Only the install user can be defined in the new cluster.\n");
00173
00174 check_for_prepared_transactions(&new_cluster);
00175 }
00176
00177
00178 void
00179 report_clusters_compatible(void)
00180 {
00181 if (user_opts.check)
00182 {
00183 pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
00184
00185 stop_postmaster(false);
00186 exit(0);
00187 }
00188
00189 pg_log(PG_REPORT, "\n"
00190 "If pg_upgrade fails after this point, you must re-initdb the\n"
00191 "new cluster before continuing.\n");
00192 }
00193
00194
00195 void
00196 issue_warnings(char *sequence_script_file_name)
00197 {
00198
00199 if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
00200 {
00201 start_postmaster(&new_cluster, true);
00202
00203
00204 if (sequence_script_file_name)
00205 {
00206 prep_status("Adjusting sequences");
00207 exec_prog(UTILITY_LOG_FILE, NULL, true,
00208 "\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
00209 new_cluster.bindir, cluster_conn_opts(&new_cluster),
00210 sequence_script_file_name);
00211 unlink(sequence_script_file_name);
00212 check_ok();
00213 }
00214
00215 old_8_3_rebuild_tsvector_tables(&new_cluster, false);
00216 old_8_3_invalidate_hash_gin_indexes(&new_cluster, false);
00217 old_8_3_invalidate_bpchar_pattern_ops_indexes(&new_cluster, false);
00218 stop_postmaster(false);
00219 }
00220
00221
00222 if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
00223 {
00224 start_postmaster(&new_cluster, true);
00225 new_9_0_populate_pg_largeobject_metadata(&new_cluster, false);
00226 stop_postmaster(false);
00227 }
00228 }
00229
00230
00231 void
00232 output_completion_banner(char *analyze_script_file_name,
00233 char *deletion_script_file_name)
00234 {
00235
00236 if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
00237 pg_log(PG_REPORT,
00238 "Optimizer statistics are not transferred by pg_upgrade so,\n"
00239 "once you start the new server, consider running:\n"
00240 " %s\n\n", analyze_script_file_name);
00241 else
00242 pg_log(PG_REPORT,
00243 "Optimizer statistics and free space information are not transferred\n"
00244 "by pg_upgrade so, once you start the new server, consider running:\n"
00245 " %s\n\n", analyze_script_file_name);
00246
00247
00248 if (deletion_script_file_name)
00249 pg_log(PG_REPORT,
00250 "Running this script will delete the old cluster's data files:\n"
00251 " %s\n",
00252 deletion_script_file_name);
00253 else
00254 pg_log(PG_REPORT,
00255 "Could not create a script to delete the old cluster's data\n"
00256 "files because user-defined tablespaces exist in the old cluster\n"
00257 "directory. The old cluster's contents must be deleted manually.\n");
00258 }
00259
00260
00261 void
00262 check_cluster_versions(void)
00263 {
00264 prep_status("Checking cluster versions");
00265
00266
00267 old_cluster.major_version = get_major_server_version(&old_cluster);
00268 new_cluster.major_version = get_major_server_version(&new_cluster);
00269
00270
00271
00272
00273
00274
00275 if (GET_MAJOR_VERSION(old_cluster.major_version) < 803)
00276 pg_log(PG_FATAL, "This utility can only upgrade from PostgreSQL version 8.3 and later.\n");
00277
00278
00279 if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
00280 pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version %s.\n",
00281 PG_MAJORVERSION);
00282
00283
00284
00285
00286
00287
00288 if (old_cluster.major_version > new_cluster.major_version)
00289 pg_log(PG_FATAL, "This utility cannot be used to downgrade to older major PostgreSQL versions.\n");
00290
00291
00292 get_bin_version(&old_cluster);
00293 get_bin_version(&new_cluster);
00294
00295
00296 if (GET_MAJOR_VERSION(old_cluster.major_version) !=
00297 GET_MAJOR_VERSION(old_cluster.bin_version))
00298 pg_log(PG_FATAL,
00299 "Old cluster data and binary directories are from different major versions.\n");
00300 if (GET_MAJOR_VERSION(new_cluster.major_version) !=
00301 GET_MAJOR_VERSION(new_cluster.bin_version))
00302 pg_log(PG_FATAL,
00303 "New cluster data and binary directories are from different major versions.\n");
00304
00305 check_ok();
00306 }
00307
00308
00309 void
00310 check_cluster_compatibility(bool live_check)
00311 {
00312
00313 get_control_data(&old_cluster, live_check);
00314 get_control_data(&new_cluster, false);
00315 check_control_data(&old_cluster.controldata, &new_cluster.controldata);
00316
00317
00318 if (GET_MAJOR_VERSION(new_cluster.major_version) == 900 &&
00319 new_cluster.controldata.cat_ver < TABLE_SPACE_SUBDIRS_CAT_VER)
00320 pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version 9.0 after 2010-01-11\n"
00321 "because of backend API changes made during development.\n");
00322
00323
00324 if (live_check && GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
00325 old_cluster.port == DEF_PGUPORT)
00326 pg_log(PG_FATAL, "When checking a pre-PG 9.1 live old server, "
00327 "you must specify the old server's port number.\n");
00328
00329 if (live_check && old_cluster.port == new_cluster.port)
00330 pg_log(PG_FATAL, "When checking a live server, "
00331 "the old and new port numbers must be different.\n");
00332 }
00333
00334
00335
00336
00337
00338
00339
00340 static void
00341 set_locale_and_encoding(ClusterInfo *cluster)
00342 {
00343 ControlData *ctrl = &cluster->controldata;
00344 PGconn *conn;
00345 PGresult *res;
00346 int i_encoding;
00347 int cluster_version = cluster->major_version;
00348
00349 conn = connectToServer(cluster, "template1");
00350
00351
00352 if (cluster_version >= 80400)
00353 {
00354 int i_datcollate;
00355 int i_datctype;
00356
00357 res = executeQueryOrDie(conn,
00358 "SELECT datcollate, datctype "
00359 "FROM pg_catalog.pg_database "
00360 "WHERE datname = 'template0' ");
00361 assert(PQntuples(res) == 1);
00362
00363 i_datcollate = PQfnumber(res, "datcollate");
00364 i_datctype = PQfnumber(res, "datctype");
00365
00366 if (GET_MAJOR_VERSION(cluster->major_version) < 902)
00367 {
00368
00369
00370
00371
00372
00373 ctrl->lc_collate = get_canonical_locale_name(LC_COLLATE,
00374 pg_strdup(PQgetvalue(res, 0, i_datcollate)));
00375 ctrl->lc_ctype = get_canonical_locale_name(LC_CTYPE,
00376 pg_strdup(PQgetvalue(res, 0, i_datctype)));
00377 }
00378 else
00379 {
00380 ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate));
00381 ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype));
00382 }
00383
00384 PQclear(res);
00385 }
00386
00387 res = executeQueryOrDie(conn,
00388 "SELECT pg_catalog.pg_encoding_to_char(encoding) "
00389 "FROM pg_catalog.pg_database "
00390 "WHERE datname = 'template0' ");
00391 assert(PQntuples(res) == 1);
00392
00393 i_encoding = PQfnumber(res, "pg_encoding_to_char");
00394 ctrl->encoding = pg_strdup(PQgetvalue(res, 0, i_encoding));
00395
00396 PQclear(res);
00397
00398 PQfinish(conn);
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408 static void
00409 check_locale_and_encoding(ControlData *oldctrl,
00410 ControlData *newctrl)
00411 {
00412
00413
00414
00415
00416
00417 if (pg_strcasecmp(oldctrl->lc_collate, newctrl->lc_collate) != 0)
00418 pg_log(PG_FATAL,
00419 "lc_collate cluster values do not match: old \"%s\", new \"%s\"\n",
00420 oldctrl->lc_collate, newctrl->lc_collate);
00421 if (pg_strcasecmp(oldctrl->lc_ctype, newctrl->lc_ctype) != 0)
00422 pg_log(PG_FATAL,
00423 "lc_ctype cluster values do not match: old \"%s\", new \"%s\"\n",
00424 oldctrl->lc_ctype, newctrl->lc_ctype);
00425 if (pg_strcasecmp(oldctrl->encoding, newctrl->encoding) != 0)
00426 pg_log(PG_FATAL,
00427 "encoding cluster values do not match: old \"%s\", new \"%s\"\n",
00428 oldctrl->encoding, newctrl->encoding);
00429 }
00430
00431
00432 static void
00433 check_new_cluster_is_empty(void)
00434 {
00435 int dbnum;
00436
00437 for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
00438 {
00439 int relnum;
00440 RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
00441
00442 for (relnum = 0; relnum < rel_arr->nrels;
00443 relnum++)
00444 {
00445
00446 if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
00447 pg_log(PG_FATAL, "New cluster database \"%s\" is not empty\n",
00448 new_cluster.dbarr.dbs[dbnum].db_name);
00449 }
00450 }
00451
00452 }
00453
00454
00455
00456
00457
00458
00459
00460 void
00461 create_script_for_cluster_analyze(char **analyze_script_file_name)
00462 {
00463 FILE *script = NULL;
00464
00465 *analyze_script_file_name = pg_malloc(MAXPGPATH);
00466
00467 prep_status("Creating script to analyze new cluster");
00468
00469 snprintf(*analyze_script_file_name, MAXPGPATH, "analyze_new_cluster.%s",
00470 SCRIPT_EXT);
00471
00472 if ((script = fopen_priv(*analyze_script_file_name, "w")) == NULL)
00473 pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
00474 *analyze_script_file_name, getErrorText(errno));
00475
00476 #ifndef WIN32
00477
00478 fprintf(script, "#!/bin/sh\n\n");
00479 #else
00480
00481 fprintf(script, "@echo off\n");
00482 #endif
00483
00484 fprintf(script, "echo %sThis script will generate minimal optimizer statistics rapidly%s\n",
00485 ECHO_QUOTE, ECHO_QUOTE);
00486 fprintf(script, "echo %sso your system is usable, and then gather statistics twice more%s\n",
00487 ECHO_QUOTE, ECHO_QUOTE);
00488 fprintf(script, "echo %swith increasing accuracy. When it is done, your system will%s\n",
00489 ECHO_QUOTE, ECHO_QUOTE);
00490 fprintf(script, "echo %shave the default level of optimizer statistics.%s\n",
00491 ECHO_QUOTE, ECHO_QUOTE);
00492 fprintf(script, "echo%s\n\n", ECHO_BLANK);
00493
00494 fprintf(script, "echo %sIf you have used ALTER TABLE to modify the statistics target for%s\n",
00495 ECHO_QUOTE, ECHO_QUOTE);
00496 fprintf(script, "echo %sany tables, you might want to remove them and restore them after%s\n",
00497 ECHO_QUOTE, ECHO_QUOTE);
00498 fprintf(script, "echo %srunning this script because they will delay fast statistics generation.%s\n",
00499 ECHO_QUOTE, ECHO_QUOTE);
00500 fprintf(script, "echo%s\n\n", ECHO_BLANK);
00501
00502 fprintf(script, "echo %sIf you would like default statistics as quickly as possible, cancel%s\n",
00503 ECHO_QUOTE, ECHO_QUOTE);
00504 fprintf(script, "echo %sthis script and run:%s\n",
00505 ECHO_QUOTE, ECHO_QUOTE);
00506 fprintf(script, "echo %s \"%s/vacuumdb\" --all %s%s\n", ECHO_QUOTE, new_cluster.bindir,
00507
00508 (GET_MAJOR_VERSION(old_cluster.major_version) >= 804) ?
00509 "--analyze-only" : "--analyze", ECHO_QUOTE);
00510 fprintf(script, "echo%s\n\n", ECHO_BLANK);
00511
00512 #ifndef WIN32
00513 fprintf(script, "sleep 2\n");
00514 fprintf(script, "PGOPTIONS='-c default_statistics_target=1 -c vacuum_cost_delay=0'\n");
00515
00516 fprintf(script, "export PGOPTIONS\n");
00517 #else
00518 fprintf(script, "REM simulate sleep 2\n");
00519 fprintf(script, "PING 1.1.1.1 -n 1 -w 2000 > nul\n");
00520 fprintf(script, "SET PGOPTIONS=-c default_statistics_target=1 -c vacuum_cost_delay=0\n");
00521 #endif
00522
00523 fprintf(script, "echo %sGenerating minimal optimizer statistics (1 target)%s\n",
00524 ECHO_QUOTE, ECHO_QUOTE);
00525 fprintf(script, "echo %s--------------------------------------------------%s\n",
00526 ECHO_QUOTE, ECHO_QUOTE);
00527 fprintf(script, "\"%s/vacuumdb\" --all --analyze-only\n", new_cluster.bindir);
00528 fprintf(script, "echo%s\n", ECHO_BLANK);
00529 fprintf(script, "echo %sThe server is now available with minimal optimizer statistics.%s\n",
00530 ECHO_QUOTE, ECHO_QUOTE);
00531 fprintf(script, "echo %sQuery performance will be optimal once this script completes.%s\n",
00532 ECHO_QUOTE, ECHO_QUOTE);
00533 fprintf(script, "echo%s\n\n", ECHO_BLANK);
00534
00535 #ifndef WIN32
00536 fprintf(script, "sleep 2\n");
00537 fprintf(script, "PGOPTIONS='-c default_statistics_target=10'\n");
00538 #else
00539 fprintf(script, "REM simulate sleep\n");
00540 fprintf(script, "PING 1.1.1.1 -n 1 -w 2000 > nul\n");
00541 fprintf(script, "SET PGOPTIONS=-c default_statistics_target=10\n");
00542 #endif
00543
00544 fprintf(script, "echo %sGenerating medium optimizer statistics (10 targets)%s\n",
00545 ECHO_QUOTE, ECHO_QUOTE);
00546 fprintf(script, "echo %s---------------------------------------------------%s\n",
00547 ECHO_QUOTE, ECHO_QUOTE);
00548 fprintf(script, "\"%s/vacuumdb\" --all --analyze-only\n", new_cluster.bindir);
00549 fprintf(script, "echo%s\n\n", ECHO_BLANK);
00550
00551 #ifndef WIN32
00552 fprintf(script, "unset PGOPTIONS\n");
00553 #else
00554 fprintf(script, "SET PGOPTIONS\n");
00555 #endif
00556
00557 fprintf(script, "echo %sGenerating default (full) optimizer statistics (100 targets?)%s\n",
00558 ECHO_QUOTE, ECHO_QUOTE);
00559 fprintf(script, "echo %s-------------------------------------------------------------%s\n",
00560 ECHO_QUOTE, ECHO_QUOTE);
00561 fprintf(script, "\"%s/vacuumdb\" --all %s\n", new_cluster.bindir,
00562
00563 (GET_MAJOR_VERSION(old_cluster.major_version) >= 804) ?
00564 "--analyze-only" : "--analyze");
00565
00566 fprintf(script, "echo%s\n\n", ECHO_BLANK);
00567 fprintf(script, "echo %sDone%s\n",
00568 ECHO_QUOTE, ECHO_QUOTE);
00569
00570 fclose(script);
00571
00572 #ifndef WIN32
00573 if (chmod(*analyze_script_file_name, S_IRWXU) != 0)
00574 pg_log(PG_FATAL, "Could not add execute permission to file \"%s\": %s\n",
00575 *analyze_script_file_name, getErrorText(errno));
00576 #endif
00577
00578 check_ok();
00579 }
00580
00581
00582
00583
00584
00585
00586
00587 void
00588 create_script_for_old_cluster_deletion(char **deletion_script_file_name)
00589 {
00590 FILE *script = NULL;
00591 int tblnum;
00592 char old_cluster_pgdata[MAXPGPATH];
00593
00594 *deletion_script_file_name = pg_malloc(MAXPGPATH);
00595
00596 snprintf(*deletion_script_file_name, MAXPGPATH, "delete_old_cluster.%s",
00597 SCRIPT_EXT);
00598
00599
00600
00601
00602
00603
00604 strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
00605 canonicalize_path(old_cluster_pgdata);
00606 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
00607 {
00608 char old_tablespace_dir[MAXPGPATH];
00609
00610 strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
00611 canonicalize_path(old_tablespace_dir);
00612 if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
00613 {
00614
00615 unlink(*deletion_script_file_name);
00616 pg_free(*deletion_script_file_name);
00617 *deletion_script_file_name = NULL;
00618 return;
00619 }
00620 }
00621
00622 prep_status("Creating script to delete old cluster");
00623
00624 if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
00625 pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
00626 *deletion_script_file_name, getErrorText(errno));
00627
00628 #ifndef WIN32
00629
00630 fprintf(script, "#!/bin/sh\n\n");
00631 #endif
00632
00633
00634 fprintf(script, RMDIR_CMD " %s\n", fix_path_separator(old_cluster.pgdata));
00635
00636
00637 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
00638 {
00639
00640
00641
00642
00643 if (strlen(old_cluster.tablespace_suffix) == 0)
00644 {
00645
00646 int dbnum;
00647
00648 fprintf(script, "\n");
00649
00650 if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
00651 fprintf(script, RM_CMD " %s%s%cPG_VERSION\n",
00652 fix_path_separator(os_info.old_tablespaces[tblnum]),
00653 fix_path_separator(old_cluster.tablespace_suffix),
00654 PATH_SEPARATOR);
00655
00656 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
00657 {
00658 fprintf(script, RMDIR_CMD " %s%s%c%d\n",
00659 fix_path_separator(os_info.old_tablespaces[tblnum]),
00660 fix_path_separator(old_cluster.tablespace_suffix),
00661 PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid);
00662 }
00663 }
00664 else
00665
00666
00667
00668
00669
00670 fprintf(script, RMDIR_CMD " %s%s\n",
00671 fix_path_separator(os_info.old_tablespaces[tblnum]),
00672 fix_path_separator(old_cluster.tablespace_suffix));
00673 }
00674
00675 fclose(script);
00676
00677 #ifndef WIN32
00678 if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
00679 pg_log(PG_FATAL, "Could not add execute permission to file \"%s\": %s\n",
00680 *deletion_script_file_name, getErrorText(errno));
00681 #endif
00682
00683 check_ok();
00684 }
00685
00686
00687
00688
00689
00690
00691
00692 static void
00693 check_is_super_user(ClusterInfo *cluster)
00694 {
00695 PGresult *res;
00696 PGconn *conn = connectToServer(cluster, "template1");
00697
00698 prep_status("Checking database user is a superuser");
00699
00700
00701 res = executeQueryOrDie(conn,
00702 "SELECT rolsuper, oid "
00703 "FROM pg_catalog.pg_roles "
00704 "WHERE rolname = current_user");
00705
00706 if (PQntuples(res) != 1 || strcmp(PQgetvalue(res, 0, 0), "t") != 0)
00707 pg_log(PG_FATAL, "database user \"%s\" is not a superuser\n",
00708 os_info.user);
00709
00710 cluster->install_role_oid = atooid(PQgetvalue(res, 0, 1));
00711
00712 PQclear(res);
00713
00714 res = executeQueryOrDie(conn,
00715 "SELECT COUNT(*) "
00716 "FROM pg_catalog.pg_roles ");
00717
00718 if (PQntuples(res) != 1)
00719 pg_log(PG_FATAL, "could not determine the number of users\n");
00720
00721 cluster->role_count = atoi(PQgetvalue(res, 0, 0));
00722
00723 PQclear(res);
00724
00725 PQfinish(conn);
00726
00727 check_ok();
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737 static void
00738 check_for_prepared_transactions(ClusterInfo *cluster)
00739 {
00740 PGresult *res;
00741 PGconn *conn = connectToServer(cluster, "template1");
00742
00743 prep_status("Checking for prepared transactions");
00744
00745 res = executeQueryOrDie(conn,
00746 "SELECT * "
00747 "FROM pg_catalog.pg_prepared_xacts");
00748
00749 if (PQntuples(res) != 0)
00750 pg_log(PG_FATAL, "The %s cluster contains prepared transactions\n",
00751 CLUSTER_NAME(cluster));
00752
00753 PQclear(res);
00754
00755 PQfinish(conn);
00756
00757 check_ok();
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 static void
00769 check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
00770 {
00771 int dbnum;
00772 FILE *script = NULL;
00773 bool found = false;
00774 char output_path[MAXPGPATH];
00775
00776 prep_status("Checking for contrib/isn with bigint-passing mismatch");
00777
00778 if (old_cluster.controldata.float8_pass_by_value ==
00779 new_cluster.controldata.float8_pass_by_value)
00780 {
00781
00782 check_ok();
00783 return;
00784 }
00785
00786 snprintf(output_path, sizeof(output_path),
00787 "contrib_isn_and_int8_pass_by_value.txt");
00788
00789 for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
00790 {
00791 PGresult *res;
00792 bool db_used = false;
00793 int ntups;
00794 int rowno;
00795 int i_nspname,
00796 i_proname;
00797 DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
00798 PGconn *conn = connectToServer(cluster, active_db->db_name);
00799
00800
00801 res = executeQueryOrDie(conn,
00802 "SELECT n.nspname, p.proname "
00803 "FROM pg_catalog.pg_proc p, "
00804 " pg_catalog.pg_namespace n "
00805 "WHERE p.pronamespace = n.oid AND "
00806 " p.probin = '$libdir/isn'");
00807
00808 ntups = PQntuples(res);
00809 i_nspname = PQfnumber(res, "nspname");
00810 i_proname = PQfnumber(res, "proname");
00811 for (rowno = 0; rowno < ntups; rowno++)
00812 {
00813 found = true;
00814 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
00815 pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
00816 output_path, getErrorText(errno));
00817 if (!db_used)
00818 {
00819 fprintf(script, "Database: %s\n", active_db->db_name);
00820 db_used = true;
00821 }
00822 fprintf(script, " %s.%s\n",
00823 PQgetvalue(res, rowno, i_nspname),
00824 PQgetvalue(res, rowno, i_proname));
00825 }
00826
00827 PQclear(res);
00828
00829 PQfinish(conn);
00830 }
00831
00832 if (script)
00833 fclose(script);
00834
00835 if (found)
00836 {
00837 pg_log(PG_REPORT, "fatal\n");
00838 pg_log(PG_FATAL,
00839 "Your installation contains \"contrib/isn\" functions which rely on the\n"
00840 "bigint data type. Your old and new clusters pass bigint values\n"
00841 "differently so this cluster cannot currently be upgraded. You can\n"
00842 "manually upgrade databases that use \"contrib/isn\" facilities and remove\n"
00843 "\"contrib/isn\" from the old cluster and restart the upgrade. A list of\n"
00844 "the problem functions is in the file:\n"
00845 " %s\n\n", output_path);
00846 }
00847 else
00848 check_ok();
00849 }
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 static void
00864 check_for_reg_data_type_usage(ClusterInfo *cluster)
00865 {
00866 int dbnum;
00867 FILE *script = NULL;
00868 bool found = false;
00869 char output_path[MAXPGPATH];
00870
00871 prep_status("Checking for reg* system OID user data types");
00872
00873 snprintf(output_path, sizeof(output_path), "tables_using_reg.txt");
00874
00875 for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
00876 {
00877 PGresult *res;
00878 bool db_used = false;
00879 int ntups;
00880 int rowno;
00881 int i_nspname,
00882 i_relname,
00883 i_attname;
00884 DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
00885 PGconn *conn = connectToServer(cluster, active_db->db_name);
00886
00887
00888
00889
00890
00891
00892 res = executeQueryOrDie(conn,
00893 "SELECT n.nspname, c.relname, a.attname "
00894 "FROM pg_catalog.pg_class c, "
00895 " pg_catalog.pg_namespace n, "
00896 " pg_catalog.pg_attribute a "
00897 "WHERE c.oid = a.attrelid AND "
00898 " NOT a.attisdropped AND "
00899 " a.atttypid IN ( "
00900 " 'pg_catalog.regproc'::pg_catalog.regtype, "
00901 " 'pg_catalog.regprocedure'::pg_catalog.regtype, "
00902 " 'pg_catalog.regoper'::pg_catalog.regtype, "
00903 " 'pg_catalog.regoperator'::pg_catalog.regtype, "
00904
00905
00906 " 'pg_catalog.regconfig'::pg_catalog.regtype, "
00907 " 'pg_catalog.regdictionary'::pg_catalog.regtype) AND "
00908 " c.relnamespace = n.oid AND "
00909 " n.nspname != 'pg_catalog' AND "
00910 " n.nspname != 'information_schema'");
00911
00912 ntups = PQntuples(res);
00913 i_nspname = PQfnumber(res, "nspname");
00914 i_relname = PQfnumber(res, "relname");
00915 i_attname = PQfnumber(res, "attname");
00916 for (rowno = 0; rowno < ntups; rowno++)
00917 {
00918 found = true;
00919 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
00920 pg_log(PG_FATAL, "Could not open file \"%s\": %s\n",
00921 output_path, getErrorText(errno));
00922 if (!db_used)
00923 {
00924 fprintf(script, "Database: %s\n", active_db->db_name);
00925 db_used = true;
00926 }
00927 fprintf(script, " %s.%s.%s\n",
00928 PQgetvalue(res, rowno, i_nspname),
00929 PQgetvalue(res, rowno, i_relname),
00930 PQgetvalue(res, rowno, i_attname));
00931 }
00932
00933 PQclear(res);
00934
00935 PQfinish(conn);
00936 }
00937
00938 if (script)
00939 fclose(script);
00940
00941 if (found)
00942 {
00943 pg_log(PG_REPORT, "fatal\n");
00944 pg_log(PG_FATAL,
00945 "Your installation contains one of the reg* data types in user tables.\n"
00946 "These data types reference system OIDs that are not preserved by\n"
00947 "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
00948 "remove the problem tables and restart the upgrade. A list of the problem\n"
00949 "columns is in the file:\n"
00950 " %s\n\n", output_path);
00951 }
00952 else
00953 check_ok();
00954 }
00955
00956
00957 static void
00958 get_bin_version(ClusterInfo *cluster)
00959 {
00960 char cmd[MAXPGPATH],
00961 cmd_output[MAX_STRING];
00962 FILE *output;
00963 int pre_dot,
00964 post_dot;
00965
00966 snprintf(cmd, sizeof(cmd), "\"%s/pg_ctl\" --version", cluster->bindir);
00967
00968 if ((output = popen(cmd, "r")) == NULL ||
00969 fgets(cmd_output, sizeof(cmd_output), output) == NULL)
00970 pg_log(PG_FATAL, "Could not get pg_ctl version data using %s: %s\n",
00971 cmd, getErrorText(errno));
00972
00973 pclose(output);
00974
00975
00976 if (strchr(cmd_output, '\n') != NULL)
00977 *strchr(cmd_output, '\n') = '\0';
00978
00979 if (sscanf(cmd_output, "%*s %*s %d.%d", &pre_dot, &post_dot) != 2)
00980 pg_log(PG_FATAL, "could not get version from %s\n", cmd);
00981
00982 cluster->bin_version = (pre_dot * 100 + post_dot) * 100;
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992 static char *
00993 get_canonical_locale_name(int category, const char *locale)
00994 {
00995 char *save;
00996 char *res;
00997
00998 save = setlocale(category, NULL);
00999 if (!save)
01000 pg_log(PG_FATAL, "failed to get the current locale\n");
01001
01002
01003 save = pg_strdup(save);
01004
01005
01006 res = setlocale(category, locale);
01007
01008 if (!res)
01009 pg_log(PG_FATAL, "failed to get system local name for \"%s\"\n", res);
01010
01011 res = pg_strdup(res);
01012
01013
01014 if (!setlocale(category, save))
01015 pg_log(PG_FATAL, "failed to restore old locale \"%s\"\n", save);
01016
01017 pg_free(save);
01018
01019 return res;
01020 }