]> granicus.if.org Git - postgresql/blob - contrib/pg_upgrade/check.c
In pg_upgrade, remove use of whichCluster, and just pass old/new cluster
[postgresql] / contrib / pg_upgrade / check.c
1 /*
2  *      check.c
3  *
4  *      server checks and output routines
5  *
6  *      Copyright (c) 2010, PostgreSQL Global Development Group
7  *      contrib/pg_upgrade/check.c
8  */
9
10 #include "pg_upgrade.h"
11
12
13 static void set_locale_and_encoding(ClusterInfo *cluster);
14 static void check_new_db_is_empty(void);
15 static void check_locale_and_encoding(ControlData *oldctrl,
16                                                   ControlData *newctrl);
17 static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
18 static void check_for_reg_data_type_usage(ClusterInfo *cluster);
19
20
21 void
22 output_check_banner(bool *live_check)
23 {
24         if (user_opts.check && is_server_running(old_cluster.pgdata))
25         {
26                 *live_check = true;
27                 if (old_cluster.port == new_cluster.port)
28                         pg_log(PG_FATAL, "When checking a live server, "
29                                    "the old and new port numbers must be different.\n");
30                 pg_log(PG_REPORT, "PerForming Consistency Checks on Old Live Server\n");
31                 pg_log(PG_REPORT, "------------------------------------------------\n");
32         }
33         else
34         {
35                 pg_log(PG_REPORT, "Performing Consistency Checks\n");
36                 pg_log(PG_REPORT, "-----------------------------\n");
37         }
38 }
39
40
41 void
42 check_old_cluster(bool live_check,
43                                   char **sequence_script_file_name)
44 {
45         /* -- OLD -- */
46
47         if (!live_check)
48                 start_postmaster(&old_cluster, false);
49
50         set_locale_and_encoding(&old_cluster);
51
52         get_pg_database_relfilenode(&old_cluster);
53
54         /* Extract a list of databases and tables from the old cluster */
55         get_db_and_rel_infos(&old_cluster);
56
57         init_tablespaces();
58
59         get_loadable_libraries();
60
61
62         /*
63          * Check for various failure cases
64          */
65
66         check_for_reg_data_type_usage(&old_cluster);
67         check_for_isn_and_int8_passing_mismatch(&old_cluster);
68
69         /* old = PG 8.3 checks? */
70         if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
71         {
72                 old_8_3_check_for_name_data_type_usage(&old_cluster);
73                 old_8_3_check_for_tsquery_usage(&old_cluster);
74                 if (user_opts.check)
75                 {
76                         old_8_3_rebuild_tsvector_tables(&old_cluster, true);
77                         old_8_3_invalidate_hash_gin_indexes(&old_cluster, true);
78                         old_8_3_invalidate_bpchar_pattern_ops_indexes(&old_cluster, true);
79                 }
80                 else
81
82                         /*
83                          * While we have the old server running, create the script to
84                          * properly restore its sequence values but we report this at the
85                          * end.
86                          */
87                         *sequence_script_file_name =
88                                 old_8_3_create_sequence_script(&old_cluster);
89         }
90
91         /* Pre-PG 9.0 had no large object permissions */
92         if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
93                 new_9_0_populate_pg_largeobject_metadata(&old_cluster, true);
94
95         /*
96          * While not a check option, we do this now because this is the only time
97          * the old server is running.
98          */
99         if (!user_opts.check)
100         {
101                 generate_old_dump();
102                 split_old_dump();
103         }
104
105         if (!live_check)
106                 stop_postmaster(false, false);
107 }
108
109
110 void
111 check_new_cluster(void)
112 {
113         set_locale_and_encoding(&new_cluster);
114
115         check_new_db_is_empty();
116
117         check_loadable_libraries();
118
119         check_locale_and_encoding(&old_cluster.controldata, &new_cluster.controldata);
120
121         if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
122                 check_hard_link();
123 }
124
125
126 void
127 report_clusters_compatible(void)
128 {
129         if (user_opts.check)
130         {
131                 pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
132                 /* stops new cluster */
133                 stop_postmaster(false, false);
134                 exit_nicely(false);
135         }
136
137         pg_log(PG_REPORT, "\n"
138                    "| If pg_upgrade fails after this point, you must\n"
139                    "| re-initdb the new cluster before continuing.\n"
140                    "| You will also need to remove the \".old\" suffix\n"
141                    "| from %s/global/pg_control.old.\n", old_cluster.pgdata);
142 }
143
144
145 void
146 issue_warnings(char *sequence_script_file_name)
147 {
148         /* old = PG 8.3 warnings? */
149         if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
150         {
151                 start_postmaster(&new_cluster, true);
152
153                 /* restore proper sequence values using file created from old server */
154                 if (sequence_script_file_name)
155                 {
156                         prep_status("Adjusting sequences");
157                         exec_prog(true,
158                                           SYSTEMQUOTE "\"%s/psql\" --set ON_ERROR_STOP=on "
159                                           "--no-psqlrc --port %d --username \"%s\" "
160                                           "-f \"%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
161                                           new_cluster.bindir, new_cluster.port, os_info.user,
162                                           sequence_script_file_name, log_opts.filename);
163                         unlink(sequence_script_file_name);
164                         check_ok();
165                 }
166
167                 old_8_3_rebuild_tsvector_tables(&new_cluster, false);
168                 old_8_3_invalidate_hash_gin_indexes(&new_cluster, false);
169                 old_8_3_invalidate_bpchar_pattern_ops_indexes(&new_cluster, false);
170                 stop_postmaster(false, true);
171         }
172
173         /* Create dummy large object permissions for old < PG 9.0? */
174         if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
175         {
176                 start_postmaster(&new_cluster, true);
177                 new_9_0_populate_pg_largeobject_metadata(&new_cluster, false);
178                 stop_postmaster(false, true);
179         }
180 }
181
182
183 void
184 output_completion_banner(char *deletion_script_file_name)
185 {
186         /* Did we copy the free space files? */
187         if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
188                 pg_log(PG_REPORT,
189                            "| Optimizer statistics is not transferred by pg_upgrade\n"
190                            "| so consider running:\n"
191                            "| \tvacuumdb --all --analyze-only\n"
192                            "| on the newly-upgraded cluster.\n\n");
193         else
194                 pg_log(PG_REPORT,
195                            "| Optimizer statistics and free space information\n"
196                            "| are not transferred by pg_upgrade so consider\n"
197                            "| running:\n"
198                            "| \tvacuumdb --all --analyze\n"
199                            "| on the newly-upgraded cluster.\n\n");
200
201         pg_log(PG_REPORT,
202                    "| Running this script will delete the old cluster's data files:\n"
203                    "| \t%s\n",
204                    deletion_script_file_name);
205 }
206
207
208 void
209 check_cluster_versions(void)
210 {
211         /* get old and new cluster versions */
212         old_cluster.major_version = get_major_server_version(&old_cluster, &old_cluster.major_version_str);
213         new_cluster.major_version = get_major_server_version(&new_cluster, &new_cluster.major_version_str);
214
215         /* We allow upgrades from/to the same major version for alpha/beta upgrades */
216
217         if (GET_MAJOR_VERSION(old_cluster.major_version) < 803)
218                 pg_log(PG_FATAL, "This utility can only upgrade from PostgreSQL version 8.3 and later.\n");
219
220         /* Only current PG version is supported as a target */
221         if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
222                 pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version %s.\n",
223                            PG_MAJORVERSION);
224
225         /*
226          * We can't allow downgrading because we use the target pg_dumpall, and
227          * pg_dumpall cannot operate on new datbase versions, only older versions.
228          */
229         if (old_cluster.major_version > new_cluster.major_version)
230                 pg_log(PG_FATAL, "This utility cannot be used to downgrade to older major PostgreSQL versions.\n");
231 }
232
233
234 void
235 check_cluster_compatibility(bool live_check)
236 {
237         char            libfile[MAXPGPATH];
238         FILE       *lib_test;
239
240         /*
241          * Test pg_upgrade_support.so is in the proper place.    We cannot copy it
242          * ourselves because install directories are typically root-owned.
243          */
244         snprintf(libfile, sizeof(libfile), "%s/pg_upgrade_support%s", new_cluster.libpath,
245                          DLSUFFIX);
246
247         if ((lib_test = fopen(libfile, "r")) == NULL)
248                 pg_log(PG_FATAL,
249                            "\npg_upgrade_support%s must be created and installed in %s\n", DLSUFFIX, libfile);
250         else
251                 fclose(lib_test);
252
253         /* get/check pg_control data of servers */
254         get_control_data(&old_cluster, live_check);
255         get_control_data(&new_cluster, false);
256         check_control_data(&old_cluster.controldata, &new_cluster.controldata);
257
258         /* Is it 9.0 but without tablespace directories? */
259         if (GET_MAJOR_VERSION(new_cluster.major_version) == 900 &&
260                 new_cluster.controldata.cat_ver < TABLE_SPACE_SUBDIRS)
261                 pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version 9.0 after 2010-01-11\n"
262                            "because of backend API changes made during development.\n");
263 }
264
265
266 /*
267  * set_locale_and_encoding()
268  *
269  * query the database to get the template0 locale
270  */
271 static void
272 set_locale_and_encoding(ClusterInfo *cluster)
273 {
274         ControlData *ctrl = &cluster->controldata;
275         PGconn     *conn;
276         PGresult   *res;
277         int                     i_encoding;
278         int                     cluster_version = cluster->major_version;
279
280         conn = connectToServer(cluster, "template1");
281
282         /* for pg < 80400, we got the values from pg_controldata */
283         if (cluster_version >= 80400)
284         {
285                 int                     i_datcollate;
286                 int                     i_datctype;
287
288                 res = executeQueryOrDie(conn,
289                                                                 "SELECT datcollate, datctype "
290                                                                 "FROM   pg_catalog.pg_database "
291                                                                 "WHERE  datname = 'template0' ");
292                 assert(PQntuples(res) == 1);
293
294                 i_datcollate = PQfnumber(res, "datcollate");
295                 i_datctype = PQfnumber(res, "datctype");
296
297                 ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate));
298                 ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype));
299
300                 PQclear(res);
301         }
302
303         res = executeQueryOrDie(conn,
304                                                         "SELECT pg_catalog.pg_encoding_to_char(encoding) "
305                                                         "FROM   pg_catalog.pg_database "
306                                                         "WHERE  datname = 'template0' ");
307         assert(PQntuples(res) == 1);
308
309         i_encoding = PQfnumber(res, "pg_encoding_to_char");
310         ctrl->encoding = pg_strdup(PQgetvalue(res, 0, i_encoding));
311
312         PQclear(res);
313
314         PQfinish(conn);
315 }
316
317
318 /*
319  * check_locale_and_encoding()
320  *
321  *      locale is not in pg_controldata in 8.4 and later so
322  *      we probably had to get via a database query.
323  */
324 static void
325 check_locale_and_encoding(ControlData *oldctrl,
326                                                   ControlData *newctrl)
327 {
328         if (strcmp(oldctrl->lc_collate, newctrl->lc_collate) != 0)
329                 pg_log(PG_FATAL,
330                            "old and new cluster lc_collate values do not match\n");
331         if (strcmp(oldctrl->lc_ctype, newctrl->lc_ctype) != 0)
332                 pg_log(PG_FATAL,
333                            "old and new cluster lc_ctype values do not match\n");
334         if (strcmp(oldctrl->encoding, newctrl->encoding) != 0)
335                 pg_log(PG_FATAL,
336                            "old and new cluster encoding values do not match\n");
337 }
338
339
340 static void
341 check_new_db_is_empty(void)
342 {
343         int                     dbnum;
344         bool            found = false;
345
346         get_db_and_rel_infos(&new_cluster);
347
348         for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
349         {
350                 int                     relnum;
351                 RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
352
353                 for (relnum = 0; relnum < rel_arr->nrels;
354                          relnum++)
355                 {
356                         /* pg_largeobject and its index should be skipped */
357                         if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
358                         {
359                                 found = true;
360                                 break;
361                         }
362                 }
363         }
364
365         dbarr_free(&new_cluster.dbarr);
366
367         if (found)
368                 pg_log(PG_FATAL, "New cluster is not empty; exiting\n");
369 }
370
371
372 /*
373  * create_script_for_old_cluster_deletion()
374  *
375  *      This is particularly useful for tablespace deletion.
376  */
377 void
378 create_script_for_old_cluster_deletion(
379                                                                            char **deletion_script_file_name)
380 {
381         FILE       *script = NULL;
382         int                     tblnum;
383
384         *deletion_script_file_name = pg_malloc(MAXPGPATH);
385
386         prep_status("Creating script to delete old cluster");
387
388         snprintf(*deletion_script_file_name, MAXPGPATH, "%s/delete_old_cluster.%s",
389                          os_info.cwd, SCRIPT_EXT);
390
391         if ((script = fopen(*deletion_script_file_name, "w")) == NULL)
392                 pg_log(PG_FATAL, "Could not create necessary file:  %s\n",
393                            *deletion_script_file_name);
394
395 #ifndef WIN32
396         /* add shebang header */
397         fprintf(script, "#!/bin/sh\n\n");
398 #endif
399
400         /* delete old cluster's default tablespace */
401         fprintf(script, RMDIR_CMD " %s\n", old_cluster.pgdata);
402
403         /* delete old cluster's alternate tablespaces */
404         for (tblnum = 0; tblnum < os_info.num_tablespaces; tblnum++)
405         {
406                 /*
407                  * Do the old cluster's per-database directories share a directory
408                  * with a new version-specific tablespace?
409                  */
410                 if (strlen(old_cluster.tablespace_suffix) == 0)
411                 {
412                         /* delete per-database directories */
413                         int                     dbnum;
414
415                         fprintf(script, "\n");
416                         /* remove PG_VERSION? */
417                         if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
418                                 fprintf(script, RM_CMD " %s%s/PG_VERSION\n",
419                                  os_info.tablespaces[tblnum], old_cluster.tablespace_suffix);
420
421                         for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
422                         {
423                                 fprintf(script, RMDIR_CMD " %s%s/%d\n",
424                                   os_info.tablespaces[tblnum], old_cluster.tablespace_suffix,
425                                                 old_cluster.dbarr.dbs[dbnum].db_oid);
426                         }
427                 }
428                 else
429
430                         /*
431                          * Simply delete the tablespace directory, which might be ".old"
432                          * or a version-specific subdirectory.
433                          */
434                         fprintf(script, RMDIR_CMD " %s%s\n",
435                                  os_info.tablespaces[tblnum], old_cluster.tablespace_suffix);
436         }
437
438         fclose(script);
439
440 #ifndef WIN32
441         if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
442                 pg_log(PG_FATAL, "Could not add execute permission to file:  %s\n",
443                            *deletion_script_file_name);
444 #endif
445
446         check_ok();
447 }
448
449
450 /*
451  *      check_for_isn_and_int8_passing_mismatch()
452  *
453  *      /contrib/isn relies on data type int8, and in 8.4 int8 can now be passed
454  *      by value.  The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
455  *      it must match for the old and new servers.
456  */
457 void
458 check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
459 {
460         int                     dbnum;
461         FILE       *script = NULL;
462         bool            found = false;
463         char            output_path[MAXPGPATH];
464
465         prep_status("Checking for /contrib/isn with bigint-passing mismatch");
466
467         if (old_cluster.controldata.float8_pass_by_value ==
468                 new_cluster.controldata.float8_pass_by_value)
469         {
470                 /* no mismatch */
471                 check_ok();
472                 return;
473         }
474
475         snprintf(output_path, sizeof(output_path), "%s/contrib_isn_and_int8_pass_by_value.txt",
476                          os_info.cwd);
477
478         for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
479         {
480                 PGresult   *res;
481                 bool            db_used = false;
482                 int                     ntups;
483                 int                     rowno;
484                 int                     i_nspname,
485                                         i_proname;
486                 DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
487                 PGconn     *conn = connectToServer(cluster, active_db->db_name);
488
489                 /* Find any functions coming from contrib/isn */
490                 res = executeQueryOrDie(conn,
491                                                                 "SELECT n.nspname, p.proname "
492                                                                 "FROM   pg_catalog.pg_proc p, "
493                                                                 "               pg_catalog.pg_namespace n "
494                                                                 "WHERE  p.pronamespace = n.oid AND "
495                                                                 "               p.probin = '$libdir/isn'");
496
497                 ntups = PQntuples(res);
498                 i_nspname = PQfnumber(res, "nspname");
499                 i_proname = PQfnumber(res, "proname");
500                 for (rowno = 0; rowno < ntups; rowno++)
501                 {
502                         found = true;
503                         if (script == NULL && (script = fopen(output_path, "w")) == NULL)
504                                 pg_log(PG_FATAL, "Could not create necessary file:  %s\n", output_path);
505                         if (!db_used)
506                         {
507                                 fprintf(script, "Database:  %s\n", active_db->db_name);
508                                 db_used = true;
509                         }
510                         fprintf(script, "  %s.%s\n",
511                                         PQgetvalue(res, rowno, i_nspname),
512                                         PQgetvalue(res, rowno, i_proname));
513                 }
514
515                 PQclear(res);
516
517                 PQfinish(conn);
518         }
519
520         if (found)
521         {
522                 fclose(script);
523                 pg_log(PG_REPORT, "fatal\n");
524                 pg_log(PG_FATAL,
525                            "| Your installation contains \"/contrib/isn\" functions\n"
526                            "| which rely on the bigint data type.  Your old and\n"
527                            "| new clusters pass bigint values differently so this\n"
528                            "| cluster cannot currently be upgraded.  You can\n"
529                            "| manually upgrade data that use \"/contrib/isn\"\n"
530                            "| facilities and remove \"/contrib/isn\" from the\n"
531                            "| old cluster and restart the upgrade.  A list\n"
532                            "| of the problem functions is in the file:\n"
533                            "| \t%s\n\n", output_path);
534         }
535         else
536                 check_ok();
537 }
538
539
540 /*
541  * check_for_reg_data_type_usage()
542  *      pg_upgrade only preserves these system values:
543  *              pg_class.relfilenode
544  *              pg_type.oid
545  *              pg_enum.oid
546  *
547  *      Most of the reg* data types reference system catalog info that is
548  *      not preserved, and hence these data types cannot be used in user
549  *      tables upgraded by pg_upgrade.
550  */
551 void
552 check_for_reg_data_type_usage(ClusterInfo *cluster)
553 {
554         int                     dbnum;
555         FILE       *script = NULL;
556         bool            found = false;
557         char            output_path[MAXPGPATH];
558
559         prep_status("Checking for reg* system oid user data types");
560
561         snprintf(output_path, sizeof(output_path), "%s/tables_using_reg.txt",
562                          os_info.cwd);
563
564         for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
565         {
566                 PGresult   *res;
567                 bool            db_used = false;
568                 int                     ntups;
569                 int                     rowno;
570                 int                     i_nspname,
571                                         i_relname,
572                                         i_attname;
573                 DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
574                 PGconn     *conn = connectToServer(cluster, active_db->db_name);
575
576                 res = executeQueryOrDie(conn,
577                                                                 "SELECT n.nspname, c.relname, a.attname "
578                                                                 "FROM   pg_catalog.pg_class c, "
579                                                                 "               pg_catalog.pg_namespace n, "
580                                                                 "               pg_catalog.pg_attribute a "
581                                                                 "WHERE  c.oid = a.attrelid AND "
582                                                                 "               NOT a.attisdropped AND "
583                                                                 "               a.atttypid IN ( "
584                   "                     'pg_catalog.regproc'::pg_catalog.regtype, "
585                                                                 "                       'pg_catalog.regprocedure'::pg_catalog.regtype, "
586                   "                     'pg_catalog.regoper'::pg_catalog.regtype, "
587                                                                 "                       'pg_catalog.regoperator'::pg_catalog.regtype, "
588                  "                      'pg_catalog.regclass'::pg_catalog.regtype, "
589                 /* regtype.oid is preserved, so 'regtype' is OK */
590                 "                       'pg_catalog.regconfig'::pg_catalog.regtype, "
591                                                                 "                       'pg_catalog.regdictionary'::pg_catalog.regtype) AND "
592                                                                 "               c.relnamespace = n.oid AND "
593                                                           "             n.nspname != 'pg_catalog' AND "
594                                                  "              n.nspname != 'information_schema'");
595
596                 ntups = PQntuples(res);
597                 i_nspname = PQfnumber(res, "nspname");
598                 i_relname = PQfnumber(res, "relname");
599                 i_attname = PQfnumber(res, "attname");
600                 for (rowno = 0; rowno < ntups; rowno++)
601                 {
602                         found = true;
603                         if (script == NULL && (script = fopen(output_path, "w")) == NULL)
604                                 pg_log(PG_FATAL, "Could not create necessary file:  %s\n", output_path);
605                         if (!db_used)
606                         {
607                                 fprintf(script, "Database:  %s\n", active_db->db_name);
608                                 db_used = true;
609                         }
610                         fprintf(script, "  %s.%s.%s\n",
611                                         PQgetvalue(res, rowno, i_nspname),
612                                         PQgetvalue(res, rowno, i_relname),
613                                         PQgetvalue(res, rowno, i_attname));
614                 }
615
616                 PQclear(res);
617
618                 PQfinish(conn);
619         }
620
621         if (found)
622         {
623                 fclose(script);
624                 pg_log(PG_REPORT, "fatal\n");
625                 pg_log(PG_FATAL,
626                            "| Your installation contains one of the reg* data types in\n"
627                            "| user tables.  These data types reference system oids that\n"
628                            "| are not preserved by pg_upgrade, so this cluster cannot\n"
629                            "| currently be upgraded.  You can remove the problem tables\n"
630                            "| and restart the upgrade.  A list of the problem columns\n"
631                            "| is in the file:\n"
632                            "| \t%s\n\n", output_path);
633         }
634         else
635                 check_ok();
636 }