]> granicus.if.org Git - postgresql/commitdiff
Fix ordering of GRANT commands in pg_dumpall for tablespaces
authorMichael Paquier <michael@paquier.xyz>
Thu, 23 May 2019 01:48:17 +0000 (10:48 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 23 May 2019 01:48:17 +0000 (10:48 +0900)
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

src/bin/pg_dump/pg_dumpall.c

index c8eb9de9fb0c286baefc4331d5f461da02c0229d..ea4ac91c00fed941a83950f47e7af7e3e933e329 100644 (file)
@@ -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 "