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