]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
pg_dump: fix mis-dumping of non-global default privileges.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 22 Oct 2021 19:22:26 +0000 (15:22 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 22 Oct 2021 19:22:26 +0000 (15:22 -0400)
Non-global default privilege entries should be dumped as-is,
not made relative to the default ACL for their object type.
This would typically only matter if one had revoked some
on-by-default privileges in a global entry, and then wanted
to grant them again in a non-global entry.

Per report from Boris Korzun.  This is an old bug, so back-patch
to all supported branches.

Neil Chen, test case by Masahiko Sawada

Discussion: https://postgr.es/m/111621616618184@mail.yandex.ru
Discussion: https://postgr.es/m/CAA3qoJnr2+1dVJObNtfec=qW4Z0nz=A9+r5bZKoTSy5RDjskMw@mail.gmail.com

src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/t/002_pg_dump.pl

index e8a8491f38171dfeeb5014761fdcababd4997889..bc5b014ec1ce9a10742b07660ebce823cc111e6c 100644 (file)
@@ -8967,9 +8967,26 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
                PQExpBuffer initacl_subquery = createPQExpBuffer();
                PQExpBuffer initracl_subquery = createPQExpBuffer();
 
+               /*
+                * Global entries (with defaclnamespace=0) replace the hard-wired
+                * default ACL for their object type.  We should dump them as deltas
+                * from the default ACL, since that will be used as a starting point
+                * for interpreting the ALTER DEFAULT PRIVILEGES commands.  On the
+                * other hand, non-global entries can only add privileges not revoke
+                * them.  We must dump those as-is (i.e., as deltas from an empty
+                * ACL).  We implement that by passing NULL as the object type for
+                * acldefault(), which works because acldefault() is STRICT.
+                *
+                * We can use defaclobjtype as the object type for acldefault(),
+                * except for the case of 'S' (DEFACLOBJ_SEQUENCE) which must be
+                * converted to 's'.
+                */
                buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
                                                initracl_subquery, "defaclacl", "defaclrole",
-                                               "CASE WHEN defaclobjtype = 'S' THEN 's' ELSE defaclobjtype END::\"char\"",
+                                               "CASE WHEN defaclnamespace = 0 THEN"
+                                               "         CASE WHEN defaclobjtype = 'S' THEN 's'::\"char\""
+                                               "         ELSE defaclobjtype END "
+                                               "ELSE NULL END",
                                                dopt->binary_upgrade);
 
                appendPQExpBuffer(query, "SELECT d.oid, d.tableoid, "
index 2efbe1b8036fbff4b51d5c91e032ba327d88495b..f59fcb6491a69e050b5677e7e7cb2d5aaddb55a2 100644 (file)
@@ -339,6 +339,46 @@ my %tests = (
                        section_pre_data         => 1,
                        section_data             => 1, }, },
 
+       'ALTER DEFAULT PRIVILEGES FOR ROLE regress_dump_test_role GRANT EXECUTE ON FUNCTIONS'
+         => {
+               all_runs     => 1,
+               create_order => 15,
+               create_sql   => 'ALTER DEFAULT PRIVILEGES
+                                          FOR ROLE regress_dump_test_role IN SCHEMA dump_test
+                                          GRANT EXECUTE ON FUNCTIONS TO regress_dump_test_role;',
+               regexp => qr/^
+                       \QALTER DEFAULT PRIVILEGES \E
+                       \QFOR ROLE regress_dump_test_role IN SCHEMA dump_test \E
+                       \QGRANT ALL ON FUNCTIONS  TO regress_dump_test_role;\E
+                       /xm,
+               like => {
+                       binary_upgrade          => 1,
+                       clean                   => 1,
+                       clean_if_exists         => 1,
+                       createdb                => 1,
+                       defaults                => 1,
+                       exclude_test_table      => 1,
+                       exclude_test_table_data => 1,
+                       no_blobs                => 1,
+                       no_owner                => 1,
+                       only_dump_test_schema   => 1,
+                       pg_dumpall_dbprivs      => 1,
+                       schema_only             => 1,
+                       section_post_data       => 1,
+                       test_schema_plus_blobs  => 1,
+                       with_oids               => 1, },
+               unlike => {
+                       column_inserts           => 1,
+                       data_only                => 1,
+                       exclude_dump_test_schema => 1,
+                       no_privs                 => 1,
+                       only_dump_test_table     => 1,
+                       pg_dumpall_globals       => 1,
+                       pg_dumpall_globals_clean => 1,
+                       role                     => 1,
+                       section_pre_data         => 1,
+                       section_data             => 1, }, },
+
        'ALTER DEFAULT PRIVILEGES FOR ROLE regress_dump_test_role REVOKE' => {
                all_runs     => 1,
                create_order => 55,