aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2019-05-23 10:48:17 +0900
committerMichael Paquier <michael@paquier.xyz>2019-05-23 10:48:17 +0900
commit156c0c2dff403fd115f3a5f6d73ab80959c84129 (patch)
tree07407013a8c269b986b34718d8585809662242cf
parent657c2384c6c79c6ed0d6f71f811b2fc7c41f104a (diff)
downloadpostgresql-156c0c2dff403fd115f3a5f6d73ab80959c84129.tar.gz
postgresql-156c0c2dff403fd115f3a5f6d73ab80959c84129.zip
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
-rw-r--r--src/bin/pg_dump/pg_dumpall.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index c8eb9de9fb0..ea4ac91c00f 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 "