static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
const char *type, const char *name, const char *subname,
const char *tag, const char *nspname, const char *owner,
- const char *acls);
+ const char *acls, const char *racls,
+ const char *initacls, const char *initracls);
static void getDependencies(Archive *fout);
static void BuildArchiveDependencies(Archive *fout);
* Returns true if object is an extension member, else false.
*/
static bool
-checkExtensionMembership(DumpableObject *dobj, DumpOptions *dopt)
+checkExtensionMembership(DumpableObject *dobj, Archive *fout)
{
ExtensionInfo *ext = findOwningExtension(dobj->catId);
addObjectDependency(dobj, ext->dobj.dumpId);
/*
- * Normally, mark the member object as not to be dumped. But in binary
- * upgrades, we still dump the members individually, since the idea is to
- * exactly reproduce the database contents rather than replace the
- * extension contents with something different.
+ * In 9.6 and above, mark the member object to have any non-initial ACL,
+ * policies, and security lables dumped.
+ *
+ * Note that any initial ACLs (see pg_init_privs) will be removed when we
+ * extract the information about the object. We don't provide support for
+ * initial policies and security labels and it seems unlikely for those to
+ * ever exist, but we may have to revisit this later.
+ *
+ * Prior to 9.6, we do not include any extension member components.
+ *
+ * In binary upgrades, we still dump all components of the members
+ * individually, since the idea is to exactly reproduce the database
+ * contents rather than replace the extension contents with something
+ * different.
*/
- if (!dopt->binary_upgrade)
+ if (!fout->dopt->binary_upgrade && fout->remoteVersion >= 90600)
+ dobj->dump = DUMP_COMPONENT_ACL |
+ DUMP_COMPONENT_SECLABEL |
+ DUMP_COMPONENT_POLICY;
+ else if (!fout->dopt->binary_upgrade)
dobj->dump = DUMP_COMPONENT_NONE;
else
dobj->dump = ext->dobj.dump;
* Mark a namespace as to be dumped or not
*/
static void
-selectDumpableNamespace(NamespaceInfo *nsinfo, DumpOptions *dopt)
+selectDumpableNamespace(NamespaceInfo *nsinfo, Archive *fout)
{
- if (checkExtensionMembership(&nsinfo->dobj, dopt))
+ if (checkExtensionMembership(&nsinfo->dobj, fout))
return; /* extension membership overrides all else */
/*
simple_oid_list_member(&schema_include_oids,
nsinfo->dobj.catId.oid) ?
DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
+ else if (fout->remoteVersion >= 90600 &&
+ strncmp(nsinfo->dobj.name, "pg_catalog",
+ strlen("pg_catalog")) == 0)
+
+ /*
+ * In 9.6 and above, we dump out any ACLs defined in pg_catalog, if
+ * they are interesting (and not the original ACLs which were set at
+ * initdb time, see pg_init_privs).
+ */
+ nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ACL;
else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
strcmp(nsinfo->dobj.name, "information_schema") == 0)
nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE;
* Mark a table as to be dumped or not
*/
static void
-selectDumpableTable(TableInfo *tbinfo, DumpOptions *dopt)
+selectDumpableTable(TableInfo *tbinfo, Archive *fout)
{
- if (checkExtensionMembership(&tbinfo->dobj, dopt))
+ if (checkExtensionMembership(&tbinfo->dobj, fout))
return; /* extension membership overrides all else */
/*
* object (the table or base type).
*/
static void
-selectDumpableType(TypeInfo *tyinfo, DumpOptions *dopt)
+selectDumpableType(TypeInfo *tyinfo, Archive *fout)
{
/* skip complex types, except for standalone composite types */
if (OidIsValid(tyinfo->typrelid) &&
*/
}
- if (checkExtensionMembership(&tyinfo->dobj, dopt))
+ if (checkExtensionMembership(&tyinfo->dobj, fout))
return; /* extension membership overrides all else */
/* Dump based on if the contents of the namespace are being dumped */
* OID is in the range reserved for initdb.
*/
static void
-selectDumpableCast(CastInfo *cast, DumpOptions *dopt)
+selectDumpableCast(CastInfo *cast, Archive *fout)
{
- if (checkExtensionMembership(&cast->dobj, dopt))
+ if (checkExtensionMembership(&cast->dobj, fout))
return; /* extension membership overrides all else */
if (cast->dobj.catId.oid < (Oid) FirstNormalObjectId)
cast->dobj.dump = DUMP_COMPONENT_NONE;
else
- cast->dobj.dump = dopt->include_everything ?
+ cast->dobj.dump = fout->dopt->include_everything ?
DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
}
* language's OID is in the range reserved for initdb.
*/
static void
-selectDumpableProcLang(ProcLangInfo *plang, DumpOptions *dopt)
+selectDumpableProcLang(ProcLangInfo *plang, Archive *fout)
{
- if (checkExtensionMembership(&plang->dobj, dopt))
+ if (checkExtensionMembership(&plang->dobj, fout))
return; /* extension membership overrides all else */
if (plang->dobj.catId.oid < (Oid) FirstNormalObjectId)
plang->dobj.dump = DUMP_COMPONENT_NONE;
else
- plang->dobj.dump = dopt->include_everything ?
+ plang->dobj.dump = fout->dopt->include_everything ?
DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
}
* method's OID is in the range reserved for initdb.
*/
static void
-selectDumpableAccessMethod(AccessMethodInfo *method, DumpOptions *dopt)
+selectDumpableAccessMethod(AccessMethodInfo *method, Archive *fout)
{
- if (checkExtensionMembership(&method->dobj, dopt))
+ if (checkExtensionMembership(&method->dobj, fout))
return; /* extension membership overrides all else */
if (method->dobj.catId.oid < (Oid) FirstNormalObjectId)
- method->dobj.dump = false;
+ method->dobj.dump = DUMP_COMPONENT_NONE;
else
- method->dobj.dump = dopt->include_everything;
+ method->dobj.dump = fout->dopt->include_everything ?
+ DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
}
/*
* Use this only for object types without a special-case routine above.
*/
static void
-selectDumpableObject(DumpableObject *dobj, DumpOptions *dopt)
+selectDumpableObject(DumpableObject *dobj, Archive *fout)
{
- if (checkExtensionMembership(dobj, dopt))
+ if (checkExtensionMembership(dobj, fout))
return; /* extension membership overrides all else */
/*
if (dobj->namespace)
dobj->dump = dobj->namespace->dobj.dump_contains;
else
- dobj->dump = dopt->include_everything ?
+ dobj->dump = fout->dopt->include_everything ?
DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
}
static void
getBlobs(Archive *fout)
{
+ DumpOptions *dopt = fout->dopt;
PQExpBuffer blobQry = createPQExpBuffer();
BlobInfo *binfo;
DumpableObject *bdata;
PGresult *res;
int ntups;
int i;
+ int i_oid;
+ int i_lomowner;
+ int i_lomacl;
+ int i_rlomacl;
+ int i_initlomacl;
+ int i_initrlomacl;
/* Verbose message */
if (g_verbose)
selectSourceSchema(fout, "pg_catalog");
/* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */
- if (fout->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer init_acl_subquery = createPQExpBuffer();
+ PQExpBuffer init_racl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery,
+ init_racl_subquery, "l.lomacl", "l.lomowner", "'L'",
+ dopt->binary_upgrade);
+
appendPQExpBuffer(blobQry,
- "SELECT oid, (%s lomowner) AS rolname, lomacl"
+ "SELECT l.oid, (%s l.lomowner) AS rolname, "
+ "%s AS lomacl, "
+ "%s AS rlomacl, "
+ "%s AS initlomacl, "
+ "%s AS initrlomacl "
+ "FROM pg_largeobject_metadata l "
+ "LEFT JOIN pg_init_privs pip ON "
+ "(l.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_largeobject')"
+ "AND pip.objsubid = 0) ",
+ username_subquery,
+ acl_subquery->data,
+ racl_subquery->data,
+ init_acl_subquery->data,
+ init_racl_subquery->data);
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(init_acl_subquery);
+ destroyPQExpBuffer(init_racl_subquery);
+ }
+ else if (fout->remoteVersion >= 90000)
+ appendPQExpBuffer(blobQry,
+ "SELECT oid, (%s lomowner) AS rolname, lomacl, "
+ "NULL AS rlomacl, NULL as initlomacl, "
+ "NULL as initrlomacl "
" FROM pg_largeobject_metadata",
username_subquery);
else if (fout->remoteVersion >= 70100)
appendPQExpBufferStr(blobQry,
- "SELECT DISTINCT loid, NULL::oid, NULL::oid"
+ "SELECT DISTINCT loid, NULL::oid, NULL, "
+ "NULL AS rlomacl, NULL AS initlomacl, "
+ "NULL AS initrlomacl "
" FROM pg_largeobject");
else
appendPQExpBufferStr(blobQry,
- "SELECT oid, NULL::oid, NULL::oid"
+ "SELECT oid, NULL::oid, NULL, "
+ "NULL AS rlomacl, NULL AS initlomacl, "
+ "NULL AS initrlomacl "
" FROM pg_class WHERE relkind = 'l'");
res = ExecuteSqlQuery(fout, blobQry->data, PGRES_TUPLES_OK);
+ i_oid = PQfnumber(res, "oid");
+ i_lomowner = PQfnumber(res, "rolname");
+ i_lomacl = PQfnumber(res, "lomacl");
+ i_rlomacl = PQfnumber(res, "rlomacl");
+ i_initlomacl = PQfnumber(res, "initlomacl");
+ i_initrlomacl = PQfnumber(res, "initrlomacl");
+
ntups = PQntuples(res);
- if (ntups > 0)
+
+ /*
+ * Each large object has its own BLOB archive entry.
+ */
+ binfo = (BlobInfo *) pg_malloc(ntups * sizeof(BlobInfo));
+
+ for (i = 0; i < ntups; i++)
{
- /*
- * Each large object has its own BLOB archive entry.
- */
- binfo = (BlobInfo *) pg_malloc(ntups * sizeof(BlobInfo));
+ binfo[i].dobj.objType = DO_BLOB;
+ binfo[i].dobj.catId.tableoid = LargeObjectRelationId;
+ binfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+ AssignDumpId(&binfo[i].dobj);
- for (i = 0; i < ntups; i++)
- {
- binfo[i].dobj.objType = DO_BLOB;
- binfo[i].dobj.catId.tableoid = LargeObjectRelationId;
- binfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, 0));
- AssignDumpId(&binfo[i].dobj);
-
- binfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, 0));
- if (!PQgetisnull(res, i, 1))
- binfo[i].rolname = pg_strdup(PQgetvalue(res, i, 1));
- else
- binfo[i].rolname = "";
- if (!PQgetisnull(res, i, 2))
- binfo[i].blobacl = pg_strdup(PQgetvalue(res, i, 2));
- else
- binfo[i].blobacl = NULL;
- }
+ binfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oid));
+ binfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_lomowner));
+ binfo[i].blobacl = pg_strdup(PQgetvalue(res, i, i_lomacl));
+ binfo[i].rblobacl = pg_strdup(PQgetvalue(res, i, i_rlomacl));
+ binfo[i].initblobacl = pg_strdup(PQgetvalue(res, i, i_initlomacl));
+ binfo[i].initrblobacl = pg_strdup(PQgetvalue(res, i, i_initrlomacl));
- /*
- * If we have any large objects, a "BLOBS" archive entry is needed.
- * This is just a placeholder for sorting; it carries no data now.
- */
+ 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;
+
+ }
+
+ /*
+ * If we have any large objects, a "BLOBS" archive entry is needed. This
+ * is just a placeholder for sorting; it carries no data now.
+ */
+ if (ntups > 0)
+ {
bdata = (DumpableObject *) pg_malloc(sizeof(DumpableObject));
bdata->objType = DO_BLOB_DATA;
bdata->catId = nilCatalogId;
if (binfo->blobacl && (binfo->dobj.dump & DUMP_COMPONENT_ACL))
dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
binfo->dobj.name, NULL, cquery->data,
- NULL, binfo->rolname, binfo->blobacl);
+ NULL, binfo->rolname, binfo->blobacl, binfo->rblobacl,
+ binfo->initblobacl, binfo->initrblobacl);
destroyPQExpBuffer(cquery);
destroyPQExpBuffer(dquery);
int i_nspname;
int i_rolname;
int i_nspacl;
+ int i_rnspacl;
+ int i_initnspacl;
+ int i_initrnspacl;
/*
* Before 7.3, there are no real namespaces; create two dummy entries, one
nsinfo[0].dobj.name = pg_strdup("public");
nsinfo[0].rolname = pg_strdup("");
nsinfo[0].nspacl = pg_strdup("");
+ nsinfo[0].rnspacl = pg_strdup("");
+ nsinfo[0].initnspacl = pg_strdup("");
+ nsinfo[0].initrnspacl = pg_strdup("");
- selectDumpableNamespace(&nsinfo[0], dopt);
+ selectDumpableNamespace(&nsinfo[0], fout);
nsinfo[1].dobj.objType = DO_NAMESPACE;
nsinfo[1].dobj.catId.tableoid = 0;
nsinfo[1].dobj.name = pg_strdup("pg_catalog");
nsinfo[1].rolname = pg_strdup("");
nsinfo[1].nspacl = pg_strdup("");
+ nsinfo[1].rnspacl = pg_strdup("");
+ nsinfo[1].initnspacl = pg_strdup("");
+ nsinfo[1].initrnspacl = pg_strdup("");
- selectDumpableNamespace(&nsinfo[1], dopt);
+ selectDumpableNamespace(&nsinfo[1], fout);
*numNamespaces = 2;
* we fetch all namespaces including system ones, so that every object we
* read in can be linked to a containing namespace.
*/
- appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, "
- "(%s nspowner) AS rolname, "
- "nspacl FROM pg_namespace",
- username_subquery);
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer init_acl_subquery = createPQExpBuffer();
+ PQExpBuffer init_racl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery,
+ init_racl_subquery, "n.nspacl", "n.nspowner", "'n'",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query, "SELECT n.tableoid, n.oid, n.nspname, "
+ "(%s nspowner) AS rolname, "
+ "%s as nspacl, "
+ "%s as rnspacl, "
+ "%s as initnspacl, "
+ "%s as initrnspacl "
+ "FROM pg_namespace n "
+ "LEFT JOIN pg_init_privs pip "
+ "ON (n.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_namespace') "
+ "AND pip.objsubid = 0) ",
+ username_subquery,
+ acl_subquery->data,
+ racl_subquery->data,
+ init_acl_subquery->data,
+ init_racl_subquery->data);
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(init_acl_subquery);
+ destroyPQExpBuffer(init_racl_subquery);
+ }
+ else
+ appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, "
+ "(%s nspowner) AS rolname, "
+ "nspacl, NULL as rnspacl, "
+ "NULL AS initnspacl, NULL as initrnspacl "
+ "FROM pg_namespace",
+ username_subquery);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
i_nspname = PQfnumber(res, "nspname");
i_rolname = PQfnumber(res, "rolname");
i_nspacl = PQfnumber(res, "nspacl");
+ i_rnspacl = PQfnumber(res, "rnspacl");
+ i_initnspacl = PQfnumber(res, "initnspacl");
+ i_initrnspacl = PQfnumber(res, "initrnspacl");
for (i = 0; i < ntups; i++)
{
nsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_nspname));
nsinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl));
+ nsinfo[i].rnspacl = pg_strdup(PQgetvalue(res, i, i_rnspacl));
+ nsinfo[i].initnspacl = pg_strdup(PQgetvalue(res, i, i_initnspacl));
+ nsinfo[i].initrnspacl = pg_strdup(PQgetvalue(res, i, i_initrnspacl));
/* Decide whether to dump this namespace */
- selectDumpableNamespace(&nsinfo[i], dopt);
+ 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;
if (strlen(nsinfo[i].rolname) == 0)
write_msg(NULL, "WARNING: owner of schema \"%s\" appears to be invalid\n",
int i_typname;
int i_typnamespace;
int i_typacl;
+ int i_rtypacl;
+ int i_inittypacl;
+ int i_initrtypacl;
int i_rolname;
int i_typinput;
int i_typoutput;
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
- if (fout->remoteVersion >= 90200)
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "t.typacl", "t.typowner", "'T'",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query, "SELECT t.tableoid, t.oid, t.typname, "
+ "t.typnamespace, "
+ "%s AS typacl, "
+ "%s AS rtypacl, "
+ "%s AS inittypacl, "
+ "%s AS initrtypacl, "
+ "(%s t.typowner) AS rolname, "
+ "t.typinput::oid AS typinput, "
+ "t.typoutput::oid AS typoutput, t.typelem, t.typrelid, "
+ "CASE WHEN t.typrelid = 0 THEN ' '::\"char\" "
+ "ELSE (SELECT relkind FROM pg_class WHERE oid = t.typrelid) END AS typrelkind, "
+ "t.typtype, t.typisdefined, "
+ "t.typname[0] = '_' AND t.typelem != 0 AND "
+ "(SELECT typarray FROM pg_type te WHERE oid = t.typelem) = t.oid AS isarray "
+ "FROM pg_type t "
+ "LEFT JOIN pg_init_privs pip "
+ "ON (t.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_type') "
+ "AND pip.objsubid = 0) ",
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data,
+ username_subquery);
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(initacl_subquery);
+ destroyPQExpBuffer(initracl_subquery);
+ }
+ else if (fout->remoteVersion >= 90200)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "typnamespace, typacl, "
+ "typnamespace, typacl, NULL as rtypacl, "
+ "NULL AS inittypacl, NULL AS initrtypacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
else if (fout->remoteVersion >= 80300)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "typnamespace, NULL AS typacl, "
+ "typnamespace, NULL AS typacl, NULL as rtypacl, "
+ "NULL AS inittypacl, NULL AS initrtypacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
else if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "typnamespace, NULL AS typacl, "
+ "typnamespace, NULL AS typacl, NULL as rtypacl, "
+ "NULL AS inittypacl, NULL AS initrtypacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "0::oid AS typnamespace, NULL AS typacl, "
+ "0::oid AS typnamespace, NULL AS typacl, NULL as rtypacl, "
+ "NULL AS inittypacl, NULL AS initrtypacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
appendPQExpBuffer(query, "SELECT "
"(SELECT oid FROM pg_class WHERE relname = 'pg_type') AS tableoid, "
"oid, typname, "
- "0::oid AS typnamespace, NULL AS typacl, "
+ "0::oid AS typnamespace, NULL AS typacl, NULL as rtypacl, "
+ "NULL AS inittypacl, NULL AS initrtypacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
i_typname = PQfnumber(res, "typname");
i_typnamespace = PQfnumber(res, "typnamespace");
i_typacl = PQfnumber(res, "typacl");
+ i_rtypacl = PQfnumber(res, "rtypacl");
+ i_inittypacl = PQfnumber(res, "inittypacl");
+ i_initrtypacl = PQfnumber(res, "initrtypacl");
i_rolname = PQfnumber(res, "rolname");
i_typinput = PQfnumber(res, "typinput");
i_typoutput = PQfnumber(res, "typoutput");
tyinfo[i].dobj.catId.oid);
tyinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
tyinfo[i].typacl = pg_strdup(PQgetvalue(res, i, i_typacl));
+ tyinfo[i].rtypacl = pg_strdup(PQgetvalue(res, i, i_rtypacl));
+ tyinfo[i].inittypacl = pg_strdup(PQgetvalue(res, i, i_inittypacl));
+ tyinfo[i].initrtypacl = pg_strdup(PQgetvalue(res, i, i_initrtypacl));
tyinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
tyinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
tyinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
tyinfo[i].isArray = false;
/* Decide whether we want to dump it */
- selectDumpableType(&tyinfo[i], dopt);
+ 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;
/*
* If it's a domain, fetch info about its constraints, if any
OprInfo *
getOperators(Archive *fout, int *numOprs)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
/* Decide whether we want to dump it */
- selectDumpableObject(&(oprinfo[i].dobj), dopt);
+ selectDumpableObject(&(oprinfo[i].dobj), fout);
if (strlen(oprinfo[i].rolname) == 0)
write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
CollInfo *
getCollations(Archive *fout, int *numCollations)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
collinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
- selectDumpableObject(&(collinfo[i].dobj), dopt);
+ selectDumpableObject(&(collinfo[i].dobj), fout);
}
PQclear(res);
ConvInfo *
getConversions(Archive *fout, int *numConversions)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
convinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
- selectDumpableObject(&(convinfo[i].dobj), dopt);
+ selectDumpableObject(&(convinfo[i].dobj), fout);
}
PQclear(res);
AccessMethodInfo *
getAccessMethods(Archive *fout, int *numAccessMethods)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
aminfo[i].amtype = *(PQgetvalue(res, i, i_amtype));
/* Decide whether we want to dump it */
- selectDumpableAccessMethod(&(aminfo[i]), dopt);
+ selectDumpableAccessMethod(&(aminfo[i]), fout);
}
PQclear(res);
OpclassInfo *
getOpclasses(Archive *fout, int *numOpclasses)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
opcinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
- selectDumpableObject(&(opcinfo[i].dobj), dopt);
+ selectDumpableObject(&(opcinfo[i].dobj), fout);
if (fout->remoteVersion >= 70300)
{
OpfamilyInfo *
getOpfamilies(Archive *fout, int *numOpfamilies)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
opfinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
- selectDumpableObject(&(opfinfo[i].dobj), dopt);
+ selectDumpableObject(&(opfinfo[i].dobj), fout);
if (fout->remoteVersion >= 70300)
{
int i_proargtypes;
int i_rolname;
int i_aggacl;
+ int i_raggacl;
+ int i_initaggacl;
+ int i_initraggacl;
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
/*
- * Find all user-defined aggregates. See comment in getFuncs() for the
+ * Find all interesting aggregates. See comment in getFuncs() for the
* rationale behind the filtering logic.
*/
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "p.proacl", "p.proowner", "'f'",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, "
+ "p.proname AS aggname, "
+ "p.pronamespace AS aggnamespace, "
+ "p.pronargs, p.proargtypes, "
+ "(%s p.proowner) AS rolname, "
+ "%s AS aggacl, "
+ "%s AS raggacl, "
+ "%s AS initaggacl, "
+ "%s AS initraggacl "
+ "FROM pg_proc p "
+ "LEFT JOIN pg_init_privs pip ON "
+ "(p.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_proc') "
+ "AND pip.objsubid = 0) "
+ "WHERE p.proisagg AND ("
+ "p.pronamespace != "
+ "(SELECT oid FROM pg_namespace "
+ "WHERE nspname = 'pg_catalog') OR "
+ "EXISTS (SELECT * FROM pg_init_privs pip "
+ "WHERE p.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class "
+ "WHERE relname = 'pg_proc') "
+ "AND p.proacl IS DISTINCT FROM pip.initprivs)",
+ username_subquery,
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data);
+ if (dopt->binary_upgrade)
+ appendPQExpBufferStr(query,
+ " OR EXISTS(SELECT 1 FROM pg_depend WHERE "
+ "classid = 'pg_proc'::regclass AND "
+ "objid = p.oid AND "
+ "refclassid = 'pg_extension'::regclass AND "
+ "deptype = 'e')");
+ appendPQExpBufferChar(query, ')');
- if (fout->remoteVersion >= 80200)
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(initacl_subquery);
+ destroyPQExpBuffer(initracl_subquery);
+ }
+ else if (fout->remoteVersion >= 80200)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
"pronamespace AS aggnamespace, "
"pronargs, proargtypes, "
"(%s proowner) AS rolname, "
- "proacl AS aggacl "
+ "proacl AS aggacl, "
+ "NULL AS raggacl, "
+ "NULL AS initaggacl, NULL AS initraggacl "
"FROM pg_proc p "
"WHERE proisagg AND ("
"pronamespace != "
"CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
"proargtypes, "
"(%s proowner) AS rolname, "
- "proacl AS aggacl "
+ "proacl AS aggacl, "
+ "NULL AS raggacl, "
+ "NULL AS initaggacl, NULL AS initraggacl "
"FROM pg_proc "
"WHERE proisagg "
"AND pronamespace != "
"CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
"aggbasetype AS proargtypes, "
"(%s aggowner) AS rolname, "
- "NULL AS aggacl "
+ "NULL AS aggacl, "
+ "NULL AS raggacl, "
+ "NULL AS initaggacl, NULL AS initraggacl "
"FROM pg_aggregate "
"where oid > '%u'::oid",
username_subquery,
"CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
"aggbasetype AS proargtypes, "
"(%s aggowner) AS rolname, "
- "NULL AS aggacl "
+ "NULL AS aggacl, "
+ "NULL AS raggacl, "
+ "NULL AS initaggacl, NULL AS initraggacl "
"FROM pg_aggregate "
"where oid > '%u'::oid",
username_subquery,
i_proargtypes = PQfnumber(res, "proargtypes");
i_rolname = PQfnumber(res, "rolname");
i_aggacl = PQfnumber(res, "aggacl");
+ i_raggacl = PQfnumber(res, "raggacl");
+ i_initaggacl = PQfnumber(res, "initaggacl");
+ i_initraggacl = PQfnumber(res, "initraggacl");
for (i = 0; i < ntups; i++)
{
agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */
agginfo[i].aggfn.prorettype = InvalidOid; /* not saved */
agginfo[i].aggfn.proacl = pg_strdup(PQgetvalue(res, i, i_aggacl));
+ agginfo[i].aggfn.rproacl = pg_strdup(PQgetvalue(res, i, i_raggacl));
+ agginfo[i].aggfn.initproacl = pg_strdup(PQgetvalue(res, i, i_initaggacl));
+ agginfo[i].aggfn.initrproacl = pg_strdup(PQgetvalue(res, i, i_initraggacl));
agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
if (agginfo[i].aggfn.nargs == 0)
agginfo[i].aggfn.argtypes = NULL;
}
/* Decide whether we want to dump it */
- selectDumpableObject(&(agginfo[i].aggfn.dobj), dopt);
+ 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;
}
PQclear(res);
int i_proargtypes;
int i_prorettype;
int i_proacl;
+ int i_rproacl;
+ int i_initproacl;
+ int i_initrproacl;
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
/*
- * Find all user-defined functions. Normally we can exclude functions in
- * pg_catalog, which is worth doing since there are several thousand of
- * 'em. However, there are some extensions that create functions in
- * pg_catalog. In normal dumps we can still ignore those --- but in
- * binary-upgrade mode, we must dump the member objects of the extension,
- * so be sure to fetch any such functions.
+ * Find all interesting functions. We include functions in pg_catalog, if
+ * they have an ACL different from what we set at initdb time (which is
+ * saved in pg_init_privs for us to perform this check). There may also
+ * be functions which are members of extensions which we must dump if we
+ * are in binary upgrade mode (we'll mark those functions as to-be-dumped
+ * when we check if the extension is to-be-dumped and we're in binary
+ * upgrade mode).
*
* Also, in 9.2 and up, exclude functions that are internally dependent on
* something else, since presumably those will be created as a result of
* because the constructors don't have any dependencies the range type
* doesn't have; otherwise we might not get creation ordering correct.
*/
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
- if (fout->remoteVersion >= 70300)
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "p.proacl", "p.proowner", "'f'",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query,
+ "SELECT p.tableoid, p.oid, p.proname, p.prolang, "
+ "p.pronargs, p.proargtypes, p.prorettype, "
+ "%s AS proacl, "
+ "%s AS rproacl, "
+ "%s AS initproacl, "
+ "%s AS initrproacl, "
+ "p.pronamespace, "
+ "(%s p.proowner) AS rolname "
+ "FROM pg_proc p "
+ "LEFT JOIN pg_init_privs pip ON "
+ "(p.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_proc') "
+ "AND pip.objsubid = 0) "
+ "WHERE NOT proisagg "
+ "AND NOT EXISTS (SELECT 1 FROM pg_depend "
+ "WHERE classid = 'pg_proc'::regclass AND "
+ "objid = p.oid AND deptype = 'i') AND ("
+ "pronamespace != "
+ "(SELECT oid FROM pg_namespace "
+ "WHERE nspname = 'pg_catalog') OR "
+ "EXISTS (SELECT * FROM pg_init_privs pip "
+ "WHERE p.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class "
+ "WHERE relname = 'pg_proc') "
+ "AND p.proacl IS DISTINCT FROM pip.initprivs)",
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data,
+ username_subquery);
+ if (dopt->binary_upgrade)
+ appendPQExpBufferStr(query,
+ "\n OR EXISTS(SELECT 1 FROM pg_depend WHERE "
+ "classid = 'pg_proc'::regclass AND "
+ "objid = p.oid AND "
+ "refclassid = 'pg_extension'::regclass AND "
+ "deptype = 'e')");
+ appendPQExpBufferChar(query, ')');
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(initacl_subquery);
+ destroyPQExpBuffer(initracl_subquery);
+ }
+ else if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query,
"SELECT tableoid, oid, proname, prolang, "
"pronargs, proargtypes, prorettype, proacl, "
+ "NULL as rproacl, "
+ "NULL as initproacl, NULL AS initrproacl, "
"pronamespace, "
"(%s proowner) AS rolname "
"FROM pg_proc p "
"SELECT tableoid, oid, proname, prolang, "
"pronargs, proargtypes, prorettype, "
"NULL AS proacl, "
+ "NULL AS rproacl, "
+ "NULL as initproacl, NULL AS initrproacl, "
"0::oid AS pronamespace, "
"(%s proowner) AS rolname "
"FROM pg_proc "
"oid, proname, prolang, "
"pronargs, proargtypes, prorettype, "
"NULL AS proacl, "
+ "NULL AS rproacl, "
+ "NULL as initproacl, NULL AS initrproacl, "
"0::oid AS pronamespace, "
"(%s proowner) AS rolname "
"FROM pg_proc "
i_proargtypes = PQfnumber(res, "proargtypes");
i_prorettype = PQfnumber(res, "prorettype");
i_proacl = PQfnumber(res, "proacl");
+ i_rproacl = PQfnumber(res, "rproacl");
+ i_initproacl = PQfnumber(res, "initproacl");
+ i_initrproacl = PQfnumber(res, "initrproacl");
for (i = 0; i < ntups; i++)
{
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
finfo[i].proacl = pg_strdup(PQgetvalue(res, i, i_proacl));
+ finfo[i].rproacl = pg_strdup(PQgetvalue(res, i, i_rproacl));
+ finfo[i].initproacl = pg_strdup(PQgetvalue(res, i, i_initproacl));
+ finfo[i].initrproacl = pg_strdup(PQgetvalue(res, i, i_initrproacl));
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
if (finfo[i].nargs == 0)
finfo[i].argtypes = NULL;
}
/* Decide whether we want to dump it */
- selectDumpableObject(&(finfo[i].dobj), dopt);
+ 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;
if (strlen(finfo[i].rolname) == 0)
write_msg(NULL,
/*
* getTables
- * read all the user-defined tables (no indexes, no catalogs)
+ * read all the tables (no indexes)
* in the system catalogs return them in the TableInfo* structure
*
* numTables is set to the number of tables read in
int i_relnamespace;
int i_relkind;
int i_relacl;
+ int i_rrelacl;
+ int i_initrelacl;
+ int i_initrrelacl;
int i_rolname;
int i_relchecks;
int i_relhastriggers;
* we cannot correctly identify inherited columns, owned sequences, etc.
*/
- if (fout->remoteVersion >= 90500)
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
+
+ /*
+ * Left join to pick up dependency info linking sequences to their
+ * owning column, if any (note this dependency is AUTO as of 8.2)
+ *
+ * Left join to detect if any privileges are still as-set-at-init, in
+ * which case we won't dump out ACL commands for those.
+ */
+
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "c.relacl", "c.relowner",
+ "CASE WHEN c.relkind = 'S' THEN 's' ELSE 'r' END::\"char\"",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query,
+ "SELECT c.tableoid, c.oid, c.relname, "
+ "%s AS relacl, %s as rrelacl, "
+ "%s AS initrelacl, %s as initrrelacl, "
+ "c.relkind, c.relnamespace, "
+ "(%s c.relowner) AS rolname, "
+ "c.relchecks, c.relhastriggers, "
+ "c.relhasindex, c.relhasrules, c.relhasoids, "
+ "c.relrowsecurity, c.relforcerowsecurity, "
+ "c.relfrozenxid, c.relminmxid, tc.oid AS toid, "
+ "tc.relfrozenxid AS tfrozenxid, "
+ "tc.relminmxid AS tminmxid, "
+ "c.relpersistence, c.relispopulated, "
+ "c.relreplident, c.relpages, "
+ "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
+ "d.refobjid AS owning_tab, "
+ "d.refobjsubid AS owning_col, "
+ "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
+ "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
+ "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
+ "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
+ "tc.reloptions AS toast_reloptions "
+ "FROM pg_class c "
+ "LEFT JOIN pg_depend d ON "
+ "(c.relkind = '%c' AND "
+ "d.classid = c.tableoid AND d.objid = c.oid AND "
+ "d.objsubid = 0 AND "
+ "d.refclassid = c.tableoid AND d.deptype = 'a') "
+ "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+ "LEFT JOIN pg_init_privs pip ON "
+ "(c.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class "
+ "WHERE relname = 'pg_class') AND pip.objsubid = 0) "
+ "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
+ "ORDER BY c.oid",
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data,
+ username_subquery,
+ RELKIND_SEQUENCE,
+ RELKIND_RELATION, RELKIND_SEQUENCE,
+ RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
+ RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(initacl_subquery);
+ destroyPQExpBuffer(initracl_subquery);
+ }
+ else if (fout->remoteVersion >= 90500)
{
/*
* Left join to pick up dependency info linking sequences to their
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, c.relkind, c.relnamespace, "
+ "c.relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "c.relkind, "
+ "c.relnamespace, "
"(%s c.relowner) AS rolname, "
"c.relchecks, c.relhastriggers, "
"c.relhasindex, c.relhasrules, c.relhasoids, "
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, c.relkind, c.relnamespace, "
+ "c.relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "c.relkind, "
+ "c.relnamespace, "
"(%s c.relowner) AS rolname, "
"c.relchecks, c.relhastriggers, "
"c.relhasindex, c.relhasrules, c.relhasoids, "
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, c.relkind, c.relnamespace, "
+ "c.relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "c.relkind, "
+ "c.relnamespace, "
"(%s c.relowner) AS rolname, "
"c.relchecks, c.relhastriggers, "
"c.relhasindex, c.relhasrules, c.relhasoids, "
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, c.relkind, c.relnamespace, "
+ "c.relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "c.relkind, "
+ "c.relnamespace, "
"(%s c.relowner) AS rolname, "
"c.relchecks, c.relhastriggers, "
"c.relhasindex, c.relhasrules, c.relhasoids, "
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, c.relkind, c.relnamespace, "
+ "c.relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "c.relkind, "
+ "c.relnamespace, "
"(%s c.relowner) AS rolname, "
"c.relchecks, c.relhastriggers, "
"c.relhasindex, c.relhasrules, c.relhasoids, "
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, c.relkind, c.relnamespace, "
+ "c.relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "c.relkind, "
+ "c.relnamespace, "
"(%s c.relowner) AS rolname, "
"c.relchecks, c.relhastriggers, "
"c.relhasindex, c.relhasrules, c.relhasoids, "
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
- "c.relacl, c.relkind, c.relnamespace, "
+ "c.relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "c.relkind, "
+ "c.relnamespace, "
"(%s c.relowner) AS rolname, "
"c.relchecks, (c.reltriggers <> 0) AS relhastriggers, "
"c.relhasindex, c.relhasrules, c.relhasoids, "
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, relname, "
- "relacl, relkind, relnamespace, "
+ "relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "relkind, relnamespace, "
"(%s relowner) AS rolname, "
"relchecks, (reltriggers <> 0) AS relhastriggers, "
"relhasindex, relhasrules, relhasoids, "
*/
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, relname, "
- "relacl, relkind, relnamespace, "
+ "relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "relkind, relnamespace, "
"(%s relowner) AS rolname, "
"relchecks, (reltriggers <> 0) AS relhastriggers, "
"relhasindex, relhasrules, relhasoids, "
else if (fout->remoteVersion >= 70200)
{
appendPQExpBuffer(query,
- "SELECT tableoid, oid, relname, relacl, relkind, "
+ "SELECT tableoid, oid, relname, relacl, "
+ "NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "relkind, "
"0::oid AS relnamespace, "
"(%s relowner) AS rolname, "
"relchecks, (reltriggers <> 0) AS relhastriggers, "
{
/* all tables have oids in 7.1 */
appendPQExpBuffer(query,
- "SELECT tableoid, oid, relname, relacl, relkind, "
+ "SELECT tableoid, oid, relname, relacl, "
+ "NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
+ "relkind, "
"0::oid AS relnamespace, "
"(%s relowner) AS rolname, "
"relchecks, (reltriggers <> 0) AS relhastriggers, "
appendPQExpBuffer(query,
"SELECT "
"(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
- "oid, relname, relacl, "
+ "oid, relname, relacl, NULL as rrelacl, "
+ "NULL AS initrelacl, NULL AS initrrelacl, "
"CASE WHEN relhasrules and relkind = 'r' "
" and EXISTS(SELECT rulename FROM pg_rewrite r WHERE "
" r.ev_class = c.oid AND r.ev_type = '1') "
i_relname = PQfnumber(res, "relname");
i_relnamespace = PQfnumber(res, "relnamespace");
i_relacl = PQfnumber(res, "relacl");
+ i_rrelacl = PQfnumber(res, "rrelacl");
+ i_initrelacl = PQfnumber(res, "initrelacl");
+ i_initrrelacl = PQfnumber(res, "initrrelacl");
i_relkind = PQfnumber(res, "relkind");
i_rolname = PQfnumber(res, "rolname");
i_relchecks = PQfnumber(res, "relchecks");
tblinfo[i].dobj.catId.oid);
tblinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
tblinfo[i].relacl = pg_strdup(PQgetvalue(res, i, i_relacl));
+ tblinfo[i].rrelacl = pg_strdup(PQgetvalue(res, i, i_rrelacl));
+ tblinfo[i].initrelacl = pg_strdup(PQgetvalue(res, i, i_initrelacl));
+ tblinfo[i].initrrelacl = pg_strdup(PQgetvalue(res, i, i_initrrelacl));
tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
tblinfo[i].relpersistence = *(PQgetvalue(res, i, i_relpersistence));
tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
tblinfo[i].dobj.dump = DUMP_COMPONENT_NONE;
else
- selectDumpableTable(&tblinfo[i], dopt);
+ selectDumpableTable(&tblinfo[i], fout);
tblinfo[i].interesting = tblinfo[i].dobj.dump ? true : false;
EventTriggerInfo *
getEventTriggers(Archive *fout, int *numEventTriggers)
{
- DumpOptions *dopt = fout->dopt;
int i;
PQExpBuffer query;
PGresult *res;
evtinfo[i].evtenabled = *(PQgetvalue(res, i, i_evtenabled));
/* Decide whether we want to dump it */
- selectDumpableObject(&(evtinfo[i].dobj), dopt);
+ selectDumpableObject(&(evtinfo[i].dobj), fout);
}
PQclear(res);
int i_laninline;
int i_lanvalidator;
int i_lanacl;
+ int i_rlanacl;
+ int i_initlanacl;
+ int i_initrlanacl;
int i_lanowner;
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
- if (fout->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "l.lanacl", "l.lanowner", "'l'",
+ dopt->binary_upgrade);
+
+ /* pg_language has a laninline column */
+ appendPQExpBuffer(query, "SELECT l.tableoid, l.oid, "
+ "l.lanname, l.lanpltrusted, l.lanplcallfoid, "
+ "l.laninline, l.lanvalidator, "
+ "%s AS lanacl, "
+ "%s AS rlanacl, "
+ "%s AS initlanacl, "
+ "%s AS initrlanacl, "
+ "(%s l.lanowner) AS lanowner "
+ "FROM pg_language l "
+ "LEFT JOIN pg_init_privs pip "
+ "ON (l.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_type') "
+ "AND pip.objsubid = 0) "
+ "WHERE l.lanispl "
+ "ORDER BY l.oid",
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data,
+ username_subquery);
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(initacl_subquery);
+ destroyPQExpBuffer(initracl_subquery);
+ }
+ else if (fout->remoteVersion >= 90000)
{
/* pg_language has a laninline column */
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
- "laninline, lanvalidator, lanacl, "
+ "laninline, lanvalidator, lanacl, NULL AS rlanacl, "
+ "NULL AS initlanacl, NULL AS initrlanacl, "
"(%s lanowner) AS lanowner "
"FROM pg_language "
"WHERE lanispl "
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
"0 AS laninline, lanvalidator, lanacl, "
+ "NULL AS rlanacl, "
+ "NULL AS initlanacl, NULL AS initrlanacl, "
"(%s lanowner) AS lanowner "
"FROM pg_language "
"WHERE lanispl "
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
"0 AS laninline, lanvalidator, lanacl, "
+ "NULL AS rlanacl, "
+ "NULL AS initlanacl, NULL AS initrlanacl, "
"(%s '10') AS lanowner "
"FROM pg_language "
"WHERE lanispl "
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
"0 AS laninline, lanvalidator, lanacl, "
+ "NULL AS rlanacl, "
+ "NULL AS initlanacl, NULL AS initrlanacl, "
"(%s '1') AS lanowner "
"FROM pg_language "
"WHERE lanispl "
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
"0 AS laninline, lanvalidator, lanacl, "
+ "NULL AS rlanacl, "
+ "NULL AS initlanacl, NULL AS initrlanacl, "
"NULL AS lanowner "
"FROM pg_language "
"WHERE lanispl "
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"lanname, lanpltrusted, lanplcallfoid, "
"0 AS laninline, 0 AS lanvalidator, NULL AS lanacl, "
+ "NULL AS rlanacl, "
+ "NULL AS initlanacl, NULL AS initrlanacl, "
"NULL AS lanowner "
"FROM pg_language "
"WHERE lanispl "
"oid, "
"lanname, lanpltrusted, lanplcallfoid, "
"0 AS laninline, 0 AS lanvalidator, NULL AS lanacl, "
+ "NULL AS rlanacl, "
+ "NULL AS initlanacl, NULL AS initrlanacl, "
"NULL AS lanowner "
"FROM pg_language "
"WHERE lanispl "
i_laninline = PQfnumber(res, "laninline");
i_lanvalidator = PQfnumber(res, "lanvalidator");
i_lanacl = PQfnumber(res, "lanacl");
+ i_rlanacl = PQfnumber(res, "rlanacl");
+ i_initlanacl = PQfnumber(res, "initlanacl");
+ i_initrlanacl = PQfnumber(res, "initrlanacl");
i_lanowner = PQfnumber(res, "lanowner");
for (i = 0; i < ntups; i++)
planginfo[i].laninline = atooid(PQgetvalue(res, i, i_laninline));
planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator));
planginfo[i].lanacl = pg_strdup(PQgetvalue(res, i, i_lanacl));
+ planginfo[i].rlanacl = pg_strdup(PQgetvalue(res, i, i_rlanacl));
+ planginfo[i].initlanacl = pg_strdup(PQgetvalue(res, i, i_initlanacl));
+ planginfo[i].initrlanacl = pg_strdup(PQgetvalue(res, i, i_initrlanacl));
planginfo[i].lanowner = pg_strdup(PQgetvalue(res, i, i_lanowner));
/* Decide whether we want to dump it */
- selectDumpableProcLang(&(planginfo[i]), dopt);
+ 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;
if (fout->remoteVersion < 70300)
{
CastInfo *
getCasts(Archive *fout, int *numCasts)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
}
/* Decide whether we want to dump it */
- selectDumpableCast(&(castinfo[i]), dopt);
+ selectDumpableCast(&(castinfo[i]), fout);
}
PQclear(res);
TransformInfo *
getTransforms(Archive *fout, int *numTransforms)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
free(lanname);
/* Decide whether we want to dump it */
- selectDumpableObject(&(transforminfo[i].dobj), dopt);
+ selectDumpableObject(&(transforminfo[i].dobj), fout);
}
PQclear(res);
TSParserInfo *
getTSParsers(Archive *fout, int *numTSParsers)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
prsinfo[i].prslextype = atooid(PQgetvalue(res, i, i_prslextype));
/* Decide whether we want to dump it */
- selectDumpableObject(&(prsinfo[i].dobj), dopt);
+ selectDumpableObject(&(prsinfo[i].dobj), fout);
}
PQclear(res);
TSDictInfo *
getTSDictionaries(Archive *fout, int *numTSDicts)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
dictinfo[i].dictinitoption = pg_strdup(PQgetvalue(res, i, i_dictinitoption));
/* Decide whether we want to dump it */
- selectDumpableObject(&(dictinfo[i].dobj), dopt);
+ selectDumpableObject(&(dictinfo[i].dobj), fout);
}
PQclear(res);
TSTemplateInfo *
getTSTemplates(Archive *fout, int *numTSTemplates)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));
/* Decide whether we want to dump it */
- selectDumpableObject(&(tmplinfo[i].dobj), dopt);
+ selectDumpableObject(&(tmplinfo[i].dobj), fout);
}
PQclear(res);
TSConfigInfo *
getTSConfigurations(Archive *fout, int *numTSConfigs)
{
- DumpOptions *dopt = fout->dopt;
PGresult *res;
int ntups;
int i;
cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
/* Decide whether we want to dump it */
- selectDumpableObject(&(cfginfo[i].dobj), dopt);
+ selectDumpableObject(&(cfginfo[i].dobj), fout);
}
PQclear(res);
int i_fdwhandler;
int i_fdwvalidator;
int i_fdwacl;
+ int i_rfdwacl;
+ int i_initfdwacl;
+ int i_initrfdwacl;
int i_fdwoptions;
/* Before 8.4, there are no foreign-data wrappers */
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
- if (fout->remoteVersion >= 90100)
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "f.fdwacl", "f.fdwowner", "'F'",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.fdwname, "
+ "(%s f.fdwowner) AS rolname, "
+ "f.fdwhandler::pg_catalog.regproc, "
+ "f.fdwvalidator::pg_catalog.regproc, "
+ "%s AS fdwacl, "
+ "%s AS rfdwacl, "
+ "%s AS initfdwacl, "
+ "%s AS initrfdwacl, "
+ "array_to_string(ARRAY("
+ "SELECT quote_ident(option_name) || ' ' || "
+ "quote_literal(option_value) "
+ "FROM pg_options_to_table(f.fdwoptions) "
+ "ORDER BY option_name"
+ "), E',\n ') AS fdwoptions "
+ "FROM pg_foreign_data_wrapper f "
+ "LEFT JOIN pg_init_privs pip "
+ "ON (f.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_foreign_data_wrapper') "
+ "AND pip.objsubid = 0) ",
+ username_subquery,
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data);
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(initacl_subquery);
+ destroyPQExpBuffer(initracl_subquery);
+ }
+ else if (fout->remoteVersion >= 90100)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
"(%s fdwowner) AS rolname, "
"fdwhandler::pg_catalog.regproc, "
"fdwvalidator::pg_catalog.regproc, fdwacl, "
+ "NULL as rfdwacl, "
+ "NULL as initfdwacl, NULL AS initrfdwacl, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
"(%s fdwowner) AS rolname, "
"'-' AS fdwhandler, "
"fdwvalidator::pg_catalog.regproc, fdwacl, "
+ "NULL as rfdwacl, "
+ "NULL as initfdwacl, NULL AS initrfdwacl, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
i_fdwhandler = PQfnumber(res, "fdwhandler");
i_fdwvalidator = PQfnumber(res, "fdwvalidator");
i_fdwacl = PQfnumber(res, "fdwacl");
+ i_rfdwacl = PQfnumber(res, "rfdwacl");
+ i_initfdwacl = PQfnumber(res, "initfdwacl");
+ i_initrfdwacl = PQfnumber(res, "initrfdwacl");
i_fdwoptions = PQfnumber(res, "fdwoptions");
for (i = 0; i < ntups; i++)
fdwinfo[i].fdwvalidator = pg_strdup(PQgetvalue(res, i, i_fdwvalidator));
fdwinfo[i].fdwoptions = pg_strdup(PQgetvalue(res, i, i_fdwoptions));
fdwinfo[i].fdwacl = pg_strdup(PQgetvalue(res, i, i_fdwacl));
+ fdwinfo[i].rfdwacl = pg_strdup(PQgetvalue(res, i, i_rfdwacl));
+ fdwinfo[i].initfdwacl = pg_strdup(PQgetvalue(res, i, i_initfdwacl));
+ fdwinfo[i].initrfdwacl = pg_strdup(PQgetvalue(res, i, i_initrfdwacl));
/* Decide whether we want to dump it */
- selectDumpableObject(&(fdwinfo[i].dobj), dopt);
+ 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;
}
PQclear(res);
int i_srvtype;
int i_srvversion;
int i_srvacl;
+ int i_rsrvacl;
+ int i_initsrvacl;
+ int i_initrsrvacl;
int i_srvoptions;
/* Before 8.4, there are no foreign servers */
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
- appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
- "(%s srvowner) AS rolname, "
- "srvfdw, srvtype, srvversion, srvacl,"
- "array_to_string(ARRAY("
- "SELECT quote_ident(option_name) || ' ' || "
- "quote_literal(option_value) "
- "FROM pg_options_to_table(srvoptions) "
- "ORDER BY option_name"
- "), E',\n ') AS srvoptions "
- "FROM pg_foreign_server",
- username_subquery);
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "f.srvacl", "f.srvowner", "'S'",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.srvname, "
+ "(%s f.srvowner) AS rolname, "
+ "f.srvfdw, f.srvtype, f.srvversion, "
+ "%s AS srvacl, "
+ "%s AS rsrvacl, "
+ "%s AS initsrvacl, "
+ "%s AS initrsrvacl, "
+ "array_to_string(ARRAY("
+ "SELECT quote_ident(option_name) || ' ' || "
+ "quote_literal(option_value) "
+ "FROM pg_options_to_table(f.srvoptions) "
+ "ORDER BY option_name"
+ "), E',\n ') AS srvoptions "
+ "FROM pg_foreign_server f "
+ "LEFT JOIN pg_init_privs pip "
+ "ON (f.oid = pip.objoid AND pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_foreign_server') "
+ "AND pip.objsubid = 0) ",
+ username_subquery,
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data);
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(initacl_subquery);
+ destroyPQExpBuffer(initracl_subquery);
+ }
+ else
+ {
+ appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
+ "(%s srvowner) AS rolname, "
+ "srvfdw, srvtype, srvversion, srvacl, "
+ "NULL AS rsrvacl, "
+ "NULL AS initsrvacl, NULL AS initrsrvacl, "
+ "array_to_string(ARRAY("
+ "SELECT quote_ident(option_name) || ' ' || "
+ "quote_literal(option_value) "
+ "FROM pg_options_to_table(srvoptions) "
+ "ORDER BY option_name"
+ "), E',\n ') AS srvoptions "
+ "FROM pg_foreign_server",
+ username_subquery);
+ }
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
i_srvtype = PQfnumber(res, "srvtype");
i_srvversion = PQfnumber(res, "srvversion");
i_srvacl = PQfnumber(res, "srvacl");
+ i_rsrvacl = PQfnumber(res, "rsrvacl");
+ i_initsrvacl = PQfnumber(res, "initsrvacl");
+ i_initrsrvacl = PQfnumber(res, "initrsrvacl");
i_srvoptions = PQfnumber(res, "srvoptions");
for (i = 0; i < ntups; i++)
srvinfo[i].srvversion = pg_strdup(PQgetvalue(res, i, i_srvversion));
srvinfo[i].srvoptions = pg_strdup(PQgetvalue(res, i, i_srvoptions));
srvinfo[i].srvacl = pg_strdup(PQgetvalue(res, i, i_srvacl));
+ srvinfo[i].rsrvacl = pg_strdup(PQgetvalue(res, i, i_rsrvacl));
+ srvinfo[i].initsrvacl = pg_strdup(PQgetvalue(res, i, i_initsrvacl));
+ srvinfo[i].initrsrvacl = pg_strdup(PQgetvalue(res, i, i_initrsrvacl));
/* Decide whether we want to dump it */
- selectDumpableObject(&(srvinfo[i].dobj), dopt);
+ 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;
}
PQclear(res);
if (nspinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
qnspname, NULL, nspinfo->dobj.name, NULL,
- nspinfo->rolname, nspinfo->nspacl);
+ nspinfo->rolname, nspinfo->nspacl, nspinfo->rnspacl,
+ nspinfo->initnspacl, nspinfo->initrnspacl);
free(qnspname);
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
qtypname, NULL, tyinfo->dobj.name,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl);
+ tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
+ tyinfo->inittypacl, tyinfo->initrtypacl);
PQclear(res);
destroyPQExpBuffer(q);
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
qtypname, NULL, tyinfo->dobj.name,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl);
+ tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
+ tyinfo->inittypacl, tyinfo->initrtypacl);
PQclear(res);
destroyPQExpBuffer(q);
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
qtypname, NULL, tyinfo->dobj.name,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl);
+ tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
+ tyinfo->inittypacl, tyinfo->initrtypacl);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
qtypname, NULL, tyinfo->dobj.name,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl);
+ tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
+ tyinfo->inittypacl, tyinfo->initrtypacl);
PQclear(res);
destroyPQExpBuffer(q);
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
qtypname, NULL, tyinfo->dobj.name,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl);
+ tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
+ tyinfo->inittypacl, tyinfo->initrtypacl);
/* Dump any per-constraint comments */
for (i = 0; i < tyinfo->nDomChecks; i++)
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
qtypname, NULL, tyinfo->dobj.name,
tyinfo->dobj.namespace->dobj.name,
- tyinfo->rolname, tyinfo->typacl);
+ tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
+ tyinfo->inittypacl, tyinfo->initrtypacl);
PQclear(res);
destroyPQExpBuffer(q);
dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
qlanname, NULL, plang->dobj.name,
lanschema,
- plang->lanowner, plang->lanacl);
+ plang->lanowner, plang->lanacl, plang->rlanacl,
+ plang->initlanacl, plang->initrlanacl);
free(qlanname);
dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION",
funcsig, NULL, funcsig_tag,
finfo->dobj.namespace->dobj.name,
- finfo->rolname, finfo->proacl);
+ finfo->rolname, finfo->proacl, finfo->rproacl,
+ finfo->initproacl, finfo->initrproacl);
PQclear(res);
"FUNCTION",
aggsig, NULL, aggsig_tag,
agginfo->aggfn.dobj.namespace->dobj.name,
- agginfo->aggfn.rolname, agginfo->aggfn.proacl);
+ agginfo->aggfn.rolname, agginfo->aggfn.proacl,
+ agginfo->aggfn.rproacl,
+ agginfo->aggfn.initproacl, agginfo->aggfn.initrproacl);
free(aggsig);
if (aggfullsig)
"FOREIGN DATA WRAPPER",
qfdwname, NULL, fdwinfo->dobj.name,
NULL, fdwinfo->rolname,
- fdwinfo->fdwacl);
+ fdwinfo->fdwacl, fdwinfo->rfdwacl,
+ fdwinfo->initfdwacl, fdwinfo->initrfdwacl);
/* Dump Foreign Data Wrapper Comments */
if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
"FOREIGN SERVER",
qsrvname, NULL, srvinfo->dobj.name,
NULL, srvinfo->rolname,
- srvinfo->srvacl);
+ srvinfo->srvacl, srvinfo->rsrvacl,
+ srvinfo->initsrvacl, srvinfo->initrsrvacl);
/* Dump user mappings */
if (srvinfo->dobj.dump & DUMP_COMPONENT_USERMAP)
if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
tag->data,
- daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
+ daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
NULL,
daclinfo->defaclrole,
false, "DEFAULT ACL", SECTION_POST_DATA,
* 'owner' is the owner, NULL if there is no owner (for languages).
* 'acls' is the string read out of the fooacl system catalog field;
* it will be parsed here.
+ * 'racls' contains any initial ACLs that the object had which have now been
+ * revoked by the user, it will also be parsed here.
*----------
*/
static void
dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
const char *type, const char *name, const char *subname,
const char *tag, const char *nspname, const char *owner,
- const char *acls)
+ const char *acls, const char *racls,
+ const char *initacls, const char *initracls)
{
DumpOptions *dopt = fout->dopt;
PQExpBuffer sql;
sql = createPQExpBuffer();
- if (!buildACLCommands(name, subname, type, acls, owner,
+ /*
+ * Check to see if this object has had any initial ACLs included for it.
+ * If so, we are in binary upgrade mode and these are the ACLs to turn
+ * into GRANT and REVOKE statements to set and record the initial
+ * privileges for an extension object. Let the backend know that these
+ * are to be recorded by calling binary_upgrade_set_record_init_privs()
+ * before and after.
+ */
+ if (strlen(initacls) != 0 || strlen(initracls) != 0)
+ {
+ appendPQExpBuffer(sql, "SELECT binary_upgrade_set_record_init_privs(true);\n");
+ if (!buildACLCommands(name, subname, type, initacls, initracls, owner,
+ "", fout->remoteVersion, sql))
+ exit_horribly(NULL,
+ "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)\n",
+ initacls, initracls, name, type);
+ appendPQExpBuffer(sql, "SELECT binary_upgrade_set_record_init_privs(false);\n");
+ }
+
+ if (!buildACLCommands(name, subname, type, acls, racls, owner,
"", fout->remoteVersion, sql))
exit_horribly(NULL,
- "could not parse ACL list (%s) for object \"%s\" (%s)\n",
- acls, name, type);
+ "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)\n",
+ acls, racls, name, type);
if (sql->len > 0)
ArchiveEntry(fout, nilCatalogId, createDumpId(),
static void
dumpTable(Archive *fout, TableInfo *tbinfo)
{
- char *namecopy;
+ DumpOptions *dopt = fout->dopt;
+ char *namecopy;
if (tbinfo->relkind == RELKIND_SEQUENCE)
dumpSequence(fout, tbinfo);
"TABLE",
namecopy, NULL, tbinfo->dobj.name,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
- tbinfo->relacl);
+ tbinfo->relacl, tbinfo->rrelacl,
+ tbinfo->initrelacl, tbinfo->initrrelacl);
/*
- * 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.
+ * 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.
*/
if (fout->remoteVersion >= 80400 && tbinfo->dobj.dump & DUMP_COMPONENT_ACL)
{
PGresult *res;
int i;
- appendPQExpBuffer(query,
- "SELECT attname, attacl FROM pg_catalog.pg_attribute "
- "WHERE attrelid = '%u' AND NOT attisdropped "
- "AND attacl IS NOT NULL "
- "ORDER BY attnum",
- tbinfo->dobj.catId.oid);
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "at.attacl", "c.relowner", "'c'",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query,
+ "SELECT at.attname, "
+ "%s AS attacl, "
+ "%s AS rattacl, "
+ "%s AS initattacl, "
+ "%s AS initrattacl "
+ "FROM pg_catalog.pg_attribute at "
+ "JOIN pg_catalog.pg_class c ON (at.attrelid = c.oid) "
+ "LEFT JOIN pg_init_privs pip ON "
+ "(pip.classoid = "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AND "
+ " at.attrelid = pip.objoid AND at.attnum = pip.objsubid) "
+ "WHERE at.attrelid = '%u' AND "
+ "NOT at.attisdropped "
+ "AND at.attacl IS NOT NULL "
+ "ORDER BY at.attnum",
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data,
+ tbinfo->dobj.catId.oid);
+
+ destroyPQExpBuffer(acl_subquery);
+ destroyPQExpBuffer(racl_subquery);
+ destroyPQExpBuffer(initacl_subquery);
+ destroyPQExpBuffer(initracl_subquery);
+ }
+ else
+ {
+ appendPQExpBuffer(query,
+ "SELECT attname, attacl, NULL as rattacl, "
+ "NULL AS initattacl, NULL AS initrattacl "
+ "FROM pg_catalog.pg_attribute "
+ "WHERE attrelid = '%u' AND NOT attisdropped "
+ "AND attacl IS NOT NULL "
+ "ORDER BY attnum",
+ tbinfo->dobj.catId.oid);
+ }
+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
for (i = 0; i < PQntuples(res); i++)
{
char *attname = PQgetvalue(res, i, 0);
char *attacl = PQgetvalue(res, i, 1);
+ char *rattacl = PQgetvalue(res, i, 2);
+ char *initattacl = PQgetvalue(res, i, 3);
+ char *initrattacl = PQgetvalue(res, i, 4);
char *attnamecopy;
char *acltag;
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
namecopy, attnamecopy, acltag,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
- attacl);
+ attacl, rattacl, initattacl, initrattacl);
free(attnamecopy);
free(acltag);
}
(strcmp(reltypename, "TABLE") == 0) ? tbinfo->hasoids : false,
reltypename,
tbinfo->postponed_def ?
- SECTION_POST_DATA : SECTION_PRE_DATA,
+ SECTION_POST_DATA : SECTION_PRE_DATA,
q->data, delq->data, NULL,
NULL, 0,
NULL, NULL);