From: Michael Paquier Date: Thu, 23 May 2019 01:48:17 +0000 (+0900) Subject: Fix ordering of GRANT commands in pg_dumpall for tablespaces X-Git-Tag: REL_12_BETA2~120 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=156c0c2dff403fd115f3a5f6d73ab80959c84129;p=postgresql Fix ordering of GRANT commands in pg_dumpall for tablespaces This uses a method similar to 68a7c24f and now b8c6014 (applied for database creation), which guarantees that GRANT commands using the WITH GRANT OPTION are dumped in a way so as cascading dependencies are respected. Note that tablespaces do not have support for initial privileges via pg_init_privs, so the same method needs to be applied again. It would be nice to merge all the logic generating ACL queries in dumps under the same banner, but this requires extending the support of pg_init_privs to objects that cannot use it yet, so this is left as future work. Discussion: https://postgr.es/m/20190522071555.GB1278@paquier.xyz Author: Michael Paquier Reviewed-by: Nathan Bossart Backpatch-through: 9.6 --- diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index c8eb9de9fb..ea4ac91c00 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -1160,19 +1160,38 @@ dumpTablespaces(PGconn *conn) * * See buildACLQueries() and buildACLCommands(). * + * The order in which privileges are in the ACL string (the order they + * have been GRANT'd in, which the backend maintains) must be preserved to + * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on + * those are dumped in the correct order. + * * Note that we do not support initial privileges (pg_init_privs) on - * tablespaces. + * tablespaces, so this logic cannot make use of buildACLQueries(). */ if (server_version >= 90600) res = executeQuery(conn, "SELECT oid, spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "pg_catalog.pg_tablespace_location(oid), " - "(SELECT pg_catalog.array_agg(acl) FROM (SELECT pg_catalog.unnest(coalesce(spcacl,pg_catalog.acldefault('t',spcowner))) AS acl " - "EXCEPT SELECT pg_catalog.unnest(pg_catalog.acldefault('t',spcowner))) as foo)" - "AS spcacl," - "(SELECT pg_catalog.array_agg(acl) FROM (SELECT pg_catalog.unnest(pg_catalog.acldefault('t',spcowner)) AS acl " - "EXCEPT SELECT pg_catalog.unnest(coalesce(spcacl,pg_catalog.acldefault('t',spcowner)))) as foo)" - "AS rspcacl," + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(coalesce(spcacl,acldefault('t',spcowner))) " + " WITH ORDINALITY AS perm(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(acldefault('t',spcowner)) " + " AS init(init_acl) " + " WHERE acl = init_acl)) AS spcacls) " + " AS spcacl, " + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(acldefault('t',spcowner)) " + " WITH ORDINALITY AS initp(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(coalesce(spcacl,acldefault('t',spcowner))) " + " AS permp(orig_acl) " + " WHERE acl = orig_acl)) AS rspcacls) " + " AS rspcacl, " "array_to_string(spcoptions, ', ')," "pg_catalog.shobj_description(oid, 'pg_tablespace') " "FROM pg_catalog.pg_tablespace "