* contents rather than replace the extension contents with something
* different.
*/
- 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
+ if (fout->dopt->binary_upgrade)
dobj->dump = ext->dobj.dump;
+ else
+ {
+ if (fout->remoteVersion < 90600)
+ dobj->dump = DUMP_COMPONENT_NONE;
+ else
+ dobj->dump = ext->dobj.dump_contains & (DUMP_COMPONENT_ACL |
+ DUMP_COMPONENT_SECLABEL | DUMP_COMPONENT_POLICY);
+
+ }
return true;
}
if (dinfo->dobj.namespace)
/* default ACLs are considered part of the namespace */
- dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump;
+ dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump_contains;
else
dinfo->dobj.dump = dopt->include_everything ?
DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
if (checkExtensionMembership(&cast->dobj, fout))
return; /* extension membership overrides all else */
+ /*
+ * This would be DUMP_COMPONENT_ACL for from-initdb casts, but they do not
+ * support ACLs currently.
+ */
if (cast->dobj.catId.oid < (Oid) FirstNormalObjectId)
cast->dobj.dump = DUMP_COMPONENT_NONE;
else
if (checkExtensionMembership(&plang->dobj, fout))
return; /* extension membership overrides all else */
- if (plang->dobj.catId.oid < (Oid) FirstNormalObjectId)
+ /*
+ * Only include procedural languages when we are dumping everything.
+ *
+ * For from-initdb procedural languages, only include ACLs, as we do for
+ * the pg_catalog namespace. We need this because procedural languages do
+ * not live in any namespace.
+ */
+ if (!fout->dopt->include_everything)
plang->dobj.dump = DUMP_COMPONENT_NONE;
else
- plang->dobj.dump = fout->dopt->include_everything ?
- DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
+ {
+ if (plang->dobj.catId.oid < (Oid) FirstNormalObjectId)
+ plang->dobj.dump = fout->remoteVersion < 90600 ?
+ DUMP_COMPONENT_NONE : DUMP_COMPONENT_ACL;
+ else
+ plang->dobj.dump = DUMP_COMPONENT_ALL;
+ }
}
/*
if (checkExtensionMembership(&method->dobj, fout))
return; /* extension membership overrides all else */
+ /*
+ * This would be DUMP_COMPONENT_ACL for from-initdb access methods, but
+ * they do not support ACLs currently.
+ */
if (method->dobj.catId.oid < (Oid) FirstNormalObjectId)
method->dobj.dump = DUMP_COMPONENT_NONE;
else
static void
selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt)
{
+ /*
+ * Use DUMP_COMPONENT_ACL for from-initdb extensions, to allow users
+ * to change permissions on those objects, if they wish to, and have
+ * those changes preserved.
+ */
if (dopt->binary_upgrade && extinfo->dobj.catId.oid < (Oid) FirstNormalObjectId)
- extinfo->dobj.dump = DUMP_COMPONENT_NONE;
+ extinfo->dobj.dump = DUMP_COMPONENT_ACL;
else
- extinfo->dobj.dump = dopt->include_everything ?
- DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
+ extinfo->dobj.dump = extinfo->dobj.dump_contains =
+ dopt->include_everything ? DUMP_COMPONENT_ALL :
+ DUMP_COMPONENT_NONE;
}
/*
/* 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)
write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
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 (fout->remoteVersion >= 70300)
{
if (strlen(opcinfo[i].rolname) == 0)
/* 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 (fout->remoteVersion >= 70300)
{
if (strlen(opfinfo[i].rolname) == 0)
int i_toastreloptions;
int i_reloftype;
int i_relpages;
+ int i_changed_acl;
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
PQExpBuffer initacl_subquery = createPQExpBuffer();
PQExpBuffer initracl_subquery = createPQExpBuffer();
+ PQExpBuffer attacl_subquery = createPQExpBuffer();
+ PQExpBuffer attracl_subquery = createPQExpBuffer();
+ PQExpBuffer attinitacl_subquery = createPQExpBuffer();
+ PQExpBuffer attinitracl_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)
"CASE WHEN c.relkind = 'S' THEN 's' ELSE 'r' END::\"char\"",
dopt->binary_upgrade);
+ buildACLQueries(attacl_subquery, attracl_subquery, attinitacl_subquery,
+ attinitracl_subquery, "at.attacl", "c.relowner", "'c'",
+ dopt->binary_upgrade);
+
appendPQExpBuffer(query,
"SELECT c.tableoid, c.oid, c.relname, "
"%s AS relacl, %s as rrelacl, "
"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 "
+ "tc.reloptions AS toast_reloptions, "
+ "EXISTS (SELECT 1 FROM pg_attribute at 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 = at.attnum)"
+ "WHERE at.attrelid = c.oid AND ("
+ "%s IS NOT NULL "
+ "OR %s IS NOT NULL "
+ "OR %s IS NOT NULL "
+ "OR %s IS NOT NULL"
+ "))"
+ "AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
initacl_subquery->data,
initracl_subquery->data,
username_subquery,
+ attacl_subquery->data,
+ attracl_subquery->data,
+ attinitacl_subquery->data,
+ attinitracl_subquery->data,
RELKIND_SEQUENCE,
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
destroyPQExpBuffer(racl_subquery);
destroyPQExpBuffer(initacl_subquery);
destroyPQExpBuffer(initracl_subquery);
+
+ destroyPQExpBuffer(attacl_subquery);
+ destroyPQExpBuffer(attracl_subquery);
+ destroyPQExpBuffer(attinitacl_subquery);
+ destroyPQExpBuffer(attinitracl_subquery);
}
else if (fout->remoteVersion >= 90500)
{
"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 "
+ "tc.reloptions AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"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 "
+ "tc.reloptions AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"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 "
+ "tc.reloptions AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"d.refobjsubid AS owning_col, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"c.reloptions AS reloptions, "
- "tc.reloptions AS toast_reloptions "
+ "tc.reloptions AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"d.refobjsubid AS owning_col, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"c.reloptions AS reloptions, "
- "tc.reloptions AS toast_reloptions "
+ "tc.reloptions AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"d.refobjsubid AS owning_col, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"c.reloptions AS reloptions, "
- "tc.reloptions AS toast_reloptions "
+ "tc.reloptions AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"d.refobjsubid AS owning_col, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"c.reloptions AS reloptions, "
- "NULL AS toast_reloptions "
+ "NULL AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"d.refobjsubid AS owning_col, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"NULL AS reloptions, "
- "NULL AS toast_reloptions "
+ "NULL AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"d.refobjsubid AS owning_col, "
"NULL AS reltablespace, "
"NULL AS reloptions, "
- "NULL AS toast_reloptions "
+ "NULL AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
"NULL::int4 AS owning_col, "
"NULL AS reltablespace, "
"NULL AS reloptions, "
- "NULL AS toast_reloptions "
+ "NULL AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class "
"WHERE relkind IN ('%c', '%c', '%c') "
"ORDER BY oid",
"NULL::int4 AS owning_col, "
"NULL AS reltablespace, "
"NULL AS reloptions, "
- "NULL AS toast_reloptions "
+ "NULL AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class "
"WHERE relkind IN ('%c', '%c', '%c') "
"ORDER BY oid",
"NULL::int4 AS owning_col, "
"NULL AS reltablespace, "
"NULL AS reloptions, "
- "NULL AS toast_reloptions "
+ "NULL AS toast_reloptions, "
+ "NULL AS changed_acl "
"FROM pg_class c "
"WHERE relkind IN ('%c', '%c') "
"ORDER BY oid",
i_checkoption = PQfnumber(res, "checkoption");
i_toastreloptions = PQfnumber(res, "toast_reloptions");
i_reloftype = PQfnumber(res, "reloftype");
+ i_changed_acl = PQfnumber(res, "changed_acl");
if (dopt->lockWaitTimeout && fout->remoteVersion >= 70300)
{
else
selectDumpableTable(&tblinfo[i], fout);
+ /*
+ * 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
+ * 'changed_acl' column from the query will indicate that.
+ *
+ * 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;
+
tblinfo[i].interesting = tblinfo[i].dobj.dump ? true : false;
tblinfo[i].postponed_def = false; /* might get set during sort */
/* 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 */
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);
" at.attrelid = pip.objoid AND at.attnum = pip.objsubid) "
"WHERE at.attrelid = '%u' AND "
"NOT at.attisdropped "
- "AND at.attacl IS NOT NULL "
+ "AND ("
+ "%s IS NOT NULL OR "
+ "%s IS NOT NULL OR "
+ "%s IS NOT NULL OR "
+ "%s IS NOT NULL)"
"ORDER BY at.attnum",
acl_subquery->data,
racl_subquery->data,
initacl_subquery->data,
initracl_subquery->data,
- tbinfo->dobj.catId.oid);
+ tbinfo->dobj.catId.oid,
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data);
destroyPQExpBuffer(acl_subquery);
destroyPQExpBuffer(racl_subquery);