static bool have_extra_float_digits = false;
static int extra_float_digits;
+/* sorted table of comments */
+static CommentItem *comments = NULL;
+static int ncomments = 0;
+
+/* sorted table of security labels */
+static SecLabelItem *seclabels = NULL;
+static int nseclabels = 0;
+
/*
* The default number of rows per INSERT when
* --inserts is specified without --rows-per-insert
int subid, DumpId dumpId);
static int findComments(Archive *fout, Oid classoid, Oid objoid,
CommentItem **items);
-static int collectComments(Archive *fout, CommentItem **items);
+static void collectComments(Archive *fout);
static void dumpSecLabel(Archive *fout, const char *type, const char *name,
const char *namespace, const char *owner,
CatalogId catalogId, int subid, DumpId dumpId);
static int findSecLabels(Archive *fout, Oid classoid, Oid objoid,
SecLabelItem **items);
-static int collectSecLabels(Archive *fout, SecLabelItem **items);
-static void dumpDumpableObject(Archive *fout, const DumpableObject *dobj);
+static void collectSecLabels(Archive *fout);
+static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
static void dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo);
static void dumpExtension(Archive *fout, const ExtensionInfo *extinfo);
static void dumpType(Archive *fout, const TypeInfo *tyinfo);
Oid pg_type_oid,
bool force_array_type,
bool include_multirange_type);
-static void binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
- PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
+static void binary_upgrade_set_type_oids_by_rel(Archive *fout,
+ PQExpBuffer upgrade_buffer,
+ const TableInfo *tbinfo);
static void binary_upgrade_set_pg_class_oids(Archive *fout,
PQExpBuffer upgrade_buffer,
Oid pg_class_oid, bool is_index);
*/
getDependencies(fout);
+ /*
+ * Collect comments and security labels, if wanted.
+ */
+ if (!dopt.no_comments)
+ collectComments(fout);
+ if (!dopt.no_security_labels)
+ collectSecLabels(fout);
+
/* Lastly, create dummy objects to represent the section boundaries */
boundaryObjs = createBoundaryObjects();
if (nsinfo->nspowner == ROLE_PG_DATABASE_OWNER)
nsinfo->dobj.dump &= ~DUMP_COMPONENT_DEFINITION;
nsinfo->dobj.dump_contains = DUMP_COMPONENT_ALL;
+
+ /*
+ * Also, make like it has a comment even if it doesn't; this is so
+ * that we'll emit a command to drop the comment, if appropriate.
+ * (Without this, we'd not call dumpCommentExtended for it.)
+ */
+ nsinfo->dobj.components |= DUMP_COMPONENT_COMMENT;
}
else
nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ALL;
* Make a dumpable object for the data of this specific table
*
* Note: we make a TableDataInfo if and only if we are going to dump the
- * table data; the "dump" flag in such objects isn't used.
+ * table data; the "dump" field in such objects isn't very interesting.
*/
static void
makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
tdinfo->filtercond = NULL; /* might get set later */
addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId);
+ /* A TableDataInfo contains data, of course */
+ tdinfo->dobj.components |= DUMP_COMPONENT_DATA;
+
tbinfo->dataObj = tdinfo;
/* Make sure that we'll collect per-column info for this table. */
binfo[i].initblobacl = pg_strdup(PQgetvalue(res, i, i_initlomacl));
binfo[i].initrblobacl = pg_strdup(PQgetvalue(res, i, i_initrlomacl));
- if (PQgetisnull(res, i, i_lomacl) &&
- PQgetisnull(res, i, i_rlomacl) &&
- PQgetisnull(res, i, i_initlomacl) &&
- PQgetisnull(res, i, i_initrlomacl))
- binfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Blobs have data */
+ binfo[i].dobj.components |= DUMP_COMPONENT_DATA;
+
+ /* Mark whether blob has an ACL */
+ if (!(PQgetisnull(res, i, i_lomacl) &&
+ PQgetisnull(res, i, i_rlomacl) &&
+ PQgetisnull(res, i, i_initlomacl) &&
+ PQgetisnull(res, i, i_initrlomacl)))
+ binfo[i].dobj.components |= DUMP_COMPONENT_ACL;
/*
* In binary-upgrade mode for blobs, we do *not* dump out the blob
bdata->catId = nilCatalogId;
AssignDumpId(bdata);
bdata->name = pg_strdup("BLOBS");
+ bdata->components |= DUMP_COMPONENT_DATA;
}
PQclear(res);
binfo->dobj.catId, 0, binfo->dobj.dumpId);
/* Dump ACL if any */
- if (binfo->blobacl && (binfo->dobj.dump & DUMP_COMPONENT_ACL))
+ if (binfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, binfo->dobj.dumpId, InvalidDumpId, "LARGE OBJECT",
binfo->dobj.name, NULL,
NULL, binfo->rolname, binfo->blobacl, binfo->rblobacl,
if (tbinfo->rowsec)
{
+ tbinfo->dobj.components |= DUMP_COMPONENT_POLICY;
+
/*
* Note: use tableoid 0 so that this object won't be mistaken for
* something that pg_depend entries apply to.
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY))
continue;
+ tbinfo->dobj.components |= DUMP_COMPONENT_POLICY;
+
polinfo[j].dobj.objType = DO_POLICY;
polinfo[j].dobj.catId.tableoid =
atooid(PQgetvalue(res, j, i_tableoid));
const char *cmd;
char *tag;
+ /* Do nothing in data-only dump */
if (dopt->dataOnly)
return;
* explicitly, because it will not match anything in pg_depend (unlike
* the case for other PolicyInfo objects).
*/
- if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
+ if (polinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
ARCHIVE_OPTS(.tag = polinfo->dobj.name,
.namespace = polinfo->dobj.namespace->dobj.name,
tag = psprintf("%s %s", tbinfo->dobj.name, polinfo->dobj.name);
- if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
+ if (polinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
ARCHIVE_OPTS(.tag = tag,
.namespace = polinfo->dobj.namespace->dobj.name,
char *qpubname;
bool first = true;
- if (!(pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
- return;
-
delq = createPQExpBuffer();
query = createPQExpBuffer();
appendPQExpBufferStr(query, ");\n");
- ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
- ARCHIVE_OPTS(.tag = pubinfo->dobj.name,
- .owner = pubinfo->rolname,
- .description = "PUBLICATION",
- .section = SECTION_POST_DATA,
- .createStmt = query->data,
- .dropStmt = delq->data));
+ if (pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = pubinfo->dobj.name,
+ .owner = pubinfo->rolname,
+ .description = "PUBLICATION",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delq->data));
if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
dumpComment(fout, "PUBLICATION", qpubname,
PQExpBuffer query;
char *tag;
- if (!(pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
- return;
-
tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name);
query = createPQExpBuffer();
* owner field anyway to ensure that the command is run by the correct
* role at restore time.
*/
- ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
- ARCHIVE_OPTS(.tag = tag,
- .namespace = tbinfo->dobj.namespace->dobj.name,
- .owner = pubinfo->rolname,
- .description = "PUBLICATION TABLE",
- .section = SECTION_POST_DATA,
- .createStmt = query->data));
+ if (pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = pubinfo->rolname,
+ .description = "PUBLICATION TABLE",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data));
free(tag);
destroyPQExpBuffer(query);
int i;
char two_phase_disabled[] = {LOGICALREP_TWOPHASE_STATE_DISABLED, '\0'};
- if (!(subinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
- return;
-
delq = createPQExpBuffer();
query = createPQExpBuffer();
appendPQExpBufferStr(query, ");\n");
- ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
- ARCHIVE_OPTS(.tag = subinfo->dobj.name,
- .owner = subinfo->rolname,
- .description = "SUBSCRIPTION",
- .section = SECTION_POST_DATA,
- .createStmt = query->data,
- .dropStmt = delq->data));
+ if (subinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = subinfo->dobj.name,
+ .owner = subinfo->rolname,
+ .description = "SUBSCRIPTION",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delq->data));
if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
dumpComment(fout, "SUBSCRIPTION", qsubname,
}
static void
-binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
- PQExpBuffer upgrade_buffer,
- Oid pg_rel_oid)
+binary_upgrade_set_type_oids_by_rel(Archive *fout,
+ PQExpBuffer upgrade_buffer,
+ const TableInfo *tbinfo)
{
- PQExpBuffer upgrade_query = createPQExpBuffer();
- PGresult *upgrade_res;
- Oid pg_type_oid;
-
- appendPQExpBuffer(upgrade_query,
- "SELECT c.reltype AS crel "
- "FROM pg_catalog.pg_class c "
- "WHERE c.oid = '%u'::pg_catalog.oid;",
- pg_rel_oid);
-
- upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
-
- pg_type_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "crel")));
+ Oid pg_type_oid = tbinfo->reltype;
if (OidIsValid(pg_type_oid))
binary_upgrade_set_type_oids_by_type_oid(fout, upgrade_buffer,
pg_type_oid, false, false);
-
- PQclear(upgrade_res);
- destroyPQExpBuffer(upgrade_query);
}
static void
/* Decide whether to dump this namespace */
selectDumpableNamespace(&nsinfo[i], fout);
- /*
- * Do not try to dump ACL if the ACL is empty or the default.
- *
- * This is useful because, for some schemas/objects, the only
- * component we are going to try and dump is the ACL and if we can
- * remove that then 'dump' goes to zero/false and we don't consider
- * this object for dumping at all later on.
- */
- if (PQgetisnull(res, i, i_nspacl) && PQgetisnull(res, i, i_rnspacl) &&
- PQgetisnull(res, i, i_initnspacl) &&
- PQgetisnull(res, i, i_initrnspacl))
- nsinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether namespace has an ACL */
+ if (!(PQgetisnull(res, i, i_nspacl) &&
+ PQgetisnull(res, i, i_rnspacl) &&
+ PQgetisnull(res, i, i_initnspacl) &&
+ PQgetisnull(res, i, i_initrnspacl)))
+ nsinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
if (strlen(nsinfo[i].rolname) == 0)
pg_log_warning("owner of schema \"%s\" appears to be invalid",
/* Decide whether we want to dump it */
selectDumpableType(&tyinfo[i], fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_typacl) && PQgetisnull(res, i, i_rtypacl) &&
- PQgetisnull(res, i, i_inittypacl) &&
- PQgetisnull(res, i, i_initrtypacl))
- tyinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether type has an ACL */
+ if (!(PQgetisnull(res, i, i_typacl) &&
+ PQgetisnull(res, i, i_rtypacl) &&
+ PQgetisnull(res, i, i_inittypacl) &&
+ PQgetisnull(res, i, i_initrtypacl)))
+ tyinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
/*
* If it's a domain, fetch info about its constraints, if any
/* Decide whether we want to dump it */
selectDumpableObject(&(oprinfo[i].dobj), fout);
- /* Operators do not currently have ACLs. */
- oprinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
-
if (strlen(oprinfo[i].rolname) == 0)
pg_log_warning("owner of operator \"%s\" appears to be invalid",
oprinfo[i].dobj.name);
/* Decide whether we want to dump it */
selectDumpableObject(&(collinfo[i].dobj), fout);
-
- /* Collations do not currently have ACLs. */
- collinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(convinfo[i].dobj), fout);
-
- /* Conversions do not currently have ACLs. */
- convinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableAccessMethod(&(aminfo[i]), fout);
-
- /* Access methods do not currently have ACLs. */
- aminfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(opcinfo[i].dobj), fout);
- /* Op Classes do not currently have ACLs. */
- opcinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
-
if (strlen(opcinfo[i].rolname) == 0)
pg_log_warning("owner of operator class \"%s\" appears to be invalid",
opcinfo[i].dobj.name);
/* Decide whether we want to dump it */
selectDumpableObject(&(opfinfo[i].dobj), fout);
- /* Extensions do not currently have ACLs. */
- opfinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
-
if (strlen(opfinfo[i].rolname) == 0)
pg_log_warning("owner of operator family \"%s\" appears to be invalid",
opfinfo[i].dobj.name);
/* Decide whether we want to dump it */
selectDumpableObject(&(agginfo[i].aggfn.dobj), fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_aggacl) && PQgetisnull(res, i, i_raggacl) &&
- PQgetisnull(res, i, i_initaggacl) &&
- PQgetisnull(res, i, i_initraggacl))
- agginfo[i].aggfn.dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether aggregate has an ACL */
+ if (!(PQgetisnull(res, i, i_aggacl) &&
+ PQgetisnull(res, i, i_raggacl) &&
+ PQgetisnull(res, i, i_initaggacl) &&
+ PQgetisnull(res, i, i_initraggacl)))
+ agginfo[i].aggfn.dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(finfo[i].dobj), fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_proacl) && PQgetisnull(res, i, i_rproacl) &&
- PQgetisnull(res, i, i_initproacl) &&
- PQgetisnull(res, i, i_initrproacl))
- finfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether function has an ACL */
+ if (!(PQgetisnull(res, i, i_proacl) &&
+ PQgetisnull(res, i, i_rproacl) &&
+ PQgetisnull(res, i, i_initproacl) &&
+ PQgetisnull(res, i, i_initrproacl)))
+ finfo[i].dobj.components |= DUMP_COMPONENT_ACL;
if (strlen(finfo[i].rolname) == 0)
pg_log_warning("owner of function \"%s\" appears to be invalid",
int i_relname;
int i_relnamespace;
int i_relkind;
+ int i_reltype;
int i_rolname;
int i_relchecks;
int i_relhasindex;
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
- "c.relnamespace, c.relkind, "
+ "c.relnamespace, c.relkind, c.reltype, "
"(%s c.relowner) AS rolname, "
"c.relchecks, "
"c.relhasindex, c.relhasrules, c.relpages, "
i_relname = PQfnumber(res, "relname");
i_relnamespace = PQfnumber(res, "relnamespace");
i_relkind = PQfnumber(res, "relkind");
+ i_reltype = PQfnumber(res, "reltype");
i_rolname = PQfnumber(res, "rolname");
i_relchecks = PQfnumber(res, "relchecks");
i_relhasindex = PQfnumber(res, "relhasindex");
tblinfo[i].dobj.namespace =
findNamespace(atooid(PQgetvalue(res, i, i_relnamespace)));
tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
+ tblinfo[i].reltype = atooid(PQgetvalue(res, i, i_reltype));
tblinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
else
selectDumpableTable(&tblinfo[i], fout);
- tblinfo[i].interesting = tblinfo[i].dobj.dump ? true : false;
+ /*
+ * Now, consider the table "interesting" if we need to dump its
+ * definition or its data. Later on, we'll skip a lot of data
+ * collection for uninteresting tables.
+ *
+ * Note: the "interesting" flag will also be set by flagInhTables for
+ * parents of interesting tables, so that we collect necessary
+ * inheritance info even when the parents are not themselves being
+ * dumped. This is the main reason why we need an "interesting" flag
+ * that's separate from the components-to-dump bitmask.
+ */
+ tblinfo[i].interesting = (tblinfo[i].dobj.dump &
+ (DUMP_COMPONENT_DEFINITION |
+ DUMP_COMPONENT_DATA)) != 0;
+
tblinfo[i].dummy_view = false; /* might get set during sort */
tblinfo[i].postponed_def = false; /* might get set during sort */
+ /* Tables have data */
+ tblinfo[i].dobj.components |= DUMP_COMPONENT_DATA;
+
/*
+ * Mark whether table has an ACL.
+ *
* If the table-level and all column-level ACLs for this table are
* unchanged, then we don't need to worry about including the ACLs for
* this table. If any column-level ACLs have been changed, the
* This can result in a significant performance improvement in cases
* where we are only looking to dump out the ACL (eg: pg_catalog).
*/
- if (PQgetisnull(res, i, i_relacl) && PQgetisnull(res, i, i_rrelacl) &&
- PQgetisnull(res, i, i_initrelacl) &&
- PQgetisnull(res, i, i_initrrelacl) &&
- strcmp(PQgetvalue(res, i, i_changed_acl), "f") == 0)
- tblinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ if (!(PQgetisnull(res, i, i_relacl) &&
+ PQgetisnull(res, i, i_rrelacl) &&
+ PQgetisnull(res, i, i_initrelacl) &&
+ PQgetisnull(res, i, i_initrrelacl) &&
+ strcmp(PQgetvalue(res, i, i_changed_acl), "f") == 0))
+ tblinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
/*
* Read-lock target tables to make sure they aren't DROPPED or altered
* We only need to lock the table for certain components; see
* pg_dump.h
*/
- if (tblinfo[i].dobj.dump &&
+ if ((tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK) &&
(tblinfo[i].relkind == RELKIND_RELATION ||
- tblinfo[i].relkind == RELKIND_PARTITIONED_TABLE) &&
- (tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK))
+ tblinfo[i].relkind == RELKIND_PARTITIONED_TABLE))
{
resetPQExpBuffer(query);
appendPQExpBuffer(query,
continue;
/*
- * Ignore indexes of tables whose definitions are not to be dumped.
- *
- * We also need indexes on partitioned tables which have partitions to
- * be dumped, in order to dump the indexes on the partitions.
+ * We can ignore indexes of uninteresting tables.
*/
- if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) &&
- !tbinfo->interesting)
+ if (!tbinfo->interesting)
continue;
pg_log_info("reading indexes for table \"%s.%s\"",
/* Decide whether we want to dump it */
selectDumpableObject(&(statsextinfo[i].dobj), fout);
-
- /* Stats objects do not currently have ACLs. */
- statsextinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(evtinfo[i].dobj), fout);
-
- /* Event Triggers do not currently have ACLs. */
- evtinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableProcLang(&(planginfo[i]), fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_lanacl) && PQgetisnull(res, i, i_rlanacl) &&
- PQgetisnull(res, i, i_initlanacl) &&
- PQgetisnull(res, i, i_initrlanacl))
- planginfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether language has an ACL */
+ if (!(PQgetisnull(res, i, i_lanacl) &&
+ PQgetisnull(res, i, i_rlanacl) &&
+ PQgetisnull(res, i, i_initlanacl) &&
+ PQgetisnull(res, i, i_initrlanacl)))
+ planginfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableCast(&(castinfo[i]), fout);
-
- /* Casts do not currently have ACLs. */
- castinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(prsinfo[i].dobj), fout);
-
- /* Text Search Parsers do not currently have ACLs. */
- prsinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(dictinfo[i].dobj), fout);
-
- /* Text Search Dictionaries do not currently have ACLs. */
- dictinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(tmplinfo[i].dobj), fout);
-
- /* Text Search Templates do not currently have ACLs. */
- tmplinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(cfginfo[i].dobj), fout);
-
- /* Text Search Configurations do not currently have ACLs. */
- cfginfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(fdwinfo[i].dobj), fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_fdwacl) && PQgetisnull(res, i, i_rfdwacl) &&
- PQgetisnull(res, i, i_initfdwacl) &&
- PQgetisnull(res, i, i_initrfdwacl))
- fdwinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Mark whether FDW has an ACL */
+ if (!(PQgetisnull(res, i, i_fdwacl) &&
+ PQgetisnull(res, i, i_rfdwacl) &&
+ PQgetisnull(res, i, i_initfdwacl) &&
+ PQgetisnull(res, i, i_initrfdwacl)))
+ fdwinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
/* Decide whether we want to dump it */
selectDumpableObject(&(srvinfo[i].dobj), fout);
- /* Do not try to dump ACL if no ACL exists. */
- if (PQgetisnull(res, i, i_srvacl) && PQgetisnull(res, i, i_rsrvacl) &&
- PQgetisnull(res, i, i_initsrvacl) &&
- PQgetisnull(res, i, i_initrsrvacl))
- srvinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
+ /* Servers have user mappings */
+ srvinfo[i].dobj.components |= DUMP_COMPONENT_USERMAP;
+
+ /* Mark whether server has an ACL */
+ if (!(PQgetisnull(res, i, i_srvacl) &&
+ PQgetisnull(res, i, i_rsrvacl) &&
+ PQgetisnull(res, i, i_initsrvacl) &&
+ PQgetisnull(res, i, i_initrsrvacl)))
+ srvinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
}
PQclear(res);
daclinfo[i].initdefaclacl = pg_strdup(PQgetvalue(res, i, i_initdefaclacl));
daclinfo[i].initrdefaclacl = pg_strdup(PQgetvalue(res, i, i_initrdefaclacl));
+ /* Default ACLs are ACLs, of course */
+ daclinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
+
/* Decide whether we want to dump it */
selectDumpableDefaultACL(&(daclinfo[i]), dopt);
}
findComments(Archive *fout, Oid classoid, Oid objoid,
CommentItem **items)
{
- /* static storage for table of comments */
- static CommentItem *comments = NULL;
- static int ncomments = -1;
-
CommentItem *middle = NULL;
CommentItem *low;
CommentItem *high;
int nmatch;
- /* Get comments if we didn't already */
- if (ncomments < 0)
- ncomments = collectComments(fout, &comments);
-
/*
* Do binary search to find some item matching the object.
*/
/*
* collectComments --
*
- * Construct a table of all comments available for database objects.
+ * Construct a table of all comments available for database objects;
+ * also set the has-comment component flag for each relevant object.
+ *
* We used to do per-object queries for the comments, but it's much faster
* to pull them all over at once, and on most databases the memory cost
* isn't high.
*
* The table is sorted by classoid/objid/objsubid for speed in lookup.
*/
-static int
-collectComments(Archive *fout, CommentItem **items)
+static void
+collectComments(Archive *fout)
{
PGresult *res;
PQExpBuffer query;
int i_objsubid;
int ntups;
int i;
- CommentItem *comments;
+ DumpableObject *dobj;
query = createPQExpBuffer();
ntups = PQntuples(res);
comments = (CommentItem *) pg_malloc(ntups * sizeof(CommentItem));
+ ncomments = 0;
+ dobj = NULL;
for (i = 0; i < ntups; i++)
{
- comments[i].descr = PQgetvalue(res, i, i_description);
- comments[i].classoid = atooid(PQgetvalue(res, i, i_classoid));
- comments[i].objoid = atooid(PQgetvalue(res, i, i_objoid));
- comments[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid));
+ CatalogId objId;
+ int subid;
+
+ objId.tableoid = atooid(PQgetvalue(res, i, i_classoid));
+ objId.oid = atooid(PQgetvalue(res, i, i_objoid));
+ subid = atoi(PQgetvalue(res, i, i_objsubid));
+
+ /* We needn't remember comments that don't match any dumpable object */
+ if (dobj == NULL ||
+ dobj->catId.tableoid != objId.tableoid ||
+ dobj->catId.oid != objId.oid)
+ dobj = findObjectByCatalogId(objId);
+ if (dobj == NULL)
+ continue;
+
+ /*
+ * Comments on columns of composite types are linked to the type's
+ * pg_class entry, but we need to set the DUMP_COMPONENT_COMMENT flag
+ * in the type's own DumpableObject.
+ */
+ if (subid != 0 && dobj->objType == DO_TABLE &&
+ ((TableInfo *) dobj)->relkind == RELKIND_COMPOSITE_TYPE)
+ {
+ TypeInfo *cTypeInfo;
+
+ cTypeInfo = findTypeByOid(((TableInfo *) dobj)->reltype);
+ if (cTypeInfo)
+ cTypeInfo->dobj.components |= DUMP_COMPONENT_COMMENT;
+ }
+ else
+ dobj->components |= DUMP_COMPONENT_COMMENT;
+
+ comments[ncomments].descr = pg_strdup(PQgetvalue(res, i, i_description));
+ comments[ncomments].classoid = objId.tableoid;
+ comments[ncomments].objoid = objId.oid;
+ comments[ncomments].objsubid = subid;
+ ncomments++;
}
- /* Do NOT free the PGresult since we are keeping pointers into it */
+ PQclear(res);
destroyPQExpBuffer(query);
-
- *items = comments;
- return ntups;
}
/*
* ArchiveEntries (TOC objects) for each object to be dumped.
*/
static void
-dumpDumpableObject(Archive *fout, const DumpableObject *dobj)
+dumpDumpableObject(Archive *fout, DumpableObject *dobj)
{
+ /*
+ * Clear any dump-request bits for components that don't exist for this
+ * object. (This makes it safe to initially use DUMP_COMPONENT_ALL as the
+ * request for every kind of object.)
+ */
+ dobj->dump &= dobj->components;
+
+ /* Now, short-circuit if there's nothing to be done here. */
+ if (dobj->dump == 0)
+ return;
+
switch (dobj->objType)
{
case DO_NAMESPACE:
PQExpBuffer delq;
char *qnspname;
- /* Skip if not to be dumped */
- if (!nspinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
PQExpBuffer delq;
char *qextname;
- /* Skip if not to be dumped */
- if (!extinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
{
DumpOptions *dopt = fout->dopt;
- /* Skip if not to be dumped */
- if (!tyinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* Dump out in proper style */
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
- /* Skip if not to be dumped */
- if (!stinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
FuncInfo *inlineInfo = NULL;
FuncInfo *validatorInfo = NULL;
- /* Skip if not to be dumped */
- if (!plang->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/*
const char *keyword;
int i;
- /* Skip if not to be dumped */
- if (!finfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
const char *sourceType;
const char *targetType;
- /* Skip if not to be dumped */
- if (!cast->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* Cannot dump if we don't have the cast function's info */
char *lanname;
const char *transformType;
- /* Skip if not to be dumped */
- if (!transform->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* Cannot dump if we don't have the transform functions' info */
char *oprregproc;
char *oprref;
- /* Skip if not to be dumped */
- if (!oprinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/*
PQExpBuffer delq;
char *qamname;
- /* Skip if not to be dumped */
- if (!aminfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
bool needComma;
int i;
- /* Skip if not to be dumped */
- if (!opcinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
bool needComma;
int i;
- /* Skip if not to be dumped */
- if (!opfinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
const char *collcollate;
const char *collctype;
- /* Skip if not to be dumped */
- if (!collinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
const char *conproc;
bool condefault;
- /* Skip if not to be dumped */
- if (!convinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
const char *proparallel;
char defaultfinalmodify;
- /* Skip if not to be dumped */
- if (!agginfo->aggfn.dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
PQExpBuffer delq;
char *qprsname;
- /* Skip if not to be dumped */
- if (!prsinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
char *nspname;
char *tmplname;
- /* Skip if not to be dumped */
- if (!dictinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
PQExpBuffer delq;
char *qtmplname;
- /* Skip if not to be dumped */
- if (!tmplinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
int i_tokenname;
int i_dictname;
- /* Skip if not to be dumped */
- if (!cfginfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
PQExpBuffer delq;
char *qfdwname;
- /* Skip if not to be dumped */
- if (!fdwinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
char *qsrvname;
char *fdwname;
- /* Skip if not to be dumped */
- if (!srvinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
PQExpBuffer tag;
const char *type;
- /* Skip if not to be dumped */
- if (!daclinfo->dobj.dump || dopt->dataOnly || dopt->aclsSkip)
+ /* Do nothing in data-only dump, or if we're skipping ACLs */
+ if (dopt->dataOnly || dopt->aclsSkip)
return;
q = createPQExpBuffer();
static int
findSecLabels(Archive *fout, Oid classoid, Oid objoid, SecLabelItem **items)
{
- /* static storage for table of security labels */
- static SecLabelItem *labels = NULL;
- static int nlabels = -1;
-
SecLabelItem *middle = NULL;
SecLabelItem *low;
SecLabelItem *high;
int nmatch;
- /* Get security labels if we didn't already */
- if (nlabels < 0)
- nlabels = collectSecLabels(fout, &labels);
-
- if (nlabels <= 0) /* no labels, so no match is possible */
+ if (nseclabels <= 0) /* no labels, so no match is possible */
{
*items = NULL;
return 0;
/*
* Do binary search to find some item matching the object.
*/
- low = &labels[0];
- high = &labels[nlabels - 1];
+ low = &seclabels[0];
+ high = &seclabels[nseclabels - 1];
while (low <= high)
{
middle = low + (high - low) / 2;
/*
* collectSecLabels
*
- * Construct a table of all security labels available for database objects.
- * It's much faster to pull them all at once.
+ * Construct a table of all security labels available for database objects;
+ * also set the has-seclabel component flag for each relevant object.
*
* The table is sorted by classoid/objid/objsubid for speed in lookup.
*/
-static int
-collectSecLabels(Archive *fout, SecLabelItem **items)
+static void
+collectSecLabels(Archive *fout)
{
PGresult *res;
PQExpBuffer query;
int i_objsubid;
int ntups;
int i;
- SecLabelItem *labels;
+ DumpableObject *dobj;
query = createPQExpBuffer();
ntups = PQntuples(res);
- labels = (SecLabelItem *) pg_malloc(ntups * sizeof(SecLabelItem));
+ seclabels = (SecLabelItem *) pg_malloc(ntups * sizeof(SecLabelItem));
+ nseclabels = 0;
+ dobj = NULL;
for (i = 0; i < ntups; i++)
{
- labels[i].label = PQgetvalue(res, i, i_label);
- labels[i].provider = PQgetvalue(res, i, i_provider);
- labels[i].classoid = atooid(PQgetvalue(res, i, i_classoid));
- labels[i].objoid = atooid(PQgetvalue(res, i, i_objoid));
- labels[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid));
+ CatalogId objId;
+ int subid;
+
+ objId.tableoid = atooid(PQgetvalue(res, i, i_classoid));
+ objId.oid = atooid(PQgetvalue(res, i, i_objoid));
+ subid = atoi(PQgetvalue(res, i, i_objsubid));
+
+ /* We needn't remember labels that don't match any dumpable object */
+ if (dobj == NULL ||
+ dobj->catId.tableoid != objId.tableoid ||
+ dobj->catId.oid != objId.oid)
+ dobj = findObjectByCatalogId(objId);
+ if (dobj == NULL)
+ continue;
+
+ /*
+ * Labels on columns of composite types are linked to the type's
+ * pg_class entry, but we need to set the DUMP_COMPONENT_SECLABEL flag
+ * in the type's own DumpableObject.
+ */
+ if (subid != 0 && dobj->objType == DO_TABLE &&
+ ((TableInfo *) dobj)->relkind == RELKIND_COMPOSITE_TYPE)
+ {
+ TypeInfo *cTypeInfo;
+
+ cTypeInfo = findTypeByOid(((TableInfo *) dobj)->reltype);
+ if (cTypeInfo)
+ cTypeInfo->dobj.components |= DUMP_COMPONENT_SECLABEL;
+ }
+ else
+ dobj->components |= DUMP_COMPONENT_SECLABEL;
+
+ seclabels[nseclabels].label = pg_strdup(PQgetvalue(res, i, i_label));
+ seclabels[nseclabels].provider = pg_strdup(PQgetvalue(res, i, i_provider));
+ seclabels[nseclabels].classoid = objId.tableoid;
+ seclabels[nseclabels].objoid = objId.oid;
+ seclabels[nseclabels].objsubid = subid;
+ nseclabels++;
}
- /* Do NOT free the PGresult since we are keeping pointers into it */
+ PQclear(res);
destroyPQExpBuffer(query);
-
- *items = labels;
- return ntups;
}
/*
DumpId tableAclDumpId = InvalidDumpId;
char *namecopy;
- /*
- * noop if we are not dumping anything about this table, or if we are
- * doing a data-only dump
- */
- if (!tbinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
- if (tbinfo->relkind == RELKIND_SEQUENCE)
- dumpSequence(fout, tbinfo);
- else
- dumpTableSchema(fout, tbinfo);
+ if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ {
+ if (tbinfo->relkind == RELKIND_SEQUENCE)
+ dumpSequence(fout, tbinfo);
+ else
+ dumpTableSchema(fout, tbinfo);
+ }
/* Handle the ACL here */
namecopy = pg_strdup(fmtId(tbinfo->dobj.name));
/*
* Handle column ACLs, if any. Note: we pull these with a separate query
* rather than trying to fetch them during getTableAttrs, so that we won't
- * miss ACLs on system columns.
+ * miss ACLs on system columns. Doing it this way also allows us to dump
+ * ACLs for catalogs that we didn't mark "interesting" back in getTables.
*/
if (fout->remoteVersion >= 80400 && tbinfo->dobj.dump & DUMP_COMPONENT_ACL)
{
qrelname);
if (dopt->binary_upgrade)
- binary_upgrade_set_type_oids_by_rel_oid(fout, q,
- tbinfo->dobj.catId.oid);
+ binary_upgrade_set_type_oids_by_rel(fout, q, tbinfo);
/* Is it a table or a view? */
if (tbinfo->relkind == RELKIND_VIEW)
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
+ /* Do nothing in data-only dump */
if (dopt->dataOnly)
return;
char *tag;
char *foreign;
- /* Skip if table definition not to be dumped */
- if (!tbinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/* Skip if not "separate"; it was dumped in the table's definition */
char *qindxname;
char *qqindxname;
+ /* Do nothing in data-only dump */
if (dopt->dataOnly)
return;
static void
dumpIndexAttach(Archive *fout, const IndexAttachInfo *attachinfo)
{
+ /* Do nothing in data-only dump */
if (fout->dopt->dataOnly)
return;
PGresult *res;
char *stxdef;
- /* Skip if not to be dumped */
- if (!statsextinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
char *tag = NULL;
char *foreign;
- /* Skip if not to be dumped */
- if (!coninfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
q = createPQExpBuffer();
int findx;
char *tag;
- /*
- * we needn't check dobj.dump because TriggerInfo wouldn't have been
- * created in the first place for non-dumpable triggers
- */
+ /* Do nothing in data-only dump */
if (dopt->dataOnly)
return;
PQExpBuffer delqry;
char *qevtname;
- /* Skip if not to be dumped */
- if (!evtinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
query = createPQExpBuffer();
PGresult *res;
char *tag;
- /* Skip if not to be dumped */
- if (!rinfo->dobj.dump || dopt->dataOnly)
+ /* Do nothing in data-only dump */
+ if (dopt->dataOnly)
return;
/*