Line data Source code
1 : /*
2 : * check.c
3 : *
4 : * server checks and output routines
5 : *
6 : * Copyright (c) 2010-2023, PostgreSQL Global Development Group
7 : * src/bin/pg_upgrade/check.c
8 : */
9 :
10 : #include "postgres_fe.h"
11 :
12 : #include "catalog/pg_authid_d.h"
13 : #include "catalog/pg_collation.h"
14 : #include "fe_utils/string_utils.h"
15 : #include "mb/pg_wchar.h"
16 : #include "pg_upgrade.h"
17 :
18 : static void check_new_cluster_is_empty(void);
19 : static void check_is_install_user(ClusterInfo *cluster);
20 : static void check_proper_datallowconn(ClusterInfo *cluster);
21 : static void check_for_prepared_transactions(ClusterInfo *cluster);
22 : static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
23 : static void check_for_user_defined_postfix_ops(ClusterInfo *cluster);
24 : static void check_for_incompatible_polymorphics(ClusterInfo *cluster);
25 : static void check_for_tables_with_oids(ClusterInfo *cluster);
26 : static void check_for_composite_data_type_usage(ClusterInfo *cluster);
27 : static void check_for_reg_data_type_usage(ClusterInfo *cluster);
28 : static void check_for_aclitem_data_type_usage(ClusterInfo *cluster);
29 : static void check_for_removed_data_type_usage(ClusterInfo *cluster,
30 : const char *version,
31 : const char *datatype);
32 : static void check_for_jsonb_9_4_usage(ClusterInfo *cluster);
33 : static void check_for_pg_role_prefix(ClusterInfo *cluster);
34 : static void check_for_new_tablespace_dir(void);
35 : static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster);
36 : static void check_new_cluster_logical_replication_slots(void);
37 : static void check_old_cluster_for_valid_slots(bool live_check);
38 :
39 :
40 : /*
41 : * fix_path_separator
42 : * For non-Windows, just return the argument.
43 : * For Windows convert any forward slash to a backslash
44 : * such as is suitable for arguments to builtin commands
45 : * like RMDIR and DEL.
46 : */
47 : static char *
48 4 : fix_path_separator(char *path)
49 : {
50 : #ifdef WIN32
51 :
52 : char *result;
53 : char *c;
54 :
55 : result = pg_strdup(path);
56 :
57 : for (c = result; *c != '\0'; c++)
58 : if (*c == '/')
59 : *c = '\\';
60 :
61 : return result;
62 : #else
63 :
64 4 : return path;
65 : #endif
66 : }
67 :
68 : void
69 12 : output_check_banner(bool live_check)
70 : {
71 12 : if (user_opts.check && live_check)
72 : {
73 0 : pg_log(PG_REPORT,
74 : "Performing Consistency Checks on Old Live Server\n"
75 : "------------------------------------------------");
76 : }
77 : else
78 : {
79 12 : pg_log(PG_REPORT,
80 : "Performing Consistency Checks\n"
81 : "-----------------------------");
82 : }
83 12 : }
84 :
85 :
86 : void
87 12 : check_and_dump_old_cluster(bool live_check)
88 : {
89 : /* -- OLD -- */
90 :
91 12 : if (!live_check)
92 12 : start_postmaster(&old_cluster, true);
93 :
94 : /*
95 : * Extract a list of databases, tables, and logical replication slots from
96 : * the old cluster.
97 : */
98 12 : get_db_rel_and_slot_infos(&old_cluster, live_check);
99 :
100 10 : init_tablespaces();
101 :
102 10 : get_loadable_libraries();
103 :
104 :
105 : /*
106 : * Check for various failure cases
107 : */
108 10 : check_is_install_user(&old_cluster);
109 10 : check_proper_datallowconn(&old_cluster);
110 10 : check_for_prepared_transactions(&old_cluster);
111 10 : check_for_composite_data_type_usage(&old_cluster);
112 10 : check_for_reg_data_type_usage(&old_cluster);
113 10 : check_for_isn_and_int8_passing_mismatch(&old_cluster);
114 :
115 : /*
116 : * Logical replication slots can be migrated since PG17. See comments atop
117 : * get_old_cluster_logical_slot_infos().
118 : */
119 10 : if (GET_MAJOR_VERSION(old_cluster.major_version) >= 1700)
120 10 : check_old_cluster_for_valid_slots(live_check);
121 :
122 : /*
123 : * PG 16 increased the size of the 'aclitem' type, which breaks the
124 : * on-disk format for existing data.
125 : */
126 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1500)
127 0 : check_for_aclitem_data_type_usage(&old_cluster);
128 :
129 : /*
130 : * PG 12 removed types abstime, reltime, tinterval.
131 : */
132 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1100)
133 : {
134 0 : check_for_removed_data_type_usage(&old_cluster, "12", "abstime");
135 0 : check_for_removed_data_type_usage(&old_cluster, "12", "reltime");
136 0 : check_for_removed_data_type_usage(&old_cluster, "12", "tinterval");
137 : }
138 :
139 : /*
140 : * PG 14 changed the function signature of encoding conversion functions.
141 : * Conversions from older versions cannot be upgraded automatically
142 : * because the user-defined functions used by the encoding conversions
143 : * need to be changed to match the new signature.
144 : */
145 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1300)
146 0 : check_for_user_defined_encoding_conversions(&old_cluster);
147 :
148 : /*
149 : * Pre-PG 14 allowed user defined postfix operators, which are not
150 : * supported anymore. Verify there are none, iff applicable.
151 : */
152 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1300)
153 0 : check_for_user_defined_postfix_ops(&old_cluster);
154 :
155 : /*
156 : * PG 14 changed polymorphic functions from anyarray to
157 : * anycompatiblearray.
158 : */
159 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1300)
160 0 : check_for_incompatible_polymorphics(&old_cluster);
161 :
162 : /*
163 : * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
164 : * supported anymore. Verify there are none, iff applicable.
165 : */
166 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1100)
167 0 : check_for_tables_with_oids(&old_cluster);
168 :
169 : /*
170 : * PG 12 changed the 'sql_identifier' type storage to be based on name,
171 : * not varchar, which breaks on-disk format for existing data. So we need
172 : * to prevent upgrade when used in user objects (tables, indexes, ...).
173 : */
174 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1100)
175 0 : old_11_check_for_sql_identifier_data_type_usage(&old_cluster);
176 :
177 : /*
178 : * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
179 : * hash indexes
180 : */
181 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906)
182 : {
183 0 : old_9_6_check_for_unknown_data_type_usage(&old_cluster);
184 0 : if (user_opts.check)
185 0 : old_9_6_invalidate_hash_indexes(&old_cluster, true);
186 : }
187 :
188 : /* 9.5 and below should not have roles starting with pg_ */
189 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905)
190 0 : check_for_pg_role_prefix(&old_cluster);
191 :
192 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) == 904 &&
193 0 : old_cluster.controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
194 0 : check_for_jsonb_9_4_usage(&old_cluster);
195 :
196 : /* Pre-PG 9.4 had a different 'line' data type internal format */
197 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 903)
198 0 : old_9_3_check_for_line_data_type_usage(&old_cluster);
199 :
200 : /*
201 : * While not a check option, we do this now because this is the only time
202 : * the old server is running.
203 : */
204 8 : if (!user_opts.check)
205 6 : generate_old_dump();
206 :
207 8 : if (!live_check)
208 8 : stop_postmaster(false);
209 8 : }
210 :
211 :
212 : void
213 8 : check_new_cluster(void)
214 : {
215 8 : get_db_rel_and_slot_infos(&new_cluster, false);
216 :
217 8 : check_new_cluster_is_empty();
218 :
219 8 : check_loadable_libraries();
220 :
221 8 : switch (user_opts.transfer_mode)
222 : {
223 0 : case TRANSFER_MODE_CLONE:
224 0 : check_file_clone();
225 0 : break;
226 8 : case TRANSFER_MODE_COPY:
227 8 : break;
228 0 : case TRANSFER_MODE_LINK:
229 0 : check_hard_link();
230 0 : break;
231 : }
232 :
233 8 : check_is_install_user(&new_cluster);
234 :
235 8 : check_for_prepared_transactions(&new_cluster);
236 :
237 8 : check_for_new_tablespace_dir();
238 :
239 8 : check_new_cluster_logical_replication_slots();
240 6 : }
241 :
242 :
243 : void
244 6 : report_clusters_compatible(void)
245 : {
246 6 : if (user_opts.check)
247 : {
248 2 : pg_log(PG_REPORT, "\n*Clusters are compatible*");
249 : /* stops new cluster */
250 2 : stop_postmaster(false);
251 :
252 2 : cleanup_output_dirs();
253 2 : exit(0);
254 : }
255 :
256 4 : pg_log(PG_REPORT, "\n"
257 : "If pg_upgrade fails after this point, you must re-initdb the\n"
258 : "new cluster before continuing.");
259 4 : }
260 :
261 :
262 : void
263 4 : issue_warnings_and_set_wal_level(void)
264 : {
265 : /*
266 : * We unconditionally start/stop the new server because pg_resetwal -o set
267 : * wal_level to 'minimum'. If the user is upgrading standby servers using
268 : * the rsync instructions, they will need pg_upgrade to write its final
269 : * WAL record showing wal_level as 'replica'.
270 : */
271 4 : start_postmaster(&new_cluster, true);
272 :
273 : /* Reindex hash indexes for old < 10.0 */
274 4 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 906)
275 0 : old_9_6_invalidate_hash_indexes(&new_cluster, false);
276 :
277 4 : report_extension_updates(&new_cluster);
278 :
279 4 : stop_postmaster(false);
280 4 : }
281 :
282 :
283 : void
284 4 : output_completion_banner(char *deletion_script_file_name)
285 : {
286 : PQExpBufferData user_specification;
287 :
288 4 : initPQExpBuffer(&user_specification);
289 4 : if (os_info.user_specified)
290 : {
291 0 : appendPQExpBufferStr(&user_specification, "-U ");
292 0 : appendShellString(&user_specification, os_info.user);
293 0 : appendPQExpBufferChar(&user_specification, ' ');
294 : }
295 :
296 4 : pg_log(PG_REPORT,
297 : "Optimizer statistics are not transferred by pg_upgrade.\n"
298 : "Once you start the new server, consider running:\n"
299 : " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
300 :
301 4 : if (deletion_script_file_name)
302 4 : pg_log(PG_REPORT,
303 : "Running this script will delete the old cluster's data files:\n"
304 : " %s",
305 : deletion_script_file_name);
306 : else
307 0 : pg_log(PG_REPORT,
308 : "Could not create a script to delete the old cluster's data files\n"
309 : "because user-defined tablespaces or the new cluster's data directory\n"
310 : "exist in the old cluster directory. The old cluster's contents must\n"
311 : "be deleted manually.");
312 :
313 4 : termPQExpBuffer(&user_specification);
314 4 : }
315 :
316 :
317 : void
318 12 : check_cluster_versions(void)
319 : {
320 12 : prep_status("Checking cluster versions");
321 :
322 : /* cluster versions should already have been obtained */
323 : Assert(old_cluster.major_version != 0);
324 : Assert(new_cluster.major_version != 0);
325 :
326 : /*
327 : * We allow upgrades from/to the same major version for alpha/beta
328 : * upgrades
329 : */
330 :
331 12 : if (GET_MAJOR_VERSION(old_cluster.major_version) < 902)
332 0 : pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
333 : "9.2");
334 :
335 : /* Only current PG version is supported as a target */
336 12 : if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
337 0 : pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
338 : PG_MAJORVERSION);
339 :
340 : /*
341 : * We can't allow downgrading because we use the target pg_dump, and
342 : * pg_dump cannot operate on newer database versions, only current and
343 : * older versions.
344 : */
345 12 : if (old_cluster.major_version > new_cluster.major_version)
346 0 : pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
347 :
348 : /* Ensure binaries match the designated data directories */
349 12 : if (GET_MAJOR_VERSION(old_cluster.major_version) !=
350 12 : GET_MAJOR_VERSION(old_cluster.bin_version))
351 0 : pg_fatal("Old cluster data and binary directories are from different major versions.");
352 12 : if (GET_MAJOR_VERSION(new_cluster.major_version) !=
353 12 : GET_MAJOR_VERSION(new_cluster.bin_version))
354 0 : pg_fatal("New cluster data and binary directories are from different major versions.");
355 :
356 12 : check_ok();
357 12 : }
358 :
359 :
360 : void
361 12 : check_cluster_compatibility(bool live_check)
362 : {
363 : /* get/check pg_control data of servers */
364 12 : get_control_data(&old_cluster, live_check);
365 12 : get_control_data(&new_cluster, false);
366 12 : check_control_data(&old_cluster.controldata, &new_cluster.controldata);
367 :
368 12 : if (live_check && old_cluster.port == new_cluster.port)
369 0 : pg_fatal("When checking a live server, "
370 : "the old and new port numbers must be different.");
371 12 : }
372 :
373 :
374 : static void
375 8 : check_new_cluster_is_empty(void)
376 : {
377 : int dbnum;
378 :
379 24 : for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
380 : {
381 : int relnum;
382 16 : RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
383 :
384 48 : for (relnum = 0; relnum < rel_arr->nrels;
385 32 : relnum++)
386 : {
387 : /* pg_largeobject and its index should be skipped */
388 32 : if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
389 0 : pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"",
390 0 : new_cluster.dbarr.dbs[dbnum].db_name,
391 0 : rel_arr->rels[relnum].nspname,
392 0 : rel_arr->rels[relnum].relname);
393 : }
394 : }
395 8 : }
396 :
397 : /*
398 : * A previous run of pg_upgrade might have failed and the new cluster
399 : * directory recreated, but they might have forgotten to remove
400 : * the new cluster's tablespace directories. Therefore, check that
401 : * new cluster tablespace directories do not already exist. If
402 : * they do, it would cause an error while restoring global objects.
403 : * This allows the failure to be detected at check time, rather than
404 : * during schema restore.
405 : */
406 : static void
407 8 : check_for_new_tablespace_dir(void)
408 : {
409 : int tblnum;
410 : char new_tablespace_dir[MAXPGPATH];
411 :
412 8 : prep_status("Checking for new cluster tablespace directories");
413 :
414 8 : for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
415 : {
416 : struct stat statbuf;
417 :
418 0 : snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
419 0 : os_info.old_tablespaces[tblnum],
420 : new_cluster.tablespace_suffix);
421 :
422 0 : if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
423 0 : pg_fatal("new cluster tablespace directory already exists: \"%s\"",
424 : new_tablespace_dir);
425 : }
426 :
427 8 : check_ok();
428 8 : }
429 :
430 : /*
431 : * create_script_for_old_cluster_deletion()
432 : *
433 : * This is particularly useful for tablespace deletion.
434 : */
435 : void
436 4 : create_script_for_old_cluster_deletion(char **deletion_script_file_name)
437 : {
438 4 : FILE *script = NULL;
439 : int tblnum;
440 : char old_cluster_pgdata[MAXPGPATH],
441 : new_cluster_pgdata[MAXPGPATH];
442 :
443 4 : *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
444 : SCRIPT_PREFIX, SCRIPT_EXT);
445 :
446 4 : strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
447 4 : canonicalize_path(old_cluster_pgdata);
448 :
449 4 : strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
450 4 : canonicalize_path(new_cluster_pgdata);
451 :
452 : /* Some people put the new data directory inside the old one. */
453 4 : if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
454 : {
455 0 : pg_log(PG_WARNING,
456 : "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
457 :
458 : /* Unlink file in case it is left over from a previous run. */
459 0 : unlink(*deletion_script_file_name);
460 0 : pg_free(*deletion_script_file_name);
461 0 : *deletion_script_file_name = NULL;
462 0 : return;
463 : }
464 :
465 : /*
466 : * Some users (oddly) create tablespaces inside the cluster data
467 : * directory. We can't create a proper old cluster delete script in that
468 : * case.
469 : */
470 4 : for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
471 : {
472 : char old_tablespace_dir[MAXPGPATH];
473 :
474 0 : strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
475 0 : canonicalize_path(old_tablespace_dir);
476 0 : if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
477 : {
478 : /* reproduce warning from CREATE TABLESPACE that is in the log */
479 0 : pg_log(PG_WARNING,
480 : "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
481 :
482 : /* Unlink file in case it is left over from a previous run. */
483 0 : unlink(*deletion_script_file_name);
484 0 : pg_free(*deletion_script_file_name);
485 0 : *deletion_script_file_name = NULL;
486 0 : return;
487 : }
488 : }
489 :
490 4 : prep_status("Creating script to delete old cluster");
491 :
492 4 : if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
493 0 : pg_fatal("could not open file \"%s\": %s",
494 0 : *deletion_script_file_name, strerror(errno));
495 :
496 : #ifndef WIN32
497 : /* add shebang header */
498 4 : fprintf(script, "#!/bin/sh\n\n");
499 : #endif
500 :
501 : /* delete old cluster's default tablespace */
502 4 : fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
503 : fix_path_separator(old_cluster.pgdata), PATH_QUOTE);
504 :
505 : /* delete old cluster's alternate tablespaces */
506 4 : for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
507 : {
508 : /*
509 : * Do the old cluster's per-database directories share a directory
510 : * with a new version-specific tablespace?
511 : */
512 0 : if (strlen(old_cluster.tablespace_suffix) == 0)
513 : {
514 : /* delete per-database directories */
515 : int dbnum;
516 :
517 0 : fprintf(script, "\n");
518 :
519 0 : for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
520 0 : fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
521 0 : fix_path_separator(os_info.old_tablespaces[tblnum]),
522 0 : PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid,
523 : PATH_QUOTE);
524 : }
525 : else
526 : {
527 0 : char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
528 :
529 : /*
530 : * Simply delete the tablespace directory, which might be ".old"
531 : * or a version-specific subdirectory.
532 : */
533 0 : fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
534 0 : fix_path_separator(os_info.old_tablespaces[tblnum]),
535 : fix_path_separator(suffix_path), PATH_QUOTE);
536 0 : pfree(suffix_path);
537 : }
538 : }
539 :
540 4 : fclose(script);
541 :
542 : #ifndef WIN32
543 4 : if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
544 0 : pg_fatal("could not add execute permission to file \"%s\": %s",
545 0 : *deletion_script_file_name, strerror(errno));
546 : #endif
547 :
548 4 : check_ok();
549 : }
550 :
551 :
552 : /*
553 : * check_is_install_user()
554 : *
555 : * Check we are the install user, and that the new cluster
556 : * has no other users.
557 : */
558 : static void
559 18 : check_is_install_user(ClusterInfo *cluster)
560 : {
561 : PGresult *res;
562 18 : PGconn *conn = connectToServer(cluster, "template1");
563 :
564 18 : prep_status("Checking database user is the install user");
565 :
566 : /* Can't use pg_authid because only superusers can view it. */
567 18 : res = executeQueryOrDie(conn,
568 : "SELECT rolsuper, oid "
569 : "FROM pg_catalog.pg_roles "
570 : "WHERE rolname = current_user "
571 : "AND rolname !~ '^pg_'");
572 :
573 : /*
574 : * We only allow the install user in the new cluster (see comment below)
575 : * and we preserve pg_authid.oid, so this must be the install user in the
576 : * old cluster too.
577 : */
578 18 : if (PQntuples(res) != 1 ||
579 18 : atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
580 0 : pg_fatal("database user \"%s\" is not the install user",
581 : os_info.user);
582 :
583 18 : PQclear(res);
584 :
585 18 : res = executeQueryOrDie(conn,
586 : "SELECT COUNT(*) "
587 : "FROM pg_catalog.pg_roles "
588 : "WHERE rolname !~ '^pg_'");
589 :
590 18 : if (PQntuples(res) != 1)
591 0 : pg_fatal("could not determine the number of users");
592 :
593 : /*
594 : * We only allow the install user in the new cluster because other defined
595 : * users might match users defined in the old cluster and generate an
596 : * error during pg_dump restore.
597 : */
598 18 : if (cluster == &new_cluster && strcmp(PQgetvalue(res, 0, 0), "1") != 0)
599 0 : pg_fatal("Only the install user can be defined in the new cluster.");
600 :
601 18 : PQclear(res);
602 :
603 18 : PQfinish(conn);
604 :
605 18 : check_ok();
606 18 : }
607 :
608 :
609 : /*
610 : * check_proper_datallowconn
611 : *
612 : * Ensure that all non-template0 databases allow connections since they
613 : * otherwise won't be restored; and that template0 explicitly doesn't allow
614 : * connections since it would make pg_dumpall --globals restore fail.
615 : */
616 : static void
617 10 : check_proper_datallowconn(ClusterInfo *cluster)
618 : {
619 : int dbnum;
620 : PGconn *conn_template1;
621 : PGresult *dbres;
622 : int ntups;
623 : int i_datname;
624 : int i_datallowconn;
625 10 : FILE *script = NULL;
626 : char output_path[MAXPGPATH];
627 :
628 10 : prep_status("Checking database connection settings");
629 :
630 10 : snprintf(output_path, sizeof(output_path), "%s/%s",
631 : log_opts.basedir,
632 : "databases_with_datallowconn_false.txt");
633 :
634 10 : conn_template1 = connectToServer(cluster, "template1");
635 :
636 : /* get database names */
637 10 : dbres = executeQueryOrDie(conn_template1,
638 : "SELECT datname, datallowconn "
639 : "FROM pg_catalog.pg_database");
640 :
641 10 : i_datname = PQfnumber(dbres, "datname");
642 10 : i_datallowconn = PQfnumber(dbres, "datallowconn");
643 :
644 10 : ntups = PQntuples(dbres);
645 56 : for (dbnum = 0; dbnum < ntups; dbnum++)
646 : {
647 46 : char *datname = PQgetvalue(dbres, dbnum, i_datname);
648 46 : char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
649 :
650 46 : if (strcmp(datname, "template0") == 0)
651 : {
652 : /* avoid restore failure when pg_dumpall tries to create template0 */
653 10 : if (strcmp(datallowconn, "t") == 0)
654 0 : pg_fatal("template0 must not allow connections, "
655 : "i.e. its pg_database.datallowconn must be false");
656 : }
657 : else
658 : {
659 : /*
660 : * avoid datallowconn == false databases from being skipped on
661 : * restore
662 : */
663 36 : if (strcmp(datallowconn, "f") == 0)
664 : {
665 0 : if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
666 0 : pg_fatal("could not open file \"%s\": %s",
667 0 : output_path, strerror(errno));
668 :
669 0 : fprintf(script, "%s\n", datname);
670 : }
671 : }
672 : }
673 :
674 10 : PQclear(dbres);
675 :
676 10 : PQfinish(conn_template1);
677 :
678 10 : if (script)
679 : {
680 0 : fclose(script);
681 0 : pg_log(PG_REPORT, "fatal");
682 0 : pg_fatal("All non-template0 databases must allow connections, i.e. their\n"
683 : "pg_database.datallowconn must be true. Your installation contains\n"
684 : "non-template0 databases with their pg_database.datallowconn set to\n"
685 : "false. Consider allowing connection for all non-template0 databases\n"
686 : "or drop the databases which do not allow connections. A list of\n"
687 : "databases with the problem is in the file:\n"
688 : " %s", output_path);
689 : }
690 : else
691 10 : check_ok();
692 10 : }
693 :
694 :
695 : /*
696 : * check_for_prepared_transactions()
697 : *
698 : * Make sure there are no prepared transactions because the storage format
699 : * might have changed.
700 : */
701 : static void
702 18 : check_for_prepared_transactions(ClusterInfo *cluster)
703 : {
704 : PGresult *res;
705 18 : PGconn *conn = connectToServer(cluster, "template1");
706 :
707 18 : prep_status("Checking for prepared transactions");
708 :
709 18 : res = executeQueryOrDie(conn,
710 : "SELECT * "
711 : "FROM pg_catalog.pg_prepared_xacts");
712 :
713 18 : if (PQntuples(res) != 0)
714 : {
715 0 : if (cluster == &old_cluster)
716 0 : pg_fatal("The source cluster contains prepared transactions");
717 : else
718 0 : pg_fatal("The target cluster contains prepared transactions");
719 : }
720 :
721 18 : PQclear(res);
722 :
723 18 : PQfinish(conn);
724 :
725 18 : check_ok();
726 18 : }
727 :
728 :
729 : /*
730 : * check_for_isn_and_int8_passing_mismatch()
731 : *
732 : * contrib/isn relies on data type int8, and in 8.4 int8 can now be passed
733 : * by value. The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
734 : * it must match for the old and new servers.
735 : */
736 : static void
737 10 : check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
738 : {
739 : int dbnum;
740 10 : FILE *script = NULL;
741 : char output_path[MAXPGPATH];
742 :
743 10 : prep_status("Checking for contrib/isn with bigint-passing mismatch");
744 :
745 10 : if (old_cluster.controldata.float8_pass_by_value ==
746 10 : new_cluster.controldata.float8_pass_by_value)
747 : {
748 : /* no mismatch */
749 10 : check_ok();
750 10 : return;
751 : }
752 :
753 0 : snprintf(output_path, sizeof(output_path), "%s/%s",
754 : log_opts.basedir,
755 : "contrib_isn_and_int8_pass_by_value.txt");
756 :
757 0 : for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
758 : {
759 : PGresult *res;
760 0 : bool db_used = false;
761 : int ntups;
762 : int rowno;
763 : int i_nspname,
764 : i_proname;
765 0 : DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
766 0 : PGconn *conn = connectToServer(cluster, active_db->db_name);
767 :
768 : /* Find any functions coming from contrib/isn */
769 0 : res = executeQueryOrDie(conn,
770 : "SELECT n.nspname, p.proname "
771 : "FROM pg_catalog.pg_proc p, "
772 : " pg_catalog.pg_namespace n "
773 : "WHERE p.pronamespace = n.oid AND "
774 : " p.probin = '$libdir/isn'");
775 :
776 0 : ntups = PQntuples(res);
777 0 : i_nspname = PQfnumber(res, "nspname");
778 0 : i_proname = PQfnumber(res, "proname");
779 0 : for (rowno = 0; rowno < ntups; rowno++)
780 : {
781 0 : if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
782 0 : pg_fatal("could not open file \"%s\": %s",
783 0 : output_path, strerror(errno));
784 0 : if (!db_used)
785 : {
786 0 : fprintf(script, "In database: %s\n", active_db->db_name);
787 0 : db_used = true;
788 : }
789 0 : fprintf(script, " %s.%s\n",
790 : PQgetvalue(res, rowno, i_nspname),
791 : PQgetvalue(res, rowno, i_proname));
792 : }
793 :
794 0 : PQclear(res);
795 :
796 0 : PQfinish(conn);
797 : }
798 :
799 0 : if (script)
800 : {
801 0 : fclose(script);
802 0 : pg_log(PG_REPORT, "fatal");
803 0 : pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
804 : "bigint data type. Your old and new clusters pass bigint values\n"
805 : "differently so this cluster cannot currently be upgraded. You can\n"
806 : "manually dump databases in the old cluster that use \"contrib/isn\"\n"
807 : "facilities, drop them, perform the upgrade, and then restore them. A\n"
808 : "list of the problem functions is in the file:\n"
809 : " %s", output_path);
810 : }
811 : else
812 0 : check_ok();
813 : }
814 :
815 : /*
816 : * Verify that no user defined postfix operators exist.
817 : */
818 : static void
819 0 : check_for_user_defined_postfix_ops(ClusterInfo *cluster)
820 : {
821 : int dbnum;
822 0 : FILE *script = NULL;
823 : char output_path[MAXPGPATH];
824 :
825 0 : prep_status("Checking for user-defined postfix operators");
826 :
827 0 : snprintf(output_path, sizeof(output_path), "%s/%s",
828 : log_opts.basedir,
829 : "postfix_ops.txt");
830 :
831 : /* Find any user defined postfix operators */
832 0 : for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
833 : {
834 : PGresult *res;
835 0 : bool db_used = false;
836 : int ntups;
837 : int rowno;
838 : int i_oproid,
839 : i_oprnsp,
840 : i_oprname,
841 : i_typnsp,
842 : i_typname;
843 0 : DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
844 0 : PGconn *conn = connectToServer(cluster, active_db->db_name);
845 :
846 : /*
847 : * The query below hardcodes FirstNormalObjectId as 16384 rather than
848 : * interpolating that C #define into the query because, if that
849 : * #define is ever changed, the cutoff we want to use is the value
850 : * used by pre-version 14 servers, not that of some future version.
851 : */
852 0 : res = executeQueryOrDie(conn,
853 : "SELECT o.oid AS oproid, "
854 : " n.nspname AS oprnsp, "
855 : " o.oprname, "
856 : " tn.nspname AS typnsp, "
857 : " t.typname "
858 : "FROM pg_catalog.pg_operator o, "
859 : " pg_catalog.pg_namespace n, "
860 : " pg_catalog.pg_type t, "
861 : " pg_catalog.pg_namespace tn "
862 : "WHERE o.oprnamespace = n.oid AND "
863 : " o.oprleft = t.oid AND "
864 : " t.typnamespace = tn.oid AND "
865 : " o.oprright = 0 AND "
866 : " o.oid >= 16384");
867 0 : ntups = PQntuples(res);
868 0 : i_oproid = PQfnumber(res, "oproid");
869 0 : i_oprnsp = PQfnumber(res, "oprnsp");
870 0 : i_oprname = PQfnumber(res, "oprname");
871 0 : i_typnsp = PQfnumber(res, "typnsp");
872 0 : i_typname = PQfnumber(res, "typname");
873 0 : for (rowno = 0; rowno < ntups; rowno++)
874 : {
875 0 : if (script == NULL &&
876 0 : (script = fopen_priv(output_path, "w")) == NULL)
877 0 : pg_fatal("could not open file \"%s\": %s",
878 0 : output_path, strerror(errno));
879 0 : if (!db_used)
880 : {
881 0 : fprintf(script, "In database: %s\n", active_db->db_name);
882 0 : db_used = true;
883 : }
884 0 : fprintf(script, " (oid=%s) %s.%s (%s.%s, NONE)\n",
885 : PQgetvalue(res, rowno, i_oproid),
886 : PQgetvalue(res, rowno, i_oprnsp),
887 : PQgetvalue(res, rowno, i_oprname),
888 : PQgetvalue(res, rowno, i_typnsp),
889 : PQgetvalue(res, rowno, i_typname));
890 : }
891 :
892 0 : PQclear(res);
893 :
894 0 : PQfinish(conn);
895 : }
896 :
897 0 : if (script)
898 : {
899 0 : fclose(script);
900 0 : pg_log(PG_REPORT, "fatal");
901 0 : pg_fatal("Your installation contains user-defined postfix operators, which are not\n"
902 : "supported anymore. Consider dropping the postfix operators and replacing\n"
903 : "them with prefix operators or function calls.\n"
904 : "A list of user-defined postfix operators is in the file:\n"
905 : " %s", output_path);
906 : }
907 : else
908 0 : check_ok();
909 0 : }
910 :
911 : /*
912 : * check_for_incompatible_polymorphics()
913 : *
914 : * Make sure nothing is using old polymorphic functions with
915 : * anyarray/anyelement rather than the new anycompatible variants.
916 : */
917 : static void
918 0 : check_for_incompatible_polymorphics(ClusterInfo *cluster)
919 : {
920 : PGresult *res;
921 0 : FILE *script = NULL;
922 : char output_path[MAXPGPATH];
923 : PQExpBufferData old_polymorphics;
924 :
925 0 : prep_status("Checking for incompatible polymorphic functions");
926 :
927 0 : snprintf(output_path, sizeof(output_path), "%s/%s",
928 : log_opts.basedir,
929 : "incompatible_polymorphics.txt");
930 :
931 : /* The set of problematic functions varies a bit in different versions */
932 0 : initPQExpBuffer(&old_polymorphics);
933 :
934 0 : appendPQExpBufferStr(&old_polymorphics,
935 : "'array_append(anyarray,anyelement)'"
936 : ", 'array_cat(anyarray,anyarray)'"
937 : ", 'array_prepend(anyelement,anyarray)'");
938 :
939 0 : if (GET_MAJOR_VERSION(cluster->major_version) >= 903)
940 0 : appendPQExpBufferStr(&old_polymorphics,
941 : ", 'array_remove(anyarray,anyelement)'"
942 : ", 'array_replace(anyarray,anyelement,anyelement)'");
943 :
944 0 : if (GET_MAJOR_VERSION(cluster->major_version) >= 905)
945 0 : appendPQExpBufferStr(&old_polymorphics,
946 : ", 'array_position(anyarray,anyelement)'"
947 : ", 'array_position(anyarray,anyelement,integer)'"
948 : ", 'array_positions(anyarray,anyelement)'"
949 : ", 'width_bucket(anyelement,anyarray)'");
950 :
951 0 : for (int dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
952 : {
953 0 : bool db_used = false;
954 0 : DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
955 0 : PGconn *conn = connectToServer(cluster, active_db->db_name);
956 : int ntups;
957 : int i_objkind,
958 : i_objname;
959 :
960 : /*
961 : * The query below hardcodes FirstNormalObjectId as 16384 rather than
962 : * interpolating that C #define into the query because, if that
963 : * #define is ever changed, the cutoff we want to use is the value
964 : * used by pre-version 14 servers, not that of some future version.
965 : */
966 0 : res = executeQueryOrDie(conn,
967 : /* Aggregate transition functions */
968 : "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
969 : "FROM pg_proc AS p "
970 : "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
971 : "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
972 : "WHERE p.oid >= 16384 "
973 : "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
974 : "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
975 :
976 : /* Aggregate final functions */
977 : "UNION ALL "
978 : "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
979 : "FROM pg_proc AS p "
980 : "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
981 : "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
982 : "WHERE p.oid >= 16384 "
983 : "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
984 : "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
985 :
986 : /* Operators */
987 : "UNION ALL "
988 : "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
989 : "FROM pg_operator AS op "
990 : "WHERE op.oid >= 16384 "
991 : "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) "
992 : "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[]);",
993 : old_polymorphics.data,
994 : old_polymorphics.data,
995 : old_polymorphics.data);
996 :
997 0 : ntups = PQntuples(res);
998 :
999 0 : i_objkind = PQfnumber(res, "objkind");
1000 0 : i_objname = PQfnumber(res, "objname");
1001 :
1002 0 : for (int rowno = 0; rowno < ntups; rowno++)
1003 : {
1004 0 : if (script == NULL &&
1005 0 : (script = fopen_priv(output_path, "w")) == NULL)
1006 0 : pg_fatal("could not open file \"%s\": %s",
1007 0 : output_path, strerror(errno));
1008 0 : if (!db_used)
1009 : {
1010 0 : fprintf(script, "In database: %s\n", active_db->db_name);
1011 0 : db_used = true;
1012 : }
1013 :
1014 0 : fprintf(script, " %s: %s\n",
1015 : PQgetvalue(res, rowno, i_objkind),
1016 : PQgetvalue(res, rowno, i_objname));
1017 : }
1018 :
1019 0 : PQclear(res);
1020 0 : PQfinish(conn);
1021 : }
1022 :
1023 0 : if (script)
1024 : {
1025 0 : fclose(script);
1026 0 : pg_log(PG_REPORT, "fatal");
1027 0 : pg_fatal("Your installation contains user-defined objects that refer to internal\n"
1028 : "polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n"
1029 : "These user-defined objects must be dropped before upgrading and restored\n"
1030 : "afterwards, changing them to refer to the new corresponding functions with\n"
1031 : "arguments of type \"anycompatiblearray\" and \"anycompatible\".\n"
1032 : "A list of the problematic objects is in the file:\n"
1033 : " %s", output_path);
1034 : }
1035 : else
1036 0 : check_ok();
1037 :
1038 0 : termPQExpBuffer(&old_polymorphics);
1039 0 : }
1040 :
1041 : /*
1042 : * Verify that no tables are declared WITH OIDS.
1043 : */
1044 : static void
1045 0 : check_for_tables_with_oids(ClusterInfo *cluster)
1046 : {
1047 : int dbnum;
1048 0 : FILE *script = NULL;
1049 : char output_path[MAXPGPATH];
1050 :
1051 0 : prep_status("Checking for tables WITH OIDS");
1052 :
1053 0 : snprintf(output_path, sizeof(output_path), "%s/%s",
1054 : log_opts.basedir,
1055 : "tables_with_oids.txt");
1056 :
1057 : /* Find any tables declared WITH OIDS */
1058 0 : for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
1059 : {
1060 : PGresult *res;
1061 0 : bool db_used = false;
1062 : int ntups;
1063 : int rowno;
1064 : int i_nspname,
1065 : i_relname;
1066 0 : DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
1067 0 : PGconn *conn = connectToServer(cluster, active_db->db_name);
1068 :
1069 0 : res = executeQueryOrDie(conn,
1070 : "SELECT n.nspname, c.relname "
1071 : "FROM pg_catalog.pg_class c, "
1072 : " pg_catalog.pg_namespace n "
1073 : "WHERE c.relnamespace = n.oid AND "
1074 : " c.relhasoids AND"
1075 : " n.nspname NOT IN ('pg_catalog')");
1076 :
1077 0 : ntups = PQntuples(res);
1078 0 : i_nspname = PQfnumber(res, "nspname");
1079 0 : i_relname = PQfnumber(res, "relname");
1080 0 : for (rowno = 0; rowno < ntups; rowno++)
1081 : {
1082 0 : if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1083 0 : pg_fatal("could not open file \"%s\": %s",
1084 0 : output_path, strerror(errno));
1085 0 : if (!db_used)
1086 : {
1087 0 : fprintf(script, "In database: %s\n", active_db->db_name);
1088 0 : db_used = true;
1089 : }
1090 0 : fprintf(script, " %s.%s\n",
1091 : PQgetvalue(res, rowno, i_nspname),
1092 : PQgetvalue(res, rowno, i_relname));
1093 : }
1094 :
1095 0 : PQclear(res);
1096 :
1097 0 : PQfinish(conn);
1098 : }
1099 :
1100 0 : if (script)
1101 : {
1102 0 : fclose(script);
1103 0 : pg_log(PG_REPORT, "fatal");
1104 0 : pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n"
1105 : "supported anymore. Consider removing the oid column using\n"
1106 : " ALTER TABLE ... SET WITHOUT OIDS;\n"
1107 : "A list of tables with the problem is in the file:\n"
1108 : " %s", output_path);
1109 : }
1110 : else
1111 0 : check_ok();
1112 0 : }
1113 :
1114 :
1115 : /*
1116 : * check_for_composite_data_type_usage()
1117 : * Check for system-defined composite types used in user tables.
1118 : *
1119 : * The OIDs of rowtypes of system catalogs and information_schema views
1120 : * can change across major versions; unlike user-defined types, we have
1121 : * no mechanism for forcing them to be the same in the new cluster.
1122 : * Hence, if any user table uses one, that's problematic for pg_upgrade.
1123 : */
1124 : static void
1125 10 : check_for_composite_data_type_usage(ClusterInfo *cluster)
1126 : {
1127 : bool found;
1128 : Oid firstUserOid;
1129 : char output_path[MAXPGPATH];
1130 : char *base_query;
1131 :
1132 10 : prep_status("Checking for system-defined composite types in user tables");
1133 :
1134 10 : snprintf(output_path, sizeof(output_path), "%s/%s",
1135 : log_opts.basedir,
1136 : "tables_using_composite.txt");
1137 :
1138 : /*
1139 : * Look for composite types that were made during initdb *or* belong to
1140 : * information_schema; that's important in case information_schema was
1141 : * dropped and reloaded.
1142 : *
1143 : * The cutoff OID here should match the source cluster's value of
1144 : * FirstNormalObjectId. We hardcode it rather than using that C #define
1145 : * because, if that #define is ever changed, our own version's value is
1146 : * NOT what to use. Eventually we may need a test on the source cluster's
1147 : * version to select the correct value.
1148 : */
1149 10 : firstUserOid = 16384;
1150 :
1151 10 : base_query = psprintf("SELECT t.oid FROM pg_catalog.pg_type t "
1152 : "LEFT JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid "
1153 : " WHERE typtype = 'c' AND (t.oid < %u OR nspname = 'information_schema')",
1154 : firstUserOid);
1155 :
1156 10 : found = check_for_data_types_usage(cluster, base_query, output_path);
1157 :
1158 10 : free(base_query);
1159 :
1160 10 : if (found)
1161 : {
1162 0 : pg_log(PG_REPORT, "fatal");
1163 0 : pg_fatal("Your installation contains system-defined composite types in user tables.\n"
1164 : "These type OIDs are not stable across PostgreSQL versions,\n"
1165 : "so this cluster cannot currently be upgraded. You can\n"
1166 : "drop the problem columns and restart the upgrade.\n"
1167 : "A list of the problem columns is in the file:\n"
1168 : " %s", output_path);
1169 : }
1170 : else
1171 10 : check_ok();
1172 10 : }
1173 :
1174 : /*
1175 : * check_for_reg_data_type_usage()
1176 : * pg_upgrade only preserves these system values:
1177 : * pg_class.oid
1178 : * pg_type.oid
1179 : * pg_enum.oid
1180 : *
1181 : * Many of the reg* data types reference system catalog info that is
1182 : * not preserved, and hence these data types cannot be used in user
1183 : * tables upgraded by pg_upgrade.
1184 : */
1185 : static void
1186 10 : check_for_reg_data_type_usage(ClusterInfo *cluster)
1187 : {
1188 : bool found;
1189 : char output_path[MAXPGPATH];
1190 :
1191 10 : prep_status("Checking for reg* data types in user tables");
1192 :
1193 10 : snprintf(output_path, sizeof(output_path), "%s/%s",
1194 : log_opts.basedir,
1195 : "tables_using_reg.txt");
1196 :
1197 : /*
1198 : * Note: older servers will not have all of these reg* types, so we have
1199 : * to write the query like this rather than depending on casts to regtype.
1200 : */
1201 10 : found = check_for_data_types_usage(cluster,
1202 : "SELECT oid FROM pg_catalog.pg_type t "
1203 : "WHERE t.typnamespace = "
1204 : " (SELECT oid FROM pg_catalog.pg_namespace "
1205 : " WHERE nspname = 'pg_catalog') "
1206 : " AND t.typname IN ( "
1207 : /* pg_class.oid is preserved, so 'regclass' is OK */
1208 : " 'regcollation', "
1209 : " 'regconfig', "
1210 : " 'regdictionary', "
1211 : " 'regnamespace', "
1212 : " 'regoper', "
1213 : " 'regoperator', "
1214 : " 'regproc', "
1215 : " 'regprocedure' "
1216 : /* pg_authid.oid is preserved, so 'regrole' is OK */
1217 : /* pg_type.oid is (mostly) preserved, so 'regtype' is OK */
1218 : " )",
1219 : output_path);
1220 :
1221 10 : if (found)
1222 : {
1223 0 : pg_log(PG_REPORT, "fatal");
1224 0 : pg_fatal("Your installation contains one of the reg* data types in user tables.\n"
1225 : "These data types reference system OIDs that are not preserved by\n"
1226 : "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
1227 : "drop the problem columns and restart the upgrade.\n"
1228 : "A list of the problem columns is in the file:\n"
1229 : " %s", output_path);
1230 : }
1231 : else
1232 10 : check_ok();
1233 10 : }
1234 :
1235 : /*
1236 : * check_for_aclitem_data_type_usage
1237 : *
1238 : * aclitem changed its storage format in 16, so check for it.
1239 : */
1240 : static void
1241 0 : check_for_aclitem_data_type_usage(ClusterInfo *cluster)
1242 : {
1243 : char output_path[MAXPGPATH];
1244 :
1245 0 : prep_status("Checking for incompatible \"%s\" data type in user tables",
1246 : "aclitem");
1247 :
1248 0 : snprintf(output_path, sizeof(output_path), "tables_using_aclitem.txt");
1249 :
1250 0 : if (check_for_data_type_usage(cluster, "pg_catalog.aclitem", output_path))
1251 : {
1252 0 : pg_log(PG_REPORT, "fatal");
1253 0 : pg_fatal("Your installation contains the \"aclitem\" data type in user tables.\n"
1254 : "The internal format of \"aclitem\" changed in PostgreSQL version 16\n"
1255 : "so this cluster cannot currently be upgraded. You can drop the\n"
1256 : "problem columns and restart the upgrade. A list of the problem\n"
1257 : "columns is in the file:\n"
1258 : " %s", output_path);
1259 : }
1260 : else
1261 0 : check_ok();
1262 0 : }
1263 :
1264 : /*
1265 : * check_for_removed_data_type_usage
1266 : *
1267 : * Check for in-core data types that have been removed. Callers know
1268 : * the exact list.
1269 : */
1270 : static void
1271 0 : check_for_removed_data_type_usage(ClusterInfo *cluster, const char *version,
1272 : const char *datatype)
1273 : {
1274 : char output_path[MAXPGPATH];
1275 : char typename[NAMEDATALEN];
1276 :
1277 0 : prep_status("Checking for removed \"%s\" data type in user tables",
1278 : datatype);
1279 :
1280 0 : snprintf(output_path, sizeof(output_path), "tables_using_%s.txt",
1281 : datatype);
1282 0 : snprintf(typename, sizeof(typename), "pg_catalog.%s", datatype);
1283 :
1284 0 : if (check_for_data_type_usage(cluster, typename, output_path))
1285 : {
1286 0 : pg_log(PG_REPORT, "fatal");
1287 0 : pg_fatal("Your installation contains the \"%s\" data type in user tables.\n"
1288 : "The \"%s\" type has been removed in PostgreSQL version %s,\n"
1289 : "so this cluster cannot currently be upgraded. You can drop the\n"
1290 : "problem columns, or change them to another data type, and restart\n"
1291 : "the upgrade. A list of the problem columns is in the file:\n"
1292 : " %s", datatype, datatype, version, output_path);
1293 : }
1294 : else
1295 0 : check_ok();
1296 0 : }
1297 :
1298 :
1299 : /*
1300 : * check_for_jsonb_9_4_usage()
1301 : *
1302 : * JSONB changed its storage format during 9.4 beta, so check for it.
1303 : */
1304 : static void
1305 0 : check_for_jsonb_9_4_usage(ClusterInfo *cluster)
1306 : {
1307 : char output_path[MAXPGPATH];
1308 :
1309 0 : prep_status("Checking for incompatible \"jsonb\" data type");
1310 :
1311 0 : snprintf(output_path, sizeof(output_path), "%s/%s",
1312 : log_opts.basedir,
1313 : "tables_using_jsonb.txt");
1314 :
1315 0 : if (check_for_data_type_usage(cluster, "pg_catalog.jsonb", output_path))
1316 : {
1317 0 : pg_log(PG_REPORT, "fatal");
1318 0 : pg_fatal("Your installation contains the \"jsonb\" data type in user tables.\n"
1319 : "The internal format of \"jsonb\" changed during 9.4 beta so this\n"
1320 : "cluster cannot currently be upgraded. You can\n"
1321 : "drop the problem columns and restart the upgrade.\n"
1322 : "A list of the problem columns is in the file:\n"
1323 : " %s", output_path);
1324 : }
1325 : else
1326 0 : check_ok();
1327 0 : }
1328 :
1329 : /*
1330 : * check_for_pg_role_prefix()
1331 : *
1332 : * Versions older than 9.6 should not have any pg_* roles
1333 : */
1334 : static void
1335 0 : check_for_pg_role_prefix(ClusterInfo *cluster)
1336 : {
1337 : PGresult *res;
1338 0 : PGconn *conn = connectToServer(cluster, "template1");
1339 : int ntups;
1340 : int i_roloid;
1341 : int i_rolname;
1342 0 : FILE *script = NULL;
1343 : char output_path[MAXPGPATH];
1344 :
1345 0 : prep_status("Checking for roles starting with \"pg_\"");
1346 :
1347 0 : snprintf(output_path, sizeof(output_path), "%s/%s",
1348 : log_opts.basedir,
1349 : "pg_role_prefix.txt");
1350 :
1351 0 : res = executeQueryOrDie(conn,
1352 : "SELECT oid AS roloid, rolname "
1353 : "FROM pg_catalog.pg_roles "
1354 : "WHERE rolname ~ '^pg_'");
1355 :
1356 0 : ntups = PQntuples(res);
1357 0 : i_roloid = PQfnumber(res, "roloid");
1358 0 : i_rolname = PQfnumber(res, "rolname");
1359 0 : for (int rowno = 0; rowno < ntups; rowno++)
1360 : {
1361 0 : if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1362 0 : pg_fatal("could not open file \"%s\": %s",
1363 0 : output_path, strerror(errno));
1364 0 : fprintf(script, "%s (oid=%s)\n",
1365 : PQgetvalue(res, rowno, i_rolname),
1366 : PQgetvalue(res, rowno, i_roloid));
1367 : }
1368 :
1369 0 : PQclear(res);
1370 :
1371 0 : PQfinish(conn);
1372 :
1373 0 : if (script)
1374 : {
1375 0 : fclose(script);
1376 0 : pg_log(PG_REPORT, "fatal");
1377 0 : pg_fatal("Your installation contains roles starting with \"pg_\".\n"
1378 : "\"pg_\" is a reserved prefix for system roles. The cluster\n"
1379 : "cannot be upgraded until these roles are renamed.\n"
1380 : "A list of roles starting with \"pg_\" is in the file:\n"
1381 : " %s", output_path);
1382 : }
1383 : else
1384 0 : check_ok();
1385 0 : }
1386 :
1387 : /*
1388 : * Verify that no user-defined encoding conversions exist.
1389 : */
1390 : static void
1391 0 : check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
1392 : {
1393 : int dbnum;
1394 0 : FILE *script = NULL;
1395 : char output_path[MAXPGPATH];
1396 :
1397 0 : prep_status("Checking for user-defined encoding conversions");
1398 :
1399 0 : snprintf(output_path, sizeof(output_path), "%s/%s",
1400 : log_opts.basedir,
1401 : "encoding_conversions.txt");
1402 :
1403 : /* Find any user defined encoding conversions */
1404 0 : for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
1405 : {
1406 : PGresult *res;
1407 0 : bool db_used = false;
1408 : int ntups;
1409 : int rowno;
1410 : int i_conoid,
1411 : i_conname,
1412 : i_nspname;
1413 0 : DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
1414 0 : PGconn *conn = connectToServer(cluster, active_db->db_name);
1415 :
1416 : /*
1417 : * The query below hardcodes FirstNormalObjectId as 16384 rather than
1418 : * interpolating that C #define into the query because, if that
1419 : * #define is ever changed, the cutoff we want to use is the value
1420 : * used by pre-version 14 servers, not that of some future version.
1421 : */
1422 0 : res = executeQueryOrDie(conn,
1423 : "SELECT c.oid as conoid, c.conname, n.nspname "
1424 : "FROM pg_catalog.pg_conversion c, "
1425 : " pg_catalog.pg_namespace n "
1426 : "WHERE c.connamespace = n.oid AND "
1427 : " c.oid >= 16384");
1428 0 : ntups = PQntuples(res);
1429 0 : i_conoid = PQfnumber(res, "conoid");
1430 0 : i_conname = PQfnumber(res, "conname");
1431 0 : i_nspname = PQfnumber(res, "nspname");
1432 0 : for (rowno = 0; rowno < ntups; rowno++)
1433 : {
1434 0 : if (script == NULL &&
1435 0 : (script = fopen_priv(output_path, "w")) == NULL)
1436 0 : pg_fatal("could not open file \"%s\": %s",
1437 0 : output_path, strerror(errno));
1438 0 : if (!db_used)
1439 : {
1440 0 : fprintf(script, "In database: %s\n", active_db->db_name);
1441 0 : db_used = true;
1442 : }
1443 0 : fprintf(script, " (oid=%s) %s.%s\n",
1444 : PQgetvalue(res, rowno, i_conoid),
1445 : PQgetvalue(res, rowno, i_nspname),
1446 : PQgetvalue(res, rowno, i_conname));
1447 : }
1448 :
1449 0 : PQclear(res);
1450 :
1451 0 : PQfinish(conn);
1452 : }
1453 :
1454 0 : if (script)
1455 : {
1456 0 : fclose(script);
1457 0 : pg_log(PG_REPORT, "fatal");
1458 0 : pg_fatal("Your installation contains user-defined encoding conversions.\n"
1459 : "The conversion function parameters changed in PostgreSQL version 14\n"
1460 : "so this cluster cannot currently be upgraded. You can remove the\n"
1461 : "encoding conversions in the old cluster and restart the upgrade.\n"
1462 : "A list of user-defined encoding conversions is in the file:\n"
1463 : " %s", output_path);
1464 : }
1465 : else
1466 0 : check_ok();
1467 0 : }
1468 :
1469 : /*
1470 : * check_new_cluster_logical_replication_slots()
1471 : *
1472 : * Verify that there are no logical replication slots on the new cluster and
1473 : * that the parameter settings necessary for creating slots are sufficient.
1474 : */
1475 : static void
1476 8 : check_new_cluster_logical_replication_slots(void)
1477 : {
1478 : PGresult *res;
1479 : PGconn *conn;
1480 : int nslots_on_old;
1481 : int nslots_on_new;
1482 : int max_replication_slots;
1483 : char *wal_level;
1484 :
1485 : /* Logical slots can be migrated since PG17. */
1486 8 : if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1600)
1487 0 : return;
1488 :
1489 8 : nslots_on_old = count_old_cluster_logical_slots();
1490 :
1491 : /* Quick return if there are no logical slots to be migrated. */
1492 8 : if (nslots_on_old == 0)
1493 4 : return;
1494 :
1495 4 : conn = connectToServer(&new_cluster, "template1");
1496 :
1497 4 : prep_status("Checking for new cluster logical replication slots");
1498 :
1499 4 : res = executeQueryOrDie(conn, "SELECT count(*) "
1500 : "FROM pg_catalog.pg_replication_slots "
1501 : "WHERE slot_type = 'logical' AND "
1502 : "temporary IS FALSE;");
1503 :
1504 4 : if (PQntuples(res) != 1)
1505 0 : pg_fatal("could not count the number of logical replication slots");
1506 :
1507 4 : nslots_on_new = atoi(PQgetvalue(res, 0, 0));
1508 :
1509 4 : if (nslots_on_new)
1510 0 : pg_fatal("Expected 0 logical replication slots but found %d.",
1511 : nslots_on_new);
1512 :
1513 4 : PQclear(res);
1514 :
1515 4 : res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
1516 : "WHERE name IN ('wal_level', 'max_replication_slots') "
1517 : "ORDER BY name DESC;");
1518 :
1519 4 : if (PQntuples(res) != 2)
1520 0 : pg_fatal("could not determine parameter settings on new cluster");
1521 :
1522 4 : wal_level = PQgetvalue(res, 0, 0);
1523 :
1524 4 : if (strcmp(wal_level, "logical") != 0)
1525 0 : pg_fatal("wal_level must be \"logical\", but is set to \"%s\"",
1526 : wal_level);
1527 :
1528 4 : max_replication_slots = atoi(PQgetvalue(res, 1, 0));
1529 :
1530 4 : if (nslots_on_old > max_replication_slots)
1531 2 : pg_fatal("max_replication_slots (%d) must be greater than or equal to the number of "
1532 : "logical replication slots (%d) on the old cluster",
1533 : max_replication_slots, nslots_on_old);
1534 :
1535 2 : PQclear(res);
1536 2 : PQfinish(conn);
1537 :
1538 2 : check_ok();
1539 : }
1540 :
1541 : /*
1542 : * check_old_cluster_for_valid_slots()
1543 : *
1544 : * Verify that all the logical slots are valid and have consumed all the WAL
1545 : * before shutdown.
1546 : */
1547 : static void
1548 10 : check_old_cluster_for_valid_slots(bool live_check)
1549 : {
1550 : char output_path[MAXPGPATH];
1551 10 : FILE *script = NULL;
1552 :
1553 10 : prep_status("Checking for valid logical replication slots");
1554 :
1555 10 : snprintf(output_path, sizeof(output_path), "%s/%s",
1556 : log_opts.basedir,
1557 : "invalid_logical_slots.txt");
1558 :
1559 46 : for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
1560 : {
1561 36 : LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
1562 :
1563 46 : for (int slotnum = 0; slotnum < slot_arr->nslots; slotnum++)
1564 : {
1565 10 : LogicalSlotInfo *slot = &slot_arr->slots[slotnum];
1566 :
1567 : /* Is the slot usable? */
1568 10 : if (slot->invalid)
1569 : {
1570 0 : if (script == NULL &&
1571 0 : (script = fopen_priv(output_path, "w")) == NULL)
1572 0 : pg_fatal("could not open file \"%s\": %s",
1573 0 : output_path, strerror(errno));
1574 :
1575 0 : fprintf(script, "The slot \"%s\" is invalid\n",
1576 : slot->slotname);
1577 :
1578 0 : continue;
1579 : }
1580 :
1581 : /*
1582 : * Do additional check to ensure that all logical replication
1583 : * slots have consumed all the WAL before shutdown.
1584 : *
1585 : * Note: This can be satisfied only when the old cluster has been
1586 : * shut down, so we skip this for live checks.
1587 : */
1588 10 : if (!live_check && !slot->caught_up)
1589 : {
1590 6 : if (script == NULL &&
1591 2 : (script = fopen_priv(output_path, "w")) == NULL)
1592 0 : pg_fatal("could not open file \"%s\": %s",
1593 0 : output_path, strerror(errno));
1594 :
1595 4 : fprintf(script,
1596 : "The slot \"%s\" has not consumed the WAL yet\n",
1597 : slot->slotname);
1598 : }
1599 : }
1600 : }
1601 :
1602 10 : if (script)
1603 : {
1604 2 : fclose(script);
1605 :
1606 2 : pg_log(PG_REPORT, "fatal");
1607 2 : pg_fatal("Your installation contains logical replication slots that can't be upgraded.\n"
1608 : "You can remove invalid slots and/or consume the pending WAL for other slots,\n"
1609 : "and then restart the upgrade.\n"
1610 : "A list of the problematic slots is in the file:\n"
1611 : " %s", output_path);
1612 : }
1613 :
1614 8 : check_ok();
1615 8 : }
|