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