diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/pg_dump/pg_backup_archiver.c | 226 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 9 |
2 files changed, 147 insertions, 88 deletions
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index fb0379377bf..94c511c936b 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -70,7 +70,7 @@ static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName); static void _selectTablespace(ArchiveHandle *AH, const char *tablespace); static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te); static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te); -static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt); +static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH); static RestorePass _tocEntryRestorePass(TocEntry *te); static bool _tocEntryIsACL(TocEntry *te); static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te); @@ -312,7 +312,7 @@ ProcessArchiveRestoreOptions(Archive *AHX) if (te->section != SECTION_NONE) curSection = te->section; - te->reqs = _tocEntryRequired(te, curSection, ropt); + te->reqs = _tocEntryRequired(te, curSection, AH); } /* Enforce strict names checking */ @@ -488,9 +488,8 @@ RestoreArchive(Archive *AHX) * In createDB mode, issue a DROP *only* for the database as a * whole. Issuing drops against anything else would be wrong, * because at this point we're connected to the wrong database. - * Conversely, if we're not in createDB mode, we'd better not - * issue a DROP against the database at all. (The DATABASE - * PROPERTIES entry, if any, works like the DATABASE entry.) + * (The DATABASE PROPERTIES entry, if any, should be treated like + * the DATABASE entry.) */ if (ropt->createDB) { @@ -498,12 +497,6 @@ RestoreArchive(Archive *AHX) strcmp(te->desc, "DATABASE PROPERTIES") != 0) continue; } - else - { - if (strcmp(te->desc, "DATABASE") == 0 || - strcmp(te->desc, "DATABASE PROPERTIES") == 0) - continue; - } /* Otherwise, drop anything that's selected and has a dropStmt */ if (((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt) @@ -752,25 +745,6 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel) AH->currentTE = te; - /* Work out what, if anything, we want from this entry */ - reqs = te->reqs; - - /* - * Ignore DATABASE and related entries unless createDB is specified. We - * must check this here, not in _tocEntryRequired, because !createDB - * should not prevent emitting these entries to an archive file. - */ - if (!ropt->createDB && - (strcmp(te->desc, "DATABASE") == 0 || - strcmp(te->desc, "DATABASE PROPERTIES") == 0 || - (strcmp(te->desc, "ACL") == 0 && - strncmp(te->tag, "DATABASE ", 9) == 0) || - (strcmp(te->desc, "COMMENT") == 0 && - strncmp(te->tag, "DATABASE ", 9) == 0) || - (strcmp(te->desc, "SECURITY LABEL") == 0 && - strncmp(te->tag, "DATABASE ", 9) == 0))) - reqs = 0; - /* Dump any relevant dump warnings to stderr */ if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0) { @@ -780,6 +754,9 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel) write_msg(modulename, "warning from original dump file: %s\n", te->copyStmt); } + /* Work out what, if anything, we want from this entry */ + reqs = te->reqs; + defnDumped = false; /* @@ -1191,7 +1168,7 @@ PrintTOCSummary(Archive *AHX) if (te->section != SECTION_NONE) curSection = te->section; if (ropt->verbose || - (_tocEntryRequired(te, curSection, ropt) & (REQ_SCHEMA | REQ_DATA)) != 0) + (_tocEntryRequired(te, curSection, AH) & (REQ_SCHEMA | REQ_DATA)) != 0) { char *sanitized_name; char *sanitized_schema; @@ -2824,16 +2801,42 @@ StrictNamesCheck(RestoreOptions *ropt) } } +/* + * Determine whether we want to restore this TOC entry. + * + * Returns 0 if entry should be skipped, or some combination of the + * REQ_SCHEMA and REQ_DATA bits if we want to restore schema and/or data + * portions of this TOC entry, or REQ_SPECIAL if it's a special entry. + */ static teReqs -_tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) +_tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) { teReqs res = REQ_SCHEMA | REQ_DATA; + RestoreOptions *ropt = AH->public.ropt; /* ENCODING and STDSTRINGS items are treated specially */ if (strcmp(te->desc, "ENCODING") == 0 || strcmp(te->desc, "STDSTRINGS") == 0) return REQ_SPECIAL; + /* + * DATABASE and DATABASE PROPERTIES also have a special rule: they are + * restored in createDB mode, and not restored otherwise, independently of + * all else. + */ + if (strcmp(te->desc, "DATABASE") == 0 || + strcmp(te->desc, "DATABASE PROPERTIES") == 0) + { + if (ropt->createDB) + return REQ_SCHEMA; + else + return 0; + } + + /* + * Process exclusions that affect certain classes of TOC entries. + */ + /* If it's an ACL, maybe ignore it */ if (ropt->aclsSkip && _tocEntryIsACL(te)) return 0; @@ -2842,11 +2845,11 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) if (ropt->no_publications && strcmp(te->desc, "PUBLICATION") == 0) return 0; - /* If it's security labels, maybe ignore it */ + /* If it's a security label, maybe ignore it */ if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0) return 0; - /* If it's a subcription, maybe ignore it */ + /* If it's a subscription, maybe ignore it */ if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0) return 0; @@ -2870,65 +2873,118 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) return 0; } - /* Check options for selective dump/restore */ - if (ropt->schemaNames.head != NULL) - { - /* If no namespace is specified, it means all. */ - if (!te->namespace) - return 0; - if (!(simple_string_list_member(&ropt->schemaNames, te->namespace))) - return 0; - } - - if (ropt->schemaExcludeNames.head != NULL && - te->namespace && - simple_string_list_member(&ropt->schemaExcludeNames, te->namespace)) + /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */ + if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1]) return 0; - if (ropt->selTypes) + /* + * Check options for selective dump/restore. + */ + if (strcmp(te->desc, "ACL") == 0 || + strcmp(te->desc, "COMMENT") == 0 || + strcmp(te->desc, "SECURITY LABEL") == 0) { - if (strcmp(te->desc, "TABLE") == 0 || - strcmp(te->desc, "TABLE DATA") == 0 || - strcmp(te->desc, "VIEW") == 0 || - strcmp(te->desc, "FOREIGN TABLE") == 0 || - strcmp(te->desc, "MATERIALIZED VIEW") == 0 || - strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 || - strcmp(te->desc, "SEQUENCE") == 0 || - strcmp(te->desc, "SEQUENCE SET") == 0) + /* Database properties react to createDB, not selectivity options. */ + if (strncmp(te->tag, "DATABASE ", 9) == 0) { - if (!ropt->selTable) - return 0; - if (ropt->tableNames.head != NULL && (!(simple_string_list_member(&ropt->tableNames, te->tag)))) + if (!ropt->createDB) return 0; } - else if (strcmp(te->desc, "INDEX") == 0) + else if (ropt->schemaNames.head != NULL || + ropt->schemaExcludeNames.head != NULL || + ropt->selTypes) { - if (!ropt->selIndex) - return 0; - if (ropt->indexNames.head != NULL && (!(simple_string_list_member(&ropt->indexNames, te->tag)))) + /* + * In a selective dump/restore, we want to restore these dependent + * TOC entry types only if their parent object is being restored. + * Without selectivity options, we let through everything in the + * archive. Note there may be such entries with no parent, eg + * non-default ACLs for built-in objects. + * + * This code depends on the parent having been marked already, + * which should be the case; if it isn't, perhaps due to + * SortTocFromFile rearrangement, skipping the dependent entry + * seems prudent anyway. + * + * Ideally we'd handle, eg, table CHECK constraints this way too. + * But it's hard to tell which of their dependencies is the one to + * consult. + */ + if (te->nDeps != 1 || + TocIDRequired(AH, te->dependencies[0]) == 0) return 0; } - else if (strcmp(te->desc, "FUNCTION") == 0 || - strcmp(te->desc, "PROCEDURE") == 0) + } + else + { + /* Apply selective-restore rules for standalone TOC entries. */ + if (ropt->schemaNames.head != NULL) { - if (!ropt->selFunction) + /* If no namespace is specified, it means all. */ + if (!te->namespace) return 0; - if (ropt->functionNames.head != NULL && (!(simple_string_list_member(&ropt->functionNames, te->tag)))) + if (!simple_string_list_member(&ropt->schemaNames, te->namespace)) return 0; } - else if (strcmp(te->desc, "TRIGGER") == 0) + + if (ropt->schemaExcludeNames.head != NULL && + te->namespace && + simple_string_list_member(&ropt->schemaExcludeNames, te->namespace)) + return 0; + + if (ropt->selTypes) { - if (!ropt->selTrigger) - return 0; - if (ropt->triggerNames.head != NULL && (!(simple_string_list_member(&ropt->triggerNames, te->tag)))) + if (strcmp(te->desc, "TABLE") == 0 || + strcmp(te->desc, "TABLE DATA") == 0 || + strcmp(te->desc, "VIEW") == 0 || + strcmp(te->desc, "FOREIGN TABLE") == 0 || + strcmp(te->desc, "MATERIALIZED VIEW") == 0 || + strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 || + strcmp(te->desc, "SEQUENCE") == 0 || + strcmp(te->desc, "SEQUENCE SET") == 0) + { + if (!ropt->selTable) + return 0; + if (ropt->tableNames.head != NULL && + !simple_string_list_member(&ropt->tableNames, te->tag)) + return 0; + } + else if (strcmp(te->desc, "INDEX") == 0) + { + if (!ropt->selIndex) + return 0; + if (ropt->indexNames.head != NULL && + !simple_string_list_member(&ropt->indexNames, te->tag)) + return 0; + } + else if (strcmp(te->desc, "FUNCTION") == 0 || + strcmp(te->desc, "AGGREGATE") == 0 || + strcmp(te->desc, "PROCEDURE") == 0) + { + if (!ropt->selFunction) + return 0; + if (ropt->functionNames.head != NULL && + !simple_string_list_member(&ropt->functionNames, te->tag)) + return 0; + } + else if (strcmp(te->desc, "TRIGGER") == 0) + { + if (!ropt->selTrigger) + return 0; + if (ropt->triggerNames.head != NULL && + !simple_string_list_member(&ropt->triggerNames, te->tag)) + return 0; + } + else return 0; } - else - return 0; } /* - * Check if we had a dataDumper. Indicates if the entry is schema or data + * Determine whether the TOC entry contains schema and/or data components, + * and mask off inapplicable REQ bits. If it had a dataDumper, assume + * it's both schema and data. Otherwise it's probably schema-only, but + * there are exceptions. */ if (!te->hadDumper) { @@ -2952,6 +3008,10 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) res = res & ~REQ_DATA; } + /* If there's no definition command, there's no schema component */ + if (!te->defn || !te->defn[0]) + res = res & ~REQ_SCHEMA; + /* * Special case: <Init> type with <Max OID> tag; this is obsolete and we * always ignore it. @@ -2963,12 +3023,12 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) if (ropt->schemaOnly) { /* - * The sequence_data option overrides schema-only for SEQUENCE SET. + * The sequence_data option overrides schemaOnly for SEQUENCE SET. * - * In binary-upgrade mode, even with schema-only set, we do not mask - * out large objects. Only large object definitions, comments and - * other information should be generated in binary-upgrade mode (not - * the actual data). + * In binary-upgrade mode, even with schemaOnly set, we do not mask + * out large objects. (Only large object definitions, comments and + * other metadata should be generated in binary-upgrade mode, not the + * actual data, but that need not concern us here.) */ if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) && !(ropt->binary_upgrade && @@ -2986,14 +3046,6 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) if (ropt->dataOnly) res = res & REQ_DATA; - /* Mask it if we don't have a schema contribution */ - if (!te->defn || strlen(te->defn) == 0) - res = res & ~REQ_SCHEMA; - - /* Finally, if there's a per-ID filter, limit based on that as well */ - if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1]) - return 0; - return res; } diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index b534fb7b95d..c34d9907299 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -632,6 +632,13 @@ main(int argc, char **argv) #endif /* + * If emitting an archive format, we always want to emit a DATABASE item, + * in case --create is specified at pg_restore time. + */ + if (!plainText) + dopt.outputCreateDB = 1; + + /* * On Windows we can only have at most MAXIMUM_WAIT_OBJECTS (= 64 usually) * parallel jobs because that's the maximum limit for the * WaitForMultipleObjects() call. @@ -841,7 +848,7 @@ main(int argc, char **argv) dumpStdStrings(fout); /* The database items are always next, unless we don't want them at all */ - if (dopt.include_everything && !dopt.dataOnly) + if (dopt.outputCreateDB) dumpDatabase(fout); /* Now the rearrangeable objects. */ |