aboutsummaryrefslogtreecommitdiff
path: root/contrib/pg_upgrade/dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pg_upgrade/dump.c')
-rw-r--r--contrib/pg_upgrade/dump.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c
new file mode 100644
index 00000000000..f0f827aeb5b
--- /dev/null
+++ b/contrib/pg_upgrade/dump.c
@@ -0,0 +1,97 @@
+/*
+ * dump.c
+ *
+ * dump functions
+ */
+
+#include "pg_upgrade.h"
+
+
+
+void
+generate_old_dump(migratorContext *ctx)
+{
+ /* run new pg_dumpall binary */
+ prep_status(ctx, "Creating catalog dump");
+
+ /*
+ * --binary-upgrade records the width of dropped columns in pg_class, and
+ * restores the frozenid's for databases and relations.
+ */
+ exec_prog(ctx, true,
+ SYSTEMQUOTE "\"%s/pg_dumpall\" --port %d --schema-only "
+ "--binary-upgrade > \"%s/" ALL_DUMP_FILE "\"" SYSTEMQUOTE,
+ ctx->new.bindir, ctx->old.port, ctx->output_dir);
+ check_ok(ctx);
+}
+
+
+/*
+ * split_old_dump
+ *
+ * This function splits pg_dumpall output into global values and
+ * database creation, and per-db schemas. This allows us to create
+ * the toast place holders between restoring these two parts of the
+ * dump. We split on the first "\connect " after a CREATE ROLE
+ * username match; this is where the per-db restore starts.
+ *
+ * We suppress recreation of our own username so we don't generate
+ * an error during restore
+ */
+void
+split_old_dump(migratorContext *ctx)
+{
+ FILE *all_dump,
+ *globals_dump,
+ *db_dump;
+ FILE *current_output;
+ char line[LINE_ALLOC];
+ bool start_of_line = true;
+ char create_role_str[MAX_STRING];
+ char create_role_str_quote[MAX_STRING];
+ char filename[MAXPGPATH];
+ bool suppressed_username = false;
+
+ snprintf(filename, sizeof(filename), "%s/%s", ctx->output_dir, ALL_DUMP_FILE);
+ if ((all_dump = fopen(filename, "r")) == NULL)
+ pg_log(ctx, PG_FATAL, "Cannot open dump file %s\n", filename);
+ snprintf(filename, sizeof(filename), "%s/%s", ctx->output_dir, GLOBALS_DUMP_FILE);
+ if ((globals_dump = fopen(filename, "w")) == NULL)
+ pg_log(ctx, PG_FATAL, "Cannot write to dump file %s\n", filename);
+ snprintf(filename, sizeof(filename), "%s/%s", ctx->output_dir, DB_DUMP_FILE);
+ if ((db_dump = fopen(filename, "w")) == NULL)
+ pg_log(ctx, PG_FATAL, "Cannot write to dump file %s\n", filename);
+ current_output = globals_dump;
+
+ /* patterns used to prevent our own username from being recreated */
+ snprintf(create_role_str, sizeof(create_role_str),
+ "CREATE ROLE %s;", ctx->user);
+ snprintf(create_role_str_quote, sizeof(create_role_str_quote),
+ "CREATE ROLE %s;", quote_identifier(ctx, ctx->user));
+
+ while (fgets(line, sizeof(line), all_dump) != NULL)
+ {
+ /* switch to db_dump file output? */
+ if (current_output == globals_dump && start_of_line &&
+ suppressed_username &&
+ strncmp(line, "\\connect ", strlen("\\connect ")) == 0)
+ current_output = db_dump;
+
+ /* output unless we are recreating our own username */
+ if (current_output != globals_dump || !start_of_line ||
+ (strncmp(line, create_role_str, strlen(create_role_str)) != 0 &&
+ strncmp(line, create_role_str_quote, strlen(create_role_str_quote)) != 0))
+ fputs(line, current_output);
+ else
+ suppressed_username = true;
+
+ if (strlen(line) > 0 && line[strlen(line) - 1] == '\n')
+ start_of_line = true;
+ else
+ start_of_line = false;
+ }
+
+ fclose(all_dump);
+ fclose(globals_dump);
+ fclose(db_dump);
+}