PostgreSQL Source Code  git master
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-2021, 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 "fe_utils/string_utils.h"
14 #include "mb/pg_wchar.h"
15 #include "pg_upgrade.h"
16 
17 static void check_new_cluster_is_empty(void);
18 static void check_databases_are_compatible(void);
19 static void check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb);
20 static bool equivalent_locale(int category, const char *loca, const char *locb);
33 static char *get_canonical_locale_name(int category, const char *locale);
34 
35 
36 /*
37  * fix_path_separator
38  * For non-Windows, just return the argument.
39  * For Windows convert any forward slash to a backslash
40  * such as is suitable for arguments to builtin commands
41  * like RMDIR and DEL.
42  */
43 static char *
44 fix_path_separator(char *path)
45 {
46 #ifdef WIN32
47 
48  char *result;
49  char *c;
50 
51  result = pg_strdup(path);
52 
53  for (c = result; *c != '\0'; c++)
54  if (*c == '/')
55  *c = '\\';
56 
57  return result;
58 #else
59 
60  return path;
61 #endif
62 }
63 
64 void
65 output_check_banner(bool live_check)
66 {
67  if (user_opts.check && live_check)
68  {
70  "Performing Consistency Checks on Old Live Server\n"
71  "------------------------------------------------\n");
72  }
73  else
74  {
76  "Performing Consistency Checks\n"
77  "-----------------------------\n");
78  }
79 }
80 
81 
82 void
84 {
85  /* -- OLD -- */
86 
87  if (!live_check)
89 
90  /* Extract a list of databases and tables from the old cluster */
92 
94 
96 
97 
98  /*
99  * Check for various failure cases
100  */
107 
108  /*
109  * PG 14 changed the function signature of encoding conversion functions.
110  * Conversions from older versions cannot be upgraded automatically
111  * because the user-defined functions used by the encoding conversions
112  * need to be changed to match the new signature.
113  */
116 
117  /*
118  * Pre-PG 14 allowed user defined postfix operators, which are not
119  * supported anymore. Verify there are none, iff applicable.
120  */
123 
124  /*
125  * Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
126  * supported anymore. Verify there are none, iff applicable.
127  */
130 
131  /*
132  * PG 12 changed the 'sql_identifier' type storage to be based on name,
133  * not varchar, which breaks on-disk format for existing data. So we need
134  * to prevent upgrade when used in user objects (tables, indexes, ...).
135  */
138 
139  /*
140  * Pre-PG 10 allowed tables with 'unknown' type columns and non WAL logged
141  * hash indexes
142  */
144  {
146  if (user_opts.check)
148  }
149 
150  /* 9.5 and below should not have roles starting with pg_ */
153 
157 
158  /* Pre-PG 9.4 had a different 'line' data type internal format */
161 
162  /* Pre-PG 9.0 had no large object permissions */
165 
166  /*
167  * While not a check option, we do this now because this is the only time
168  * the old server is running.
169  */
170  if (!user_opts.check)
172 
173  if (!live_check)
174  stop_postmaster(false);
175 }
176 
177 
178 void
180 {
182 
185 
187 
188  switch (user_opts.transfer_mode)
189  {
190  case TRANSFER_MODE_CLONE:
192  break;
193  case TRANSFER_MODE_COPY:
194  break;
195  case TRANSFER_MODE_LINK:
196  check_hard_link();
197  break;
198  }
199 
201 
203 
205 }
206 
207 
208 void
210 {
211  if (user_opts.check)
212  {
213  pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
214  /* stops new cluster */
215  stop_postmaster(false);
216  exit(0);
217  }
218 
219  pg_log(PG_REPORT, "\n"
220  "If pg_upgrade fails after this point, you must re-initdb the\n"
221  "new cluster before continuing.\n");
222 }
223 
224 
225 void
227 {
228  /*
229  * We unconditionally start/stop the new server because pg_resetwal -o set
230  * wal_level to 'minimum'. If the user is upgrading standby servers using
231  * the rsync instructions, they will need pg_upgrade to write its final
232  * WAL record showing wal_level as 'replica'.
233  */
235 
236  /* Create dummy large object permissions for old < PG 9.0? */
239 
240  /* Reindex hash indexes for old < 10.0 */
243 
245 
246  stop_postmaster(false);
247 }
248 
249 
250 void
251 output_completion_banner(char *deletion_script_file_name)
252 {
253  PQExpBufferData user_specification;
254 
255  initPQExpBuffer(&user_specification);
257  {
258  appendPQExpBufferStr(&user_specification, "-U ");
259  appendShellString(&user_specification, os_info.user);
260  appendPQExpBufferChar(&user_specification, ' ');
261  }
262 
264  "Optimizer statistics are not transferred by pg_upgrade.\n"
265  "Once you start the new server, consider running:\n"
266  " %s/vacuumdb %s--all --analyze-in-stages\n\n", new_cluster.bindir, user_specification.data);
267 
268  if (deletion_script_file_name)
270  "Running this script will delete the old cluster's data files:\n"
271  " %s\n",
272  deletion_script_file_name);
273  else
275  "Could not create a script to delete the old cluster's data files\n"
276  "because user-defined tablespaces or the new cluster's data directory\n"
277  "exist in the old cluster directory. The old cluster's contents must\n"
278  "be deleted manually.\n");
279 
280  termPQExpBuffer(&user_specification);
281 }
282 
283 
284 void
286 {
287  prep_status("Checking cluster versions");
288 
289  /* cluster versions should already have been obtained */
292 
293  /*
294  * We allow upgrades from/to the same major version for alpha/beta
295  * upgrades
296  */
297 
299  pg_fatal("This utility can only upgrade from PostgreSQL version 8.4 and later.\n");
300 
301  /* Only current PG version is supported as a target */
303  pg_fatal("This utility can only upgrade to PostgreSQL version %s.\n",
304  PG_MAJORVERSION);
305 
306  /*
307  * We can't allow downgrading because we use the target pg_dump, and
308  * pg_dump cannot operate on newer database versions, only current and
309  * older versions.
310  */
312  pg_fatal("This utility cannot be used to downgrade to older major PostgreSQL versions.\n");
313 
314  /* Ensure binaries match the designated data directories */
317  pg_fatal("Old cluster data and binary directories are from different major versions.\n");
320  pg_fatal("New cluster data and binary directories are from different major versions.\n");
321 
322  check_ok();
323 }
324 
325 
326 void
328 {
329  /* get/check pg_control data of servers */
330  get_control_data(&old_cluster, live_check);
331  get_control_data(&new_cluster, false);
333 
334  /* We read the real port number for PG >= 9.1 */
335  if (live_check && GET_MAJOR_VERSION(old_cluster.major_version) <= 900 &&
337  pg_fatal("When checking a pre-PG 9.1 live old server, "
338  "you must specify the old server's port number.\n");
339 
340  if (live_check && old_cluster.port == new_cluster.port)
341  pg_fatal("When checking a live server, "
342  "the old and new port numbers must be different.\n");
343 }
344 
345 
346 /*
347  * check_locale_and_encoding()
348  *
349  * Check that locale and encoding of a database in the old and new clusters
350  * are compatible.
351  */
352 static void
354 {
355  if (olddb->db_encoding != newdb->db_encoding)
356  pg_fatal("encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
357  olddb->db_name,
360  if (!equivalent_locale(LC_COLLATE, olddb->db_collate, newdb->db_collate))
361  pg_fatal("lc_collate values for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
362  olddb->db_name, olddb->db_collate, newdb->db_collate);
363  if (!equivalent_locale(LC_CTYPE, olddb->db_ctype, newdb->db_ctype))
364  pg_fatal("lc_ctype values for database \"%s\" do not match: old \"%s\", new \"%s\"\n",
365  olddb->db_name, olddb->db_ctype, newdb->db_ctype);
366 }
367 
368 /*
369  * equivalent_locale()
370  *
371  * Best effort locale-name comparison. Return false if we are not 100% sure
372  * the locales are equivalent.
373  *
374  * Note: The encoding parts of the names are ignored. This function is
375  * currently used to compare locale names stored in pg_database, and
376  * pg_database contains a separate encoding field. That's compared directly
377  * in check_locale_and_encoding().
378  */
379 static bool
380 equivalent_locale(int category, const char *loca, const char *locb)
381 {
382  const char *chara;
383  const char *charb;
384  char *canona;
385  char *canonb;
386  int lena;
387  int lenb;
388 
389  /*
390  * If the names are equal, the locales are equivalent. Checking this first
391  * avoids calling setlocale() in the common case that the names are equal.
392  * That's a good thing, if setlocale() is buggy, for example.
393  */
394  if (pg_strcasecmp(loca, locb) == 0)
395  return true;
396 
397  /*
398  * Not identical. Canonicalize both names, remove the encoding parts, and
399  * try again.
400  */
401  canona = get_canonical_locale_name(category, loca);
402  chara = strrchr(canona, '.');
403  lena = chara ? (chara - canona) : strlen(canona);
404 
405  canonb = get_canonical_locale_name(category, locb);
406  charb = strrchr(canonb, '.');
407  lenb = charb ? (charb - canonb) : strlen(canonb);
408 
409  if (lena == lenb && pg_strncasecmp(canona, canonb, lena) == 0)
410  {
411  pg_free(canona);
412  pg_free(canonb);
413  return true;
414  }
415 
416  pg_free(canona);
417  pg_free(canonb);
418  return false;
419 }
420 
421 
422 static void
424 {
425  int dbnum;
426 
427  for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
428  {
429  int relnum;
430  RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
431 
432  for (relnum = 0; relnum < rel_arr->nrels;
433  relnum++)
434  {
435  /* pg_largeobject and its index should be skipped */
436  if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
437  pg_fatal("New cluster database \"%s\" is not empty: found relation \"%s.%s\"\n",
438  new_cluster.dbarr.dbs[dbnum].db_name,
439  rel_arr->rels[relnum].nspname,
440  rel_arr->rels[relnum].relname);
441  }
442  }
443 }
444 
445 /*
446  * Check that every database that already exists in the new cluster is
447  * compatible with the corresponding database in the old one.
448  */
449 static void
451 {
452  int newdbnum;
453  int olddbnum;
454  DbInfo *newdbinfo;
455  DbInfo *olddbinfo;
456 
457  for (newdbnum = 0; newdbnum < new_cluster.dbarr.ndbs; newdbnum++)
458  {
459  newdbinfo = &new_cluster.dbarr.dbs[newdbnum];
460 
461  /* Find the corresponding database in the old cluster */
462  for (olddbnum = 0; olddbnum < old_cluster.dbarr.ndbs; olddbnum++)
463  {
464  olddbinfo = &old_cluster.dbarr.dbs[olddbnum];
465  if (strcmp(newdbinfo->db_name, olddbinfo->db_name) == 0)
466  {
467  check_locale_and_encoding(olddbinfo, newdbinfo);
468  break;
469  }
470  }
471  }
472 }
473 
474 /*
475  * A previous run of pg_upgrade might have failed and the new cluster
476  * directory recreated, but they might have forgotten to remove
477  * the new cluster's tablespace directories. Therefore, check that
478  * new cluster tablespace directories do not already exist. If
479  * they do, it would cause an error while restoring global objects.
480  * This allows the failure to be detected at check time, rather than
481  * during schema restore.
482  *
483  * Note, v8.4 has no tablespace_suffix, which is fine so long as the
484  * version being upgraded *to* has a suffix, since it's not allowed
485  * to pg_upgrade from a version to the same version if tablespaces are
486  * in use.
487  */
488 static void
490 {
491  int tblnum;
492  char new_tablespace_dir[MAXPGPATH];
493 
494  prep_status("Checking for new cluster tablespace directories");
495 
496  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
497  {
498  struct stat statbuf;
499 
500  snprintf(new_tablespace_dir, MAXPGPATH, "%s%s",
501  os_info.old_tablespaces[tblnum],
502  new_cluster->tablespace_suffix);
503 
504  if (stat(new_tablespace_dir, &statbuf) == 0 || errno != ENOENT)
505  pg_fatal("new cluster tablespace directory already exists: \"%s\"\n",
506  new_tablespace_dir);
507  }
508 
509  check_ok();
510 }
511 
512 /*
513  * create_script_for_old_cluster_deletion()
514  *
515  * This is particularly useful for tablespace deletion.
516  */
517 void
518 create_script_for_old_cluster_deletion(char **deletion_script_file_name)
519 {
520  FILE *script = NULL;
521  int tblnum;
522  char old_cluster_pgdata[MAXPGPATH],
523  new_cluster_pgdata[MAXPGPATH];
524 
525  *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s",
527 
528  strlcpy(old_cluster_pgdata, old_cluster.pgdata, MAXPGPATH);
529  canonicalize_path(old_cluster_pgdata);
530 
531  strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
532  canonicalize_path(new_cluster_pgdata);
533 
534  /* Some people put the new data directory inside the old one. */
535  if (path_is_prefix_of_path(old_cluster_pgdata, new_cluster_pgdata))
536  {
538  "\nWARNING: new data directory should not be inside the old data directory, e.g. %s\n", old_cluster_pgdata);
539 
540  /* Unlink file in case it is left over from a previous run. */
541  unlink(*deletion_script_file_name);
542  pg_free(*deletion_script_file_name);
543  *deletion_script_file_name = NULL;
544  return;
545  }
546 
547  /*
548  * Some users (oddly) create tablespaces inside the cluster data
549  * directory. We can't create a proper old cluster delete script in that
550  * case.
551  */
552  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
553  {
554  char old_tablespace_dir[MAXPGPATH];
555 
556  strlcpy(old_tablespace_dir, os_info.old_tablespaces[tblnum], MAXPGPATH);
557  canonicalize_path(old_tablespace_dir);
558  if (path_is_prefix_of_path(old_cluster_pgdata, old_tablespace_dir))
559  {
560  /* reproduce warning from CREATE TABLESPACE that is in the log */
562  "\nWARNING: user-defined tablespace locations should not be inside the data directory, e.g. %s\n", old_tablespace_dir);
563 
564  /* Unlink file in case it is left over from a previous run. */
565  unlink(*deletion_script_file_name);
566  pg_free(*deletion_script_file_name);
567  *deletion_script_file_name = NULL;
568  return;
569  }
570  }
571 
572  prep_status("Creating script to delete old cluster");
573 
574  if ((script = fopen_priv(*deletion_script_file_name, "w")) == NULL)
575  pg_fatal("could not open file \"%s\": %s\n",
576  *deletion_script_file_name, strerror(errno));
577 
578 #ifndef WIN32
579  /* add shebang header */
580  fprintf(script, "#!/bin/sh\n\n");
581 #endif
582 
583  /* delete old cluster's default tablespace */
584  fprintf(script, RMDIR_CMD " %c%s%c\n", PATH_QUOTE,
586 
587  /* delete old cluster's alternate tablespaces */
588  for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++)
589  {
590  /*
591  * Do the old cluster's per-database directories share a directory
592  * with a new version-specific tablespace?
593  */
594  if (strlen(old_cluster.tablespace_suffix) == 0)
595  {
596  /* delete per-database directories */
597  int dbnum;
598 
599  fprintf(script, "\n");
600  /* remove PG_VERSION? */
602  fprintf(script, RM_CMD " %s%cPG_VERSION\n",
605 
606  for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
607  fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE,
610  PATH_QUOTE);
611  }
612  else
613  {
614  char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
615 
616  /*
617  * Simply delete the tablespace directory, which might be ".old"
618  * or a version-specific subdirectory.
619  */
620  fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE,
622  fix_path_separator(suffix_path), PATH_QUOTE);
623  pfree(suffix_path);
624  }
625  }
626 
627  fclose(script);
628 
629 #ifndef WIN32
630  if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
631  pg_fatal("could not add execute permission to file \"%s\": %s\n",
632  *deletion_script_file_name, strerror(errno));
633 #endif
634 
635  check_ok();
636 }
637 
638 
639 /*
640  * check_is_install_user()
641  *
642  * Check we are the install user, and that the new cluster
643  * has no other users.
644  */
645 static void
647 {
648  PGresult *res;
649  PGconn *conn = connectToServer(cluster, "template1");
650 
651  prep_status("Checking database user is the install user");
652 
653  /* Can't use pg_authid because only superusers can view it. */
654  res = executeQueryOrDie(conn,
655  "SELECT rolsuper, oid "
656  "FROM pg_catalog.pg_roles "
657  "WHERE rolname = current_user "
658  "AND rolname !~ '^pg_'");
659 
660  /*
661  * We only allow the install user in the new cluster (see comment below)
662  * and we preserve pg_authid.oid, so this must be the install user in the
663  * old cluster too.
664  */
665  if (PQntuples(res) != 1 ||
666  atooid(PQgetvalue(res, 0, 1)) != BOOTSTRAP_SUPERUSERID)
667  pg_fatal("database user \"%s\" is not the install user\n",
668  os_info.user);
669 
670  PQclear(res);
671 
672  res = executeQueryOrDie(conn,
673  "SELECT COUNT(*) "
674  "FROM pg_catalog.pg_roles "
675  "WHERE rolname !~ '^pg_'");
676 
677  if (PQntuples(res) != 1)
678  pg_fatal("could not determine the number of users\n");
679 
680  /*
681  * We only allow the install user in the new cluster because other defined
682  * users might match users defined in the old cluster and generate an
683  * error during pg_dump restore.
684  */
685  if (cluster == &new_cluster && atooid(PQgetvalue(res, 0, 0)) != 1)
686  pg_fatal("Only the install user can be defined in the new cluster.\n");
687 
688  PQclear(res);
689 
690  PQfinish(conn);
691 
692  check_ok();
693 }
694 
695 
696 static void
698 {
699  int dbnum;
700  PGconn *conn_template1;
701  PGresult *dbres;
702  int ntups;
703  int i_datname;
704  int i_datallowconn;
705 
706  prep_status("Checking database connection settings");
707 
708  conn_template1 = connectToServer(cluster, "template1");
709 
710  /* get database names */
711  dbres = executeQueryOrDie(conn_template1,
712  "SELECT datname, datallowconn "
713  "FROM pg_catalog.pg_database");
714 
715  i_datname = PQfnumber(dbres, "datname");
716  i_datallowconn = PQfnumber(dbres, "datallowconn");
717 
718  ntups = PQntuples(dbres);
719  for (dbnum = 0; dbnum < ntups; dbnum++)
720  {
721  char *datname = PQgetvalue(dbres, dbnum, i_datname);
722  char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
723 
724  if (strcmp(datname, "template0") == 0)
725  {
726  /* avoid restore failure when pg_dumpall tries to create template0 */
727  if (strcmp(datallowconn, "t") == 0)
728  pg_fatal("template0 must not allow connections, "
729  "i.e. its pg_database.datallowconn must be false\n");
730  }
731  else
732  {
733  /*
734  * avoid datallowconn == false databases from being skipped on
735  * restore
736  */
737  if (strcmp(datallowconn, "f") == 0)
738  pg_fatal("All non-template0 databases must allow connections, "
739  "i.e. their pg_database.datallowconn must be true\n");
740  }
741  }
742 
743  PQclear(dbres);
744 
745  PQfinish(conn_template1);
746 
747  check_ok();
748 }
749 
750 
751 /*
752  * check_for_prepared_transactions()
753  *
754  * Make sure there are no prepared transactions because the storage format
755  * might have changed.
756  */
757 static void
759 {
760  PGresult *res;
761  PGconn *conn = connectToServer(cluster, "template1");
762 
763  prep_status("Checking for prepared transactions");
764 
765  res = executeQueryOrDie(conn,
766  "SELECT * "
767  "FROM pg_catalog.pg_prepared_xacts");
768 
769  if (PQntuples(res) != 0)
770  {
771  if (cluster == &old_cluster)
772  pg_fatal("The source cluster contains prepared transactions\n");
773  else
774  pg_fatal("The target cluster contains prepared transactions\n");
775  }
776 
777  PQclear(res);
778 
779  PQfinish(conn);
780 
781  check_ok();
782 }
783 
784 
785 /*
786  * check_for_isn_and_int8_passing_mismatch()
787  *
788  * contrib/isn relies on data type int8, and in 8.4 int8 can now be passed
789  * by value. The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
790  * it must match for the old and new servers.
791  */
792 static void
794 {
795  int dbnum;
796  FILE *script = NULL;
797  bool found = false;
798  char output_path[MAXPGPATH];
799 
800  prep_status("Checking for contrib/isn with bigint-passing mismatch");
801 
804  {
805  /* no mismatch */
806  check_ok();
807  return;
808  }
809 
810  snprintf(output_path, sizeof(output_path),
811  "contrib_isn_and_int8_pass_by_value.txt");
812 
813  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
814  {
815  PGresult *res;
816  bool db_used = false;
817  int ntups;
818  int rowno;
819  int i_nspname,
820  i_proname;
821  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
822  PGconn *conn = connectToServer(cluster, active_db->db_name);
823 
824  /* Find any functions coming from contrib/isn */
825  res = executeQueryOrDie(conn,
826  "SELECT n.nspname, p.proname "
827  "FROM pg_catalog.pg_proc p, "
828  " pg_catalog.pg_namespace n "
829  "WHERE p.pronamespace = n.oid AND "
830  " p.probin = '$libdir/isn'");
831 
832  ntups = PQntuples(res);
833  i_nspname = PQfnumber(res, "nspname");
834  i_proname = PQfnumber(res, "proname");
835  for (rowno = 0; rowno < ntups; rowno++)
836  {
837  found = true;
838  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
839  pg_fatal("could not open file \"%s\": %s\n",
840  output_path, strerror(errno));
841  if (!db_used)
842  {
843  fprintf(script, "In database: %s\n", active_db->db_name);
844  db_used = true;
845  }
846  fprintf(script, " %s.%s\n",
847  PQgetvalue(res, rowno, i_nspname),
848  PQgetvalue(res, rowno, i_proname));
849  }
850 
851  PQclear(res);
852 
853  PQfinish(conn);
854  }
855 
856  if (script)
857  fclose(script);
858 
859  if (found)
860  {
861  pg_log(PG_REPORT, "fatal\n");
862  pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n"
863  "bigint data type. Your old and new clusters pass bigint values\n"
864  "differently so this cluster cannot currently be upgraded. You can\n"
865  "manually dump databases in the old cluster that use \"contrib/isn\"\n"
866  "facilities, drop them, perform the upgrade, and then restore them. A\n"
867  "list of the problem functions is in the file:\n"
868  " %s\n\n", output_path);
869  }
870  else
871  check_ok();
872 }
873 
874 /*
875  * Verify that no user defined postfix operators exist.
876  */
877 static void
879 {
880  int dbnum;
881  FILE *script = NULL;
882  bool found = false;
883  char output_path[MAXPGPATH];
884 
885  prep_status("Checking for user-defined postfix operators");
886 
887  snprintf(output_path, sizeof(output_path),
888  "postfix_ops.txt");
889 
890  /* Find any user defined postfix operators */
891  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
892  {
893  PGresult *res;
894  bool db_used = false;
895  int ntups;
896  int rowno;
897  int i_oproid,
898  i_oprnsp,
899  i_oprname,
900  i_typnsp,
901  i_typname;
902  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
903  PGconn *conn = connectToServer(cluster, active_db->db_name);
904 
905  /*
906  * The query below hardcodes FirstNormalObjectId as 16384 rather than
907  * interpolating that C #define into the query because, if that
908  * #define is ever changed, the cutoff we want to use is the value
909  * used by pre-version 14 servers, not that of some future version.
910  */
911  res = executeQueryOrDie(conn,
912  "SELECT o.oid AS oproid, "
913  " n.nspname AS oprnsp, "
914  " o.oprname, "
915  " tn.nspname AS typnsp, "
916  " t.typname "
917  "FROM pg_catalog.pg_operator o, "
918  " pg_catalog.pg_namespace n, "
919  " pg_catalog.pg_type t, "
920  " pg_catalog.pg_namespace tn "
921  "WHERE o.oprnamespace = n.oid AND "
922  " o.oprleft = t.oid AND "
923  " t.typnamespace = tn.oid AND "
924  " o.oprright = 0 AND "
925  " o.oid >= 16384");
926  ntups = PQntuples(res);
927  i_oproid = PQfnumber(res, "oproid");
928  i_oprnsp = PQfnumber(res, "oprnsp");
929  i_oprname = PQfnumber(res, "oprname");
930  i_typnsp = PQfnumber(res, "typnsp");
931  i_typname = PQfnumber(res, "typname");
932  for (rowno = 0; rowno < ntups; rowno++)
933  {
934  found = true;
935  if (script == NULL &&
936  (script = fopen_priv(output_path, "w")) == NULL)
937  pg_fatal("could not open file \"%s\": %s\n",
938  output_path, strerror(errno));
939  if (!db_used)
940  {
941  fprintf(script, "In database: %s\n", active_db->db_name);
942  db_used = true;
943  }
944  fprintf(script, " (oid=%s) %s.%s (%s.%s, NONE)\n",
945  PQgetvalue(res, rowno, i_oproid),
946  PQgetvalue(res, rowno, i_oprnsp),
947  PQgetvalue(res, rowno, i_oprname),
948  PQgetvalue(res, rowno, i_typnsp),
949  PQgetvalue(res, rowno, i_typname));
950  }
951 
952  PQclear(res);
953 
954  PQfinish(conn);
955  }
956 
957  if (script)
958  fclose(script);
959 
960  if (found)
961  {
962  pg_log(PG_REPORT, "fatal\n");
963  pg_fatal("Your installation contains user-defined postfix operators, which are not\n"
964  "supported anymore. Consider dropping the postfix operators and replacing\n"
965  "them with prefix operators or function calls.\n"
966  "A list of user-defined postfix operators is in the file:\n"
967  " %s\n\n", output_path);
968  }
969  else
970  check_ok();
971 }
972 
973 /*
974  * Verify that no tables are declared WITH OIDS.
975  */
976 static void
978 {
979  int dbnum;
980  FILE *script = NULL;
981  bool found = false;
982  char output_path[MAXPGPATH];
983 
984  prep_status("Checking for tables WITH OIDS");
985 
986  snprintf(output_path, sizeof(output_path),
987  "tables_with_oids.txt");
988 
989  /* Find any tables declared WITH OIDS */
990  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
991  {
992  PGresult *res;
993  bool db_used = false;
994  int ntups;
995  int rowno;
996  int i_nspname,
997  i_relname;
998  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
999  PGconn *conn = connectToServer(cluster, active_db->db_name);
1000 
1001  res = executeQueryOrDie(conn,
1002  "SELECT n.nspname, c.relname "
1003  "FROM pg_catalog.pg_class c, "
1004  " pg_catalog.pg_namespace n "
1005  "WHERE c.relnamespace = n.oid AND "
1006  " c.relhasoids AND"
1007  " n.nspname NOT IN ('pg_catalog')");
1008 
1009  ntups = PQntuples(res);
1010  i_nspname = PQfnumber(res, "nspname");
1011  i_relname = PQfnumber(res, "relname");
1012  for (rowno = 0; rowno < ntups; rowno++)
1013  {
1014  found = true;
1015  if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
1016  pg_fatal("could not open file \"%s\": %s\n",
1017  output_path, strerror(errno));
1018  if (!db_used)
1019  {
1020  fprintf(script, "In database: %s\n", active_db->db_name);
1021  db_used = true;
1022  }
1023  fprintf(script, " %s.%s\n",
1024  PQgetvalue(res, rowno, i_nspname),
1025  PQgetvalue(res, rowno, i_relname));
1026  }
1027 
1028  PQclear(res);
1029 
1030  PQfinish(conn);
1031  }
1032 
1033  if (script)
1034  fclose(script);
1035 
1036  if (found)
1037  {
1038  pg_log(PG_REPORT, "fatal\n");
1039  pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n"
1040  "supported anymore. Consider removing the oid column using\n"
1041  " ALTER TABLE ... SET WITHOUT OIDS;\n"
1042  "A list of tables with the problem is in the file:\n"
1043  " %s\n\n", output_path);
1044  }
1045  else
1046  check_ok();
1047 }
1048 
1049 
1050 /*
1051  * check_for_composite_data_type_usage()
1052  * Check for system-defined composite types used in user tables.
1053  *
1054  * The OIDs of rowtypes of system catalogs and information_schema views
1055  * can change across major versions; unlike user-defined types, we have
1056  * no mechanism for forcing them to be the same in the new cluster.
1057  * Hence, if any user table uses one, that's problematic for pg_upgrade.
1058  */
1059 static void
1061 {
1062  bool found;
1063  Oid firstUserOid;
1064  char output_path[MAXPGPATH];
1065  char *base_query;
1066 
1067  prep_status("Checking for system-defined composite types in user tables");
1068 
1069  snprintf(output_path, sizeof(output_path), "tables_using_composite.txt");
1070 
1071  /*
1072  * Look for composite types that were made during initdb *or* belong to
1073  * information_schema; that's important in case information_schema was
1074  * dropped and reloaded.
1075  *
1076  * The cutoff OID here should match the source cluster's value of
1077  * FirstNormalObjectId. We hardcode it rather than using that C #define
1078  * because, if that #define is ever changed, our own version's value is
1079  * NOT what to use. Eventually we may need a test on the source cluster's
1080  * version to select the correct value.
1081  */
1082  firstUserOid = 16384;
1083 
1084  base_query = psprintf("SELECT t.oid FROM pg_catalog.pg_type t "
1085  "LEFT JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid "
1086  " WHERE typtype = 'c' AND (t.oid < %u OR nspname = 'information_schema')",
1087  firstUserOid);
1088 
1089  found = check_for_data_types_usage(cluster, base_query, output_path);
1090 
1091  free(base_query);
1092 
1093  if (found)
1094  {
1095  pg_log(PG_REPORT, "fatal\n");
1096  pg_fatal("Your installation contains system-defined composite type(s) in user tables.\n"
1097  "These type OIDs are not stable across PostgreSQL versions,\n"
1098  "so this cluster cannot currently be upgraded. You can\n"
1099  "drop the problem columns and restart the upgrade.\n"
1100  "A list of the problem columns is in the file:\n"
1101  " %s\n\n", output_path);
1102  }
1103  else
1104  check_ok();
1105 }
1106 
1107 /*
1108  * check_for_reg_data_type_usage()
1109  * pg_upgrade only preserves these system values:
1110  * pg_class.oid
1111  * pg_type.oid
1112  * pg_enum.oid
1113  *
1114  * Many of the reg* data types reference system catalog info that is
1115  * not preserved, and hence these data types cannot be used in user
1116  * tables upgraded by pg_upgrade.
1117  */
1118 static void
1120 {
1121  bool found;
1122  char output_path[MAXPGPATH];
1123 
1124  prep_status("Checking for reg* data types in user tables");
1125 
1126  snprintf(output_path, sizeof(output_path), "tables_using_reg.txt");
1127 
1128  /*
1129  * Note: older servers will not have all of these reg* types, so we have
1130  * to write the query like this rather than depending on casts to regtype.
1131  */
1132  found = check_for_data_types_usage(cluster,
1133  "SELECT oid FROM pg_catalog.pg_type t "
1134  "WHERE t.typnamespace = "
1135  " (SELECT oid FROM pg_catalog.pg_namespace "
1136  " WHERE nspname = 'pg_catalog') "
1137  " AND t.typname IN ( "
1138  /* pg_class.oid is preserved, so 'regclass' is OK */
1139  " 'regcollation', "
1140  " 'regconfig', "
1141  " 'regdictionary', "
1142  " 'regnamespace', "
1143  " 'regoper', "
1144  " 'regoperator', "
1145  " 'regproc', "
1146  " 'regprocedure' "
1147  /* pg_authid.oid is preserved, so 'regrole' is OK */
1148  /* pg_type.oid is (mostly) preserved, so 'regtype' is OK */
1149  " )",
1150  output_path);
1151 
1152  if (found)
1153  {
1154  pg_log(PG_REPORT, "fatal\n");
1155  pg_fatal("Your installation contains one of the reg* data types in user tables.\n"
1156  "These data types reference system OIDs that are not preserved by\n"
1157  "pg_upgrade, so this cluster cannot currently be upgraded. You can\n"
1158  "drop the problem columns and restart the upgrade.\n"
1159  "A list of the problem columns is in the file:\n"
1160  " %s\n\n", output_path);
1161  }
1162  else
1163  check_ok();
1164 }
1165 
1166 
1167 /*
1168  * check_for_jsonb_9_4_usage()
1169  *
1170  * JSONB changed its storage format during 9.4 beta, so check for it.
1171  */
1172 static void
1174 {
1175  char output_path[MAXPGPATH];
1176 
1177  prep_status("Checking for incompatible \"jsonb\" data type");
1178 
1179  snprintf(output_path, sizeof(output_path), "tables_using_jsonb.txt");
1180 
1181  if (check_for_data_type_usage(cluster, "pg_catalog.jsonb", output_path))
1182  {
1183  pg_log(PG_REPORT, "fatal\n");
1184  pg_fatal("Your installation contains the \"jsonb\" data type in user tables.\n"
1185  "The internal format of \"jsonb\" changed during 9.4 beta so this\n"
1186  "cluster cannot currently be upgraded. You can\n"
1187  "drop the problem columns and restart the upgrade.\n"
1188  "A list of the problem columns is in the file:\n"
1189  " %s\n\n", output_path);
1190  }
1191  else
1192  check_ok();
1193 }
1194 
1195 /*
1196  * check_for_pg_role_prefix()
1197  *
1198  * Versions older than 9.6 should not have any pg_* roles
1199  */
1200 static void
1202 {
1203  PGresult *res;
1204  PGconn *conn = connectToServer(cluster, "template1");
1205 
1206  prep_status("Checking for roles starting with \"pg_\"");
1207 
1208  res = executeQueryOrDie(conn,
1209  "SELECT * "
1210  "FROM pg_catalog.pg_roles "
1211  "WHERE rolname ~ '^pg_'");
1212 
1213  if (PQntuples(res) != 0)
1214  {
1215  if (cluster == &old_cluster)
1216  pg_fatal("The source cluster contains roles starting with \"pg_\"\n");
1217  else
1218  pg_fatal("The target cluster contains roles starting with \"pg_\"\n");
1219  }
1220 
1221  PQclear(res);
1222 
1223  PQfinish(conn);
1224 
1225  check_ok();
1226 }
1227 
1228 /*
1229  * Verify that no user-defined encoding conversions exist.
1230  */
1231 static void
1233 {
1234  int dbnum;
1235  FILE *script = NULL;
1236  bool found = false;
1237  char output_path[MAXPGPATH];
1238 
1239  prep_status("Checking for user-defined encoding conversions");
1240 
1241  snprintf(output_path, sizeof(output_path),
1242  "encoding_conversions.txt");
1243 
1244  /* Find any user defined encoding conversions */
1245  for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
1246  {
1247  PGresult *res;
1248  bool db_used = false;
1249  int ntups;
1250  int rowno;
1251  int i_conoid,
1252  i_conname,
1253  i_nspname;
1254  DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
1255  PGconn *conn = connectToServer(cluster, active_db->db_name);
1256 
1257  /*
1258  * The query below hardcodes FirstNormalObjectId as 16384 rather than
1259  * interpolating that C #define into the query because, if that
1260  * #define is ever changed, the cutoff we want to use is the value
1261  * used by pre-version 14 servers, not that of some future version.
1262  */
1263  res = executeQueryOrDie(conn,
1264  "SELECT c.oid as conoid, c.conname, n.nspname "
1265  "FROM pg_catalog.pg_conversion c, "
1266  " pg_catalog.pg_namespace n "
1267  "WHERE c.connamespace = n.oid AND "
1268  " c.oid >= 16384");
1269  ntups = PQntuples(res);
1270  i_conoid = PQfnumber(res, "conoid");
1271  i_conname = PQfnumber(res, "conname");
1272  i_nspname = PQfnumber(res, "nspname");
1273  for (rowno = 0; rowno < ntups; rowno++)
1274  {
1275  found = true;
1276  if (script == NULL &&
1277  (script = fopen_priv(output_path, "w")) == NULL)
1278  pg_fatal("could not open file \"%s\": %s\n",
1279  output_path, strerror(errno));
1280  if (!db_used)
1281  {
1282  fprintf(script, "In database: %s\n", active_db->db_name);
1283  db_used = true;
1284  }
1285  fprintf(script, " (oid=%s) %s.%s\n",
1286  PQgetvalue(res, rowno, i_conoid),
1287  PQgetvalue(res, rowno, i_nspname),
1288  PQgetvalue(res, rowno, i_conname));
1289  }
1290 
1291  PQclear(res);
1292 
1293  PQfinish(conn);
1294  }
1295 
1296  if (script)
1297  fclose(script);
1298 
1299  if (found)
1300  {
1301  pg_log(PG_REPORT, "fatal\n");
1302  pg_fatal("Your installation contains user-defined encoding conversions.\n"
1303  "The conversion function parameters changed in PostgreSQL version 14\n"
1304  "so this cluster cannot currently be upgraded. You can remove the\n"
1305  "encoding conversions in the old cluster and restart the upgrade.\n"
1306  "A list of user-defined encoding conversions is in the file:\n"
1307  " %s\n\n", output_path);
1308  }
1309  else
1310  check_ok();
1311 }
1312 
1313 
1314 /*
1315  * get_canonical_locale_name
1316  *
1317  * Send the locale name to the system, and hope we get back a canonical
1318  * version. This should match the backend's check_locale() function.
1319  */
1320 static char *
1321 get_canonical_locale_name(int category, const char *locale)
1322 {
1323  char *save;
1324  char *res;
1325 
1326  /* get the current setting, so we can restore it. */
1327  save = setlocale(category, NULL);
1328  if (!save)
1329  pg_fatal("failed to get the current locale\n");
1330 
1331  /* 'save' may be pointing at a modifiable scratch variable, so copy it. */
1332  save = pg_strdup(save);
1333 
1334  /* set the locale with setlocale, to see if it accepts it. */
1335  res = setlocale(category, locale);
1336 
1337  if (!res)
1338  pg_fatal("failed to get system locale name for \"%s\"\n", locale);
1339 
1340  res = pg_strdup(res);
1341 
1342  /* restore old value. */
1343  if (!setlocale(category, save))
1344  pg_fatal("failed to restore old locale \"%s\"\n", save);
1345 
1346  pg_free(save);
1347 
1348  return res;
1349 }
void check_file_clone(void)
Definition: file.c:317
uint32 major_version
Definition: pg_upgrade.h:269
void check_hard_link(void)
Definition: file.c:359
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:103
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3642
static void check_databases_are_compatible(void)
Definition: check.c:450
#define setlocale(a, b)
Definition: win32_port.h:436
bool check_for_data_types_usage(ClusterInfo *cluster, const char *base_query, const char *output_path)
Definition: version.c:113
ControlData controldata
Definition: pg_upgrade.h:259
void check_loadable_libraries(void)
Definition: function.c:180
void check_cluster_versions(void)
Definition: check.c:285
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:438
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define PATH_SEPARATOR
Definition: pg_upgrade.h:68
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define SCRIPT_EXT
Definition: pg_upgrade.h:73
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:23
char * relname
Definition: pg_upgrade.h:135
void canonicalize_path(char *path)
Definition: path.c:254
void output_completion_banner(char *deletion_script_file_name)
Definition: check.c:251
#define pg_fatal(...)
Definition: pg_rewind.h:37
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4231
void old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
Definition: version.c:334
unsigned short port
Definition: pg_upgrade.h:268
NameData datname
Definition: pg_database.h:35
static char * get_canonical_locale_name(int category, const char *locale)
Definition: check.c:1321
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
void check_cluster_compatibility(bool live_check)
Definition: check.c:327
static bool equivalent_locale(int category, const char *loca, const char *locb)
Definition: check.c:380
unsigned int Oid
Definition: postgres_ext.h:31
void check_control_data(ControlData *oldctrl, ControlData *newctrl)
Definition: controldata.c:648
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3248
#define fprintf
Definition: port.h:220
char * nspname
Definition: pg_upgrade.h:134
Oid db_oid
Definition: pg_upgrade.h:179
bool user_specified
Definition: pg_upgrade.h:312
static void check_for_reg_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1119
static void check_for_prepared_transactions(ClusterInfo *cluster)
Definition: check.c:758
ClusterInfo new_cluster
Definition: pg_upgrade.c:59
bool datallowconn
Definition: pg_database.h:53
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
static void check_for_user_defined_postfix_ops(ClusterInfo *cluster)
Definition: check.c:878
char * db_ctype
Definition: pg_upgrade.h:184
void pfree(void *pointer)
Definition: mcxt.c:1169
static void check_for_new_tablespace_dir(ClusterInfo *new_cluster)
Definition: check.c:489
PGconn * conn
Definition: streamutil.c:54
void output_check_banner(bool live_check)
Definition: check.c:65
#define MAXPGPATH
static void check_proper_datallowconn(ClusterInfo *cluster)
Definition: check.c:697
RelInfo * rels
Definition: pg_upgrade.h:147
#define RMDIR_CMD
Definition: pg_upgrade.h:71
char * c
void prep_status(const char *fmt,...) pg_attribute_printf(1
static void check_for_pg_role_prefix(ClusterInfo *cluster)
Definition: check.c:1201
void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster, bool check_mode)
Definition: version.c:22
ClusterInfo old_cluster
Definition: pg_upgrade.c:59
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static void check_for_tables_with_oids(ClusterInfo *cluster)
Definition: check.c:977
void generate_old_dump(void)
Definition: dump.c:16
#define atooid(x)
Definition: postgres_ext.h:42
static void check_ok(void)
Definition: initdb.c:1920
static void check_is_install_user(ClusterInfo *cluster)
Definition: check.c:646
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
Definition: check.c:793
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
Definition: server.c:27
void report_extension_updates(ClusterInfo *cluster)
Definition: version.c:478
bool check_for_data_type_usage(ClusterInfo *cluster, const char *type_name, const char *output_path)
Definition: version.c:241
void create_script_for_old_cluster_deletion(char **deletion_script_file_name)
Definition: check.c:518
transferMode transfer_mode
Definition: pg_upgrade.h:294
UserOpts user_opts
Definition: option.c:30
char * bindir
Definition: pg_upgrade.h:264
uint32 cat_ver
Definition: pg_upgrade.h:203
char ** old_tablespaces
Definition: pg_upgrade.h:313
#define DEF_PGUPORT
Definition: pg_upgrade.h:16
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:3356
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
void stop_postmaster(bool in_atexit)
Definition: server.c:330
const char * tablespace_suffix
Definition: pg_upgrade.h:272
void PQclear(PGresult *res)
Definition: fe-exec.c:694
void appendShellString(PQExpBuffer buf, const char *str)
Definition: string_utils.c:429
static void check_new_cluster_is_empty(void)
Definition: check.c:423
void get_loadable_libraries(void)
Definition: function.c:53
#define free(a)
Definition: header.h:65
uint32 bin_version
Definition: pg_upgrade.h:271
DbInfoArr dbarr
Definition: pg_upgrade.h:260
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
#define Assert(condition)
Definition: c.h:804
RelInfoArr rel_arr
Definition: pg_upgrade.h:186
void get_db_and_rel_infos(ClusterInfo *cluster)
Definition: info.c:309
void get_control_data(ClusterInfo *cluster, bool live_check)
Definition: controldata.c:34
#define strerror
Definition: port.h:229
#define JSONB_FORMAT_CHANGE_CAT_VER
Definition: pg_upgrade.h:125
bool check
Definition: pg_upgrade.h:292
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#define SCRIPT_PREFIX
Definition: pg_upgrade.h:72
int db_encoding
Definition: pg_upgrade.h:185
static pgpid_t start_postmaster(void)
Definition: pg_ctl.c:443
static void check_for_jsonb_9_4_usage(ClusterInfo *cluster)
Definition: check.c:1173
#define PATH_QUOTE
Definition: pg_upgrade.h:69
void init_tablespaces(void)
Definition: tablespace.c:19
#define fopen_priv(path, mode)
Definition: pg_upgrade.h:380
char * pgdata
Definition: pg_upgrade.h:261
#define S_IRWXU
Definition: win32_port.h:289
int num_old_tablespaces
Definition: pg_upgrade.h:314
OSInfo os_info
Definition: pg_upgrade.c:61
char * db_name
Definition: pg_upgrade.h:180
static char * locale
Definition: initdb.c:126
void old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster)
Definition: version.c:268
char * db_collate
Definition: pg_upgrade.h:183
void check_new_cluster(void)
Definition: check.c:179
void check_and_dump_old_cluster(bool live_check)
Definition: check.c:83
void report_clusters_compatible(void)
Definition: check.c:209
static void check_for_composite_data_type_usage(ClusterInfo *cluster)
Definition: check.c:1060
void issue_warnings_and_set_wal_level(void)
Definition: check.c:226
DbInfo * dbs
Definition: pg_upgrade.h:191
static void check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb)
Definition: check.c:353
#define snprintf
Definition: port.h:216
char * user
Definition: pg_upgrade.h:311
#define RM_CMD
Definition: pg_upgrade.h:70
bool float8_pass_by_value
Definition: pg_upgrade.h:222
static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster)
Definition: check.c:1232
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
#define stat
Definition: win32_port.h:275
static char * fix_path_separator(char *path)
Definition: check.c:44
void old_11_check_for_sql_identifier_data_type_usage(ClusterInfo *cluster)
Definition: version.c:449
void old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster)
Definition: version.c:306