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