PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
check.c
Go to the documentation of this file.
1/*
2 * check.c
3 *
4 * server checks and output routines
5 *
6 * Copyright (c) 2010-2024, 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_class_d.h"
15#include "pg_upgrade.h"
16
17static void check_new_cluster_is_empty(void);
26static void check_for_new_tablespace_dir(void);
30static void check_old_cluster_for_valid_slots(void);
32
33/*
34 * DataTypesUsageChecks - definitions of data type checks for the old cluster
35 * in order to determine if an upgrade can be performed. See the comment on
36 * data_types_usage_checks below for a more detailed description.
37 */
38typedef struct
39{
40 /* Status line to print to the user */
41 const char *status;
42 /* Filename to store report to */
43 const char *report_filename;
44 /* Query to extract the oid of the datatype */
45 const char *base_query;
46 /* Text to store to report in case of error */
47 const char *report_text;
48 /* The latest version where the check applies */
50 /* A function pointer for determining if the check applies */
53
54/*
55 * Special values for threshold_version for indicating that a check applies to
56 * all versions, or that a custom function needs to be invoked to determine
57 * if the check applies.
58 */
59#define MANUAL_CHECK 1
60#define ALL_VERSIONS -1
61
62/*--
63 * Data type usage checks. Each check for problematic data type usage is
64 * defined in this array with metadata, SQL query for finding the data type
65 * and functionality for deciding if the check is applicable to the version
66 * of the old cluster. The struct members are described in detail below:
67 *
68 * status A oneline string which can be printed to the user to
69 * inform about progress. Should not end with newline.
70 * report_filename The filename in which the list of problems detected by
71 * the check will be printed.
72 * base_query A query which extracts the Oid of the datatype checked
73 * for.
74 * report_text The text which will be printed to the user to explain
75 * what the check did, and why it failed. The text should
76 * end with a newline, and does not need to refer to the
77 * report_filename as that is automatically appended to
78 * the report with the path to the log folder.
79 * threshold_version The major version of PostgreSQL for which to run the
80 * check. Iff the old cluster is less than, or equal to,
81 * the threshold version then the check will be executed.
82 * If the old version is greater than the threshold then
83 * the check is skipped. If the threshold_version is set
84 * to ALL_VERSIONS then it will be run unconditionally,
85 * if set to MANUAL_CHECK then the version_hook function
86 * will be executed in order to determine whether or not
87 * to run.
88 * version_hook A function pointer to a version check function of type
89 * DataTypesUsageVersionCheck which is used to determine
90 * if the check is applicable to the old cluster. If the
91 * version_hook returns true then the check will be run,
92 * else it will be skipped. The function will only be
93 * executed iff threshold_version is set to MANUAL_CHECK.
94 */
96{
97 /*
98 * Look for composite types that were made during initdb *or* belong to
99 * information_schema; that's important in case information_schema was
100 * dropped and reloaded.
101 *
102 * The cutoff OID here should match the source cluster's value of
103 * FirstNormalObjectId. We hardcode it rather than using that C #define
104 * because, if that #define is ever changed, our own version's value is
105 * NOT what to use. Eventually we may need a test on the source cluster's
106 * version to select the correct value.
107 */
108 {
109 .status = gettext_noop("Checking for system-defined composite types in user tables"),
110 .report_filename = "tables_using_composite.txt",
111 .base_query =
112 "SELECT t.oid FROM pg_catalog.pg_type t "
113 "LEFT JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid "
114 " WHERE typtype = 'c' AND (t.oid < 16384 OR nspname = 'information_schema')",
115 .report_text =
116 gettext_noop("Your installation contains system-defined composite types in user tables.\n"
117 "These type OIDs are not stable across PostgreSQL versions,\n"
118 "so this cluster cannot currently be upgraded. You can drop the\n"
119 "problem columns and restart the upgrade.\n"),
120 .threshold_version = ALL_VERSIONS
121 },
122
123 /*
124 * 9.3 -> 9.4 Fully implement the 'line' data type in 9.4, which
125 * previously returned "not enabled" by default and was only functionally
126 * enabled with a compile-time switch; as of 9.4 "line" has a different
127 * on-disk representation format.
128 */
129 {
130 .status = gettext_noop("Checking for incompatible \"line\" data type"),
131 .report_filename = "tables_using_line.txt",
132 .base_query =
133 "SELECT 'pg_catalog.line'::pg_catalog.regtype AS oid",
134 .report_text =
135 gettext_noop("Your installation contains the \"line\" data type in user tables.\n"
136 "This data type changed its internal and input/output format\n"
137 "between your old and new versions so this\n"
138 "cluster cannot currently be upgraded. You can\n"
139 "drop the problem columns and restart the upgrade.\n"),
140 .threshold_version = 903
141 },
142
143 /*
144 * pg_upgrade only preserves these system values: pg_class.oid pg_type.oid
145 * pg_enum.oid
146 *
147 * Many of the reg* data types reference system catalog info that is not
148 * preserved, and hence these data types cannot be used in user tables
149 * upgraded by pg_upgrade.
150 */
151 {
152 .status = gettext_noop("Checking for reg* data types in user tables"),
153 .report_filename = "tables_using_reg.txt",
154
155 /*
156 * Note: older servers will not have all of these reg* types, so we
157 * have to write the query like this rather than depending on casts to
158 * regtype.
159 */
160 .base_query =
161 "SELECT oid FROM pg_catalog.pg_type t "
162 "WHERE t.typnamespace = "
163 " (SELECT oid FROM pg_catalog.pg_namespace "
164 " WHERE nspname = 'pg_catalog') "
165 " AND t.typname IN ( "
166 /* pg_class.oid is preserved, so 'regclass' is OK */
167 " 'regcollation', "
168 " 'regconfig', "
169 " 'regdictionary', "
170 " 'regnamespace', "
171 " 'regoper', "
172 " 'regoperator', "
173 " 'regproc', "
174 " 'regprocedure' "
175 /* pg_authid.oid is preserved, so 'regrole' is OK */
176 /* pg_type.oid is (mostly) preserved, so 'regtype' is OK */
177 " )",
178 .report_text =
179 gettext_noop("Your installation contains one of the reg* data types in user tables.\n"
180 "These data types reference system OIDs that are not preserved by\n"
181 "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
182 "drop the problem columns and restart the upgrade.\n"),
183 .threshold_version = ALL_VERSIONS
184 },
185
186 /*
187 * PG 16 increased the size of the 'aclitem' type, which breaks the
188 * on-disk format for existing data.
189 */
190 {
191 .status = gettext_noop("Checking for incompatible \"aclitem\" data type"),
192 .report_filename = "tables_using_aclitem.txt",
193 .base_query =
194 "SELECT 'pg_catalog.aclitem'::pg_catalog.regtype AS oid",
195 .report_text =
196 gettext_noop("Your installation contains the \"aclitem\" data type in user tables.\n"
197 "The internal format of \"aclitem\" changed in PostgreSQL version 16\n"
198 "so this cluster cannot currently be upgraded. You can drop the\n"
199 "problem columns and restart the upgrade.\n"),
200 .threshold_version = 1500
201 },
202
203 /*
204 * It's no longer allowed to create tables or views with "unknown"-type
205 * columns. We do not complain about views with such columns, because
206 * they should get silently converted to "text" columns during the DDL
207 * dump and reload; it seems unlikely to be worth making users do that by
208 * hand. However, if there's a table with such a column, the DDL reload
209 * will fail, so we should pre-detect that rather than failing
210 * mid-upgrade. Worse, if there's a matview with such a column, the DDL
211 * reload will silently change it to "text" which won't match the on-disk
212 * storage (which is like "cstring"). So we *must* reject that.
213 */
214 {
215 .status = gettext_noop("Checking for invalid \"unknown\" user columns"),
216 .report_filename = "tables_using_unknown.txt",
217 .base_query =
218 "SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid",
219 .report_text =
220 gettext_noop("Your installation contains the \"unknown\" data type in user tables.\n"
221 "This data type is no longer allowed in tables, so this cluster\n"
222 "cannot currently be upgraded. You can drop the problem columns\n"
223 "and restart the upgrade.\n"),
224 .threshold_version = 906
225 },
226
227 /*
228 * PG 12 changed the 'sql_identifier' type storage to be based on name,
229 * not varchar, which breaks on-disk format for existing data. So we need
230 * to prevent upgrade when used in user objects (tables, indexes, ...). In
231 * 12, the sql_identifier data type was switched from name to varchar,
232 * which does affect the storage (name is by-ref, but not varlena). This
233 * means user tables using sql_identifier for columns are broken because
234 * the on-disk format is different.
235 */
236 {
237 .status = gettext_noop("Checking for invalid \"sql_identifier\" user columns"),
238 .report_filename = "tables_using_sql_identifier.txt",
239 .base_query =
240 "SELECT 'information_schema.sql_identifier'::pg_catalog.regtype AS oid",
241 .report_text =
242 gettext_noop("Your installation contains the \"sql_identifier\" data type in user tables.\n"
243 "The on-disk format for this data type has changed, so this\n"
244 "cluster cannot currently be upgraded. You can drop the problem\n"
245 "columns and restart the upgrade.\n"),
246 .threshold_version = 1100
247 },
248
249 /*
250 * JSONB changed its storage format during 9.4 beta, so check for it.
251 */
252 {
253 .status = gettext_noop("Checking for incompatible \"jsonb\" data type in user tables"),
254 .report_filename = "tables_using_jsonb.txt",
255 .base_query =
256 "SELECT 'pg_catalog.jsonb'::pg_catalog.regtype AS oid",
257 .report_text =
258 gettext_noop("Your installation contains the \"jsonb\" data type in user tables.\n"
259 "The internal format of \"jsonb\" changed during 9.4 beta so this\n"
260 "cluster cannot currently be upgraded. You can drop the problem \n"
261 "columns and restart the upgrade.\n"),
262 .threshold_version = MANUAL_CHECK,
263 .version_hook = jsonb_9_4_check_applicable
264 },
265
266 /*
267 * PG 12 removed types abstime, reltime, tinterval.
268 */
269 {
270 .status = gettext_noop("Checking for removed \"abstime\" data type in user tables"),
271 .report_filename = "tables_using_abstime.txt",
272 .base_query =
273 "SELECT 'pg_catalog.abstime'::pg_catalog.regtype AS oid",
274 .report_text =
275 gettext_noop("Your installation contains the \"abstime\" data type in user tables.\n"
276 "The \"abstime\" type has been removed in PostgreSQL version 12,\n"
277 "so this cluster cannot currently be upgraded. You can drop the\n"
278 "problem columns, or change them to another data type, and restart\n"
279 "the upgrade.\n"),
280 .threshold_version = 1100
281 },
282 {
283 .status = gettext_noop("Checking for removed \"reltime\" data type in user tables"),
284 .report_filename = "tables_using_reltime.txt",
285 .base_query =
286 "SELECT 'pg_catalog.reltime'::pg_catalog.regtype AS oid",
287 .report_text =
288 gettext_noop("Your installation contains the \"reltime\" data type in user tables.\n"
289 "The \"reltime\" type has been removed in PostgreSQL version 12,\n"
290 "so this cluster cannot currently be upgraded. You can drop the\n"
291 "problem columns, or change them to another data type, and restart\n"
292 "the upgrade.\n"),
293 .threshold_version = 1100
294 },
295 {
296 .status = gettext_noop("Checking for removed \"tinterval\" data type in user tables"),
297 .report_filename = "tables_using_tinterval.txt",
298 .base_query =
299 "SELECT 'pg_catalog.tinterval'::pg_catalog.regtype AS oid",
300 .report_text =
301 gettext_noop("Your installation contains the \"tinterval\" data type in user tables.\n"
302 "The \"tinterval\" type has been removed in PostgreSQL version 12,\n"
303 "so this cluster cannot currently be upgraded. You can drop the\n"
304 "problem columns, or change them to another data type, and restart\n"
305 "the upgrade.\n"),
306 .threshold_version = 1100
307 },
308
309 /* End of checks marker, must remain last */
310 {
311 NULL, NULL, NULL, NULL, 0, NULL
312 }
313};
314
315/*
316 * Private state for check_for_data_types_usage()'s UpgradeTask.
317 */
319{
320 DataTypesUsageChecks *check; /* the check for this step */
321 bool result; /* true if check failed for any database */
322 PQExpBuffer *report; /* buffer for report on failed checks */
323};
324
325/*
326 * Returns a palloc'd query string for the data type check, for use by
327 * check_for_data_types_usage()'s UpgradeTask.
328 */
329static char *
331{
333
334 return psprintf("WITH RECURSIVE oids AS ( "
335 /* start with the type(s) returned by base_query */
336 " %s "
337 " UNION ALL "
338 " SELECT * FROM ( "
339 /* inner WITH because we can only reference the CTE once */
340 " WITH x AS (SELECT oid FROM oids) "
341 /* domains on any type selected so far */
342 " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typbasetype = x.oid AND typtype = 'd' "
343 " UNION ALL "
344 /* arrays over any type selected so far */
345 " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typelem = x.oid AND typtype = 'b' "
346 " UNION ALL "
347 /* composite types containing any type selected so far */
348 " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_class c, pg_catalog.pg_attribute a, x "
349 " WHERE t.typtype = 'c' AND "
350 " t.oid = c.reltype AND "
351 " c.oid = a.attrelid AND "
352 " NOT a.attisdropped AND "
353 " a.atttypid = x.oid "
354 " UNION ALL "
355 /* ranges containing any type selected so far */
356 " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_range r, x "
357 " WHERE t.typtype = 'r' AND r.rngtypid = t.oid AND r.rngsubtype = x.oid"
358 " ) foo "
359 ") "
360 /* now look for stored columns of any such type */
361 "SELECT n.nspname, c.relname, a.attname "
362 "FROM pg_catalog.pg_class c, "
363 " pg_catalog.pg_namespace n, "
364 " pg_catalog.pg_attribute a "
365 "WHERE c.oid = a.attrelid AND "
366 " NOT a.attisdropped AND "
367 " a.atttypid IN (SELECT oid FROM oids) AND "
368 " c.relkind IN ("
369 CppAsString2(RELKIND_RELATION) ", "
370 CppAsString2(RELKIND_MATVIEW) ", "
371 CppAsString2(RELKIND_INDEX) ") AND "
372 " c.relnamespace = n.oid AND "
373 /* exclude possible orphaned temp tables */
374 " n.nspname !~ '^pg_temp_' AND "
375 " n.nspname !~ '^pg_toast_temp_' AND "
376 /* exclude system catalogs, too */
377 " n.nspname NOT IN ('pg_catalog', 'information_schema')",
378 check->base_query);
379}
380
381/*
382 * Callback function for processing results of queries for
383 * check_for_data_types_usage()'s UpgradeTask. If the query returned any rows
384 * (i.e., the check failed), write the details to the report file.
385 */
386static void
388{
390 int ntups = PQntuples(res);
391 char output_path[MAXPGPATH];
392 int i_nspname = PQfnumber(res, "nspname");
393 int i_relname = PQfnumber(res, "relname");
394 int i_attname = PQfnumber(res, "attname");
395 FILE *script = NULL;
396
398
399 if (ntups == 0)
400 return;
401
402 snprintf(output_path, sizeof(output_path), "%s/%s",
404 state->check->report_filename);
405
406 /*
407 * Make sure we have a buffer to save reports to now that we found a first
408 * failing check.
409 */
410 if (*state->report == NULL)
411 *state->report = createPQExpBuffer();
412
413 /*
414 * If this is the first time we see an error for the check in question
415 * then print a status message of the failure.
416 */
417 if (!state->result)
418 {
419 pg_log(PG_REPORT, "failed check: %s", _(state->check->status));
420 appendPQExpBuffer(*state->report, "\n%s\n%s %s\n",
421 _(state->check->report_text),
422 _("A list of the problem columns is in the file:"),
423 output_path);
424 }
425 state->result = true;
426
427 if ((script = fopen_priv(output_path, "a")) == NULL)
428 pg_fatal("could not open file \"%s\": %m", output_path);
429
430 fprintf(script, "In database: %s\n", dbinfo->db_name);
431
432 for (int rowno = 0; rowno < ntups; rowno++)
433 fprintf(script, " %s.%s.%s\n",
434 PQgetvalue(res, rowno, i_nspname),
435 PQgetvalue(res, rowno, i_relname),
436 PQgetvalue(res, rowno, i_attname));
437
438 fclose(script);
439}
440
441/*
442 * check_for_data_types_usage()
443 * Detect whether there are any stored columns depending on given type(s)
444 *
445 * If so, write a report to the given file name and signal a failure to the
446 * user.
447 *
448 * The checks to run are defined in a DataTypesUsageChecks structure where
449 * each check has a metadata for explaining errors to the user, a base_query,
450 * a report filename and a function pointer hook for validating if the check
451 * should be executed given the cluster at hand.
452 *
453 * base_query should be a SELECT yielding a single column named "oid",
454 * containing the pg_type OIDs of one or more types that are known to have
455 * inconsistent on-disk representations across server versions.
456 *
457 * We check for the type(s) in tables, matviews, and indexes, but not views;
458 * there's no storage involved in a view.
459 */
460static void
462{
463 PQExpBuffer report = NULL;
465 int n_data_types_usage_checks = 0;
467 char **queries = NULL;
468 struct data_type_check_state *states;
469
470 prep_status("Checking data type usage");
471
472 /* Gather number of checks to perform */
473 while (tmp->status != NULL)
474 {
475 n_data_types_usage_checks++;
476 tmp++;
477 }
478
479 /* Allocate memory for queries and for task states */
480 queries = pg_malloc0(sizeof(char *) * n_data_types_usage_checks);
481 states = pg_malloc0(sizeof(struct data_type_check_state) * n_data_types_usage_checks);
482
483 for (int i = 0; i < n_data_types_usage_checks; i++)
484 {
486
488 {
490
491 /*
492 * Make sure that the check applies to the current cluster version
493 * and skip it if not.
494 */
496 continue;
497 }
499 {
500 if (GET_MAJOR_VERSION(cluster->major_version) > check->threshold_version)
501 continue;
502 }
503 else
505
506 queries[i] = data_type_check_query(i);
507
508 states[i].check = check;
509 states[i].report = &report;
510
512 true, &states[i]);
513 }
514
515 /*
516 * Connect to each database in the cluster and run all defined checks
517 * against that database before trying the next one.
518 */
520 upgrade_task_free(task);
521
522 if (report)
523 {
524 pg_fatal("Data type checks failed: %s", report->data);
526 }
527
528 for (int i = 0; i < n_data_types_usage_checks; i++)
529 {
530 if (queries[i])
531 pg_free(queries[i]);
532 }
533 pg_free(queries);
534 pg_free(states);
535
536 check_ok();
537}
538
539/*
540 * fix_path_separator
541 * For non-Windows, just return the argument.
542 * For Windows convert any forward slash to a backslash
543 * such as is suitable for arguments to builtin commands
544 * like RMDIR and DEL.
545 */
546static char *
548{
549#ifdef WIN32
550
551 char *result;
552 char *c;
553
554 result = pg_strdup(path);
555
556 for (c = result; *c != '\0'; c++)
557 if (*c == '/')
558 *c = '\\';
559
560 return result;
561#else
562
563 return path;
564#endif
565}
566
567void
569{
571 {
573 "Performing Consistency Checks on Old Live Server\n"
574 "------------------------------------------------");
575 }
576 else
577 {
579 "Performing Consistency Checks\n"
580 "-----------------------------");
581 }
582}
583
584
585void
587{
588 /* -- OLD -- */
589
592
593 /*
594 * First check that all databases allow connections since we'll otherwise
595 * fail in later stages.
596 */
598
599 /*
600 * Extract a list of databases, tables, and logical replication slots from
601 * the old cluster.
602 */
604
606
608
609
610 /*
611 * Check for various failure cases
612 */
616
618 {
619 /*
620 * Logical replication slots can be migrated since PG17. See comments
621 * atop get_old_cluster_logical_slot_infos().
622 */
624
625 /*
626 * Subscriptions and their dependencies can be migrated since PG17.
627 * Before that the logical slots are not upgraded, so we will not be
628 * able to upgrade the logical replication clusters completely.
629 */
632 }
633
635
636 /*
637 * PG 14 changed the function signature of encoding conversion functions.
638 * Conversions from older versions cannot be upgraded automatically
639 * because the user-defined functions used by the encoding conversions
640 * need to be changed to match the new signature.
641 */
644
645 /*
646 * Pre-PG 14 allowed user defined postfix operators, which are not
647 * supported anymore. Verify there are none, iff applicable.
648 */
651
652 /*
653 * PG 14 changed polymorphic functions from anyarray to
654 * anycompatiblearray.
655 */
658
659 /*
660 * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
661 * supported anymore. Verify there are none, iff applicable.
662 */
665
666 /*
667 * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
668 * hash indexes
669 */
671 {
672 if (user_opts.check)
674 }
675
676 /* 9.5 and below should not have roles starting with pg_ */
679
680 /*
681 * While not a check option, we do this now because this is the only time
682 * the old server is running.
683 */
684 if (!user_opts.check)
686
688 stop_postmaster(false);
689}
690
691
692void
694{
696
698
700
701 switch (user_opts.transfer_mode)
702 {
705 break;
707 break;
710 break;
713 break;
714 }
715
717
719
721
723
725}
726
727
728void
730{
731 if (user_opts.check)
732 {
733 pg_log(PG_REPORT, "\n*Clusters are compatible*");
734 /* stops new cluster */
735 stop_postmaster(false);
736
738 exit(0);
739 }
740
741 pg_log(PG_REPORT, "\n"
742 "If pg_upgrade fails after this point, you must re-initdb the\n"
743 "new cluster before continuing.");
744}
745
746
747void
749{
750 /*
751 * We unconditionally start/stop the new server because pg_resetwal -o set
752 * wal_level to 'minimum'. If the user is upgrading standby servers using
753 * the rsync instructions, they will need pg_upgrade to write its final
754 * WAL record showing wal_level as 'replica'.
755 */
757
758 /* Reindex hash indexes for old < 10.0 */
761
763
764 stop_postmaster(false);
765}
766
767
768void
769output_completion_banner(char *deletion_script_file_name)
770{
771 PQExpBufferData user_specification;
772
773 initPQExpBuffer(&user_specification);
775 {
776 appendPQExpBufferStr(&user_specification, "-U ");
777 appendShellString(&user_specification, os_info.user);
778 appendPQExpBufferChar(&user_specification, ' ');
779 }
780
782 "Optimizer statistics are not transferred by pg_upgrade.\n"
783 "Once you start the new server, consider running:\n"
784 " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data);
785
786 if (deletion_script_file_name)
788 "Running this script will delete the old cluster's data files:\n"
789 " %s",
790 deletion_script_file_name);
791 else
793 "Could not create a script to delete the old cluster's data files\n"
794 "because user-defined tablespaces or the new cluster's data directory\n"
795 "exist in the old cluster directory. The old cluster's contents must\n"
796 "be deleted manually.");
797
798 termPQExpBuffer(&user_specification);
799}
800
801
802void
804{
805 prep_status("Checking cluster versions");
806
807 /* cluster versions should already have been obtained */
810
811 /*
812 * We allow upgrades from/to the same major version for alpha/beta
813 * upgrades
814 */
815
817 pg_fatal("This utility can only upgrade from PostgreSQL version %s and later.",
818 "9.2");
819
820 /* Only current PG version is supported as a target */
822 pg_fatal("This utility can only upgrade to PostgreSQL version %s.",
823 PG_MAJORVERSION);
824
825 /*
826 * We can't allow downgrading because we use the target pg_dump, and
827 * pg_dump cannot operate on newer database versions, only current and
828 * older versions.
829 */
831 pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.");
832
833 /* Ensure binaries match the designated data directories */
836 pg_fatal("Old cluster data and binary directories are from different major versions.");
839 pg_fatal("New cluster data and binary directories are from different major versions.");
840
841 check_ok();
842}
843
844
845void
847{
848 /* get/check pg_control data of servers */
852
854 pg_fatal("When checking a live server, "
855 "the old and new port numbers must be different.");
856}
857
858
859static void
861{
862 int dbnum;
863
864 for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
865 {
866 int relnum;
867 RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
868
869 for (relnum = 0; relnum < rel_arr->nrels;
870 relnum++)
871 {
872 /* pg_largeobject and its index should be skipped */
873 if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
874 pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"",
876 rel_arr->rels[relnum].nspname,
877 rel_arr->rels[relnum].relname);
878 }
879 }
880}
881
882/*
883 * A previous run of pg_upgrade might have failed and the new cluster
884 * directory recreated, but they might have forgotten to remove
885 * the new cluster's tablespace directories. Therefore, check that
886 * new cluster tablespace directories do not already exist. If
887 * they do, it would cause an error while restoring global objects.
888 * This allows the failure to be detected at check time, rather than
889 * during schema restore.
890 */
891static void
893{
894 int tblnum;
895 char new_tablespace_dir[MAXPGPATH];
896
897 prep_status("Checking for new cluster tablespace directories");
898
899 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
900 {
901 struct stat statbuf;
902
903 snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
904 os_info.old_tablespaces[tblnum],
906
907 if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
908 pg_fatal("new cluster tablespace directory already exists: \"%s\"",
909 new_tablespace_dir);
910 }
911
912 check_ok();
913}
914
915/*
916 * create_script_for_old_cluster_deletion()
917 *
918 * This is particularly useful for tablespace deletion.
919 */
920void
921create_script_for_old_cluster_deletion(char **deletion_script_file_name)
922{
923 FILE *script = NULL;
924 int tblnum;
925 char old_cluster_pgdata[MAXPGPATH],
926 new_cluster_pgdata[MAXPGPATH];
927
928 *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
930
931 strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
932 canonicalize_path(old_cluster_pgdata);
933
934 strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
935 canonicalize_path(new_cluster_pgdata);
936
937 /* Some people put the new data directory inside the old one. */
938 if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
939 {
941 "\nWARNING: new data directory should not be inside the old data directory, i.e. %s", old_cluster_pgdata);
942
943 /* Unlink file in case it is left over from a previous run. */
944 unlink(*deletion_script_file_name);
945 pg_free(*deletion_script_file_name);
946 *deletion_script_file_name = NULL;
947 return;
948 }
949
950 /*
951 * Some users (oddly) create tablespaces inside the cluster data
952 * directory. We can't create a proper old cluster delete script in that
953 * case.
954 */
955 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
956 {
957 char old_tablespace_dir[MAXPGPATH];
958
959 strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
960 canonicalize_path(old_tablespace_dir);
961 if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
962 {
963 /* reproduce warning from CREATE TABLESPACE that is in the log */
965 "\nWARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s", old_tablespace_dir);
966
967 /* Unlink file in case it is left over from a previous run. */
968 unlink(*deletion_script_file_name);
969 pg_free(*deletion_script_file_name);
970 *deletion_script_file_name = NULL;
971 return;
972 }
973 }
974
975 prep_status("Creating script to delete old cluster");
976
977 if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
978 pg_fatal("could not open file \"%s\": %m",
979 *deletion_script_file_name);
980
981#ifndef WIN32
982 /* add shebang header */
983 fprintf(script, "#!/bin/sh\n\n");
984#endif
985
986 /* delete old cluster's default tablespace */
987 fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
989
990 /* delete old cluster's alternate tablespaces */
991 for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
992 {
993 /*
994 * Do the old cluster's per-database directories share a directory
995 * with a new version-specific tablespace?
996 */
997 if (strlen(old_cluster.tablespace_suffix) == 0)
998 {
999 /* delete per-database directories */
1000 int dbnum;
1001
1002 fprintf(script, "\n");
1003
1004 for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
1005 fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
1008 PATH_QUOTE);
1009 }
1010 else
1011 {
1012 char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
1013
1014 /*
1015 * Simply delete the tablespace directory, which might be ".old"
1016 * or a version-specific subdirectory.
1017 */
1018 fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
1020 fix_path_separator(suffix_path), PATH_QUOTE);
1021 pfree(suffix_path);
1022 }
1023 }
1024
1025 fclose(script);
1026
1027#ifndef WIN32
1028 if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
1029 pg_fatal("could not add execute permission to file \"%s\": %m",
1030 *deletion_script_file_name);
1031#endif
1032
1033 check_ok();
1034}
1035
1036
1037/*
1038 * check_is_install_user()
1039 *
1040 * Check we are the install user, and that the new cluster
1041 * has no other users.
1042 */
1043static void
1045{
1046 PGresult *res;
1047 PGconn *conn = connectToServer(cluster, "template1");
1048
1049 prep_status("Checking database user is the install user");
1050
1051 /* Can't use pg_authid because only superusers can view it. */
1053 "SELECT rolsuper, oid "
1054 "FROM pg_catalog.pg_roles "
1055 "WHERE rolname = current_user "
1056 "AND rolname !~ '^pg_'");
1057
1058 /*
1059 * We only allow the install user in the new cluster (see comment below)
1060 * and we preserve pg_authid.oid, so this must be the install user in the
1061 * old cluster too.
1062 */
1063 if (PQntuples(res) != 1 ||
1064 atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
1065 pg_fatal("database user \"%s\" is not the install user",
1066 os_info.user);
1067
1068 PQclear(res);
1069
1071 "SELECT COUNT(*) "
1072 "FROM pg_catalog.pg_roles "
1073 "WHERE rolname !~ '^pg_'");
1074
1075 if (PQntuples(res) != 1)
1076 pg_fatal("could not determine the number of users");
1077
1078 /*
1079 * We only allow the install user in the new cluster because other defined
1080 * users might match users defined in the old cluster and generate an
1081 * error during pg_dump restore.
1082 */
1083 if (cluster == &new_cluster && strcmp(PQgetvalue(res, 0, 0), "1") != 0)
1084 pg_fatal("Only the install user can be defined in the new cluster.");
1085
1086 PQclear(res);
1087
1088 PQfinish(conn);
1089
1090 check_ok();
1091}
1092
1093
1094/*
1095 * check_for_connection_status
1096 *
1097 * Ensure that all non-template0 databases allow connections since they
1098 * otherwise won't be restored; and that template0 explicitly doesn't allow
1099 * connections since it would make pg_dumpall --globals restore fail.
1100 */
1101static void
1103{
1104 int dbnum;
1105 PGconn *conn_template1;
1106 PGresult *dbres;
1107 int ntups;
1108 int i_datname;
1109 int i_datallowconn;
1110 int i_datconnlimit;
1111 FILE *script = NULL;
1112 char output_path[MAXPGPATH];
1113
1114 prep_status("Checking database connection settings");
1115
1116 snprintf(output_path, sizeof(output_path), "%s/%s",
1118 "databases_cannot_connect_to.txt");
1119
1120 conn_template1 = connectToServer(cluster, "template1");
1121
1122 /* get database names */
1123 dbres = executeQueryOrDie(conn_template1,
1124 "SELECT datname, datallowconn, datconnlimit "
1125 "FROM pg_catalog.pg_database");
1126
1127 i_datname = PQfnumber(dbres, "datname");
1128 i_datallowconn = PQfnumber(dbres, "datallowconn");
1129 i_datconnlimit = PQfnumber(dbres, "datconnlimit");
1130
1131 ntups = PQntuples(dbres);
1132 for (dbnum = 0; dbnum < ntups; dbnum++)
1133 {
1134 char *datname = PQgetvalue(dbres, dbnum, i_datname);
1135 char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
1136 char *datconnlimit = PQgetvalue(dbres, dbnum, i_datconnlimit);
1137
1138 if (strcmp(datname, "template0") == 0)
1139 {
1140 /* avoid restore failure when pg_dumpall tries to create template0 */
1141 if (strcmp(datallowconn, "t") == 0)
1142 pg_fatal("template0 must not allow connections, "
1143 "i.e. its pg_database.datallowconn must be false");
1144 }
1145 else
1146 {
1147 /*
1148 * Avoid datallowconn == false databases from being skipped on
1149 * restore, and ensure that no databases are marked invalid with
1150 * datconnlimit == -2.
1151 */
1152 if ((strcmp(datallowconn, "f") == 0) || strcmp(datconnlimit, "-2") == 0)
1153 {
1154 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1155 pg_fatal("could not open file \"%s\": %m", output_path);
1156
1157 fprintf(script, "%s\n", datname);
1158 }
1159 }
1160 }
1161
1162 PQclear(dbres);
1163
1164 PQfinish(conn_template1);
1165
1166 if (script)
1167 {
1168 fclose(script);
1169 pg_log(PG_REPORT, "fatal");
1170 pg_fatal("All non-template0 databases must allow connections, i.e. their\n"
1171 "pg_database.datallowconn must be true and pg_database.datconnlimit\n"
1172 "must not be -2. Your installation contains non-template0 databases\n"
1173 "which cannot be connected to. Consider allowing connection for all\n"
1174 "non-template0 databases or drop the databases which do not allow\n"
1175 "connections. A list of databases with the problem is in the file:\n"
1176 " %s", output_path);
1177 }
1178 else
1179 check_ok();
1180}
1181
1182
1183/*
1184 * check_for_prepared_transactions()
1185 *
1186 * Make sure there are no prepared transactions because the storage format
1187 * might have changed.
1188 */
1189static void
1191{
1192 PGresult *res;
1193 PGconn *conn = connectToServer(cluster, "template1");
1194
1195 prep_status("Checking for prepared transactions");
1196
1198 "SELECT * "
1199 "FROM pg_catalog.pg_prepared_xacts");
1200
1201 if (PQntuples(res) != 0)
1202 {
1203 if (cluster == &old_cluster)
1204 pg_fatal("The source cluster contains prepared transactions");
1205 else
1206 pg_fatal("The target cluster contains prepared transactions");
1207 }
1208
1209 PQclear(res);
1210
1211 PQfinish(conn);
1212
1213 check_ok();
1214}
1215
1216/*
1217 * Callback function for processing result of query for
1218 * check_for_isn_and_int8_passing_mismatch()'s UpgradeTask. If the query
1219 * returned any rows (i.e., the check failed), write the details to the report
1220 * file.
1221 */
1222static void
1224{
1225 int ntups = PQntuples(res);
1226 int i_nspname = PQfnumber(res, "nspname");
1227 int i_proname = PQfnumber(res, "proname");
1229
1232
1233 if (ntups == 0)
1234 return;
1235
1236 if (report->file == NULL &&
1237 (report->file = fopen_priv(report->path, "w")) == NULL)
1238 pg_fatal("could not open file \"%s\": %m", report->path);
1239
1240 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1241
1242 for (int rowno = 0; rowno < ntups; rowno++)
1243 fprintf(report->file, " %s.%s\n",
1244 PQgetvalue(res, rowno, i_nspname),
1245 PQgetvalue(res, rowno, i_proname));
1246}
1247
1248/*
1249 * check_for_isn_and_int8_passing_mismatch()
1250 *
1251 * contrib/isn relies on data type int8, and in 8.4 int8 can now be passed
1252 * by value. The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
1253 * it must match for the old and new servers.
1254 */
1255static void
1257{
1258 UpgradeTask *task;
1259 UpgradeTaskReport report;
1260 const char *query = "SELECT n.nspname, p.proname "
1261 "FROM pg_catalog.pg_proc p, "
1262 " pg_catalog.pg_namespace n "
1263 "WHERE p.pronamespace = n.oid AND "
1264 " p.probin = '$libdir/isn'";
1265
1266 prep_status("Checking for contrib/isn with bigint-passing mismatch");
1267
1270 {
1271 /* no mismatch */
1272 check_ok();
1273 return;
1274 }
1275
1276 report.file = NULL;
1277 snprintf(report.path, sizeof(report.path), "%s/%s",
1279 "contrib_isn_and_int8_pass_by_value.txt");
1280
1281 task = upgrade_task_create();
1283 true, &report);
1285 upgrade_task_free(task);
1286
1287 if (report.file)
1288 {
1289 fclose(report.file);
1290 pg_log(PG_REPORT, "fatal");
1291 pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
1292 "bigint data type. Your old and new clusters pass bigint values\n"
1293 "differently so this cluster cannot currently be upgraded. You can\n"
1294 "manually dump databases in the old cluster that use \"contrib/isn\"\n"
1295 "facilities, drop them, perform the upgrade, and then restore them. A\n"
1296 "list of the problem functions is in the file:\n"
1297 " %s", report.path);
1298 }
1299 else
1300 check_ok();
1301}
1302
1303/*
1304 * Callback function for processing result of query for
1305 * check_for_user_defined_postfix_ops()'s UpgradeTask. If the query returned
1306 * any rows (i.e., the check failed), write the details to the report file.
1307 */
1308static void
1310{
1312 int ntups = PQntuples(res);
1313 int i_oproid = PQfnumber(res, "oproid");
1314 int i_oprnsp = PQfnumber(res, "oprnsp");
1315 int i_oprname = PQfnumber(res, "oprname");
1316 int i_typnsp = PQfnumber(res, "typnsp");
1317 int i_typname = PQfnumber(res, "typname");
1318
1321
1322 if (ntups == 0)
1323 return;
1324
1325 if (report->file == NULL &&
1326 (report->file = fopen_priv(report->path, "w")) == NULL)
1327 pg_fatal("could not open file \"%s\": %m", report->path);
1328
1329 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1330
1331 for (int rowno = 0; rowno < ntups; rowno++)
1332 fprintf(report->file, " (oid=%s) %s.%s (%s.%s, NONE)\n",
1333 PQgetvalue(res, rowno, i_oproid),
1334 PQgetvalue(res, rowno, i_oprnsp),
1335 PQgetvalue(res, rowno, i_oprname),
1336 PQgetvalue(res, rowno, i_typnsp),
1337 PQgetvalue(res, rowno, i_typname));
1338}
1339
1340/*
1341 * Verify that no user defined postfix operators exist.
1342 */
1343static void
1345{
1346 UpgradeTaskReport report;
1348 const char *query;
1349
1350 /*
1351 * The query below hardcodes FirstNormalObjectId as 16384 rather than
1352 * interpolating that C #define into the query because, if that #define is
1353 * ever changed, the cutoff we want to use is the value used by
1354 * pre-version 14 servers, not that of some future version.
1355 */
1356 query = "SELECT o.oid AS oproid, "
1357 " n.nspname AS oprnsp, "
1358 " o.oprname, "
1359 " tn.nspname AS typnsp, "
1360 " t.typname "
1361 "FROM pg_catalog.pg_operator o, "
1362 " pg_catalog.pg_namespace n, "
1363 " pg_catalog.pg_type t, "
1364 " pg_catalog.pg_namespace tn "
1365 "WHERE o.oprnamespace = n.oid AND "
1366 " o.oprleft = t.oid AND "
1367 " t.typnamespace = tn.oid AND "
1368 " o.oprright = 0 AND "
1369 " o.oid >= 16384";
1370
1371 prep_status("Checking for user-defined postfix operators");
1372
1373 report.file = NULL;
1374 snprintf(report.path, sizeof(report.path), "%s/%s",
1376 "postfix_ops.txt");
1377
1379 true, &report);
1381 upgrade_task_free(task);
1382
1383 if (report.file)
1384 {
1385 fclose(report.file);
1386 pg_log(PG_REPORT, "fatal");
1387 pg_fatal("Your installation contains user-defined postfix operators, which are not\n"
1388 "supported anymore. Consider dropping the postfix operators and replacing\n"
1389 "them with prefix operators or function calls.\n"
1390 "A list of user-defined postfix operators is in the file:\n"
1391 " %s", report.path);
1392 }
1393 else
1394 check_ok();
1395}
1396
1397/*
1398 * Callback function for processing results of query for
1399 * check_for_incompatible_polymorphics()'s UpgradeTask. If the query returned
1400 * any rows (i.e., the check failed), write the details to the report file.
1401 */
1402static void
1404{
1406 int ntups = PQntuples(res);
1407 int i_objkind = PQfnumber(res, "objkind");
1408 int i_objname = PQfnumber(res, "objname");
1409
1412
1413 if (ntups == 0)
1414 return;
1415
1416 if (report->file == NULL &&
1417 (report->file = fopen_priv(report->path, "w")) == NULL)
1418 pg_fatal("could not open file \"%s\": %m", report->path);
1419
1420 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1421
1422 for (int rowno = 0; rowno < ntups; rowno++)
1423 fprintf(report->file, " %s: %s\n",
1424 PQgetvalue(res, rowno, i_objkind),
1425 PQgetvalue(res, rowno, i_objname));
1426}
1427
1428/*
1429 * check_for_incompatible_polymorphics()
1430 *
1431 * Make sure nothing is using old polymorphic functions with
1432 * anyarray/anyelement rather than the new anycompatible variants.
1433 */
1434static void
1436{
1437 PQExpBufferData old_polymorphics;
1439 UpgradeTaskReport report;
1440 char *query;
1441
1442 prep_status("Checking for incompatible polymorphic functions");
1443
1444 report.file = NULL;
1445 snprintf(report.path, sizeof(report.path), "%s/%s",
1447 "incompatible_polymorphics.txt");
1448
1449 /* The set of problematic functions varies a bit in different versions */
1450 initPQExpBuffer(&old_polymorphics);
1451
1452 appendPQExpBufferStr(&old_polymorphics,
1453 "'array_append(anyarray,anyelement)'"
1454 ", 'array_cat(anyarray,anyarray)'"
1455 ", 'array_prepend(anyelement,anyarray)'");
1456
1457 if (GET_MAJOR_VERSION(cluster->major_version) >= 903)
1458 appendPQExpBufferStr(&old_polymorphics,
1459 ", 'array_remove(anyarray,anyelement)'"
1460 ", 'array_replace(anyarray,anyelement,anyelement)'");
1461
1462 if (GET_MAJOR_VERSION(cluster->major_version) >= 905)
1463 appendPQExpBufferStr(&old_polymorphics,
1464 ", 'array_position(anyarray,anyelement)'"
1465 ", 'array_position(anyarray,anyelement,integer)'"
1466 ", 'array_positions(anyarray,anyelement)'"
1467 ", 'width_bucket(anyelement,anyarray)'");
1468
1469 /*
1470 * The query below hardcodes FirstNormalObjectId as 16384 rather than
1471 * interpolating that C #define into the query because, if that #define is
1472 * ever changed, the cutoff we want to use is the value used by
1473 * pre-version 14 servers, not that of some future version.
1474 */
1475
1476 /* Aggregate transition functions */
1477 query = psprintf("SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1478 "FROM pg_proc AS p "
1479 "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1480 "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
1481 "WHERE p.oid >= 16384 "
1482 "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
1483 "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1484
1485 /* Aggregate final functions */
1486 "UNION ALL "
1487 "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1488 "FROM pg_proc AS p "
1489 "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1490 "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
1491 "WHERE p.oid >= 16384 "
1492 "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
1493 "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1494
1495 /* Operators */
1496 "UNION ALL "
1497 "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
1498 "FROM pg_operator AS op "
1499 "WHERE op.oid >= 16384 "
1500 "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) "
1501 "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[])",
1502 old_polymorphics.data,
1503 old_polymorphics.data,
1504 old_polymorphics.data);
1505
1507 true, &report);
1509 upgrade_task_free(task);
1510
1511 if (report.file)
1512 {
1513 fclose(report.file);
1514 pg_log(PG_REPORT, "fatal");
1515 pg_fatal("Your installation contains user-defined objects that refer to internal\n"
1516 "polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n"
1517 "These user-defined objects must be dropped before upgrading and restored\n"
1518 "afterwards, changing them to refer to the new corresponding functions with\n"
1519 "arguments of type \"anycompatiblearray\" and \"anycompatible\".\n"
1520 "A list of the problematic objects is in the file:\n"
1521 " %s", report.path);
1522 }
1523 else
1524 check_ok();
1525
1526 termPQExpBuffer(&old_polymorphics);
1527 pg_free(query);
1528}
1529
1530/*
1531 * Callback function for processing results of query for
1532 * check_for_tables_with_oids()'s UpgradeTask. If the query returned any rows
1533 * (i.e., the check failed), write the details to the report file.
1534 */
1535static void
1537{
1539 int ntups = PQntuples(res);
1540 int i_nspname = PQfnumber(res, "nspname");
1541 int i_relname = PQfnumber(res, "relname");
1542
1544
1545 if (ntups == 0)
1546 return;
1547
1548 if (report->file == NULL &&
1549 (report->file = fopen_priv(report->path, "w")) == NULL)
1550 pg_fatal("could not open file \"%s\": %m", report->path);
1551
1552 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1553
1554 for (int rowno = 0; rowno < ntups; rowno++)
1555 fprintf(report->file, " %s.%s\n",
1556 PQgetvalue(res, rowno, i_nspname),
1557 PQgetvalue(res, rowno, i_relname));
1558}
1559
1560/*
1561 * Verify that no tables are declared WITH OIDS.
1562 */
1563static void
1565{
1566 UpgradeTaskReport report;
1568 const char *query = "SELECT n.nspname, c.relname "
1569 "FROM pg_catalog.pg_class c, "
1570 " pg_catalog.pg_namespace n "
1571 "WHERE c.relnamespace = n.oid AND "
1572 " c.relhasoids AND"
1573 " n.nspname NOT IN ('pg_catalog')";
1574
1575 prep_status("Checking for tables WITH OIDS");
1576
1577 report.file = NULL;
1578 snprintf(report.path, sizeof(report.path), "%s/%s",
1580 "tables_with_oids.txt");
1581
1583 true, &report);
1585 upgrade_task_free(task);
1586
1587 if (report.file)
1588 {
1589 fclose(report.file);
1590 pg_log(PG_REPORT, "fatal");
1591 pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n"
1592 "supported anymore. Consider removing the oid column using\n"
1593 " ALTER TABLE ... SET WITHOUT OIDS;\n"
1594 "A list of tables with the problem is in the file:\n"
1595 " %s", report.path);
1596 }
1597 else
1598 check_ok();
1599}
1600
1601
1602/*
1603 * check_for_pg_role_prefix()
1604 *
1605 * Versions older than 9.6 should not have any pg_* roles
1606 */
1607static void
1609{
1610 PGresult *res;
1611 PGconn *conn = connectToServer(cluster, "template1");
1612 int ntups;
1613 int i_roloid;
1614 int i_rolname;
1615 FILE *script = NULL;
1616 char output_path[MAXPGPATH];
1617
1618 prep_status("Checking for roles starting with \"pg_\"");
1619
1620 snprintf(output_path, sizeof(output_path), "%s/%s",
1622 "pg_role_prefix.txt");
1623
1625 "SELECT oid AS roloid, rolname "
1626 "FROM pg_catalog.pg_roles "
1627 "WHERE rolname ~ '^pg_'");
1628
1629 ntups = PQntuples(res);
1630 i_roloid = PQfnumber(res, "roloid");
1631 i_rolname = PQfnumber(res, "rolname");
1632 for (int rowno = 0; rowno < ntups; rowno++)
1633 {
1634 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1635 pg_fatal("could not open file \"%s\": %m", output_path);
1636 fprintf(script, "%s (oid=%s)\n",
1637 PQgetvalue(res, rowno, i_rolname),
1638 PQgetvalue(res, rowno, i_roloid));
1639 }
1640
1641 PQclear(res);
1642
1643 PQfinish(conn);
1644
1645 if (script)
1646 {
1647 fclose(script);
1648 pg_log(PG_REPORT, "fatal");
1649 pg_fatal("Your installation contains roles starting with \"pg_\".\n"
1650 "\"pg_\" is a reserved prefix for system roles. The cluster\n"
1651 "cannot be upgraded until these roles are renamed.\n"
1652 "A list of roles starting with \"pg_\" is in the file:\n"
1653 " %s", output_path);
1654 }
1655 else
1656 check_ok();
1657}
1658
1659/*
1660 * Callback function for processing results of query for
1661 * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query
1662 * returned any rows (i.e., the check failed), write the details to the report
1663 * file.
1664 */
1665static void
1667{
1669 int ntups = PQntuples(res);
1670 int i_conoid = PQfnumber(res, "conoid");
1671 int i_conname = PQfnumber(res, "conname");
1672 int i_nspname = PQfnumber(res, "nspname");
1673
1676
1677 if (ntups == 0)
1678 return;
1679
1680 if (report->file == NULL &&
1681 (report->file = fopen_priv(report->path, "w")) == NULL)
1682 pg_fatal("could not open file \"%s\": %m", report->path);
1683
1684 fprintf(report->file, "In database: %s\n", dbinfo->db_name);
1685
1686 for (int rowno = 0; rowno < ntups; rowno++)
1687 fprintf(report->file, " (oid=%s) %s.%s\n",
1688 PQgetvalue(res, rowno, i_conoid),
1689 PQgetvalue(res, rowno, i_nspname),
1690 PQgetvalue(res, rowno, i_conname));
1691}
1692
1693/*
1694 * Verify that no user-defined encoding conversions exist.
1695 */
1696static void
1698{
1699 UpgradeTaskReport report;
1701 const char *query;
1702
1703 prep_status("Checking for user-defined encoding conversions");
1704
1705 report.file = NULL;
1706 snprintf(report.path, sizeof(report.path), "%s/%s",
1708 "encoding_conversions.txt");
1709
1710 /*
1711 * The query below hardcodes FirstNormalObjectId as 16384 rather than
1712 * interpolating that C #define into the query because, if that #define is
1713 * ever changed, the cutoff we want to use is the value used by
1714 * pre-version 14 servers, not that of some future version.
1715 */
1716 query = "SELECT c.oid as conoid, c.conname, n.nspname "
1717 "FROM pg_catalog.pg_conversion c, "
1718 " pg_catalog.pg_namespace n "
1719 "WHERE c.connamespace = n.oid AND "
1720 " c.oid >= 16384";
1721
1722 upgrade_task_add_step(task, query,
1724 true, &report);
1726 upgrade_task_free(task);
1727
1728 if (report.file)
1729 {
1730 fclose(report.file);
1731 pg_log(PG_REPORT, "fatal");
1732 pg_fatal("Your installation contains user-defined encoding conversions.\n"
1733 "The conversion function parameters changed in PostgreSQL version 14\n"
1734 "so this cluster cannot currently be upgraded. You can remove the\n"
1735 "encoding conversions in the old cluster and restart the upgrade.\n"
1736 "A list of user-defined encoding conversions is in the file:\n"
1737 " %s", report.path);
1738 }
1739 else
1740 check_ok();
1741}
1742
1743/*
1744 * check_new_cluster_logical_replication_slots()
1745 *
1746 * Verify that there are no logical replication slots on the new cluster and
1747 * that the parameter settings necessary for creating slots are sufficient.
1748 */
1749static void
1751{
1752 PGresult *res;
1753 PGconn *conn;
1754 int nslots_on_old;
1755 int nslots_on_new;
1757 char *wal_level;
1758
1759 /* Logical slots can be migrated since PG17. */
1761 return;
1762
1763 nslots_on_old = count_old_cluster_logical_slots();
1764
1765 /* Quick return if there are no logical slots to be migrated. */
1766 if (nslots_on_old == 0)
1767 return;
1768
1769 conn = connectToServer(&new_cluster, "template1");
1770
1771 prep_status("Checking for new cluster logical replication slots");
1772
1773 res = executeQueryOrDie(conn, "SELECT count(*) "
1774 "FROM pg_catalog.pg_replication_slots "
1775 "WHERE slot_type = 'logical' AND "
1776 "temporary IS FALSE;");
1777
1778 if (PQntuples(res) != 1)
1779 pg_fatal("could not count the number of logical replication slots");
1780
1781 nslots_on_new = atoi(PQgetvalue(res, 0, 0));
1782
1783 if (nslots_on_new)
1784 pg_fatal("expected 0 logical replication slots but found %d",
1785 nslots_on_new);
1786
1787 PQclear(res);
1788
1789 res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
1790 "WHERE name IN ('wal_level', 'max_replication_slots') "
1791 "ORDER BY name DESC;");
1792
1793 if (PQntuples(res) != 2)
1794 pg_fatal("could not determine parameter settings on new cluster");
1795
1796 wal_level = PQgetvalue(res, 0, 0);
1797
1798 if (strcmp(wal_level, "logical") != 0)
1799 pg_fatal("\"wal_level\" must be \"logical\" but is set to \"%s\"",
1800 wal_level);
1801
1802 max_replication_slots = atoi(PQgetvalue(res, 1, 0));
1803
1804 if (nslots_on_old > max_replication_slots)
1805 pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of "
1806 "logical replication slots (%d) on the old cluster",
1807 max_replication_slots, nslots_on_old);
1808
1809 PQclear(res);
1810 PQfinish(conn);
1811
1812 check_ok();
1813}
1814
1815/*
1816 * check_new_cluster_subscription_configuration()
1817 *
1818 * Verify that the max_replication_slots configuration specified is enough for
1819 * creating the subscriptions. This is required to create the replication
1820 * origin for each subscription.
1821 */
1822static void
1824{
1825 PGresult *res;
1826 PGconn *conn;
1828
1829 /* Subscriptions and their dependencies can be migrated since PG17. */
1831 return;
1832
1833 /* Quick return if there are no subscriptions to be migrated. */
1834 if (old_cluster.nsubs == 0)
1835 return;
1836
1837 prep_status("Checking for new cluster configuration for subscriptions");
1838
1839 conn = connectToServer(&new_cluster, "template1");
1840
1841 res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings "
1842 "WHERE name = 'max_replication_slots';");
1843
1844 if (PQntuples(res) != 1)
1845 pg_fatal("could not determine parameter settings on new cluster");
1846
1847 max_replication_slots = atoi(PQgetvalue(res, 0, 0));
1849 pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of "
1850 "subscriptions (%d) on the old cluster",
1852
1853 PQclear(res);
1854 PQfinish(conn);
1855
1856 check_ok();
1857}
1858
1859/*
1860 * check_old_cluster_for_valid_slots()
1861 *
1862 * Verify that all the logical slots are valid and have consumed all the WAL
1863 * before shutdown.
1864 */
1865static void
1867{
1868 char output_path[MAXPGPATH];
1869 FILE *script = NULL;
1870
1871 prep_status("Checking for valid logical replication slots");
1872
1873 snprintf(output_path, sizeof(output_path), "%s/%s",
1875 "invalid_logical_slots.txt");
1876
1877 for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
1878 {
1879 LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
1880
1881 for (int slotnum = 0; slotnum < slot_arr->nslots; slotnum++)
1882 {
1883 LogicalSlotInfo *slot = &slot_arr->slots[slotnum];
1884
1885 /* Is the slot usable? */
1886 if (slot->invalid)
1887 {
1888 if (script == NULL &&
1889 (script = fopen_priv(output_path, "w")) == NULL)
1890 pg_fatal("could not open file \"%s\": %m", output_path);
1891
1892 fprintf(script, "The slot \"%s\" is invalid\n",
1893 slot->slotname);
1894
1895 continue;
1896 }
1897
1898 /*
1899 * Do additional check to ensure that all logical replication
1900 * slots have consumed all the WAL before shutdown.
1901 *
1902 * Note: This can be satisfied only when the old cluster has been
1903 * shut down, so we skip this for live checks.
1904 */
1905 if (!user_opts.live_check && !slot->caught_up)
1906 {
1907 if (script == NULL &&
1908 (script = fopen_priv(output_path, "w")) == NULL)
1909 pg_fatal("could not open file \"%s\": %m", output_path);
1910
1911 fprintf(script,
1912 "The slot \"%s\" has not consumed the WAL yet\n",
1913 slot->slotname);
1914 }
1915 }
1916 }
1917
1918 if (script)
1919 {
1920 fclose(script);
1921
1922 pg_log(PG_REPORT, "fatal");
1923 pg_fatal("Your installation contains logical replication slots that cannot be upgraded.\n"
1924 "You can remove invalid slots and/or consume the pending WAL for other slots,\n"
1925 "and then restart the upgrade.\n"
1926 "A list of the problematic slots is in the file:\n"
1927 " %s", output_path);
1928 }
1929
1930 check_ok();
1931}
1932
1933/*
1934 * Callback function for processing results of query for
1935 * check_old_cluster_subscription_state()'s UpgradeTask. If the query returned
1936 * any rows (i.e., the check failed), write the details to the report file.
1937 */
1938static void
1940{
1942 int ntups = PQntuples(res);
1943 int i_srsubstate = PQfnumber(res, "srsubstate");
1944 int i_subname = PQfnumber(res, "subname");
1945 int i_nspname = PQfnumber(res, "nspname");
1946 int i_relname = PQfnumber(res, "relname");
1947
1949
1950 if (ntups == 0)
1951 return;
1952
1953 if (report->file == NULL &&
1954 (report->file = fopen_priv(report->path, "w")) == NULL)
1955 pg_fatal("could not open file \"%s\": %m", report->path);
1956
1957 for (int i = 0; i < ntups; i++)
1958 fprintf(report->file, "The table sync state \"%s\" is not allowed for database:\"%s\" subscription:\"%s\" schema:\"%s\" relation:\"%s\"\n",
1959 PQgetvalue(res, i, i_srsubstate),
1960 dbinfo->db_name,
1961 PQgetvalue(res, i, i_subname),
1962 PQgetvalue(res, i, i_nspname),
1963 PQgetvalue(res, i, i_relname));
1964}
1965
1966/*
1967 * check_old_cluster_subscription_state()
1968 *
1969 * Verify that the replication origin corresponding to each of the
1970 * subscriptions are present and each of the subscribed tables is in
1971 * 'i' (initialize) or 'r' (ready) state.
1972 */
1973static void
1975{
1977 UpgradeTaskReport report;
1978 const char *query;
1979 PGresult *res;
1980 PGconn *conn;
1981 int ntup;
1982
1983 prep_status("Checking for subscription state");
1984
1985 report.file = NULL;
1986 snprintf(report.path, sizeof(report.path), "%s/%s",
1988 "subs_invalid.txt");
1989
1990 /*
1991 * Check that all the subscriptions have their respective replication
1992 * origin. This check only needs to run once.
1993 */
1996 "SELECT d.datname, s.subname "
1997 "FROM pg_catalog.pg_subscription s "
1998 "LEFT OUTER JOIN pg_catalog.pg_replication_origin o "
1999 " ON o.roname = 'pg_' || s.oid "
2000 "INNER JOIN pg_catalog.pg_database d "
2001 " ON d.oid = s.subdbid "
2002 "WHERE o.roname IS NULL;");
2003 ntup = PQntuples(res);
2004 for (int i = 0; i < ntup; i++)
2005 {
2006 if (report.file == NULL &&
2007 (report.file = fopen_priv(report.path, "w")) == NULL)
2008 pg_fatal("could not open file \"%s\": %m", report.path);
2009 fprintf(report.file, "The replication origin is missing for database:\"%s\" subscription:\"%s\"\n",
2010 PQgetvalue(res, i, 0),
2011 PQgetvalue(res, i, 1));
2012 }
2013 PQclear(res);
2014 PQfinish(conn);
2015
2016 /*
2017 * We don't allow upgrade if there is a risk of dangling slot or origin
2018 * corresponding to initial sync after upgrade.
2019 *
2020 * A slot/origin not created yet refers to the 'i' (initialize) state,
2021 * while 'r' (ready) state refers to a slot/origin created previously but
2022 * already dropped. These states are supported for pg_upgrade. The other
2023 * states listed below are not supported:
2024 *
2025 * a) SUBREL_STATE_DATASYNC: A relation upgraded while in this state would
2026 * retain a replication slot, which could not be dropped by the sync
2027 * worker spawned after the upgrade because the subscription ID used for
2028 * the slot name won't match anymore.
2029 *
2030 * b) SUBREL_STATE_SYNCDONE: A relation upgraded while in this state would
2031 * retain the replication origin when there is a failure in tablesync
2032 * worker immediately after dropping the replication slot in the
2033 * publisher.
2034 *
2035 * c) SUBREL_STATE_FINISHEDCOPY: A tablesync worker spawned to work on a
2036 * relation upgraded while in this state would expect an origin ID with
2037 * the OID of the subscription used before the upgrade, causing it to
2038 * fail.
2039 *
2040 * d) SUBREL_STATE_SYNCWAIT, SUBREL_STATE_CATCHUP and
2041 * SUBREL_STATE_UNKNOWN: These states are not stored in the catalog, so we
2042 * need not allow these states.
2043 */
2044 query = "SELECT r.srsubstate, s.subname, n.nspname, c.relname "
2045 "FROM pg_catalog.pg_subscription_rel r "
2046 "LEFT JOIN pg_catalog.pg_subscription s"
2047 " ON r.srsubid = s.oid "
2048 "LEFT JOIN pg_catalog.pg_class c"
2049 " ON r.srrelid = c.oid "
2050 "LEFT JOIN pg_catalog.pg_namespace n"
2051 " ON c.relnamespace = n.oid "
2052 "WHERE r.srsubstate NOT IN ('i', 'r') "
2053 "ORDER BY s.subname";
2054
2056 true, &report);
2057
2059 upgrade_task_free(task);
2060
2061 if (report.file)
2062 {
2063 fclose(report.file);
2064 pg_log(PG_REPORT, "fatal");
2065 pg_fatal("Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n"
2066 "You can allow the initial sync to finish for all relations and then restart the upgrade.\n"
2067 "A list of the problematic subscriptions is in the file:\n"
2068 " %s", report.path);
2069 }
2070 else
2071 check_ok();
2072}
#define gettext_noop(x)
Definition: c.h:1150
#define AssertVariableIsOfType(varname, typename)
Definition: c.h:935
#define Assert(condition)
Definition: c.h:812
#define CppAsString2(x)
Definition: c.h:346
void check_cluster_versions(void)
Definition: check.c:803
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:1564
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1608
static void process_old_sub_state_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1939
static void check_for_data_types_usage(ClusterInfo *cluster)
Definition: check.c:461
static char * data_type_check_query(int checknum)
Definition: check.c:330
static void process_incompat_polymorphics(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1403
static DataTypesUsageChecks data_types_usage_checks[]
Definition: check.c:95
static void process_with_oids_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1536
static void check_new_cluster_logical_replication_slots(void)
Definition: check.c:1750
static void check_old_cluster_subscription_state(void)
Definition: check.c:1974
#define ALL_VERSIONS
Definition: check.c:60
void issue_warnings_and_set_wal_level(void)
Definition: check.c:748
void check_cluster_compatibility(void)
Definition: check.c:846
#define MANUAL_CHECK
Definition: check.c:59
void check_new_cluster(void)
Definition: check.c:693
void report_clusters_compatible(void)
Definition: check.c:729
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:1044
static void check_new_cluster_subscription_configuration(void)
Definition: check.c:1823
void create_script_for_old_cluster_deletion(char **deletion_script_file_name)
Definition: check.c:921
static void check_for_connection_status(ClusterInfo *cluster)
Definition: check.c:1102
static void process_user_defined_encoding_conversions(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1666
static void process_data_type_check(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:387
void check_and_dump_old_cluster(void)
Definition: check.c:586
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:1256
static char * fix_path_separator(char *path)
Definition: check.c:547
static void check_new_cluster_is_empty(void)
Definition: check.c:860
static void check_old_cluster_for_valid_slots(void)
Definition: check.c:1866
static void process_isn_and_int8_passing_mismatch(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1223
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:1344
void output_completion_banner(char *deletion_script_file_name)
Definition: check.c:769
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:1190
static void check_for_new_tablespace_dir(void)
Definition: check.c:892
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1697
static void check_for_incompatible_polymorphics(ClusterInfo *cluster)
Definition: check.c:1435
void output_check_banner(void)
Definition: check.c:568
static void process_user_defined_postfix_ops(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: check.c:1309
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:107
void get_control_data(ClusterInfo *cluster)
Definition: controldata.c:36
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:655
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
void generate_old_dump(void)
Definition: dump.c:16
#define _(x)
Definition: elog.c:90
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4880
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:3589
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void check_file_clone(void)
Definition: file.c:360
void check_hard_link(void)
Definition: file.c:437
void check_copy_file_range(void)
Definition: file.c:400
void check_loadable_libraries(void)
Definition: function.c:165
void get_loadable_libraries(void)
Definition: function.c:79
void get_subscription_count(ClusterInfo *cluster)
Definition: info.c:758
int count_old_cluster_logical_slots(void)
Definition: info.c:742
void get_db_rel_and_slot_infos(ClusterInfo *cluster)
Definition: info.c:280
static void check_ok(void)
Definition: initdb.c:2091
int i
Definition: isn.c:72
exit(1)
void pfree(void *pointer)
Definition: mcxt.c:1521
void * arg
#define pg_fatal(...)
#define MAXPGPATH
static struct LogicalRepInfo * dbinfo
static pid_t start_postmaster(void)
Definition: pg_ctl.c:440
NameData datname
Definition: pg_database.h:35
bool datallowconn
Definition: pg_database.h:50
int32 datconnlimit
Definition: pg_database.h:59
OSInfo os_info
Definition: pg_upgrade.c:69
ClusterInfo new_cluster
Definition: pg_upgrade.c:68
ClusterInfo old_cluster
Definition: pg_upgrade.c:67
UpgradeTask * upgrade_task_create(void)
Definition: task.c:117
#define PATH_SEPARATOR
Definition: pg_upgrade.h:82
void init_tablespaces(void)
Definition: tablespace.c:19
bool(* DataTypesUsageVersionCheck)(ClusterInfo *cluster)
Definition: pg_upgrade.h:355
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:28
bool jsonb_9_4_check_applicable(ClusterInfo *cluster)
Definition: version.c:21
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
Definition: task.c:420
#define RMDIR_CMD
Definition: pg_upgrade.h:85
void cleanup_output_dirs(void)
Definition: util.c:63
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:179
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
@ TRANSFER_MODE_COPY
Definition: pg_upgrade.h:256
@ TRANSFER_MODE_LINK
Definition: pg_upgrade.h:258
@ TRANSFER_MODE_CLONE
Definition: pg_upgrade.h:255
@ TRANSFER_MODE_COPY_FILE_RANGE
Definition: pg_upgrade.h:257
#define SCRIPT_EXT
Definition: pg_upgrade.h:87
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:86
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
#define PATH_QUOTE
Definition: pg_upgrade.h:83
LogOpts log_opts
Definition: util.c:17
void upgrade_task_free(UpgradeTask *task)
Definition: task.c:133
#define fopen_priv(path, mode)
Definition: pg_upgrade.h:419
void(* UpgradeTaskProcessCB)(DbInfo *dbinfo, PGresult *res, void *arg)
Definition: pg_upgrade.h:500
@ PG_WARNING
Definition: pg_upgrade.h:270
@ PG_REPORT
Definition: pg_upgrade.h:269
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:27
void stop_postmaster(bool in_atexit)
Definition: server.c:342
void prep_status(const char *fmt,...) pg_attribute_printf(1
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:37
void upgrade_task_add_step(UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
Definition: task.c:151
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:560
void canonicalize_path(char *path)
Definition: path.c:265
#define snprintf
Definition: port.h:238
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define atooid(x)
Definition: postgres_ext.h:42
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:72
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:114
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
char * c
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
int max_replication_slots
Definition: slot.c:141
UserOpts user_opts
Definition: option.c:30
PGconn * conn
Definition: streamutil.c:53
void appendShellString(PQExpBuffer buf, const char *str)
Definition: string_utils.c:429
char * pgdata
Definition: pg_upgrade.h:285
unsigned short port
Definition: pg_upgrade.h:292
ControlData controldata
Definition: pg_upgrade.h:282
char * bindir
Definition: pg_upgrade.h:288
uint32 bin_version
Definition: pg_upgrade.h:295
DbInfoArr dbarr
Definition: pg_upgrade.h:284
uint32 major_version
Definition: pg_upgrade.h:293
const char * tablespace_suffix
Definition: pg_upgrade.h:296
bool float8_pass_by_value
Definition: pg_upgrade.h:246
const char * report_text
Definition: check.c:47
int threshold_version
Definition: check.c:49
DataTypesUsageVersionCheck version_hook
Definition: check.c:51
const char * status
Definition: check.c:41
const char * report_filename
Definition: check.c:43
const char * base_query
Definition: check.c:45
DbInfo * dbs
Definition: pg_upgrade.h:215
LogicalSlotInfoArr slot_arr
Definition: pg_upgrade.h:198
char * db_name
Definition: pg_upgrade.h:194
RelInfoArr rel_arr
Definition: pg_upgrade.h:197
Oid db_oid
Definition: pg_upgrade.h:193
char * basedir
Definition: pg_upgrade.h:311
LogicalSlotInfo * slots
Definition: pg_upgrade.h:169
int num_old_tablespaces
Definition: pg_upgrade.h:347
char * user
Definition: pg_upgrade.h:344
char ** old_tablespaces
Definition: pg_upgrade.h:346
bool user_specified
Definition: pg_upgrade.h:345
RelInfo * rels
Definition: pg_upgrade.h:148
char * nspname
Definition: pg_upgrade.h:135
char * relname
Definition: pg_upgrade.h:136
char path[MAXPGPATH]
Definition: pg_upgrade.h:516
bool live_check
Definition: pg_upgrade.h:324
transferMode transfer_mode
Definition: pg_upgrade.h:326
bool check
Definition: pg_upgrade.h:323
PQExpBuffer * report
Definition: check.c:322
DataTypesUsageChecks * check
Definition: check.c:320
Definition: regguts.h:323
#define stat
Definition: win32_port.h:284
#define S_IRWXU
Definition: win32_port.h:298
int wal_level
Definition: xlog.c:131