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);
if (te->section != SECTION_NONE)
curSection = te->section;
- te->reqs = _tocEntryRequired(te, curSection, ropt);
+ te->reqs = _tocEntryRequired(te, curSection, AH);
}
/* Enforce strict names checking */
* 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)
{
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)
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)
{
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;
/*
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;
}
}
+/*
+ * 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;
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;
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)
{
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.
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 &&
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;
}