diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index a8f1ad7333..e8ce719a0a 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -2664,20 +2664,41 @@ dumpDatabase(Archive *fout) pg_log_info("saving database definition"); - /* Fetch the database-level properties for this database */ + /* + * Fetch the database-level properties for this database. + * + * 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 initial privileges + * (pg_init_privs) are not supported on databases, so this logic cannot + * make use of buildACLQueries(). + */ if (fout->remoteVersion >= 90600) { appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, " "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " "datcollate, datctype, datfrozenxid, datminmxid, " - "(SELECT array_agg(acl ORDER BY acl::text COLLATE \"C\") FROM ( " - " SELECT unnest(coalesce(datacl,acldefault('d',datdba))) AS acl " - " EXCEPT SELECT unnest(acldefault('d',datdba))) as datacls)" + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(coalesce(datacl,acldefault('d',datdba))) " + " WITH ORDINALITY AS perm(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(acldefault('d',datdba)) " + " AS init(init_acl) " + " WHERE acl = init_acl)) AS datacls) " " AS datacl, " - "(SELECT array_agg(acl ORDER BY acl::text COLLATE \"C\") FROM ( " - " SELECT unnest(acldefault('d',datdba)) AS acl " - " EXCEPT SELECT unnest(coalesce(datacl,acldefault('d',datdba)))) as rdatacls)" + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(acldefault('d',datdba)) " + " WITH ORDINALITY AS initp(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(coalesce(datacl,acldefault('d',datdba))) " + " AS permp(orig_acl) " + " WHERE acl = orig_acl)) AS rdatacls) " " AS rdatacl, " "datistemplate, datconnlimit, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "