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
This commit is contained in:
Michael Paquier 2019-05-23 10:48:17 +09:00
parent 657c2384c6
commit 156c0c2dff
1 changed files with 26 additions and 7 deletions

View 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 "