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