This is an automated email from the ASF dual-hosted git repository.

tuhaihe pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 2e9632afed1c84ae89310d49c7e1ac1b31f2baf0
Author: Tom Lane <[email protected]>
AuthorDate: Mon Dec 6 12:39:45 2021 -0500

    Rethink pg_dump's handling of object ACLs.
    
    Backported from PG15 0c9d84427f
    
    Conflicts resolved:
    * Rejected changes to special handling of public
      schema from upstream a7a7be1f2 and b073c3ccd
      which have not been backported. These changes
      cause pg_dump to believe that schema public has
      a specific initprivs value even when it doesn't.
      In GPDB pg_upgrade we drop and recreate the public
      schema and with the above changes the public schema
      ACL would be different in the destination cluster.
      Ref: 
https://www.postgresql.org/message-id/[email protected]
    * Refactored getExtProtocols to use new ACL logic
    * Removed code handling pre 8.3 servers
    
    Original commit message follows:
    
    Throw away most of the existing logic for this, as it was very
    inefficient thanks to expensive sub-selects executed to collect
    ACL data that we very possibly would have no interest in dumping.
    Reduce the ACL handling in the initial per-object-type queries
    to be just collection of the catalog ACL fields, as it was
    originally.  Fetch pg_init_privs data separately in a single
    scan of that catalog, and do the merging calculations on the
    client side.  Remove the separate code path used for pre-9.6
    source servers; there is no good reason to treat them differently
    from newer servers that happen to have empty pg_init_privs.
    
    Discussion: https://postgr.es/m/[email protected]
    Discussion: 
https://postgr.es/m/[email protected]
---
 src/bin/pg_dump/dumputils.c         |  507 ++++++--------
 src/bin/pg_dump/dumputils.h         |   13 +-
 src/bin/pg_dump/pg_dump.c           | 1285 +++++++++++++----------------------
 src/bin/pg_dump/pg_dump.h           |   68 +-
 src/bin/pg_dump/pg_dumpall.c        |   93 +--
 src/fe_utils/string_utils.c         |   63 ++
 src/include/fe_utils/string_utils.h |    1 +
 7 files changed, 793 insertions(+), 1237 deletions(-)

diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index ebb3654b725..2f40f0838ea 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -25,7 +25,7 @@ static bool parseAclItem(const char *item, const char *type,
                                                 const char *name, const char 
*subname, int remoteVersion,
                                                 PQExpBuffer grantee, 
PQExpBuffer grantor,
                                                 PQExpBuffer privs, PQExpBuffer 
privswgo);
-static char *copyAclUserName(PQExpBuffer output, char *input);
+static char *dequoteAclUserName(PQExpBuffer output, char *input);
 static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
                                   const char *subname);
 
@@ -77,7 +77,8 @@ sanitize_line(const char *str, bool want_hyphen)
  *             TABLE, SEQUENCE, FUNCTION, PROCEDURE, LANGUAGE, SCHEMA, 
DATABASE, TABLESPACE,
  *             FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT)
  *     acls: the ACL string fetched from the database
- *     racls: the ACL string of any initial-but-now-revoked privileges
+ *     baseacls: the initial ACL string for this object; can be
+ *             NULL or empty string to indicate "not available from server"
  *     owner: username of object owner (will be passed through fmtId); can be
  *             NULL or empty string to indicate "no owner known"
  *     prefix: string to prefix to each generated command; typically empty
@@ -86,6 +87,12 @@ sanitize_line(const char *str, bool want_hyphen)
  * Returns true if okay, false if could not parse the acl string.
  * The resulting commands (if any) are appended to the contents of 'sql'.
  *
+ * baseacls is typically the result of acldefault() for the object's type
+ * and owner.  However, if there is a pg_init_privs entry for the object,
+ * it should instead be the initprivs ACLs.  When acls is itself a
+ * pg_init_privs entry, baseacls is what to dump that relative to; then
+ * it can be either an acldefault() value or an empty ACL "{}".
+ *
  * Note: when processing a default ACL, prefix is "ALTER DEFAULT PRIVILEGES "
  * or something similar, and name is an empty string.
  *
@@ -94,15 +101,19 @@ sanitize_line(const char *str, bool want_hyphen)
  */
 bool
 buildACLCommands(const char *name, const char *subname, const char *nspname,
-                                const char *type, const char *acls, const char 
*racls,
+                                const char *type, const char *acls, const char 
*baseacls,
                                 const char *owner, const char *prefix, int 
remoteVersion,
                                 PQExpBuffer sql)
 {
        bool            ok = true;
        char      **aclitems = NULL;
-       char      **raclitems = NULL;
+       char      **baseitems = NULL;
+       char      **grantitems = NULL;
+       char      **revokeitems = NULL;
        int                     naclitems = 0;
-       int                     nraclitems = 0;
+       int                     nbaseitems = 0;
+       int                     ngrantitems = 0;
+       int                     nrevokeitems = 0;
        int                     i;
        PQExpBuffer grantee,
                                grantor,
@@ -110,37 +121,88 @@ buildACLCommands(const char *name, const char *subname, 
const char *nspname,
                                privswgo;
        PQExpBuffer firstsql,
                                secondsql;
-       bool            found_owner_privs = false;
 
-       if (strlen(acls) == 0 && strlen(racls) == 0)
+       /*
+        * If the acl was NULL (initial default state), we need do nothing.  
Note
+        * that this is distinguishable from all-privileges-revoked, which will
+        * look like an empty array ("{}").
+        */
+       if (acls == NULL || *acls == '\0')
                return true;                    /* object has default 
permissions */
 
        /* treat empty-string owner same as NULL */
        if (owner && *owner == '\0')
                owner = NULL;
 
-       if (strlen(acls) != 0)
+       /* Parse the acls array */
+       if (!parsePGArray(acls, &aclitems, &naclitems))
+       {
+               if (aclitems)
+                       free(aclitems);
+               return false;
+       }
+
+       /* Parse the baseacls, if provided */
+       if (baseacls && *baseacls != '\0')
        {
-               if (!parsePGArray(acls, &aclitems, &naclitems))
+               if (!parsePGArray(baseacls, &baseitems, &nbaseitems))
                {
                        if (aclitems)
                                free(aclitems);
+                       if (baseitems)
+                               free(baseitems);
                        return false;
                }
        }
 
-       if (strlen(racls) != 0)
+       /*
+        * Compare the actual ACL with the base ACL, extracting the privileges
+        * that need to be granted (i.e., are in the actual ACL but not the base
+        * ACL) and the ones that need to be revoked (the reverse).  We use 
plain
+        * string comparisons to check for matches.  In principle that could be
+        * fooled by extraneous issues such as whitespace, but since all these
+        * strings are the work of aclitemout(), it should be OK in practice.
+        * Besides, a false mismatch will just cause the output to be a little
+        * more verbose than it really needed to be.
+        *
+        * (If we weren't given a base ACL, this stanza winds up with all the
+        * ACL's items in grantitems and nothing in revokeitems.  It's not worth
+        * special-casing that.)
+        */
+       grantitems = (char **) pg_malloc(naclitems * sizeof(char *));
+       for (i = 0; i < naclitems; i++)
        {
-               if (!parsePGArray(racls, &raclitems, &nraclitems))
+               bool            found = false;
+
+               for (int j = 0; j < nbaseitems; j++)
                {
-                       if (aclitems)
-                               free(aclitems);
-                       if (raclitems)
-                               free(raclitems);
-                       return false;
+                       if (strcmp(aclitems[i], baseitems[j]) == 0)
+                       {
+                               found = true;
+                               break;
+                       }
                }
+               if (!found)
+                       grantitems[ngrantitems++] = aclitems[i];
        }
+       revokeitems = (char **) pg_malloc(nbaseitems * sizeof(char *));
+       for (i = 0; i < nbaseitems; i++)
+       {
+               bool            found = false;
 
+               for (int j = 0; j < naclitems; j++)
+               {
+                       if (strcmp(baseitems[i], aclitems[j]) == 0)
+                       {
+                               found = true;
+                               break;
+                       }
+               }
+               if (!found)
+                       revokeitems[nrevokeitems++] = baseitems[i];
+       }
+
+       /* Prepare working buffers */
        grantee = createPQExpBuffer();
        grantor = createPQExpBuffer();
        privs = createPQExpBuffer();
@@ -148,50 +210,21 @@ buildACLCommands(const char *name, const char *subname, 
const char *nspname,
 
        /*
         * At the end, these two will be pasted together to form the result.
-        *
-        * For older systems we use these to ensure that the owner privileges go
-        * before the other ones, as a GRANT could create the default entry for
-        * the object, which generally includes all rights for the owner. In 
more
-        * recent versions we normally handle this because the owner rights come
-        * first in the ACLs, but older versions might have them after the 
PUBLIC
-        * privileges.
-        *
-        * For 9.6 and later systems, much of this changes.  With 9.6, we check
-        * the default privileges for the objects at dump time and create two 
sets
-        * of ACLs- "racls" which are the ACLs to REVOKE from the object (as the
-        * object may have initial privileges on it, along with any default ACLs
-        * which are not part of the current set of privileges), and regular
-        * "acls", which are the ACLs to GRANT to the object.  We handle the
-        * REVOKEs first, followed by the GRANTs.
         */
        firstsql = createPQExpBuffer();
        secondsql = createPQExpBuffer();
 
        /*
-        * For pre-9.6 systems, we always start with REVOKE ALL FROM PUBLIC, as 
we
-        * don't wish to make any assumptions about what the default ACLs are, 
and
-        * we do not collect them during the dump phase (and racls will always 
be
-        * the empty set, see above).
-        *
-        * For 9.6 and later, if any revoke ACLs have been provided, then 
include
-        * them in 'firstsql'.
+        * If we weren't given baseacls information, we just revoke everything 
and
+        * then grant what's listed in the ACL.  This avoids having to embed
+        * detailed knowledge about what the defaults are/were, and it's not 
very
+        * expensive since servers lacking acldefault() are now rare.
         *
-        * Revoke ACLs happen when an object starts out life with a set of
-        * privileges (eg: GRANT SELECT ON pg_class TO PUBLIC;) and the user has
-        * decided to revoke those rights.  Since those objects come into being
-        * with those default privileges, we have to revoke them to match what 
the
-        * current state of affairs is.  Note that we only started explicitly
-        * tracking such initial rights in 9.6, and prior to that all initial
-        * rights are actually handled by the simple 'REVOKE ALL .. FROM PUBLIC'
-        * case, for initdb-created objects.  Prior to 9.6, we didn't handle
-        * extensions correctly, but we do now by tracking their initial
-        * privileges, in the same way we track initdb initial privileges, see
-        * pg_init_privs.
+        * Otherwise, we need only revoke what's listed in revokeitems.
         */
-       if (remoteVersion < 90600)
+       if (baseacls == NULL || *baseacls == '\0')
        {
-               Assert(nraclitems == 0);
-
+               /* We assume the old defaults only involved the owner and 
PUBLIC */
                appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
                if (subname)
                        appendPQExpBuffer(firstsql, "(%s)", subname);
@@ -199,13 +232,24 @@ buildACLCommands(const char *name, const char *subname, 
const char *nspname,
                if (nspname && *nspname)
                        appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
                appendPQExpBuffer(firstsql, "%s FROM PUBLIC;\n", name);
+               if (owner)
+               {
+                       appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
+                       if (subname)
+                               appendPQExpBuffer(firstsql, "(%s)", subname);
+                       appendPQExpBuffer(firstsql, " ON %s ", type);
+                       if (nspname && *nspname)
+                               appendPQExpBuffer(firstsql, "%s.", 
fmtId(nspname));
+                       appendPQExpBuffer(firstsql, "%s FROM %s;\n", name, 
fmtId(owner));
+               }
        }
        else
        {
                /* Scan individual REVOKE ACL items */
-               for (i = 0; i < nraclitems; i++)
+               for (i = 0; i < nrevokeitems; i++)
                {
-                       if (!parseAclItem(raclitems[i], type, name, subname, 
remoteVersion,
+                       if (!parseAclItem(revokeitems[i],
+                                                         type, name, subname, 
remoteVersion,
                                                          grantee, grantor, 
privs, NULL))
                        {
                                ok = false;
@@ -232,146 +276,92 @@ buildACLCommands(const char *name, const char *subname, 
const char *nspname,
                }
        }
 
-       /* Scan individual ACL items */
-       for (i = 0; i < naclitems; i++)
+       /*
+        * Scan individual ACL items to be granted.
+        *
+        * The order in which privileges appear 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.  However, some old server
+        * versions will show grants to PUBLIC before the owner's own grants; 
for
+        * consistency's sake, force the owner's grants to be output first.
+        */
+       for (i = 0; i < ngrantitems; i++)
        {
-               if (!parseAclItem(aclitems[i], type, name, subname, 
remoteVersion,
-                                                 grantee, grantor, privs, 
privswgo))
-               {
-                       ok = false;
-                       break;
-               }
-
-               if (grantor->len == 0 && owner)
-                       printfPQExpBuffer(grantor, "%s", owner);
-
-               if (privs->len > 0 || privswgo->len > 0)
+               if (parseAclItem(grantitems[i], type, name, subname, 
remoteVersion,
+                                                grantee, grantor, privs, 
privswgo))
                {
                        /*
-                        * Prior to 9.6, we had to handle owner privileges in a 
special
-                        * manner by first REVOKE'ing the rights and then 
GRANT'ing them
-                        * after.  With 9.6 and above, what we need to REVOKE 
and what we
-                        * need to GRANT is figured out when we dump and 
stashed into
-                        * "racls" and "acls", respectively.  See above.
+                        * If the grantor isn't the owner, we'll need to use 
SET SESSION
+                        * AUTHORIZATION to become the grantor.  Issue the 
SET/RESET only
+                        * if there's something useful to do.
                         */
-                       if (remoteVersion < 90600 && owner
-                               && strcmp(grantee->data, owner) == 0
-                               && strcmp(grantor->data, owner) == 0)
+                       if (privs->len > 0 || privswgo->len > 0)
                        {
-                               found_owner_privs = true;
+                               PQExpBuffer thissql;
+
+                               /* Set owner as grantor if that's not explicit 
in the ACL */
+                               if (grantor->len == 0 && owner)
+                                       printfPQExpBuffer(grantor, "%s", owner);
+
+                               /* Make sure owner's own grants are output 
before others */
+                               if (owner &&
+                                       strcmp(grantee->data, owner) == 0 &&
+                                       strcmp(grantor->data, owner) == 0)
+                                       thissql = firstsql;
+                               else
+                                       thissql = secondsql;
 
-                               /*
-                                * For the owner, the default privilege level 
is ALL WITH
-                                * GRANT OPTION.
-                                */
-                               if (strcmp(privswgo->data, "ALL") != 0)
-                               {
-                                       appendPQExpBuffer(firstsql, "%sREVOKE 
ALL", prefix);
-                                       if (subname)
-                                               appendPQExpBuffer(firstsql, 
"(%s)", subname);
-                                       appendPQExpBuffer(firstsql, " ON %s ", 
type);
-                                       if (nspname && *nspname)
-                                               appendPQExpBuffer(firstsql, 
"%s.", fmtId(nspname));
-                                       appendPQExpBuffer(firstsql, "%s FROM 
%s;\n",
-                                                                         name, 
fmtId(grantee->data));
-                                       if (privs->len > 0)
-                                       {
-                                               appendPQExpBuffer(firstsql,
-                                                                               
  "%sGRANT %s ON %s ",
-                                                                               
  prefix, privs->data, type);
-                                               if (nspname && *nspname)
-                                                       
appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
-                                               appendPQExpBuffer(firstsql,
-                                                                               
  "%s TO %s;\n",
-                                                                               
  name, fmtId(grantee->data));
-                                       }
-                                       if (privswgo->len > 0)
-                                       {
-                                               appendPQExpBuffer(firstsql,
-                                                                               
  "%sGRANT %s ON %s ",
-                                                                               
  prefix, privswgo->data, type);
-                                               if (nspname && *nspname)
-                                                       
appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
-                                               appendPQExpBuffer(firstsql,
-                                                                               
  "%s TO %s WITH GRANT OPTION;\n",
-                                                                               
  name, fmtId(grantee->data));
-                                       }
-                               }
-                       }
-                       else
-                       {
-                               /*
-                                * For systems prior to 9.6, we can assume we 
are starting
-                                * from no privs at this point.
-                                *
-                                * For 9.6 and above, at this point we have 
issued REVOKE
-                                * statements for all initial and default 
privileges which are
-                                * no longer present on the object (as they 
were passed in as
-                                * 'racls') and we can simply GRANT the rights 
which are in
-                                * 'acls'.
-                                */
                                if (grantor->len > 0
                                        && (!owner || strcmp(owner, 
grantor->data) != 0))
-                                       appendPQExpBuffer(secondsql, "SET 
SESSION AUTHORIZATION %s;\n",
+                                       appendPQExpBuffer(thissql, "SET SESSION 
AUTHORIZATION %s;\n",
                                                                          
fmtId(grantor->data));
 
                                if (privs->len > 0)
                                {
-                                       appendPQExpBuffer(secondsql, "%sGRANT 
%s ON %s ",
+                                       appendPQExpBuffer(thissql, "%sGRANT %s 
ON %s ",
                                                                          
prefix, privs->data, type);
                                        if (nspname && *nspname)
-                                               appendPQExpBuffer(secondsql, 
"%s.", fmtId(nspname));
-                                       appendPQExpBuffer(secondsql, "%s TO ", 
name);
+                                               appendPQExpBuffer(thissql, 
"%s.", fmtId(nspname));
+                                       appendPQExpBuffer(thissql, "%s TO ", 
name);
                                        if (grantee->len == 0)
-                                               appendPQExpBufferStr(secondsql, 
"PUBLIC;\n");
+                                               appendPQExpBufferStr(thissql, 
"PUBLIC;\n");
                                        else if (strncmp(grantee->data, "group 
",
                                                                         
strlen("group ")) == 0)
-                                               appendPQExpBuffer(secondsql, 
"GROUP %s;\n",
+                                               appendPQExpBuffer(thissql, 
"GROUP %s;\n",
                                                                                
  fmtId(grantee->data + strlen("group ")));
                                        else
-                                               appendPQExpBuffer(secondsql, 
"%s;\n", fmtId(grantee->data));
+                                               appendPQExpBuffer(thissql, 
"%s;\n", fmtId(grantee->data));
                                }
                                if (privswgo->len > 0)
                                {
-                                       appendPQExpBuffer(secondsql, "%sGRANT 
%s ON %s ",
+                                       appendPQExpBuffer(thissql, "%sGRANT %s 
ON %s ",
                                                                          
prefix, privswgo->data, type);
                                        if (nspname && *nspname)
-                                               appendPQExpBuffer(secondsql, 
"%s.", fmtId(nspname));
-                                       appendPQExpBuffer(secondsql, "%s TO ", 
name);
+                                               appendPQExpBuffer(thissql, 
"%s.", fmtId(nspname));
+                                       appendPQExpBuffer(thissql, "%s TO ", 
name);
                                        if (grantee->len == 0)
-                                               appendPQExpBufferStr(secondsql, 
"PUBLIC");
+                                               appendPQExpBufferStr(thissql, 
"PUBLIC");
                                        else if (strncmp(grantee->data, "group 
",
                                                                         
strlen("group ")) == 0)
-                                               appendPQExpBuffer(secondsql, 
"GROUP %s",
+                                               appendPQExpBuffer(thissql, 
"GROUP %s",
                                                                                
  fmtId(grantee->data + strlen("group ")));
                                        else
-                                               appendPQExpBufferStr(secondsql, 
fmtId(grantee->data));
-                                       appendPQExpBufferStr(secondsql, " WITH 
GRANT OPTION;\n");
+                                               appendPQExpBufferStr(thissql, 
fmtId(grantee->data));
+                                       appendPQExpBufferStr(thissql, " WITH 
GRANT OPTION;\n");
                                }
 
                                if (grantor->len > 0
                                        && (!owner || strcmp(owner, 
grantor->data) != 0))
-                                       appendPQExpBufferStr(secondsql, "RESET 
SESSION AUTHORIZATION;\n");
+                                       appendPQExpBufferStr(thissql, "RESET 
SESSION AUTHORIZATION;\n");
                        }
                }
-       }
-
-       /*
-        * For systems prior to 9.6, if we didn't find any owner privs, the 
owner
-        * must have revoked 'em all.
-        *
-        * For 9.6 and above, we handle this through the 'racls'.  See above.
-        */
-       if (remoteVersion < 90600 && !found_owner_privs && owner)
-       {
-               appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
-               if (subname)
-                       appendPQExpBuffer(firstsql, "(%s)", subname);
-               appendPQExpBuffer(firstsql, " ON %s ", type);
-               if (nspname && *nspname)
-                       appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
-               appendPQExpBuffer(firstsql, "%s FROM %s;\n",
-                                                 name, fmtId(owner));
+               else
+               {
+                       /* parseAclItem failed, give up */
+                       ok = false;
+                       break;
+               }
        }
 
        destroyPQExpBuffer(grantee);
@@ -385,19 +375,23 @@ buildACLCommands(const char *name, const char *subname, 
const char *nspname,
 
        if (aclitems)
                free(aclitems);
-
-       if (raclitems)
-               free(raclitems);
+       if (baseitems)
+               free(baseitems);
+       if (grantitems)
+               free(grantitems);
+       if (revokeitems)
+               free(revokeitems);
 
        return ok;
 }
 
 /*
- * Build ALTER DEFAULT PRIVILEGES command(s) for single pg_default_acl entry.
+ * Build ALTER DEFAULT PRIVILEGES command(s) for a single pg_default_acl entry.
  *
  *     type: the object type (TABLES, FUNCTIONS, etc)
  *     nspname: schema name, or NULL for global default privileges
  *     acls: the ACL string fetched from the database
+ *     acldefault: the appropriate default ACL for the object type and owner
  *     owner: username of privileges owner (will be passed through fmtId)
  *     remoteVersion: version of database
  *
@@ -406,8 +400,7 @@ buildACLCommands(const char *name, const char *subname, 
const char *nspname,
  */
 bool
 buildDefaultACLCommands(const char *type, const char *nspname,
-                                               const char *acls, const char 
*racls,
-                                               const char *initacls, const 
char *initracls,
+                                               const char *acls, const char 
*acldefault,
                                                const char *owner,
                                                int remoteVersion,
                                                PQExpBuffer sql)
@@ -427,21 +420,12 @@ buildDefaultACLCommands(const char *type, const char 
*nspname,
        if (nspname)
                appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname));
 
-       if (strlen(initacls) != 0 || strlen(initracls) != 0)
-       {
-               appendPQExpBufferStr(sql, "SELECT 
pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
-               if (!buildACLCommands("", NULL, NULL, type,
-                                                         initacls, initracls, 
owner,
-                                                         prefix->data, 
remoteVersion, sql))
-               {
-                       destroyPQExpBuffer(prefix);
-                       return false;
-               }
-               appendPQExpBufferStr(sql, "SELECT 
pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
-       }
-
+       /*
+        * There's no such thing as initprivs for a default ACL, so the base ACL
+        * is always just the object-type-specific default.
+        */
        if (!buildACLCommands("", NULL, NULL, type,
-                                                 acls, racls, owner,
+                                                 acls, acldefault, owner,
                                                  prefix->data, remoteVersion, 
sql))
        {
                destroyPQExpBuffer(prefix);
@@ -491,7 +475,7 @@ parseAclItem(const char *item, const char *type,
        buf = pg_strdup(item);
 
        /* user or group name is string up to = */
-       eqpos = copyAclUserName(grantee, buf);
+       eqpos = dequoteAclUserName(grantee, buf);
        if (*eqpos != '=')
        {
                pg_free(buf);
@@ -503,7 +487,7 @@ parseAclItem(const char *item, const char *type,
        if (slpos)
        {
                *slpos++ = '\0';
-               slpos = copyAclUserName(grantor, slpos);
+               slpos = dequoteAclUserName(grantor, slpos);
                if (*slpos != '\0')
                {
                        pg_free(buf);
@@ -632,13 +616,46 @@ do { \
        return true;
 }
 
+/*
+ * Transfer the role name at *input into the output buffer, adding
+ * quoting according to the same rules as putid() in backend's acl.c.
+ */
+void
+quoteAclUserName(PQExpBuffer output, const char *input)
+{
+       const char *src;
+       bool            safe = true;
+
+       for (src = input; *src; src++)
+       {
+               /* This test had better match what putid() does */
+               if (!isalnum((unsigned char) *src) && *src != '_')
+               {
+                       safe = false;
+                       break;
+               }
+       }
+       if (!safe)
+               appendPQExpBufferChar(output, '"');
+       for (src = input; *src; src++)
+       {
+               /* A double quote character in a username is encoded as "" */
+               if (*src == '"')
+                       appendPQExpBufferChar(output, '"');
+               appendPQExpBufferChar(output, *src);
+       }
+       if (!safe)
+               appendPQExpBufferChar(output, '"');
+}
+
 /*
  * Transfer a user or group name starting at *input into the output buffer,
  * dequoting if needed.  Returns a pointer to just past the input name.
  * The name is taken to end at an unquoted '=' or end of string.
+ * Note: unlike quoteAclUserName(), this first clears the output buffer.
  */
 static char *
-copyAclUserName(PQExpBuffer output, char *input)
+dequoteAclUserName(PQExpBuffer output, char *input)
 {
        resetPQExpBuffer(output);
 
@@ -737,132 +754,6 @@ emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer 
buffer,
        }
 }
 
-/*
- * buildACLQueries
- *
- * Build the subqueries to extract out the correct set of ACLs to be
- * GRANT'd and REVOKE'd for the specific kind of object, accounting for any
- * initial privileges (from pg_init_privs) and based on if we are in binary
- * upgrade mode or not.
- *
- * Also builds subqueries to extract out the set of ACLs to go from the object
- * default privileges to the privileges in pg_init_privs, if we are in binary
- * upgrade mode, so that those privileges can be set up and recorded in the new
- * cluster before the regular privileges are added on top of those.
- */
-void
-buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer racl_subquery,
-                               PQExpBuffer init_acl_subquery, PQExpBuffer 
init_racl_subquery,
-                               const char *acl_column, const char *acl_owner,
-                               const char *obj_kind, bool binary_upgrade)
-{
-       /*
-        * To get the delta from what the permissions were at creation time
-        * (either initdb or CREATE EXTENSION) vs. what they are now, we have to
-        * look at two things:
-        *
-        * What privileges have been added, which we calculate by extracting all
-        * the current privileges (using the set of default privileges for the
-        * object type if current privileges are NULL) and then removing those
-        * which existed at creation time (again, using the set of default
-        * privileges for the object type if there were no creation time
-        * privileges).
-        *
-        * What privileges have been removed, which we calculate by extracting 
the
-        * privileges as they were at creation time (or the default privileges, 
as
-        * above), and then removing the current privileges (or the default
-        * privileges, if current privileges are NULL).
-        *
-        * As a good cross-check, both directions of these checks should result 
in
-        * the empty set if both the current ACL and the initial privs are NULL
-        * (meaning, in practice, that the default ACLs were there at init time
-        * and is what the current privileges are).
-        *
-        * We always perform this delta on all ACLs and expect that by the time
-        * these are run the initial privileges will be in place, even in a 
binary
-        * upgrade situation (see below).
-        *
-        * Finally, the order in which privileges are in the ACL string (the 
order
-        * they 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.
-        */
-       printfPQExpBuffer(acl_subquery,
-                                         "(SELECT pg_catalog.array_agg(acl 
ORDER BY row_n) FROM "
-                                         "(SELECT acl, row_n FROM "
-                                         
"pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) "
-                                         "WITH ORDINALITY AS perm(acl,row_n) "
-                                         "WHERE NOT EXISTS ( "
-                                         "SELECT 1 FROM "
-                                         
"pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) "
-                                         "AS init(init_acl) WHERE acl = 
init_acl)) as foo)",
-                                         acl_column,
-                                         obj_kind,
-                                         acl_owner,
-                                         obj_kind,
-                                         acl_owner);
-
-       printfPQExpBuffer(racl_subquery,
-                                         "(SELECT pg_catalog.array_agg(acl 
ORDER BY row_n) FROM "
-                                         "(SELECT acl, row_n FROM "
-                                         
"pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) "
-                                         "WITH ORDINALITY AS initp(acl,row_n) "
-                                         "WHERE NOT EXISTS ( "
-                                         "SELECT 1 FROM "
-                                         
"pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) "
-                                         "AS permp(orig_acl) WHERE acl = 
orig_acl)) as foo)",
-                                         obj_kind,
-                                         acl_owner,
-                                         acl_column,
-                                         obj_kind,
-                                         acl_owner);
-
-       /*
-        * In binary upgrade mode we don't run the extension script but instead
-        * dump out the objects independently and then recreate them.  To 
preserve
-        * the initial privileges which were set on extension objects, we need 
to
-        * grab the set of GRANT and REVOKE commands necessary to get from the
-        * default privileges of an object to the initial privileges as recorded
-        * in pg_init_privs.
-        *
-        * These will then be run ahead of the regular ACL commands, which were
-        * calculated using the queries above, inside of a block which sets a 
flag
-        * to indicate that the backend should record the results of these GRANT
-        * and REVOKE statements into pg_init_privs.  This is how we preserve 
the
-        * contents of that catalog across binary upgrades.
-        */
-       if (binary_upgrade)
-       {
-               printfPQExpBuffer(init_acl_subquery,
-                                                 "CASE WHEN privtype = 'e' 
THEN "
-                                                 "(SELECT 
pg_catalog.array_agg(acl ORDER BY row_n) FROM "
-                                                 "(SELECT acl, row_n FROM 
pg_catalog.unnest(pip.initprivs) "
-                                                 "WITH ORDINALITY AS 
initp(acl,row_n) "
-                                                 "WHERE NOT EXISTS ( "
-                                                 "SELECT 1 FROM "
-                                                 
"pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) "
-                                                 "AS privm(orig_acl) WHERE acl 
= orig_acl)) as foo) END",
-                                                 obj_kind,
-                                                 acl_owner);
-
-               printfPQExpBuffer(init_racl_subquery,
-                                                 "CASE WHEN privtype = 'e' 
THEN "
-                                                 "(SELECT 
pg_catalog.array_agg(acl) FROM "
-                                                 "(SELECT acl, row_n FROM "
-                                                 
"pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) "
-                                                 "WITH ORDINALITY AS 
privp(acl,row_n) "
-                                                 "WHERE NOT EXISTS ( "
-                                                 "SELECT 1 FROM 
pg_catalog.unnest(pip.initprivs) "
-                                                 "AS initp(init_acl) WHERE acl 
= init_acl)) as foo) END",
-                                                 obj_kind,
-                                                 acl_owner);
-       }
-       else
-       {
-               printfPQExpBuffer(init_acl_subquery, "NULL");
-               printfPQExpBuffer(init_racl_subquery, "NULL");
-       }
-}
 
 /*
  * Detect whether the given GUC variable is of GUC_LIST_QUOTE type.
diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h
index 2dc6b38992b..cf6f89c6074 100644
--- a/src/bin/pg_dump/dumputils.h
+++ b/src/bin/pg_dump/dumputils.h
@@ -37,25 +37,22 @@
 
 extern char *sanitize_line(const char *str, bool want_hyphen);
 extern bool buildACLCommands(const char *name, const char *subname, const char 
*nspname,
-                                                        const char *type, 
const char *acls, const char *racls,
+                                                        const char *type, 
const char *acls, const char *baseacls,
                                                         const char *owner, 
const char *prefix, int remoteVersion,
                                                         PQExpBuffer sql);
 extern bool buildDefaultACLCommands(const char *type, const char *nspname,
-                                                                       const 
char *acls, const char *racls,
-                                                                       const 
char *initacls, const char *initracls,
+                                                                       const 
char *acls, const char *acldefault,
                                                                        const 
char *owner,
                                                                        int 
remoteVersion,
                                                                        
PQExpBuffer sql);
+
+extern void quoteAclUserName(PQExpBuffer output, const char *input);
+
 extern void buildShSecLabelQuery(const char *catalog_name,
                                                                 Oid objectId, 
PQExpBuffer sql);
 extern void emitShSecLabels(PGconn *conn, PGresult *res,
                                                        PQExpBuffer buffer, 
const char *objtype, const char *objname);
 
-extern void buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer 
racl_subquery,
-                                                       PQExpBuffer 
init_acl_subquery, PQExpBuffer init_racl_subquery,
-                                                       const char *acl_column, 
const char *acl_owner,
-                                                       const char *obj_kind, 
bool binary_upgrade);
-
 extern bool variable_is_guc_list_quote(const char *name);
 
 extern bool SplitGUCList(char *rawstring, char separator,
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index a44b8bd8192..0b14c04097e 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -219,6 +219,7 @@ static void guessConstraintInheritance(TableInfo *tblinfo, 
int numTables);
 static void dumpComment(Archive *fout, const char *type, const char *name,
                                                const char *namespace, const 
char *owner,
                                                CatalogId catalogId, int subid, 
DumpId dumpId);
+static void getAdditionalACLs(Archive *fout);
 static int     findComments(Archive *fout, Oid classoid, Oid objoid,
                                                 CommentItem **items);
 static void collectComments(Archive *fout);
@@ -283,8 +284,7 @@ static void dumpDefaultACL(Archive *fout, const 
DefaultACLInfo *daclinfo);
 static DumpId dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId,
                                          const char *type, const char *name, 
const char *subname,
                                          const char *nspname, const char 
*owner,
-                                         const char *acls, const char *racls,
-                                         const char *initacls, const char 
*initracls);
+                                         const DumpableAcl *dacl);
 
 static void getDependencies(Archive *fout);
 static void BuildArchiveDependencies(Archive *fout);
@@ -1142,8 +1142,10 @@ main(int argc, char **argv)
        setExtPartDependency(tblinfo, numTables);
 
        /*
-        * Collect comments and security labels, if wanted.
+        * Collect ACLs, comments, and security labels, if wanted.
         */
+       if (!dopt.aclsSkip)
+               getAdditionalACLs(fout);
        if (!dopt.no_comments)
                collectComments(fout);
        if (!dopt.no_security_labels)
@@ -2034,7 +2036,7 @@ selectDumpableNamespace(NamespaceInfo *nsinfo, Archive 
*fout)
                /*
                 * Also, make like it has a comment even if it doesn't; this is 
so
                 * that we'll emit a command to drop the comment, if 
appropriate.
-                * (Without this, we'd not call dumpCommentExtended for it.)
+                * (Without this, we'd not call dumpComment for it.)
                 */
                nsinfo->dobj.components |= DUMP_COMPONENT_COMMENT;
        }
@@ -3387,19 +3389,18 @@ dumpDatabase(Archive *fout)
                                i_frozenxid,
                                i_minmxid,
                                i_datacl,
-                               i_rdatacl,
+                               i_acldefault,
                                i_datistemplate,
                                i_datconnlimit,
                                i_tablespace;
        CatalogId       dbCatId;
        DumpId          dbDumpId;
+       DumpableAcl dbdacl;
        const char *datname,
                           *dba,
                           *encoding,
                           *collate,
                           *ctype,
-                          *datacl,
-                          *rdatacl,
                           *datistemplate,
                           *datconnlimit,
                           *tablespace;
@@ -3411,40 +3412,14 @@ dumpDatabase(Archive *fout)
 
        /*
         * 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)
+       if (fout->remoteVersion >= 90300)
        {
                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 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 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, "
+                                                 "datacl, acldefault('d', 
datdba) AS acldefault, "
                                                  "datistemplate, datconnlimit, 
"
                                                  "(SELECT spcname FROM 
pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
                                                  "shobj_description(oid, 
'pg_database') AS description "
@@ -3453,13 +3428,14 @@ dumpDatabase(Archive *fout)
                                                  "WHERE datname = 
current_database()",
                                                  username_subquery);
        }
-       else if (fout->remoteVersion >= 90300)
+       else if (fout->remoteVersion >= 90200)
        {
                appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
                                                  "(%s datdba) AS dba, "
                                                  
"pg_encoding_to_char(encoding) AS encoding, "
-                                                 "datcollate, datctype, 
datfrozenxid, datminmxid, "
-                                                 "datacl, '' as rdatacl, 
datistemplate, datconnlimit, "
+                                                 "datcollate, datctype, 
datfrozenxid, 0 AS datminmxid, "
+                                                 "datacl, acldefault('d', 
datdba) AS acldefault, "
+                                                 "datistemplate, datconnlimit, 
"
                                                  "(SELECT spcname FROM 
pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
                                                  "shobj_description(oid, 
'pg_database') AS description "
 
@@ -3473,7 +3449,8 @@ dumpDatabase(Archive *fout)
                                                  "(%s datdba) AS dba, "
                                                  
"pg_encoding_to_char(encoding) AS encoding, "
                                                  "datcollate, datctype, 
datfrozenxid, 0 AS datminmxid, "
-                                                 "datacl, '' as rdatacl, 
datistemplate, datconnlimit, "
+                                                 "datacl, NULL AS acldefault, "
+                                                 "datistemplate, datconnlimit, 
"
                                                  "(SELECT spcname FROM 
pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
                                                  "shobj_description(oid, 
'pg_database') AS description "
 
@@ -3487,7 +3464,8 @@ dumpDatabase(Archive *fout)
                                                  "(%s datdba) AS dba, "
                                                  
"pg_encoding_to_char(encoding) AS encoding, "
                                                  "NULL AS datcollate, NULL AS 
datctype, datfrozenxid, 0 AS datminmxid, "
-                                                 "datacl, '' as rdatacl, 
datistemplate, datconnlimit, "
+                                                 "datacl, NULL AS acldefault, "
+                                                 "datistemplate, datconnlimit, 
"
                                                  "(SELECT spcname FROM 
pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
                                                  "shobj_description(oid, 
'pg_database') AS description "
 
@@ -3508,7 +3486,7 @@ dumpDatabase(Archive *fout)
        i_frozenxid = PQfnumber(res, "datfrozenxid");
        i_minmxid = PQfnumber(res, "datminmxid");
        i_datacl = PQfnumber(res, "datacl");
-       i_rdatacl = PQfnumber(res, "rdatacl");
+       i_acldefault = PQfnumber(res, "acldefault");
        i_datistemplate = PQfnumber(res, "datistemplate");
        i_datconnlimit = PQfnumber(res, "datconnlimit");
        i_tablespace = PQfnumber(res, "tablespace");
@@ -3522,8 +3500,8 @@ dumpDatabase(Archive *fout)
        ctype = PQgetvalue(res, 0, i_ctype);
        frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid));
        minmxid = atooid(PQgetvalue(res, 0, i_minmxid));
-       datacl = PQgetvalue(res, 0, i_datacl);
-       rdatacl = PQgetvalue(res, 0, i_rdatacl);
+       dbdacl.acl = PQgetvalue(res, 0, i_datacl);
+       dbdacl.acldefault = PQgetvalue(res, 0, i_acldefault);
        datistemplate = PQgetvalue(res, 0, i_datistemplate);
        datconnlimit = PQgetvalue(res, 0, i_datconnlimit);
        tablespace = PQgetvalue(res, 0, i_tablespace);
@@ -3647,9 +3625,12 @@ dumpDatabase(Archive *fout)
         * Dump ACL if any.  Note that we do not support initial privileges
         * (pg_init_privs) on databases.
         */
+       dbdacl.privtype = 0;
+       dbdacl.initprivs = NULL;
+
        dumpACL(fout, dbDumpId, InvalidDumpId, "DATABASE",
                        qdatname, NULL, NULL,
-                       dba, datacl, rdatacl, "", "");
+                       dba, &dbdacl);
 
        /*
         * Now construct a DATABASE PROPERTIES archive entry to restore any
@@ -3988,59 +3969,30 @@ getBlobs(Archive *fout)
        int                     i_oid;
        int                     i_lomowner;
        int                     i_lomacl;
-       int                     i_rlomacl;
-       int                     i_initlomacl;
-       int                     i_initrlomacl;
+       int                     i_acldefault;
 
        pg_log_info("reading large objects");
 
        /* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */
-       if (fout->remoteVersion >= 90600)
+       if (fout->remoteVersion >= 90200)
        {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer init_acl_subquery = createPQExpBuffer();
-               PQExpBuffer init_racl_subquery = createPQExpBuffer();
-
-               buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery,
-                                               init_racl_subquery, "l.lomacl", 
"l.lomowner", "'L'",
-                                               dopt->binary_upgrade);
-
                appendPQExpBuffer(blobQry,
-                                                 "SELECT l.oid, (%s 
l.lomowner) AS rolname, "
-                                                 "%s AS lomacl, "
-                                                 "%s AS rlomacl, "
-                                                 "%s AS initlomacl, "
-                                                 "%s AS initrlomacl "
-                                                 "FROM pg_largeobject_metadata 
l "
-                                                 "LEFT JOIN pg_init_privs pip 
ON "
-                                                 "(l.oid = pip.objoid "
-                                                 "AND pip.classoid = 
'pg_largeobject'::regclass "
-                                                 "AND pip.objsubid = 0) ",
-                                                 username_subquery,
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 init_acl_subquery->data,
-                                                 init_racl_subquery->data);
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(init_acl_subquery);
-               destroyPQExpBuffer(init_racl_subquery);
+                                                 "SELECT oid, (%s lomowner) AS 
rolname, lomacl, "
+                                                 "acldefault('L', lomowner) AS 
acldefault "
+                                                 "FROM 
pg_largeobject_metadata",
+                                                 username_subquery);
        }
        else if (fout->remoteVersion >= 90000)
                appendPQExpBuffer(blobQry,
                                                  "SELECT oid, (%s lomowner) AS 
rolname, lomacl, "
-                                                 "NULL AS rlomacl, NULL AS 
initlomacl, "
-                                                 "NULL AS initrlomacl "
-                                                 " FROM 
pg_largeobject_metadata",
+                                                 "NULL AS acldefault "
+                                                 "FROM 
pg_largeobject_metadata",
                                                  username_subquery);
        else
                appendPQExpBufferStr(blobQry,
                                                         "SELECT DISTINCT loid 
AS oid, "
                                                         "NULL::name AS 
rolname, NULL::oid AS lomacl, "
-                                                        "NULL::oid AS rlomacl, 
NULL::oid AS initlomacl, "
-                                                        "NULL::oid AS 
initrlomacl "
+                                                        "NULL::oid AS 
acldefault "
                                                         " FROM 
pg_largeobject");
 
        res = ExecuteSqlQuery(fout, blobQry->data, PGRES_TUPLES_OK);
@@ -4048,9 +4000,7 @@ getBlobs(Archive *fout)
        i_oid = PQfnumber(res, "oid");
        i_lomowner = PQfnumber(res, "rolname");
        i_lomacl = PQfnumber(res, "lomacl");
-       i_rlomacl = PQfnumber(res, "rlomacl");
-       i_initlomacl = PQfnumber(res, "initlomacl");
-       i_initrlomacl = PQfnumber(res, "initrlomacl");
+       i_acldefault = PQfnumber(res, "acldefault");
 
        ntups = PQntuples(res);
 
@@ -4067,20 +4017,17 @@ getBlobs(Archive *fout)
                AssignDumpId(&binfo[i].dobj);
 
                binfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oid));
+               binfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_lomacl));
+               binfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               binfo[i].dacl.privtype = 0;
+               binfo[i].dacl.initprivs = NULL;
                binfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_lomowner));
-               binfo[i].blobacl = pg_strdup(PQgetvalue(res, i, i_lomacl));
-               binfo[i].rblobacl = pg_strdup(PQgetvalue(res, i, i_rlomacl));
-               binfo[i].initblobacl = pg_strdup(PQgetvalue(res, i, 
i_initlomacl));
-               binfo[i].initrblobacl = pg_strdup(PQgetvalue(res, i, 
i_initrlomacl));
 
                /* Blobs have data */
                binfo[i].dobj.components |= DUMP_COMPONENT_DATA;
 
                /* Mark whether blob has an ACL */
-               if (!(PQgetisnull(res, i, i_lomacl) &&
-                         PQgetisnull(res, i, i_rlomacl) &&
-                         PQgetisnull(res, i, i_initlomacl) &&
-                         PQgetisnull(res, i, i_initrlomacl)))
+               if (!PQgetisnull(res, i, i_lomacl))
                        binfo[i].dobj.components |= DUMP_COMPONENT_ACL;
 
                /*
@@ -4156,8 +4103,7 @@ dumpBlob(Archive *fout, const BlobInfo *binfo)
        if (binfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, binfo->dobj.dumpId, InvalidDumpId, "LARGE OBJECT",
                                binfo->dobj.name, NULL,
-                               NULL, binfo->rolname, binfo->blobacl, 
binfo->rblobacl,
-                               binfo->initblobacl, binfo->initrblobacl);
+                               NULL, binfo->rolname, &binfo->dacl);
 
        destroyPQExpBuffer(cquery);
        destroyPQExpBuffer(dquery);
@@ -5796,7 +5742,6 @@ binary_upgrade_extension_member(PQExpBuffer 
upgrade_buffer,
 NamespaceInfo *
 getNamespaces(Archive *fout, int *numNamespaces)
 {
-       DumpOptions *dopt = fout->dopt;
        PGresult   *res;
        int                     ntups;
        int                     i;
@@ -5807,9 +5752,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
        int                     i_nspname;
        int                     i_rolname;
        int                     i_nspacl;
-       int                     i_rnspacl;
-       int                     i_initnspacl;
-       int                     i_initrnspacl;
+       int                     i_acldefault;
 
        query = createPQExpBuffer();
 
@@ -5817,48 +5760,18 @@ getNamespaces(Archive *fout, int *numNamespaces)
         * we fetch all namespaces including system ones, so that every object 
we
         * read in can be linked to a containing namespace.
         */
-       if (fout->remoteVersion >= 90600)
-       {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer init_acl_subquery = createPQExpBuffer();
-               PQExpBuffer init_racl_subquery = createPQExpBuffer();
-
-               buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery,
-                                               init_racl_subquery, "n.nspacl", 
"n.nspowner", "'n'",
-                                               dopt->binary_upgrade);
-
+       if (fout->remoteVersion >= 90200)
                appendPQExpBuffer(query, "SELECT n.tableoid, n.oid, n.nspname, "
                                                  "(%s nspowner) AS rolname, "
-                                                 "%s as nspacl, "
-                                                 "%s as rnspacl, "
-                                                 "%s as initnspacl, "
-                                                 "%s as initrnspacl "
-                                                 "FROM pg_namespace n "
-                                                 "LEFT JOIN pg_init_privs pip "
-                                                 "ON (n.oid = pip.objoid "
-                                                 "AND pip.classoid = 
'pg_namespace'::regclass "
-                                                 "AND pip.objsubid = 0",
-                                                 username_subquery,
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 init_acl_subquery->data,
-                                                 init_racl_subquery->data);
-
-               appendPQExpBufferStr(query, ") ");
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(init_acl_subquery);
-               destroyPQExpBuffer(init_racl_subquery);
-       }
-       else
-               appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, "
-                                                 "(%s nspowner) AS rolname, "
-                                                 "nspacl, NULL as rnspacl, "
-                                                 "NULL AS initnspacl, NULL as 
initrnspacl "
-                                                 "FROM pg_namespace",
+                                                 "n.nspacl, "
+                                                 "acldefault('n', n.nspowner) 
AS acldefault "
+                                                 "FROM pg_namespace n",
                                                  username_subquery);
+       else
+               appendPQExpBuffer(query, "SELECT n.tableoid, n.oid, n.nspname, "
+                                                 "n.nspowner, "
+                                                 "n.nspacl, NULL AS acldefault 
"
+                                                 "FROM pg_namespace n");
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
@@ -5871,9 +5784,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
        i_nspname = PQfnumber(res, "nspname");
        i_rolname = PQfnumber(res, "rolname");
        i_nspacl = PQfnumber(res, "nspacl");
-       i_rnspacl = PQfnumber(res, "rnspacl");
-       i_initnspacl = PQfnumber(res, "initnspacl");
-       i_initrnspacl = PQfnumber(res, "initrnspacl");
+       i_acldefault = PQfnumber(res, "acldefault");
 
        for (i = 0; i < ntups; i++)
        {
@@ -5882,22 +5793,21 @@ getNamespaces(Archive *fout, int *numNamespaces)
                nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
                AssignDumpId(&nsinfo[i].dobj);
                nsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_nspname));
+               nsinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_nspacl));
+               nsinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               nsinfo[i].dacl.privtype = 0;
+               nsinfo[i].dacl.initprivs = NULL;
                nsinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
-               nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl));
-               nsinfo[i].rnspacl = pg_strdup(PQgetvalue(res, i, i_rnspacl));
-               nsinfo[i].initnspacl = pg_strdup(PQgetvalue(res, i, 
i_initnspacl));
-               nsinfo[i].initrnspacl = pg_strdup(PQgetvalue(res, i, 
i_initrnspacl));
 
                /* Decide whether to dump this namespace */
                selectDumpableNamespace(&nsinfo[i], fout);
 
                /* Mark whether namespace has an ACL */
-               if (!(PQgetisnull(res, i, i_nspacl) &&
-                         PQgetisnull(res, i, i_rnspacl) &&
-                         PQgetisnull(res, i, i_initnspacl) &&
-                         PQgetisnull(res, i, i_initrnspacl)))
+               if (!PQgetisnull(res, i, i_nspacl))
                        nsinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
 
+
+
                if (strlen(nsinfo[i].rolname) == 0)
                        pg_log_warning("owner of schema \"%s\" appears to be 
invalid",
                                                   nsinfo[i].dobj.name);
@@ -6036,7 +5946,6 @@ getBinaryUpgradeObjects(void)
 TypeInfo *
 getTypes(Archive *fout, int *numTypes)
 {
-       DumpOptions *dopt = fout->dopt;
        PGresult   *res;
        int                     ntups;
        int                     i;
@@ -6048,9 +5957,7 @@ getTypes(Archive *fout, int *numTypes)
        int                     i_typname;
        int                     i_typnamespace;
        int                     i_typacl;
-       int                     i_rtypacl;
-       int                     i_inittypacl;
-       int                     i_initrtypacl;
+       int                     i_acldefault;
        int                     i_rolname;
        int                     i_typelem;
        int                     i_typrelid;
@@ -6074,25 +5981,13 @@ getTypes(Archive *fout, int *numTypes)
         * still check for name beginning with '_', though, so as to avoid the
         * cost of the subselect probe for all standard types.  This would have 
to
         * be revisited if the backend ever allows renaming of array types.
+        * 
         */
-
-       if (fout->remoteVersion >= 90600)
+       if (fout->remoteVersion >= 90200)
        {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
-
-               buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
-                                               initracl_subquery, "t.typacl", 
"t.typowner", "'T'",
-                                               dopt->binary_upgrade);
-
                appendPQExpBuffer(query, "SELECT t.tableoid, t.oid, t.typname, "
-                                                 "t.typnamespace, "
-                                                 "%s AS typacl, "
-                                                 "%s AS rtypacl, "
-                                                 "%s AS inittypacl, "
-                                                 "%s AS initrtypacl, "
+                                                 "t.typnamespace, t.typacl, "
+                                                 "acldefault('T', t.typowner) 
AS acldefault, "
                                                  "(%s t.typowner) AS rolname, "
                                                  "t.typelem, t.typrelid, "
                                                  "CASE WHEN t.typrelid = 0 
THEN ' '::\"char\" "
@@ -6102,50 +5997,24 @@ getTypes(Archive *fout, int *numTypes)
                                                  "(SELECT typarray FROM 
pg_type te WHERE oid = t.typelem) = t.oid AS isarray, "
                                                        
"coalesce(array_to_string(e.typoptions, ', '), '') AS typstorage "
                                                  "FROM pg_type t "
-                                                       "LEFT JOIN 
pg_type_encoding e ON t.oid = e.typid "
-                                                 "LEFT JOIN pg_init_privs pip 
ON "
-                                                 "(t.oid = pip.objoid "
-                                                 "AND pip.classoid = 
'pg_type'::regclass "
-                                                 "AND pip.objsubid = 0) ",
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 initacl_subquery->data,
-                                                 initracl_subquery->data,
-                                                 username_subquery);
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
-       }
-       else if (fout->remoteVersion >= 90200)
-       {
-               appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
-                                                 "typnamespace, typacl, NULL 
as rtypacl, "
-                                                 "NULL AS inittypacl, NULL AS 
initrtypacl, "
-                                                 "(%s typowner) AS rolname, "
-                                                 "typelem, typrelid, "
-                                                 "CASE WHEN typrelid = 0 THEN 
' '::\"char\" "
-                                                 "ELSE (SELECT relkind FROM 
pg_class WHERE oid = typrelid) END AS typrelkind, "
-                                                 "typtype, typisdefined, "
-                                                 "typname[0] = '_' AND typelem 
!= 0 AND "
-                                                 "(SELECT typarray FROM 
pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
-                                                 "FROM pg_type",
+                                                       "LEFT JOIN 
pg_type_encoding e ON t.oid = e.typid ",
                                                  username_subquery);
        }
        else
        {
-               appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
-                                                 "typnamespace, NULL AS 
typacl, NULL as rtypacl, "
-                                                 "NULL AS inittypacl, NULL AS 
initrtypacl, "
-                                                 "(%s typowner) AS rolname, "
-                                                 "typelem, typrelid, "
-                                                 "CASE WHEN typrelid = 0 THEN 
' '::\"char\" "
-                                                 "ELSE (SELECT relkind FROM 
pg_class WHERE oid = typrelid) END AS typrelkind, "
-                                                 "typtype, typisdefined, "
-                                                 "typname[0] = '_' AND typelem 
!= 0 AND "
-                                                 "(SELECT typarray FROM 
pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
-                                                 "FROM pg_type",
+               appendPQExpBuffer(query, "SELECT t.tableoid, t.oid, t.typname, "
+                                                 "t.typnamespace, t.typacl, "
+                                                 "NULL AS acldefault, "
+                                                 "(%s t.typowner) AS rolname, "
+                                                 "t.typelem, t.typrelid, "
+                                                 "CASE WHEN t.typrelid = 0 
THEN ' '::\"char\" "
+                                                 "ELSE (SELECT relkind FROM 
pg_class WHERE oid = t.typrelid) END AS typrelkind, "
+                                                 "t.typtype, t.typisdefined, "
+                                                 "t.typname[0] = '_' AND 
t.typelem != 0 AND "
+                                                 "(SELECT typarray FROM 
pg_type te WHERE oid = t.typelem) = t.oid AS isarray, "
+                                                       
"coalesce(array_to_string(e.typoptions, ', '), '') AS typstorage "
+                                                 "FROM pg_type t "
+                                                       "LEFT JOIN 
pg_type_encoding e ON t.oid = e.typid ",
                                                  username_subquery);
        }
 
@@ -6160,9 +6029,7 @@ getTypes(Archive *fout, int *numTypes)
        i_typname = PQfnumber(res, "typname");
        i_typnamespace = PQfnumber(res, "typnamespace");
        i_typacl = PQfnumber(res, "typacl");
-       i_rtypacl = PQfnumber(res, "rtypacl");
-       i_inittypacl = PQfnumber(res, "inittypacl");
-       i_initrtypacl = PQfnumber(res, "initrtypacl");
+       i_acldefault = PQfnumber(res, "acldefault");
        i_rolname = PQfnumber(res, "rolname");
        i_typelem = PQfnumber(res, "typelem");
        i_typrelid = PQfnumber(res, "typrelid");
@@ -6181,12 +6048,12 @@ getTypes(Archive *fout, int *numTypes)
                tyinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_typname));
                tyinfo[i].dobj.namespace =
                        findNamespace(atooid(PQgetvalue(res, i, 
i_typnamespace)));
+               tyinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_typacl));
+               tyinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               tyinfo[i].dacl.privtype = 0;
+               tyinfo[i].dacl.initprivs = NULL;
                tyinfo[i].ftypname = NULL;      /* may get filled later */
                tyinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
-               tyinfo[i].typacl = pg_strdup(PQgetvalue(res, i, i_typacl));
-               tyinfo[i].rtypacl = pg_strdup(PQgetvalue(res, i, i_rtypacl));
-               tyinfo[i].inittypacl = pg_strdup(PQgetvalue(res, i, 
i_inittypacl));
-               tyinfo[i].initrtypacl = pg_strdup(PQgetvalue(res, i, 
i_initrtypacl));
                tyinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
                tyinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
                tyinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
@@ -6214,10 +6081,7 @@ getTypes(Archive *fout, int *numTypes)
                selectDumpableType(&tyinfo[i], fout);
 
                /* Mark whether type has an ACL */
-               if (!(PQgetisnull(res, i, i_typacl) &&
-                         PQgetisnull(res, i, i_rtypacl) &&
-                         PQgetisnull(res, i, i_inittypacl) &&
-                         PQgetisnull(res, i, i_initrtypacl)))
+               if (!PQgetisnull(res, i, i_typacl))
                        tyinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
 
                /*
@@ -6744,9 +6608,7 @@ getAggregates(Archive *fout, int *numAggs)
        int                     i_proargtypes;
        int                     i_rolname;
        int                     i_aggacl;
-       int                     i_raggacl;
-       int                     i_initaggacl;
-       int                     i_initraggacl;
+       int                     i_acldefault;
 
        /*
         * Find all interesting aggregates.  See comment in getFuncs() for the
@@ -6754,16 +6616,8 @@ getAggregates(Archive *fout, int *numAggs)
         */
        if (fout->remoteVersion >= 90600)
        {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
                const char *agg_check;
 
-               buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
-                                               initracl_subquery, "p.proacl", 
"p.proowner", "'f'",
-                                               dopt->binary_upgrade);
-
                agg_check = (fout->remoteVersion >= 110000 ? "p.prokind = 'a'"
                                         : "p.proisagg");
 
@@ -6772,10 +6626,8 @@ getAggregates(Archive *fout, int *numAggs)
                                                  "p.pronamespace AS 
aggnamespace, "
                                                  "p.pronargs, p.proargtypes, "
                                                  "(%s p.proowner) AS rolname, "
-                                                 "%s AS aggacl, "
-                                                 "%s AS raggacl, "
-                                                 "%s AS initaggacl, "
-                                                 "%s AS initraggacl "
+                                                 "p.proacl AS aggacl, "
+                                                 "acldefault('f', p.proowner) 
AS acldefault "
                                                  "FROM pg_proc p "
                                                  "LEFT JOIN pg_init_privs pip 
ON "
                                                  "(p.oid = pip.objoid "
@@ -6787,10 +6639,6 @@ getAggregates(Archive *fout, int *numAggs)
                                                  "WHERE nspname = 
'pg_catalog') OR "
                                                  "p.proacl IS DISTINCT FROM 
pip.initprivs",
                                                  username_subquery,
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 initacl_subquery->data,
-                                                 initracl_subquery->data,
                                                  agg_check);
                if (dopt->binary_upgrade)
                        appendPQExpBufferStr(query,
@@ -6800,11 +6648,29 @@ getAggregates(Archive *fout, int *numAggs)
                                                                 "refclassid = 
'pg_extension'::regclass AND "
                                                                 "deptype = 
'e')");
                appendPQExpBufferChar(query, ')');
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
+       }
+       else if (fout->remoteVersion >= 90200)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS 
aggname, "
+                                                 "pronamespace AS 
aggnamespace, "
+                                                 "pronargs, proargtypes, "
+                                                 "(%s proowner) AS rolname, "
+                                                 "proacl AS aggacl, "
+                                                 "acldefault('f', proowner) AS 
acldefault "
+                                                 "FROM pg_proc p "
+                                                 "WHERE proisagg AND ("
+                                                 "pronamespace != "
+                                                 "(SELECT oid FROM 
pg_namespace "
+                                                 "WHERE nspname = 
'pg_catalog')",
+                                                 username_subquery);
+               if (dopt->binary_upgrade)
+                       appendPQExpBufferStr(query,
+                                                                " OR 
EXISTS(SELECT 1 FROM pg_depend WHERE "
+                                                                "classid = 
'pg_proc'::regclass AND "
+                                                                "objid = p.oid 
AND "
+                                                                "refclassid = 
'pg_extension'::regclass AND "
+                                                                "deptype = 
'e')");
+               appendPQExpBufferChar(query, ')');
        }
        else
        {
@@ -6813,8 +6679,7 @@ getAggregates(Archive *fout, int *numAggs)
                                                  "pronargs, proargtypes, "
                                                  "(%s proowner) AS rolname, "
                                                  "proacl AS aggacl, "
-                                                 "NULL AS raggacl, "
-                                                 "NULL AS initaggacl, NULL AS 
initraggacl "
+                                                 "NULL AS acldefault "
                                                  "FROM pg_proc p "
                                                  "WHERE proisagg AND ("
                                                  "pronamespace != "
@@ -6846,9 +6711,7 @@ getAggregates(Archive *fout, int *numAggs)
        i_proargtypes = PQfnumber(res, "proargtypes");
        i_rolname = PQfnumber(res, "rolname");
        i_aggacl = PQfnumber(res, "aggacl");
-       i_raggacl = PQfnumber(res, "raggacl");
-       i_initaggacl = PQfnumber(res, "initaggacl");
-       i_initraggacl = PQfnumber(res, "initraggacl");
+       i_acldefault = PQfnumber(res, "acldefault");
 
        for (i = 0; i < ntups; i++)
        {
@@ -6859,16 +6722,16 @@ getAggregates(Archive *fout, int *numAggs)
                agginfo[i].aggfn.dobj.name = pg_strdup(PQgetvalue(res, i, 
i_aggname));
                agginfo[i].aggfn.dobj.namespace =
                        findNamespace(atooid(PQgetvalue(res, i, 
i_aggnamespace)));
+               agginfo[i].aggfn.dacl.acl = pg_strdup(PQgetvalue(res, i, 
i_aggacl));
+               agginfo[i].aggfn.dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               agginfo[i].aggfn.dacl.privtype = 0;
+               agginfo[i].aggfn.dacl.initprivs = NULL;
                agginfo[i].aggfn.rolname = pg_strdup(PQgetvalue(res, i, 
i_rolname));
                if (strlen(agginfo[i].aggfn.rolname) == 0)
                        pg_log_warning("owner of aggregate function \"%s\" 
appears to be invalid",
                                                   agginfo[i].aggfn.dobj.name);
                agginfo[i].aggfn.lang = InvalidOid; /* not currently 
interesting */
                agginfo[i].aggfn.prorettype = InvalidOid;       /* not saved */
-               agginfo[i].aggfn.proacl = pg_strdup(PQgetvalue(res, i, 
i_aggacl));
-               agginfo[i].aggfn.rproacl = pg_strdup(PQgetvalue(res, i, 
i_raggacl));
-               agginfo[i].aggfn.initproacl = pg_strdup(PQgetvalue(res, i, 
i_initaggacl));
-               agginfo[i].aggfn.initrproacl = pg_strdup(PQgetvalue(res, i, 
i_initraggacl));
                agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
                if (agginfo[i].aggfn.nargs == 0)
                        agginfo[i].aggfn.argtypes = NULL;
@@ -6884,10 +6747,7 @@ getAggregates(Archive *fout, int *numAggs)
                selectDumpableObject(&(agginfo[i].aggfn.dobj), fout);
 
                /* Mark whether aggregate has an ACL */
-               if (!(PQgetisnull(res, i, i_aggacl) &&
-                         PQgetisnull(res, i, i_raggacl) &&
-                         PQgetisnull(res, i, i_initaggacl) &&
-                         PQgetisnull(res, i, i_initraggacl)))
+               if (!PQgetisnull(res, i, i_aggacl))
                        agginfo[i].aggfn.dobj.components |= DUMP_COMPONENT_ACL;
        }
 
@@ -6919,72 +6779,40 @@ getExtProtocols(Archive *fout, int *numExtProtocols)
        int                     i_ptcname;
        int                     i_rolname;
        int                     i_ptcacl;
-       int                     i_ptcracl;
-       int                     i_ptcinitacl;
-       int                     i_ptcinitracl;
+       int                     i_acldefault;
        int                     i_ptctrusted;
        int             i_ptcreadid;
        int                     i_ptcwriteid;
        int                     i_ptcvalidid;
 
        /* find all user-defined external protocol */
-
-
-       if (fout->remoteVersion >= 90600)
+       if (fout->remoteVersion >= 90200)
        {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
-
-               buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
-                                               initracl_subquery, 
"ptc.ptcacl", "ptc.ptcowner", "'E'",
-                                               fout->dopt->binary_upgrade);
-
-               appendPQExpBuffer(query, "SELECT ptc.tableoid as tableoid, "
-                                                                "       
ptc.oid as oid, "
-                                                                "       
ptc.ptcname as ptcname, "
-                                                                "       
ptcreadfn as ptcreadoid, "
-                                                                "       
ptcwritefn as ptcwriteoid, "
-                                                                "              
 ptcvalidatorfn as ptcvaloid, "
-                                                                "       (%s 
ptc.ptcowner) as rolname, "
-                                                                "       
ptc.ptctrusted as ptctrusted, "
-                                                                "       %s AS 
ptcacl, "
-                                                                "       %s AS 
ptcracl, "
-                                                                "       %s AS 
ptcinitacl, "
-                                                                "       %s AS 
ptcinitracl "
-                                                                "FROM   
pg_extprotocol ptc "
-                                                                "LEFT JOIN 
pg_init_privs pip ON "
-                                                                "              
 (ptc.oid = pip.objoid "
-                                                                "              
 AND pip.classoid = 'pg_extprotocol'::regclass "
-                                                                "              
 AND pip.objsubid = 0)",
-                                                                               
 username_subquery,
-                                                                               
 acl_subquery->data,
-                                                                               
 racl_subquery->data,
-                                                                               
 initacl_subquery->data,
-                                                                               
 initracl_subquery->data);
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
+               appendPQExpBuffer(query, "SELECT tableoid, "
+                                                                "oid, "
+                                                                "ptcname, "
+                                                                "ptcreadfn as 
ptcreadoid, "
+                                                                "ptcwritefn as 
ptcwriteoid, "
+                                                                
"ptcvalidatorfn as ptcvaloid, "
+                                                                "(%s ptcowner) 
as rolname, "
+                                                                "ptctrusted, 
ptcacl, "
+                                                                
"acldefault('E', ptcowner) AS acldefault "
+                                                                "FROM 
pg_extprotocol ", 
+                                                                
username_subquery);
        }
        else
        {
-               appendPQExpBuffer(query, "SELECT ptc.tableoid as tableoid, "
-                                                                "       
ptc.oid as oid, "
-                                                                "       
ptc.ptcname as ptcname, "
-                                                                "       
ptcreadfn as ptcreadoid, "
-                                                                "       
ptcwritefn as ptcwriteoid, "
-                                                                "              
 ptcvalidatorfn as ptcvaloid, "
-                                                                "       (%s 
ptc.ptcowner) as rolname, "
-                                                                "       
ptc.ptctrusted as ptctrusted, "
-                                                                "       
ptc.ptcacl as ptcacl, "
-                                                                "       NULL 
as ptcracl, "
-                                                                "       NULL 
as ptcinitacl, "
-                                                                "       NULL 
as ptcinitracl "
-                                                                "FROM   
pg_extprotocol ptc",
-                                                                               
 username_subquery);
+               appendPQExpBuffer(query, "SELECT tableoid, "
+                                                                "oid, "
+                                                                "ptcname, "
+                                                                "ptcreadfn as 
ptcreadoid, "
+                                                                "ptcwritefn as 
ptcwriteoid, "
+                                                                
"ptcvalidatorfn as ptcvaloid, "
+                                                                "(%s ptcowner) 
as rolname, "
+                                                                "ptctrusted, 
ptcacl, "
+                                                                "NULL AS 
acldefault "
+                                                                "FROM 
pg_extprotocol ", 
+                                                                
username_subquery);
        }
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -6999,9 +6827,7 @@ getExtProtocols(Archive *fout, int *numExtProtocols)
        i_ptcname = PQfnumber(res, "ptcname");
        i_rolname = PQfnumber(res, "rolname");
        i_ptcacl = PQfnumber(res, "ptcacl");
-       i_ptcracl = PQfnumber(res, "ptcracl");
-       i_ptcinitacl = PQfnumber(res, "ptcinitacl");
-       i_ptcinitracl = PQfnumber(res, "ptcinitracl");
+       i_acldefault = PQfnumber(res, "acldefault");
        i_ptctrusted = PQfnumber(res, "ptctrusted");
        i_ptcreadid = PQfnumber(res, "ptcreadoid");
        i_ptcwriteid = PQfnumber(res, "ptcwriteoid");
@@ -7035,14 +6861,20 @@ getExtProtocols(Archive *fout, int *numExtProtocols)
                else
                        ptcinfo[i].ptcvalidid = atooid(PQgetvalue(res, i, 
i_ptcvalidid));
 
-               ptcinfo[i].ptcacl = pg_strdup(PQgetvalue(res, i, i_ptcacl));
-               ptcinfo[i].rproacl = pg_strdup(PQgetvalue(res, i, i_ptcracl));
-               ptcinfo[i].initproacl = pg_strdup(PQgetvalue(res, i, 
i_ptcinitacl));
-               ptcinfo[i].initrproacl = pg_strdup(PQgetvalue(res, i, 
i_ptcinitracl));
                ptcinfo[i].ptctrusted = *(PQgetvalue(res, i, i_ptctrusted)) == 
't';
 
+               ptcinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_ptcacl));
+               ptcinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               ptcinfo[i].dacl.privtype = 0;
+               ptcinfo[i].dacl.initprivs = NULL;
+
+
                /* Decide whether we want to dump it */
                selectDumpableObject(&(ptcinfo[i].dobj), fout);
+
+               /* Mark whether function has an ACL */
+               if (!PQgetisnull(res, i, i_ptcacl))
+                       ptcinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
        }
 
        PQclear(res);
@@ -7078,9 +6910,7 @@ getFuncs(Archive *fout, int *numFuncs)
        int                     i_proargtypes;
        int                     i_prorettype;
        int                     i_proacl;
-       int                     i_rproacl;
-       int                     i_initproacl;
-       int                     i_initrproacl;
+       int                     i_acldefault;
 
        /*
         * Find all interesting functions.  This is a bit complicated:
@@ -7102,30 +6932,20 @@ getFuncs(Archive *fout, int *numFuncs)
         * to gather the information about them, though they won't be dumped if
         * they are built-in.  Also, in 9.6 and up, include functions in
         * pg_catalog if they have an ACL different from what's shown in
-        * pg_init_privs.
+        * pg_init_privs (so we have to join to pg_init_privs; annoying).
         */
        if (fout->remoteVersion >= 90600)
        {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
                const char *not_agg_check;
 
-               buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
-                                               initracl_subquery, "p.proacl", 
"p.proowner", "'f'",
-                                               dopt->binary_upgrade);
-
                not_agg_check = (fout->remoteVersion >= 110000 ? "p.prokind <> 
'a'"
                                                 : "NOT p.proisagg");
 
                appendPQExpBuffer(query,
                                                  "SELECT p.tableoid, p.oid, 
p.proname, p.prolang, "
                                                  "p.pronargs, p.proargtypes, 
p.prorettype, "
-                                                 "%s AS proacl, "
-                                                 "%s AS rproacl, "
-                                                 "%s AS initproacl, "
-                                                 "%s AS initrproacl, "
+                                                 "p.proacl, "
+                                                 "acldefault('f', p.proowner) 
AS acldefault, "
                                                  "p.pronamespace, "
                                                  "(%s p.proowner) AS rolname "
                                                  "FROM pg_proc p "
@@ -7148,10 +6968,6 @@ getFuncs(Archive *fout, int *numFuncs)
                                                  "\n  WHERE pg_transform.oid > 
%u AND "
                                                  "\n  (p.oid = 
pg_transform.trffromsql"
                                                  "\n  OR p.oid = 
pg_transform.trftosql))",
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 initacl_subquery->data,
-                                                 initracl_subquery->data,
                                                  username_subquery,
                                                  not_agg_check,
                                                  g_last_builtin_oid,
@@ -7166,23 +6982,23 @@ getFuncs(Archive *fout, int *numFuncs)
                appendPQExpBufferStr(query,
                                                         "\n  OR p.proacl IS 
DISTINCT FROM pip.initprivs");
                appendPQExpBufferChar(query, ')');
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
        }
        else
        {
+               const char *acldefault_call;
+
+               acldefault_call = (fout->remoteVersion >= 90200 ?
+                                                  "acldefault('f', proowner)" 
: "NULL");
+
                appendPQExpBuffer(query,
                                                  "SELECT tableoid, oid, 
proname, prolang, "
                                                  "pronargs, proargtypes, 
prorettype, proacl, "
-                                                 "NULL as rproacl, "
-                                                 "NULL as initproacl, NULL AS 
initrproacl, "
+                                                 "%s AS acldefault, "
                                                  "pronamespace, "
                                                  "(%s proowner) AS rolname "
                                                  "FROM pg_proc p "
                                                  "WHERE NOT proisagg",
+                                                 acldefault_call,
                                                  username_subquery);
                if (fout->remoteVersion >= 90200)
                        appendPQExpBufferStr(query,
@@ -7242,9 +7058,7 @@ getFuncs(Archive *fout, int *numFuncs)
        i_proargtypes = PQfnumber(res, "proargtypes");
        i_prorettype = PQfnumber(res, "prorettype");
        i_proacl = PQfnumber(res, "proacl");
-       i_rproacl = PQfnumber(res, "rproacl");
-       i_initproacl = PQfnumber(res, "initproacl");
-       i_initrproacl = PQfnumber(res, "initrproacl");
+       i_acldefault = PQfnumber(res, "acldefault");
 
        for (i = 0; i < ntups; i++)
        {
@@ -7255,13 +7069,13 @@ getFuncs(Archive *fout, int *numFuncs)
                finfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_proname));
                finfo[i].dobj.namespace =
                        findNamespace(atooid(PQgetvalue(res, i, 
i_pronamespace)));
+               finfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_proacl));
+               finfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               finfo[i].dacl.privtype = 0;
+               finfo[i].dacl.initprivs = NULL;
                finfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
                finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
                finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
-               finfo[i].proacl = pg_strdup(PQgetvalue(res, i, i_proacl));
-               finfo[i].rproacl = pg_strdup(PQgetvalue(res, i, i_rproacl));
-               finfo[i].initproacl = pg_strdup(PQgetvalue(res, i, 
i_initproacl));
-               finfo[i].initrproacl = pg_strdup(PQgetvalue(res, i, 
i_initrproacl));
                finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
                if (finfo[i].nargs == 0)
                        finfo[i].argtypes = NULL;
@@ -7277,10 +7091,7 @@ getFuncs(Archive *fout, int *numFuncs)
                selectDumpableObject(&(finfo[i].dobj), fout);
 
                /* Mark whether function has an ACL */
-               if (!(PQgetisnull(res, i, i_proacl) &&
-                         PQgetisnull(res, i, i_rproacl) &&
-                         PQgetisnull(res, i, i_initproacl) &&
-                         PQgetisnull(res, i, i_initrproacl)))
+               if (!PQgetisnull(res, i, i_proacl))
                        finfo[i].dobj.components |= DUMP_COMPONENT_ACL;
 
                if (strlen(finfo[i].rolname) == 0)
@@ -7317,10 +7128,6 @@ getTables(Archive *fout, int *numTables)
        int                     i_relname;
        int                     i_relnamespace;
        int                     i_relkind;
-       int                     i_relacl;
-       int                     i_rrelacl;
-       int                     i_initrelacl;
-       int                     i_initrrelacl;
        int                     i_reltype;
        int                     i_rolname;
        int                     i_relchecks;
@@ -7350,7 +7157,8 @@ getTables(Archive *fout, int *numTables)
        int                     i_parlevel;
        int                     i_foreignserver;
        int                     i_is_identity_sequence;
-       int                     i_changed_acl;
+       int                     i_relacl;
+       int                     i_acldefault;
        int                     i_partkeydef;
        int                     i_ispartition;
        int                     i_partbound;
@@ -7501,7 +7309,7 @@ getTables(Archive *fout, int *numTables)
                                                  "p.parrelid as parrelid, "
                                                  "pl.parlevel as parlevel, ");
 
-    if (fout->remoteVersion >= 90100)
+       if (fout->remoteVersion >= 90100)
                appendPQExpBufferStr(query,
                                                  "CASE WHEN c.relkind = 'f' 
THEN "
                                                  "(SELECT ftserver FROM 
pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) "
@@ -7512,70 +7320,20 @@ getTables(Archive *fout, int *numTables)
 
     if (fout->remoteVersion >= 90600)
                appendPQExpBuffer(query,
-                                                 "c.relisivm AS isivm, %s, ",
-                                                 (fout->version.type == 
Cloudberry && fout->version.version >= 2) ? "c.relisdynamic AS isdynamic " : 
"false AS isdynamic ");
-               
-
-       if (fout->remoteVersion >= 90600)
-       {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
-               PQExpBuffer attacl_subquery = createPQExpBuffer();
-               PQExpBuffer attracl_subquery = createPQExpBuffer();
-               PQExpBuffer attinitacl_subquery = createPQExpBuffer();
-               PQExpBuffer attinitracl_subquery = createPQExpBuffer();
-
-               buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
-                                               initracl_subquery, "c.relacl", 
"c.relowner",
-                                               "CASE WHEN c.relkind = " 
CppAsString2(RELKIND_SEQUENCE)
-                                               " THEN 's' ELSE 'r' 
END::\"char\"",
-                                               dopt->binary_upgrade);
-
-               buildACLQueries(attacl_subquery, attracl_subquery, 
attinitacl_subquery,
-                                               attinitracl_subquery, 
"at.attacl", "c.relowner","'c'",
-                                               dopt->binary_upgrade);
-
-               appendPQExpBuffer(query,
-                                                 "%s AS relacl, %s as rrelacl, 
"
-                                                 "%s AS initrelacl, %s as 
initrrelacl, ",
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 initacl_subquery->data,
-                                                 initracl_subquery->data);
+                                                 "c.relisivm AS isivm, %s",
+                                                 (fout->version.type == 
Cloudberry && fout->version.version >= 2) ? 
+                                                       "c.relisdynamic AS 
isdynamic, " : "false AS isdynamic, ");
+       else
+               appendPQExpBufferStr(query,     "false as isivm, false as 
isdynamic, ");
 
-               appendPQExpBuffer(query,
-                                                 "EXISTS (SELECT 1 FROM 
pg_attribute at LEFT JOIN pg_init_privs pip ON "
-                                                 "(c.oid = pip.objoid "
-                                                 "AND pip.classoid = 
'pg_class'::regclass "
-                                                 "AND pip.objsubid = 
at.attnum)"
-                                                 "WHERE at.attrelid = c.oid 
AND ("
-                                                 "%s IS NOT NULL "
-                                                 "OR %s IS NOT NULL "
-                                                 "OR %s IS NOT NULL "
-                                                 "OR %s IS NOT NULL"
-                                                 "))"
-                                                 "AS changed_acl, ",
-                                                 attacl_subquery->data,
-                                                 attracl_subquery->data,
-                                                 attinitacl_subquery->data,
-                                                 attinitracl_subquery->data);
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
-               destroyPQExpBuffer(attacl_subquery);
-               destroyPQExpBuffer(attracl_subquery);
-               destroyPQExpBuffer(attinitacl_subquery);
-               destroyPQExpBuffer(attinitracl_subquery);
-       }
+       if (fout->remoteVersion >= 90200)
+               appendPQExpBufferStr(query,
+                                                        "c.relacl, "
+                                                        "acldefault(CASE WHEN 
c.relkind = " CppAsString2(RELKIND_SEQUENCE)
+                                                        " THEN 's'::\"char\" 
ELSE 'r'::\"char\" END, c.relowner) AS acldefault, ");
        else
                appendPQExpBufferStr(query,
-                                                 "c.relacl, NULL as rrelacl, "
-                                                 "NULL AS initrelacl, NULL AS 
initrrelacl, "
-                                                 "false AS changed_acl, ");
+                                                        "c.relacl, NULL AS 
acldefault, ");
 
        if (fout->remoteVersion >= 100000)
                appendPQExpBufferStr(query,
@@ -7594,25 +7352,21 @@ getTables(Archive *fout, int *numTables)
         * Also join to pg_tablespace to collect the spcname.
         */
        appendPQExpBufferStr(query,
-                                                 "\nFROM pg_class c\n"
-                                                 "LEFT JOIN pg_depend d ON "
-                                                 "(c.relkind = " 
CppAsString2(RELKIND_SEQUENCE) " AND "
-                                                 "d.classid = c.tableoid AND 
d.objid = c.oid AND "
-                                                 "d.objsubid = 0 AND "
-                                                 "d.refclassid = c.tableoid 
AND d.deptype IN ('a', 'i'))\n"
-                                                 "LEFT JOIN pg_tablespace tsp 
ON (tsp.oid = c.reltablespace)\n");
+                                                "\nFROM pg_class c\n"
+                                                "LEFT JOIN pg_depend d ON "
+                                                "(c.relkind = " 
CppAsString2(RELKIND_SEQUENCE) " AND "
+                                                "d.classid = 
'pg_class'::regclass AND d.objid = c.oid AND "
+                                                "d.objsubid = 0 AND "
+                                                "d.refclassid = 
'pg_class'::regclass AND d.deptype IN ('a', 'i'))\n"
+                                                "LEFT JOIN pg_tablespace tsp 
ON (tsp.oid = c.reltablespace)\n");
+
        /*
-        * In 9.6 and up, left join to pg_init_privs to detect if any privileges
-        * are still as-set-at-init, in which case we won't dump out ACL 
commands
-        * for those.  We also are interested in the amname as of 9.6.
+        * In 9.6 and up, left join to pg_am to pick up the amname.
         */
        if (fout->remoteVersion >= 90600)
                appendPQExpBufferStr(query,
-                                                        "LEFT JOIN pg_am am ON 
(c.relam = am.oid)\n"
-                                                        "LEFT JOIN 
pg_init_privs pip ON "
-                                                        "(c.oid = pip.objoid "
-                                                        "AND pip.classoid = 
'pg_class'::regclass "
-                                                        "AND pip.objsubid = 
0)\n");
+                                                        "LEFT JOIN pg_am am ON 
(c.relam = am.oid)\n");
+
        /*
         *
         * We purposefully ignore toast OIDs for partitioned tables; the reason 
is
@@ -7720,10 +7474,7 @@ getTables(Archive *fout, int *numTables)
        i_amname = PQfnumber(res, "amname");
        i_is_identity_sequence = PQfnumber(res, "is_identity_sequence");
        i_relacl = PQfnumber(res, "relacl");
-       i_rrelacl = PQfnumber(res, "rrelacl");
-       i_initrelacl = PQfnumber(res, "initrelacl");
-       i_initrrelacl = PQfnumber(res, "initrrelacl");
-       i_changed_acl = PQfnumber(res, "changed_acl");
+       i_acldefault = PQfnumber(res, "acldefault");
        i_partkeydef = PQfnumber(res, "partkeydef");
        i_ispartition = PQfnumber(res, "ispartition");
        i_partbound = PQfnumber(res, "partbound");
@@ -7760,6 +7511,10 @@ getTables(Archive *fout, int *numTables)
                tblinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_relname));
                tblinfo[i].dobj.namespace =
                        findNamespace(atooid(PQgetvalue(res, i, 
i_relnamespace)));
+               tblinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_relacl));
+               tblinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               tblinfo[i].dacl.privtype = 0;
+               tblinfo[i].dacl.initprivs = NULL;
                tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
                tblinfo[i].reltype = atooid(PQgetvalue(res, i, i_reltype));
                tblinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
@@ -7805,10 +7560,6 @@ getTables(Archive *fout, int *numTables)
                else
                        tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, 
i_amname));
                tblinfo[i].is_identity_sequence = (strcmp(PQgetvalue(res, i, 
i_is_identity_sequence), "t") == 0);
-               tblinfo[i].relacl = pg_strdup(PQgetvalue(res, i, i_relacl));
-               tblinfo[i].rrelacl = pg_strdup(PQgetvalue(res, i, i_rrelacl));
-               tblinfo[i].initrelacl = pg_strdup(PQgetvalue(res, i, 
i_initrelacl));
-               tblinfo[i].initrrelacl = pg_strdup(PQgetvalue(res, i, 
i_initrrelacl));
                tblinfo[i].partkeydef = pg_strdup(PQgetvalue(res, i, 
i_partkeydef));
                tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, 
i_ispartition), "t") == 0);
                tblinfo[i].partbound = pg_strdup(PQgetvalue(res, i, 
i_partbound));
@@ -7879,23 +7630,10 @@ getTables(Archive *fout, int *numTables)
                /* Tables have data */
                tblinfo[i].dobj.components |= DUMP_COMPONENT_DATA;
 
-               /*
-                * Mark whether table has an ACL.
-                *
-                * If the table-level and all column-level ACLs for this table 
are
-                * unchanged, then we don't need to worry about including the 
ACLs for
-                * this table.  If any column-level ACLs have been changed, the
-                * 'changed_acl' column from the query will indicate that.
-                *
-                * This can result in a significant performance improvement in 
cases
-                * where we are only looking to dump out the ACL (eg: 
pg_catalog).
-                */
-               if (!(PQgetisnull(res, i, i_relacl) &&
-                         PQgetisnull(res, i, i_rrelacl) &&
-                         PQgetisnull(res, i, i_initrelacl) &&
-                         PQgetisnull(res, i, i_initrrelacl) &&
-                         strcmp(PQgetvalue(res, i, i_changed_acl), "f") == 0))
+               /* Mark whether table has an ACL */
+               if (!PQgetisnull(res, i, i_relacl))
                        tblinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
+               tblinfo[i].hascolumnACLs = false;       /* may get set later */
 
                /*
                 * Read-lock target tables to make sure they aren't DROPPED or 
altered
@@ -9235,7 +8973,6 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
 ProcLangInfo *
 getProcLangs(Archive *fout, int *numProcLangs)
 {
-       DumpOptions *dopt = fout->dopt;
        PGresult   *res;
        int                     ntups;
        int                     i;
@@ -9249,9 +8986,7 @@ getProcLangs(Archive *fout, int *numProcLangs)
        int                     i_laninline;
        int                     i_lanvalidator;
        int                     i_lanacl;
-       int                     i_rlanacl;
-       int                     i_initlanacl;
-       int                     i_initrlanacl;
+       int                     i_acldefault;
        int                     i_lanowner;
 
        /*
@@ -9259,82 +8994,43 @@ getProcLangs(Archive *fout, int *numProcLangs)
         * Cloudberry 5, so the check needs to go further back than 90000.
         */
 
-       if (fout->remoteVersion >= 90600)
-       {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
-
-               buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
-                                               initracl_subquery, "l.lanacl", 
"l.lanowner", "'l'",
-                                               dopt->binary_upgrade);
-
-               /* pg_language has a laninline column */
-               appendPQExpBuffer(query, "SELECT l.tableoid, l.oid, "
-                                                 "l.lanname, l.lanpltrusted, 
l.lanplcallfoid, "
-                                                 "l.laninline, l.lanvalidator, 
"
-                                                 "%s AS lanacl, "
-                                                 "%s AS rlanacl, "
-                                                 "%s AS initlanacl, "
-                                                 "%s AS initrlanacl, "
-                                                 "(%s l.lanowner) AS lanowner "
-                                                 "FROM pg_language l "
-                                                 "LEFT JOIN pg_init_privs pip 
ON "
-                                                 "(l.oid = pip.objoid "
-                                                 "AND pip.classoid = 
'pg_language'::regclass "
-                                                 "AND pip.objsubid = 0) "
-                                                 "WHERE l.lanispl "
-                                                 "ORDER BY l.oid",
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 initacl_subquery->data,
-                                                 initracl_subquery->data,
-                                                 username_subquery);
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
-       }
-       else if (fout->remoteVersion >= 90000)
+       if (fout->remoteVersion >= 90200)
        {
-               /* pg_language has a laninline column */
+               /* acldefault() exists */
                appendPQExpBuffer(query, "SELECT tableoid, oid, "
                                                  "lanname, lanpltrusted, 
lanplcallfoid, "
-                                                 "laninline, lanvalidator, 
lanacl, NULL AS rlanacl, "
-                                                 "NULL AS initlanacl, NULL AS 
initrlanacl, "
+                                                 "laninline, lanvalidator, "
+                                                 "lanacl, "
+                                                 "acldefault('l', lanowner) AS 
acldefault, "
                                                  "(%s lanowner) AS lanowner "
                                                  "FROM pg_language "
                                                  "WHERE lanispl "
                                                  "ORDER BY oid",
                                                  username_subquery);
        }
-       else if (fout->remoteVersion >= 80300)
+       else if (fout->remoteVersion >= 90000)
        {
                /* pg_language has a laninline column */
-               /* pg_language has a lanowner column */
                appendPQExpBuffer(query, "SELECT tableoid, oid, "
                                                  "lanname, lanpltrusted, 
lanplcallfoid, "
-                                                 "laninline, lanvalidator, 
lanacl, "
-                                                 "0 AS laninline, 
lanvalidator, lanacl, "
-                                                 "NULL AS rlanacl, "
-                                                 "NULL AS initlanacl, NULL AS 
initrlanacl, "
+                                                 "laninline, lanvalidator, "
+                                                 "lanacl, NULL AS acldefault, "
                                                  "(%s lanowner) AS lanowner "
                                                  "FROM pg_language "
                                                  "WHERE lanispl "
                                                  "ORDER BY oid",
                                                  username_subquery);
        }
-       else
+       else /* GPDB5 */
        {
-               /* Languages are owned by the bootstrap superuser, OID 10 */
+               /* pg_language has a laninline column */
+               /* pg_language has a lanowner column */
                appendPQExpBuffer(query, "SELECT tableoid, oid, "
                                                  "lanname, lanpltrusted, 
lanplcallfoid, "
+                                                 "laninline, lanvalidator, 
lanacl, "
                                                  "0 AS laninline, 
lanvalidator, lanacl, "
-                                                 "NULL AS rlanacl, "
-                                                 "NULL AS initlanacl, NULL AS 
initrlanacl, "
-                                                 "(%s '10') AS lanowner "
+                                                 "NULL AS acldefault, "
+                                                 "(%s lanowner) AS lanowner "
                                                  "FROM pg_language "
                                                  "WHERE lanispl "
                                                  "ORDER BY oid",
@@ -9357,9 +9053,7 @@ getProcLangs(Archive *fout, int *numProcLangs)
        i_laninline = PQfnumber(res, "laninline");
        i_lanvalidator = PQfnumber(res, "lanvalidator");
        i_lanacl = PQfnumber(res, "lanacl");
-       i_rlanacl = PQfnumber(res, "rlanacl");
-       i_initlanacl = PQfnumber(res, "initlanacl");
-       i_initrlanacl = PQfnumber(res, "initrlanacl");
+       i_acldefault = PQfnumber(res, "acldefault");
        i_lanowner = PQfnumber(res, "lanowner");
 
        for (i = 0; i < ntups; i++)
@@ -9370,24 +9064,21 @@ getProcLangs(Archive *fout, int *numProcLangs)
                AssignDumpId(&planginfo[i].dobj);
 
                planginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, 
i_lanname));
+               planginfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_lanacl));
+               planginfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               planginfo[i].dacl.privtype = 0;
+               planginfo[i].dacl.initprivs = NULL;
                planginfo[i].lanpltrusted = *(PQgetvalue(res, i, 
i_lanpltrusted)) == 't';
                planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, 
i_lanplcallfoid));
                planginfo[i].laninline = atooid(PQgetvalue(res, i, 
i_laninline));
                planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, 
i_lanvalidator));
-               planginfo[i].lanacl = pg_strdup(PQgetvalue(res, i, i_lanacl));
-               planginfo[i].rlanacl = pg_strdup(PQgetvalue(res, i, i_rlanacl));
-               planginfo[i].initlanacl = pg_strdup(PQgetvalue(res, i, 
i_initlanacl));
-               planginfo[i].initrlanacl = pg_strdup(PQgetvalue(res, i, 
i_initrlanacl));
                planginfo[i].lanowner = pg_strdup(PQgetvalue(res, i, 
i_lanowner));
 
                /* Decide whether we want to dump it */
                selectDumpableProcLang(&(planginfo[i]), fout);
 
                /* Mark whether language has an ACL */
-               if (!(PQgetisnull(res, i, i_lanacl) &&
-                         PQgetisnull(res, i, i_rlanacl) &&
-                         PQgetisnull(res, i, i_initlanacl) &&
-                         PQgetisnull(res, i, i_initrlanacl)))
+               if (!PQgetisnull(res, i, i_lanacl))
                        planginfo[i].dobj.components |= DUMP_COMPONENT_ACL;
        }
 
@@ -10454,7 +10145,6 @@ getTSConfigurations(Archive *fout, int *numTSConfigs)
 FdwInfo *
 getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
 {
-       DumpOptions *dopt = fout->dopt;
        PGresult   *res;
        int                     ntups;
        int                     i;
@@ -10467,9 +10157,7 @@ getForeignDataWrappers(Archive *fout, int 
*numForeignDataWrappers)
        int                     i_fdwhandler;
        int                     i_fdwvalidator;
        int                     i_fdwacl;
-       int                     i_rfdwacl;
-       int                     i_initfdwacl;
-       int                     i_initrfdwacl;
+       int                     i_acldefault;
        int                     i_fdwoptions;
 
        /* Before 8.4, there are no foreign-data wrappers */
@@ -10481,46 +10169,22 @@ getForeignDataWrappers(Archive *fout, int 
*numForeignDataWrappers)
 
        query = createPQExpBuffer();
 
-       if (fout->remoteVersion >= 90600)
+       if (fout->remoteVersion >= 90200)
        {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
-
-               buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
-                                               initracl_subquery, "f.fdwacl", 
"f.fdwowner", "'F'",
-                                               dopt->binary_upgrade);
-
-               appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.fdwname, "
-                                                 "(%s f.fdwowner) AS rolname, "
-                                                 
"f.fdwhandler::pg_catalog.regproc, "
-                                                 
"f.fdwvalidator::pg_catalog.regproc, "
-                                                 "%s AS fdwacl, "
-                                                 "%s AS rfdwacl, "
-                                                 "%s AS initfdwacl, "
-                                                 "%s AS initrfdwacl, "
+               appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
+                                                 "(%s fdwowner) AS rolname, "
+                                                 
"fdwhandler::pg_catalog.regproc, "
+                                                 
"fdwvalidator::pg_catalog.regproc, "
+                                                 "fdwacl, "
+                                                 "acldefault('F', fdwowner) AS 
acldefault, "
                                                  "array_to_string(ARRAY("
                                                  "SELECT 
quote_ident(option_name) || ' ' || "
                                                  "quote_literal(option_value) "
-                                                 "FROM 
pg_options_to_table(f.fdwoptions) "
+                                                 "FROM 
pg_options_to_table(fdwoptions) "
                                                  "ORDER BY option_name"
                                                  "), E',\n    ') AS fdwoptions 
"
-                                                 "FROM pg_foreign_data_wrapper 
f "
-                                                 "LEFT JOIN pg_init_privs pip 
ON "
-                                                 "(f.oid = pip.objoid "
-                                                 "AND pip.classoid = 
'pg_foreign_data_wrapper'::regclass "
-                                                 "AND pip.objsubid = 0) ",
-                                                 username_subquery,
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 initacl_subquery->data,
-                                                 initracl_subquery->data);
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
+                                                 "FROM 
pg_foreign_data_wrapper",
+                                                 username_subquery);
        }
        else if (fout->remoteVersion >= 90100)
        {
@@ -10528,8 +10192,7 @@ getForeignDataWrappers(Archive *fout, int 
*numForeignDataWrappers)
                                                  "(%s fdwowner) AS rolname, "
                                                  
"fdwhandler::pg_catalog.regproc, "
                                                  
"fdwvalidator::pg_catalog.regproc, fdwacl, "
-                                                 "NULL as rfdwacl, "
-                                                 "NULL as initfdwacl, NULL AS 
initrfdwacl, "
+                                                 "NULL AS acldefault, "
                                                  "array_to_string(ARRAY("
                                                  "SELECT 
quote_ident(option_name) || ' ' || "
                                                  "quote_literal(option_value) "
@@ -10545,8 +10208,7 @@ getForeignDataWrappers(Archive *fout, int 
*numForeignDataWrappers)
                                                  "(%s fdwowner) AS rolname, "
                                                  "'-' AS fdwhandler, "
                                                  
"fdwvalidator::pg_catalog.regproc, fdwacl, "
-                                                 "NULL as rfdwacl, "
-                                                 "NULL as initfdwacl, NULL AS 
initrfdwacl, "
+                                                 "NULL AS acldefault, "
                                                  "array_to_string(ARRAY("
                                                  "SELECT 
quote_ident(option_name) || ' ' || "
                                                  "quote_literal(option_value) "
@@ -10571,9 +10233,7 @@ getForeignDataWrappers(Archive *fout, int 
*numForeignDataWrappers)
        i_fdwhandler = PQfnumber(res, "fdwhandler");
        i_fdwvalidator = PQfnumber(res, "fdwvalidator");
        i_fdwacl = PQfnumber(res, "fdwacl");
-       i_rfdwacl = PQfnumber(res, "rfdwacl");
-       i_initfdwacl = PQfnumber(res, "initfdwacl");
-       i_initrfdwacl = PQfnumber(res, "initrfdwacl");
+       i_acldefault = PQfnumber(res, "acldefault");
        i_fdwoptions = PQfnumber(res, "fdwoptions");
 
        for (i = 0; i < ntups; i++)
@@ -10584,14 +10244,14 @@ getForeignDataWrappers(Archive *fout, int 
*numForeignDataWrappers)
                AssignDumpId(&fdwinfo[i].dobj);
                fdwinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_fdwname));
                fdwinfo[i].dobj.namespace = NULL;
+               fdwinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_fdwacl));
+               fdwinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               fdwinfo[i].dacl.privtype = 0;
+               fdwinfo[i].dacl.initprivs = NULL;
                fdwinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
                fdwinfo[i].fdwhandler = pg_strdup(PQgetvalue(res, i, 
i_fdwhandler));
                fdwinfo[i].fdwvalidator = pg_strdup(PQgetvalue(res, i, 
i_fdwvalidator));
                fdwinfo[i].fdwoptions = pg_strdup(PQgetvalue(res, i, 
i_fdwoptions));
-               fdwinfo[i].fdwacl = pg_strdup(PQgetvalue(res, i, i_fdwacl));
-               fdwinfo[i].rfdwacl = pg_strdup(PQgetvalue(res, i, i_rfdwacl));
-               fdwinfo[i].initfdwacl = pg_strdup(PQgetvalue(res, i, 
i_initfdwacl));
-               fdwinfo[i].initrfdwacl = pg_strdup(PQgetvalue(res, i, 
i_initrfdwacl));
 
                /* Decide whether we want to dump it */
                selectDumpableObject(&(fdwinfo[i].dobj), fout);
@@ -10601,10 +10261,7 @@ getForeignDataWrappers(Archive *fout, int 
*numForeignDataWrappers)
                        fdwinfo[i].dobj.dump = DUMP_COMPONENT_NONE;
 
                /* Mark whether FDW has an ACL */
-               if (!(PQgetisnull(res, i, i_fdwacl) &&
-                         PQgetisnull(res, i, i_rfdwacl) &&
-                         PQgetisnull(res, i, i_initfdwacl) &&
-                         PQgetisnull(res, i, i_initrfdwacl)))
+               if (!PQgetisnull(res, i, i_fdwacl))
                        fdwinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
        }
 
@@ -10625,7 +10282,6 @@ getForeignDataWrappers(Archive *fout, int 
*numForeignDataWrappers)
 ForeignServerInfo *
 getForeignServers(Archive *fout, int *numForeignServers)
 {
-       DumpOptions *dopt = fout->dopt;
        PGresult   *res;
        int                     ntups;
        int                     i;
@@ -10639,9 +10295,7 @@ getForeignServers(Archive *fout, int *numForeignServers)
        int                     i_srvtype;
        int                     i_srvversion;
        int                     i_srvacl;
-       int                     i_rsrvacl;
-       int                     i_initsrvacl;
-       int                     i_initrsrvacl;
+       int                     i_acldefault;
        int                     i_srvoptions;
 
        /* Before 8.4, there are no foreign servers */
@@ -10653,53 +10307,27 @@ getForeignServers(Archive *fout, int 
*numForeignServers)
 
        query = createPQExpBuffer();
 
-       if (fout->remoteVersion >= 90600)
+       if (fout->remoteVersion >= 90200)
        {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
-
-               buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
-                                               initracl_subquery, "f.srvacl", 
"f.srvowner", "'S'",
-                                               dopt->binary_upgrade);
-
-               appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.srvname, "
-                                                 "(%s f.srvowner) AS rolname, "
-                                                 "f.srvfdw, f.srvtype, 
f.srvversion, "
-                                                 "%s AS srvacl, "
-                                                 "%s AS rsrvacl, "
-                                                 "%s AS initsrvacl, "
-                                                 "%s AS initrsrvacl, "
+               appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
+                                                 "(%s srvowner) AS rolname, "
+                                                 "srvfdw, srvtype, srvversion, 
srvacl, "
+                                                 "acldefault('S', srvowner) AS 
acldefault, "
                                                  "array_to_string(ARRAY("
                                                  "SELECT 
quote_ident(option_name) || ' ' || "
                                                  "quote_literal(option_value) "
-                                                 "FROM 
pg_options_to_table(f.srvoptions) "
+                                                 "FROM 
pg_options_to_table(srvoptions) "
                                                  "ORDER BY option_name"
                                                  "), E',\n    ') AS srvoptions 
"
-                                                 "FROM pg_foreign_server f "
-                                                 "LEFT JOIN pg_init_privs pip "
-                                                 "ON (f.oid = pip.objoid "
-                                                 "AND pip.classoid = 
'pg_foreign_server'::regclass "
-                                                 "AND pip.objsubid = 0) ",
-                                                 username_subquery,
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 initacl_subquery->data,
-                                                 initracl_subquery->data);
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
+                                                 "FROM pg_foreign_server",
+                                                 username_subquery);
        }
        else
        {
                appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
                                                  "(%s srvowner) AS rolname, "
                                                  "srvfdw, srvtype, srvversion, 
srvacl, "
-                                                 "NULL AS rsrvacl, "
-                                                 "NULL AS initsrvacl, NULL AS 
initrsrvacl, "
+                                                 "NULL AS acldefault, "
                                                  "array_to_string(ARRAY("
                                                  "SELECT 
quote_ident(option_name) || ' ' || "
                                                  "quote_literal(option_value) "
@@ -10725,9 +10353,7 @@ getForeignServers(Archive *fout, int *numForeignServers)
        i_srvtype = PQfnumber(res, "srvtype");
        i_srvversion = PQfnumber(res, "srvversion");
        i_srvacl = PQfnumber(res, "srvacl");
-       i_rsrvacl = PQfnumber(res, "rsrvacl");
-       i_initsrvacl = PQfnumber(res, "initsrvacl");
-       i_initrsrvacl = PQfnumber(res, "initrsrvacl");
+       i_acldefault = PQfnumber(res, "acldefault");
        i_srvoptions = PQfnumber(res, "srvoptions");
 
        for (i = 0; i < ntups; i++)
@@ -10738,15 +10364,15 @@ getForeignServers(Archive *fout, int 
*numForeignServers)
                AssignDumpId(&srvinfo[i].dobj);
                srvinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_srvname));
                srvinfo[i].dobj.namespace = NULL;
+               srvinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_srvacl));
+               srvinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               srvinfo[i].dacl.privtype = 0;
+               srvinfo[i].dacl.initprivs = NULL;
                srvinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
                srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
                srvinfo[i].srvtype = pg_strdup(PQgetvalue(res, i, i_srvtype));
                srvinfo[i].srvversion = pg_strdup(PQgetvalue(res, i, 
i_srvversion));
                srvinfo[i].srvoptions = pg_strdup(PQgetvalue(res, i, 
i_srvoptions));
-               srvinfo[i].srvacl = pg_strdup(PQgetvalue(res, i, i_srvacl));
-               srvinfo[i].rsrvacl = pg_strdup(PQgetvalue(res, i, i_rsrvacl));
-               srvinfo[i].initsrvacl = pg_strdup(PQgetvalue(res, i, 
i_initsrvacl));
-               srvinfo[i].initrsrvacl = pg_strdup(PQgetvalue(res, i, 
i_initrsrvacl));
 
                /* Decide whether we want to dump it */
                selectDumpableObject(&(srvinfo[i].dobj), fout);
@@ -10759,10 +10385,7 @@ getForeignServers(Archive *fout, int 
*numForeignServers)
                srvinfo[i].dobj.components |= DUMP_COMPONENT_USERMAP;
 
                /* Mark whether server has an ACL */
-               if (!(PQgetisnull(res, i, i_srvacl) &&
-                         PQgetisnull(res, i, i_rsrvacl) &&
-                         PQgetisnull(res, i, i_initsrvacl) &&
-                         PQgetisnull(res, i, i_initrsrvacl)))
+               if (!PQgetisnull(res, i, i_srvacl))
                        srvinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
        }
 
@@ -10793,9 +10416,7 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
        int                     i_defaclnamespace;
        int                     i_defaclobjtype;
        int                     i_defaclacl;
-       int                     i_rdefaclacl;
-       int                     i_initdefaclacl;
-       int                     i_initrdefaclacl;
+       int                     i_acldefault;
        int                     i,
                                ntups;
 
@@ -10807,13 +10428,16 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
 
        query = createPQExpBuffer();
 
-       if (fout->remoteVersion >= 90600)
-       {
-               PQExpBuffer acl_subquery = createPQExpBuffer();
-               PQExpBuffer racl_subquery = createPQExpBuffer();
-               PQExpBuffer initacl_subquery = createPQExpBuffer();
-               PQExpBuffer initracl_subquery = createPQExpBuffer();
+       appendPQExpBuffer(query,
+                                         "SELECT oid, tableoid, "
+                                         "(%s defaclrole) AS defaclrole, "
+                                         "defaclnamespace, "
+                                         "defaclobjtype, "
+                                         "defaclacl, ",
+                                         username_subquery);
 
+       if (fout->remoteVersion >= 90200)
+       {
                /*
                 * Global entries (with defaclnamespace=0) replace the 
hard-wired
                 * default ACL for their object type.  We should dump them as 
deltas
@@ -10821,58 +10445,24 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
                 * 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.
+                * ACL).
                 *
                 * 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 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, "
-                                                 "(%s d.defaclrole) AS 
defaclrole, "
-                                                 "d.defaclnamespace, "
-                                                 "d.defaclobjtype, "
-                                                 "%s AS defaclacl, "
-                                                 "%s AS rdefaclacl, "
-                                                 "%s AS initdefaclacl, "
-                                                 "%s AS initrdefaclacl "
-                                                 "FROM pg_default_acl d "
-                                                 "LEFT JOIN pg_init_privs pip 
ON "
-                                                 "(d.oid = pip.objoid "
-                                                 "AND pip.classoid = 
'pg_default_acl'::regclass "
-                                                 "AND pip.objsubid = 0) ",
-                                                 username_subquery,
-                                                 acl_subquery->data,
-                                                 racl_subquery->data,
-                                                 initacl_subquery->data,
-                                                 initracl_subquery->data);
-
-               destroyPQExpBuffer(acl_subquery);
-               destroyPQExpBuffer(racl_subquery);
-               destroyPQExpBuffer(initacl_subquery);
-               destroyPQExpBuffer(initracl_subquery);
+               appendPQExpBufferStr(query,
+                                                        "CASE WHEN 
defaclnamespace = 0 THEN "
+                                                        "acldefault(CASE WHEN 
defaclobjtype = 'S' "
+                                                        "THEN 's'::\"char\" 
ELSE defaclobjtype END, "
+                                                        "defaclrole) ELSE '{}' 
END AS acldefault ");
        }
        else
-       {
-               appendPQExpBuffer(query, "SELECT oid, tableoid, "
-                                                 "(%s defaclrole) AS 
defaclrole, "
-                                                 "defaclnamespace, "
-                                                 "defaclobjtype, "
-                                                 "defaclacl, "
-                                                 "NULL AS rdefaclacl, "
-                                                 "NULL AS initdefaclacl, "
-                                                 "NULL AS initrdefaclacl "
-                                                 "FROM pg_default_acl",
-                                                 username_subquery);
-       }
+               appendPQExpBufferStr(query,
+                                                        "NULL AS acldefault ");
+
+       appendPQExpBufferStr(query,
+                                                "FROM pg_default_acl");
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
@@ -10887,9 +10477,7 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
        i_defaclnamespace = PQfnumber(res, "defaclnamespace");
        i_defaclobjtype = PQfnumber(res, "defaclobjtype");
        i_defaclacl = PQfnumber(res, "defaclacl");
-       i_rdefaclacl = PQfnumber(res, "rdefaclacl");
-       i_initdefaclacl = PQfnumber(res, "initdefaclacl");
-       i_initrdefaclacl = PQfnumber(res, "initrdefaclacl");
+       i_acldefault = PQfnumber(res, "acldefault");
 
        for (i = 0; i < ntups; i++)
        {
@@ -10907,12 +10495,12 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
                else
                        daclinfo[i].dobj.namespace = NULL;
 
+               daclinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, 
i_defaclacl));
+               daclinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, 
i_acldefault));
+               daclinfo[i].dacl.privtype = 0;
+               daclinfo[i].dacl.initprivs = NULL;
                daclinfo[i].defaclrole = pg_strdup(PQgetvalue(res, i, 
i_defaclrole));
                daclinfo[i].defaclobjtype = *(PQgetvalue(res, i, 
i_defaclobjtype));
-               daclinfo[i].defaclacl = pg_strdup(PQgetvalue(res, i, 
i_defaclacl));
-               daclinfo[i].rdefaclacl = pg_strdup(PQgetvalue(res, i, 
i_rdefaclacl));
-               daclinfo[i].initdefaclacl = pg_strdup(PQgetvalue(res, i, 
i_initdefaclacl));
-               daclinfo[i].initrdefaclacl = pg_strdup(PQgetvalue(res, i, 
i_initrdefaclacl));
 
                /* Default ACLs are ACLs, of course */
                daclinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
@@ -10928,6 +10516,118 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
        return daclinfo;
 }
 
+/*
+ * getAdditionalACLs
+ *
+ * We have now created all the DumpableObjects, and collected the ACL data
+ * that appears in the directly-associated catalog entries.  However, there's
+ * more ACL-related info to collect.  If any of a table's columns have ACLs,
+ * we must set the TableInfo's DUMP_COMPONENT_ACL components flag, as well as
+ * its hascolumnACLs flag (we won't store the ACLs themselves here, though).
+ * Also, in versions having the pg_init_privs catalog, read that and load the
+ * information into the relevant DumpableObjects.
+ */
+static void
+getAdditionalACLs(Archive *fout)
+{
+       PQExpBuffer query = createPQExpBuffer();
+       PGresult   *res;
+       int                     ntups,
+                               i;
+
+       /* Check for per-column ACLs */
+       if (fout->remoteVersion >= 80400)
+       {
+               appendPQExpBufferStr(query,
+                                                        "SELECT DISTINCT 
attrelid FROM pg_attribute "
+                                                        "WHERE attacl IS NOT 
NULL");
+
+               res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+               ntups = PQntuples(res);
+               for (i = 0; i < ntups; i++)
+               {
+                       Oid                     relid = atooid(PQgetvalue(res, 
i, 0));
+                       TableInfo  *tblinfo;
+
+                       tblinfo = findTableByOid(relid);
+                       /* OK to ignore tables we haven't got a DumpableObject 
for */
+                       if (tblinfo)
+                       {
+                               tblinfo->dobj.components |= DUMP_COMPONENT_ACL;
+                               tblinfo->hascolumnACLs = true;
+                       }
+               }
+               PQclear(res);
+       }
+
+       /* Fetch initial-privileges data */
+       if (fout->remoteVersion >= 90600)
+       {
+               printfPQExpBuffer(query,
+                                                 "SELECT objoid, classoid, 
objsubid, privtype, initprivs "
+                                                 "FROM pg_init_privs");
+
+               res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+               ntups = PQntuples(res);
+               for (i = 0; i < ntups; i++)
+               {
+                       Oid                     objoid = atooid(PQgetvalue(res, 
i, 0));
+                       Oid                     classoid = 
atooid(PQgetvalue(res, i, 1));
+                       int                     objsubid = atoi(PQgetvalue(res, 
i, 2));
+                       char            privtype = *(PQgetvalue(res, i, 3));
+                       char       *initprivs = PQgetvalue(res, i, 4);
+                       CatalogId       objId;
+                       DumpableObject *dobj;
+
+                       objId.tableoid = classoid;
+                       objId.oid = objoid;
+                       dobj = findObjectByCatalogId(objId);
+                       /* OK to ignore entries we haven't got a DumpableObject 
for */
+                       if (dobj)
+                       {
+                               /* Cope with sub-object initprivs */
+                               if (objsubid != 0)
+                               {
+                                       if (dobj->objType == DO_TABLE)
+                                       {
+                                               /* For a column initpriv, set 
the table's ACL flags */
+                                               dobj->components |= 
DUMP_COMPONENT_ACL;
+                                               ((TableInfo *) 
dobj)->hascolumnACLs = true;
+                                       }
+                                       else
+                                               pg_log_warning("unsupported 
pg_init_privs entry: %u %u %d",
+                                                                          
classoid, objoid, objsubid);
+                                       continue;
+                               }
+
+                               /* Else it had better be of a type we think has 
ACLs */
+                               if (dobj->objType == DO_NAMESPACE ||
+                                       dobj->objType == DO_TYPE ||
+                                       dobj->objType == DO_FUNC ||
+                                       dobj->objType == DO_AGG ||
+                                       dobj->objType == DO_TABLE ||
+                                       dobj->objType == DO_PROCLANG ||
+                                       dobj->objType == DO_FDW ||
+                                       dobj->objType == DO_FOREIGN_SERVER)
+                               {
+                                       DumpableObjectWithAcl *daobj = 
(DumpableObjectWithAcl *) dobj;
+
+                                       daobj->dacl.privtype = privtype;
+                                       daobj->dacl.initprivs = 
pstrdup(initprivs);
+                               }
+                               else
+                                       pg_log_warning("unsupported 
pg_init_privs entry: %u %u %d",
+                                                                  classoid, 
objoid, objsubid);
+                       }
+               }
+               PQclear(res);
+       }
+
+       destroyPQExpBuffer(query);
+}
+
 /*
  * dumpComment --
  *
@@ -11535,8 +11235,7 @@ dumpNamespace(Archive *fout, const NamespaceInfo 
*nspinfo)
        if (nspinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, nspinfo->dobj.dumpId, InvalidDumpId, "SCHEMA",
                                qnspname, NULL, NULL,
-                               nspinfo->rolname, nspinfo->nspacl, 
nspinfo->rnspacl,
-                               nspinfo->initnspacl, nspinfo->initrnspacl);
+                               nspinfo->rolname, &nspinfo->dacl);
 
        free(qnspname);
 
@@ -11833,8 +11532,7 @@ dumpEnumType(Archive *fout, const TypeInfo *tyinfo)
                dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
                                qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
-                               tyinfo->rolname, tyinfo->typacl, 
tyinfo->rtypacl,
-                               tyinfo->inittypacl, tyinfo->initrtypacl);
+                               tyinfo->rolname, &tyinfo->dacl);
 
        PQclear(res);
        destroyPQExpBuffer(q);
@@ -11975,8 +11673,7 @@ dumpRangeType(Archive *fout, const TypeInfo *tyinfo)
                dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
                                qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
-                               tyinfo->rolname, tyinfo->typacl, 
tyinfo->rtypacl,
-                               tyinfo->inittypacl, tyinfo->initrtypacl);
+                               tyinfo->rolname, &tyinfo->dacl);
 
        PQclear(res);
        destroyPQExpBuffer(q);
@@ -12049,8 +11746,7 @@ dumpUndefinedType(Archive *fout, const TypeInfo *tyinfo)
                dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
                                qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
-                               tyinfo->rolname, tyinfo->typacl, 
tyinfo->rtypacl,
-                               tyinfo->inittypacl, tyinfo->initrtypacl);
+                               tyinfo->rolname, &tyinfo->dacl);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
@@ -12311,8 +12007,7 @@ dumpBaseType(Archive *fout, const TypeInfo *tyinfo)
                dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
                                qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
-                               tyinfo->rolname, tyinfo->typacl, 
tyinfo->rtypacl,
-                               tyinfo->inittypacl, tyinfo->initrtypacl);
+                               tyinfo->rolname, &tyinfo->dacl);
 
        PQclear(res);
        destroyPQExpBuffer(q);
@@ -12499,8 +12194,7 @@ dumpDomain(Archive *fout, const TypeInfo *tyinfo)
                dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
                                qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
-                               tyinfo->rolname, tyinfo->typacl, 
tyinfo->rtypacl,
-                               tyinfo->inittypacl, tyinfo->initrtypacl);
+                               tyinfo->rolname, &tyinfo->dacl);
 
        /* Dump any per-constraint comments */
        for (i = 0; i < tyinfo->nDomChecks; i++)
@@ -12725,8 +12419,7 @@ dumpCompositeType(Archive *fout, const TypeInfo *tyinfo)
                dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
                                qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
-                               tyinfo->rolname, tyinfo->typacl, 
tyinfo->rtypacl,
-                               tyinfo->inittypacl, tyinfo->initrtypacl);
+                               tyinfo->rolname, &tyinfo->dacl);
 
        PQclear(res);
        destroyPQExpBuffer(q);
@@ -13026,8 +12719,7 @@ dumpProcLang(Archive *fout, const ProcLangInfo *plang)
        if (plang->lanpltrusted && plang->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, plang->dobj.dumpId, InvalidDumpId, "LANGUAGE",
                                qlanname, NULL, NULL,
-                               plang->lanowner, plang->lanacl, plang->rlanacl,
-                               plang->initlanacl, plang->initrlanacl);
+                               plang->lanowner, &plang->dacl);
 
        free(qlanname);
 
@@ -13843,8 +13535,7 @@ dumpFunc(Archive *fout, const FuncInfo *finfo)
                dumpACL(fout, finfo->dobj.dumpId, InvalidDumpId, keyword,
                                funcsig, NULL,
                                finfo->dobj.namespace->dobj.name,
-                               finfo->rolname, finfo->proacl, finfo->rproacl,
-                               finfo->initproacl, finfo->initrproacl);
+                               finfo->rolname, &finfo->dacl);
 
        PQclear(res);
 
@@ -15755,9 +15446,7 @@ dumpAgg(Archive *fout, const AggInfo *agginfo)
                dumpACL(fout, agginfo->aggfn.dobj.dumpId, InvalidDumpId,
                                "FUNCTION", aggsig, NULL,
                                agginfo->aggfn.dobj.namespace->dobj.name,
-                               agginfo->aggfn.rolname, agginfo->aggfn.proacl,
-                               agginfo->aggfn.rproacl,
-                               agginfo->aggfn.initproacl, 
agginfo->aggfn.initrproacl);
+                               agginfo->aggfn.rolname, &agginfo->aggfn.dacl);
 
        free(aggsig);
        if (aggfullsig)
@@ -15981,9 +15670,7 @@ dumpExtProtocol(Archive *fout, const ExtProtInfo 
*ptcinfo)
        dumpACL(fout, ptcinfo->dobj.dumpId, InvalidDumpId,
                        "PROTOCOL",
                        namecopy, NULL,
-                       NULL, ptcinfo->ptcowner,
-                       ptcinfo->ptcacl, ptcinfo->rproacl,
-                       ptcinfo->initproacl, ptcinfo->initrproacl);
+                       NULL, ptcinfo->ptcowner, &ptcinfo->dacl);
        free(namecopy);
 
        destroyPQExpBuffer(q);
@@ -16380,9 +16067,7 @@ dumpForeignDataWrapper(Archive *fout, const FdwInfo 
*fdwinfo)
        if (fdwinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, fdwinfo->dobj.dumpId, InvalidDumpId,
                                "FOREIGN DATA WRAPPER", qfdwname, NULL,
-                               NULL, fdwinfo->rolname,
-                               fdwinfo->fdwacl, fdwinfo->rfdwacl,
-                               fdwinfo->initfdwacl, fdwinfo->initrfdwacl);
+                               NULL, fdwinfo->rolname, &fdwinfo->dacl);
 
        free(qfdwname);
 
@@ -16469,9 +16154,7 @@ dumpForeignServer(Archive *fout, const 
ForeignServerInfo *srvinfo)
        if (srvinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, srvinfo->dobj.dumpId, InvalidDumpId,
                                "FOREIGN SERVER", qsrvname, NULL,
-                               NULL, srvinfo->rolname,
-                               srvinfo->srvacl, srvinfo->rsrvacl,
-                               srvinfo->initsrvacl, srvinfo->initrsrvacl);
+                               NULL, srvinfo->rolname, &srvinfo->dacl);
 
        /* Dump user mappings */
        if (srvinfo->dobj.dump & DUMP_COMPONENT_USERMAP)
@@ -16635,15 +16318,13 @@ dumpDefaultACL(Archive *fout, const DefaultACLInfo 
*daclinfo)
        if (!buildDefaultACLCommands(type,
                                                                 
daclinfo->dobj.namespace != NULL ?
                                                                 
daclinfo->dobj.namespace->dobj.name : NULL,
-                                                                
daclinfo->defaclacl,
-                                                                
daclinfo->rdefaclacl,
-                                                                
daclinfo->initdefaclacl,
-                                                                
daclinfo->initrdefaclacl,
+                                                                
daclinfo->dacl.acl,
+                                                                
daclinfo->dacl.acldefault,
                                                                 
daclinfo->defaclrole,
                                                                 
fout->remoteVersion,
                                                                 q))
                fatal("could not parse default ACL list (%s)",
-                         daclinfo->defaclacl);
+                         daclinfo->dacl.acl);
 
        if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
                ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
@@ -16673,20 +16354,7 @@ dumpDefaultACL(Archive *fout, const DefaultACLInfo 
*daclinfo)
  *             (Currently we assume that subname is only provided for table 
columns.)
  * 'nspname' is the namespace the object is in (NULL if none).
  * 'owner' is the owner, NULL if there is no owner (for languages).
- * 'acls' contains the ACL string of the object from the appropriate system
- *             catalog field; it will be passed to buildACLCommands for 
building the
- *             appropriate GRANT commands.
- * 'racls' contains the ACL string of any initial-but-now-revoked ACLs of the
- *             object; it will be passed to buildACLCommands for building the
- *             appropriate REVOKE commands.
- * 'initacls' In binary-upgrade mode, ACL string of the object's initial
- *             privileges, to be recorded into pg_init_privs
- * 'initracls' In binary-upgrade mode, ACL string of the object's
- *             revoked-from-default privileges, to be recorded into 
pg_init_privs
- *
- * NB: initacls/initracls are needed because extensions can set privileges on
- * an object during the extension's script file and we record those into
- * pg_init_privs as that object's initial privileges.
+ * 'dacl' is the DumpableAcl struct fpr the object.
  *
  * Returns the dump ID assigned to the ACL TocEntry, or InvalidDumpId if
  * no ACL entry was created.
@@ -16696,11 +16364,15 @@ static DumpId
 dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId,
                const char *type, const char *name, const char *subname,
                const char *nspname, const char *owner,
-               const char *acls, const char *racls,
-               const char *initacls, const char *initracls)
+               const DumpableAcl *dacl)
 {
        DumpId          aclDumpId = InvalidDumpId;
        DumpOptions *dopt = fout->dopt;
+       const char *acls = dacl->acl;
+       const char *acldefault = dacl->acldefault;
+       char            privtype = dacl->privtype;
+       const char *initprivs = dacl->initprivs;
+       const char *baseacls;
        PQExpBuffer sql;
 
        /* Do nothing if ACL dump is not enabled */
@@ -16714,29 +16386,52 @@ dumpACL(Archive *fout, DumpId objDumpId, DumpId 
altDumpId,
        sql = createPQExpBuffer();
 
        /*
-        * Check to see if this object has had any initial ACLs included for it.
-        * If so, we are in binary upgrade mode and these are the ACLs to turn
-        * into GRANT and REVOKE statements to set and record the initial
-        * privileges for an extension object.  Let the backend know that these
-        * are to be recorded by calling binary_upgrade_set_record_init_privs()
-        * before and after.
+        * In binary upgrade mode, we don't run an extension's script but 
instead
+        * dump out the objects independently and then recreate them.  To 
preserve
+        * any initial privileges which were set on extension objects, we need 
to
+        * compute the set of GRANT and REVOKE commands necessary to get from 
the
+        * default privileges of an object to its initial privileges as recorded
+        * in pg_init_privs.
+        *
+        * At restore time, we apply these commands after having called
+        * binary_upgrade_set_record_init_privs(true).  That tells the backend 
to
+        * copy the results into pg_init_privs.  This is how we preserve the
+        * contents of that catalog across binary upgrades.
         */
-       if (strlen(initacls) != 0 || strlen(initracls) != 0)
+       if (dopt->binary_upgrade && privtype == 'e' &&
+               initprivs && *initprivs != '\0')
        {
                appendPQExpBufferStr(sql, "SELECT 
pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
                if (!buildACLCommands(name, subname, nspname, type,
-                                                         initacls, initracls, 
owner,
+                                                         initprivs, 
acldefault, owner,
                                                          "", 
fout->remoteVersion, sql))
-                       fatal("could not parse initial GRANT ACL list (%s) or 
initial REVOKE ACL list (%s) for object \"%s\" (%s)",
-                                 initacls, initracls, name, type);
+                       fatal("could not parse initial ACL list (%s) or default 
(%s) for object \"%s\" (%s)",
+                                 initprivs, acldefault, name, type);
                appendPQExpBufferStr(sql, "SELECT 
pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
        }
 
+       /*
+        * Now figure the GRANT and REVOKE commands needed to get to the 
object's
+        * actual current ACL, starting from the initprivs if given, else from 
the
+        * object-type-specific default.  Also, while buildACLCommands will 
assume
+        * that a NULL/empty acls string means it needn't do anything, what that
+        * actually represents is the object-type-specific default; so we need 
to
+        * substitute the acldefault string to get the right results in that 
case.
+        */
+       if (initprivs && *initprivs != '\0')
+       {
+               baseacls = initprivs;
+               if (acls == NULL || *acls == '\0')
+                       acls = acldefault;
+       }
+       else
+               baseacls = acldefault;
+
        if (!buildACLCommands(name, subname, nspname, type,
-                                                 acls, racls, owner,
+                                                 acls, baseacls, owner,
                                                  "", fout->remoteVersion, sql))
-               fatal("could not parse GRANT ACL list (%s) or REVOKE ACL list 
(%s) for object \"%s\" (%s)",
-                         acls, racls, name, type);
+               fatal("could not parse ACL list (%s) or default (%s) for object 
\"%s\" (%s)",
+                         acls, baseacls, name, type);
 
        if (sql->len > 0)
        {
@@ -17146,8 +16841,7 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
                        dumpACL(fout, tbinfo->dobj.dumpId, InvalidDumpId,
                                        objtype, namecopy, NULL,
                                        tbinfo->dobj.namespace->dobj.name, 
tbinfo->rolname,
-                                       tbinfo->relacl, tbinfo->rrelacl,
-                                       tbinfo->initrelacl, 
tbinfo->initrrelacl);
+                                       &tbinfo->dacl);
        }
 
        /*
@@ -17156,7 +16850,7 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
         * miss ACLs on system columns.  Doing it this way also allows us to 
dump
         * ACLs for catalogs that we didn't mark "interesting" back in 
getTables.
         */
-       if (fout->remoteVersion >= 80400 && tbinfo->dobj.dump & 
DUMP_COMPONENT_ACL)
+       if ((tbinfo->dobj.dump & DUMP_COMPONENT_ACL) && tbinfo->hascolumnACLs)
        {
                PQExpBuffer query = createPQExpBuffer();
                PGresult   *res;
@@ -17164,55 +16858,37 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
 
                if (fout->remoteVersion >= 90600)
                {
-                       PQExpBuffer acl_subquery = createPQExpBuffer();
-                       PQExpBuffer racl_subquery = createPQExpBuffer();
-                       PQExpBuffer initacl_subquery = createPQExpBuffer();
-                       PQExpBuffer initracl_subquery = createPQExpBuffer();
-
-                       buildACLQueries(acl_subquery, racl_subquery, 
initacl_subquery,
-                                                       initracl_subquery, 
"at.attacl", "c.relowner", "'c'",
-                                                       dopt->binary_upgrade);
-
+                       /*
+                        * In principle we should call acldefault('c', 
relowner) to get
+                        * the default ACL for a column.  However, we don't 
currently
+                        * store the numeric OID of the relowner in TableInfo.  
We could
+                        * convert the owner name using regrole, but that 
creates a risk
+                        * of failure due to concurrent role renames.  Given 
that the
+                        * default ACL for columns is empty and is likely to 
stay that
+                        * way, it's not worth extra cycles and risk to avoid 
hard-wiring
+                        * that knowledge here.
+                        */
                        appendPQExpBuffer(query,
                                                          "SELECT at.attname, "
-                                                         "%s AS attacl, "
-                                                         "%s AS rattacl, "
-                                                         "%s AS initattacl, "
-                                                         "%s AS initrattacl "
+                                                         "at.attacl, "
+                                                         "'{}' AS acldefault, "
+                                                         "pip.privtype, 
pip.initprivs "
                                                          "FROM 
pg_catalog.pg_attribute at "
-                                                         "JOIN 
pg_catalog.pg_class c ON (at.attrelid = c.oid) "
                                                          "LEFT JOIN 
pg_catalog.pg_init_privs pip ON "
                                                          "(at.attrelid = 
pip.objoid "
                                                          "AND pip.classoid = 
'pg_catalog.pg_class'::pg_catalog.regclass "
                                                          "AND at.attnum = 
pip.objsubid) "
                                                          "WHERE at.attrelid = 
'%u'::pg_catalog.oid AND "
                                                          "NOT at.attisdropped "
-                                                         "AND ("
-                                                         "%s IS NOT NULL OR "
-                                                         "%s IS NOT NULL OR "
-                                                         "%s IS NOT NULL OR "
-                                                         "%s IS NOT NULL)"
+                                                         "AND (at.attacl IS 
NOT NULL OR pip.initprivs IS NOT NULL) "
                                                          "ORDER BY at.attnum",
-                                                         acl_subquery->data,
-                                                         racl_subquery->data,
-                                                         
initacl_subquery->data,
-                                                         
initracl_subquery->data,
-                                                         
tbinfo->dobj.catId.oid,
-                                                         acl_subquery->data,
-                                                         racl_subquery->data,
-                                                         
initacl_subquery->data,
-                                                         
initracl_subquery->data);
-
-                       destroyPQExpBuffer(acl_subquery);
-                       destroyPQExpBuffer(racl_subquery);
-                       destroyPQExpBuffer(initacl_subquery);
-                       destroyPQExpBuffer(initracl_subquery);
+                                                         
tbinfo->dobj.catId.oid);
                }
                else
                {
                        appendPQExpBuffer(query,
-                                                         "SELECT attname, 
attacl, NULL as rattacl, "
-                                                         "NULL AS initattacl, 
NULL AS initrattacl "
+                                                         "SELECT attname, 
attacl, '{}' AS acldefault, "
+                                                         "NULL AS privtype, 
NULL AS initprivs "
                                                          "FROM 
pg_catalog.pg_attribute "
                                                          "WHERE attrelid = 
'%u'::pg_catalog.oid AND NOT attisdropped "
                                                          "AND attacl IS NOT 
NULL "
@@ -17226,11 +16902,16 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
                {
                        char       *attname = PQgetvalue(res, i, 0);
                        char       *attacl = PQgetvalue(res, i, 1);
-                       char       *rattacl = PQgetvalue(res, i, 2);
-                       char       *initattacl = PQgetvalue(res, i, 3);
-                       char       *initrattacl = PQgetvalue(res, i, 4);
+                       char       *acldefault = PQgetvalue(res, i, 2);
+                       char            privtype = *(PQgetvalue(res, i, 3));
+                       char       *initprivs = PQgetvalue(res, i, 4);
+                       DumpableAcl coldacl;
                        char       *attnamecopy;
 
+                       coldacl.acl = attacl;
+                       coldacl.acldefault = acldefault;
+                       coldacl.privtype = privtype;
+                       coldacl.initprivs = initprivs;
                        attnamecopy = pg_strdup(fmtId(attname));
 
                        /*
@@ -17241,7 +16922,7 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
                        dumpACL(fout, tbinfo->dobj.dumpId, tableAclDumpId,
                                        "TABLE", namecopy, attnamecopy,
                                        tbinfo->dobj.namespace->dobj.name, 
tbinfo->rolname,
-                                       attacl, rattacl, initattacl, 
initrattacl);
+                                       &coldacl);
                        free(attnamecopy);
                }
                PQclear(res);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 8c84fee05fb..1badb50b482 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -154,14 +154,33 @@ typedef struct _binaryupgradeinfo
        DumpableObject dobj;
 } BinaryUpgradeInfo;
 
+/*
+ * Object types that have ACLs must store them in a DumpableAcl sub-struct,
+ * which must immediately follow the DumpableObject base struct.
+ *
+ * Note: when dumping from a pre-9.2 server, which lacks the acldefault()
+ * function, acldefault will be NULL or empty.
+ */
+typedef struct _dumpableAcl
+{
+       char       *acl;                        /* the object's actual ACL 
string */
+       char       *acldefault;         /* default ACL for the object's type & 
owner */
+       /* these fields come from the object's pg_init_privs entry, if any: */
+       char            privtype;               /* entry type, 'i' or 'e'; 0 if 
no entry */
+       char       *initprivs;          /* the object's initial ACL string, or 
NULL */
+} DumpableAcl;
+
+/* Generic struct that can be used to access any object type having an ACL */
+typedef struct _dumpableObjectWithAcl
+{
+       DumpableObject dobj;
+       DumpableAcl dacl;
+} DumpableObjectWithAcl;
 typedef struct _namespaceInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
        char       *rolname;            /* name of owner, or empty string */
-       char       *nspacl;
-       char       *rnspacl;
-       char       *initnspacl;
-       char       *initrnspacl;
 } NamespaceInfo;
 
 typedef struct _extensionInfo
@@ -177,6 +196,7 @@ typedef struct _extensionInfo
 typedef struct _typeInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
 
        /*
         * Note: dobj.name is the raw pg_type.typname entry.  ftypname is the
@@ -215,15 +235,12 @@ typedef struct _shellTypeInfo
 typedef struct _funcInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
        char       *rolname;            /* name of owner, or empty string */
        Oid                     lang;
        int                     nargs;
        Oid                *argtypes;
        Oid                     prorettype;
-       char       *proacl;
-       char       *rproacl;
-       char       *initproacl;
-       char       *initrproacl;
 } FuncInfo;
 
 /* AggInfo is a superset of FuncInfo */
@@ -236,13 +253,11 @@ typedef struct _aggInfo
 typedef struct _ptcInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
        char       *ptcreadfn;
        char       *ptcwritefn;
        char       *ptcowner;
        char       *ptcacl;
-       char       *rproacl;
-       char       *initproacl;
-       char       *initrproacl;
        bool       ptctrusted;
        Oid                ptcreadid;
        Oid                ptcwriteid;
@@ -294,11 +309,8 @@ typedef struct _tableInfo
         * These fields are collected for every table in the database.
         */
        DumpableObject dobj;
+       DumpableAcl dacl;
        char       *rolname;            /* name of owner, or empty string */
-       char       *relacl;
-       char       *rrelacl;
-       char       *initrelacl;
-       char       *initrrelacl;
        char            relkind;
        char            relstorage;
        char            relpersistence; /* relation persistence */
@@ -311,6 +323,7 @@ typedef struct _tableInfo
        bool            hasindex;               /* does it have any indexes? */
        bool            hasrules;               /* does it have any rules? */
        bool            hastriggers;    /* does it have any triggers? */
+       bool            hascolumnACLs;  /* do any columns have non-default 
ACLs? */
        bool            rowsec;                 /* is row security enabled? */
        bool            forcerowsec;    /* is row security forced? */
        bool            hasoids;                /* does it have OIDs? */
@@ -510,14 +523,11 @@ typedef struct _constraintInfo
 typedef struct _procLangInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
        bool            lanpltrusted;
        Oid                     lanplcallfoid;
        Oid                     laninline;
        Oid                     lanvalidator;
-       char       *lanacl;
-       char       *rlanacl;
-       char       *initlanacl;
-       char       *initrlanacl;
        char       *lanowner;           /* name of owner, or empty string */
 } ProcLangInfo;
 
@@ -582,49 +592,37 @@ typedef struct _cfgInfo
 typedef struct _fdwInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
        char       *rolname;
        char       *fdwhandler;
        char       *fdwvalidator;
        char       *fdwoptions;
-       char       *fdwacl;
-       char       *rfdwacl;
-       char       *initfdwacl;
-       char       *initrfdwacl;
 } FdwInfo;
 
 typedef struct _foreignServerInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
        char       *rolname;
        Oid                     srvfdw;
        char       *srvtype;
        char       *srvversion;
-       char       *srvacl;
-       char       *rsrvacl;
-       char       *initsrvacl;
-       char       *initrsrvacl;
        char       *srvoptions;
 } ForeignServerInfo;
 
 typedef struct _defaultACLInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
        char       *defaclrole;
        char            defaclobjtype;
-       char       *defaclacl;
-       char       *rdefaclacl;
-       char       *initdefaclacl;
-       char       *initrdefaclacl;
 } DefaultACLInfo;
 
 typedef struct _blobInfo
 {
        DumpableObject dobj;
+       DumpableAcl dacl;
        char       *rolname;
-       char       *blobacl;
-       char       *rblobacl;
-       char       *initblobacl;
-       char       *initrblobacl;
 } BlobInfo;
 
 /*
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 1684a2b87ca..b1ff242a5dd 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -1673,89 +1673,12 @@ dumpTablespaces(PGconn *conn)
         * [FIXME] the queries need to be slightly different if the backend 
isn't
         * Cloudberry, and the dump format should vary depending on if the dump 
is
         * --gp-syntax or --no-gp-syntax.
-        *
-        * For the tablespace ACLs, as of 9.6, we extract both the positive (as
-        * spcacl) and negative (as rspcacl) ACLs, relative to the default ACL 
for
-        * tablespaces, which are then passed to buildACLCommands() below.
-        *
-        * 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, so this logic cannot make use of buildACLQueries().
         */
-
-       if (server_version >= 140000)
-       {
-               res = executeQuery(conn, "SELECT oid, spcname, "
-                                                  
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
-                                                  
"pg_catalog.pg_tablespace_location(oid), "
-                                                  "(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'), "
-                                                  "spcfilehandlersrc AS 
spchandlersrc, "
-                                                  "spcfilehandlerbin AS 
spchandlerbin "
-                                                  "FROM 
pg_catalog.pg_tablespace "
-                                                  "WHERE spcname !~ '^pg_' "
-                                                  "ORDER BY 1");
-       }
-       else if (server_version >= 90600)
+       if (server_version >= 90200)
                res = executeQuery(conn, "SELECT oid, spcname, "
                                                   
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
                                                   
"pg_catalog.pg_tablespace_location(oid), "
-                                                  "(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'), null "
-                                                  "FROM 
pg_catalog.pg_tablespace "
-                                                  "WHERE spcname !~ '^pg_' "
-                                                  "ORDER BY 1");
-       else if (server_version >= 90200)
-               res = executeQuery(conn, "SELECT oid, spcname, "
-                                                  
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
-                                                  
"pg_catalog.pg_tablespace_location(oid), "
-                                                  "spcacl, '' as rspcacl, "
+                                                  "spcacl, acldefault('t', 
spcowner) AS acldefault, "
                                                   "array_to_string(spcoptions, 
', '),"
                                                   
"pg_catalog.shobj_description(oid, 'pg_tablespace'), null "
                                                   "FROM 
pg_catalog.pg_tablespace "
@@ -1764,7 +1687,7 @@ dumpTablespaces(PGconn *conn)
        else if (server_version >= 90000)
                res = executeQuery(conn, "SELECT oid, spcname, "
                                                   
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
-                                                  "spclocation, spcacl, '' as 
rspcacl, "
+                                                  "spclocation, spcacl, NULL 
AS acldefault, "
                                                   "array_to_string(spcoptions, 
', '),"
                                                   
"pg_catalog.shobj_description(oid, 'pg_tablespace'), null "
                                                   "FROM 
pg_catalog.pg_tablespace "
@@ -1773,8 +1696,8 @@ dumpTablespaces(PGconn *conn)
        else
                res = executeQuery(conn, "SELECT oid, spcname, "
                                                   
"pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
-                                                  "spclocation, spcacl, '' as 
rspcacl, null, "
-                                                  
"pg_catalog.shobj_description(oid, 'pg_tablespace'), null "
+                                                  "spclocation, spcacl, NULL 
AS acldefault, null, "
+                                                  
"pg_catalog.shobj_description(oid, 'pg_tablespace') "
                                                   "FROM 
pg_catalog.pg_tablespace "
                                                   "WHERE spcname !~ '^pg_' "
                                                   "ORDER BY 1");
@@ -1790,7 +1713,7 @@ dumpTablespaces(PGconn *conn)
                char       *spcowner = PQgetvalue(res, i, 2);
                char       *spclocation = PQgetvalue(res, i, 3);
                char       *spcacl = PQgetvalue(res, i, 4);
-               char       *rspcacl = PQgetvalue(res, i, 5);
+               char       *acldefault = PQgetvalue(res, i, 5);
                char       *spcoptions = PQgetvalue(res, i, 6);
                char       *spccomment = PQgetvalue(res, i, 7);
                char       *spchandlersrc = PQgetvalue(res, i, 8);
@@ -1824,9 +1747,11 @@ dumpTablespaces(PGconn *conn)
                        appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET 
(%s);\n",
                                                          fspcname, spcoptions);
 
+               /* tablespaces can't have initprivs */
+
                if (!skip_acls &&
                        !buildACLCommands(fspcname, NULL, NULL, "TABLESPACE",
-                                                         spcacl, rspcacl,
+                                                         spcacl, acldefault,
                                                          spcowner, "", 
server_version, buf))
                {
                        pg_log_error("could not parse ACL list (%s) for 
tablespace \"%s\"",
diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c
index ba409e63879..462c5bc8cea 100644
--- a/src/fe_utils/string_utils.c
+++ b/src/fe_utils/string_utils.c
@@ -909,6 +909,69 @@ parsePGArray(const char *atext, char ***itemarray, int 
*nitems)
 }
 
 
+/*
+ * Append one element to the text representation of a 1-dimensional Postgres
+ * array.
+ *
+ * The caller must provide the initial '{' and closing '}' of the array.
+ * This function handles all else, including insertion of commas and
+ * quoting of values.
+ *
+ * We assume that typdelim is ','.
+ */
+void
+appendPGArray(PQExpBuffer buffer, const char *value)
+{
+       bool            needquote;
+       const char *tmp;
+
+       if (buffer->data[buffer->len - 1] != '{')
+               appendPQExpBufferChar(buffer, ',');
+
+       /* Decide if we need quotes; this should match array_out()'s choices. */
+       if (value[0] == '\0')
+               needquote = true;               /* force quotes for empty 
string */
+       else if (pg_strcasecmp(value, "NULL") == 0)
+               needquote = true;               /* force quotes for literal 
NULL */
+       else
+               needquote = false;
+
+       if (!needquote)
+       {
+               for (tmp = value; *tmp; tmp++)
+               {
+                       char            ch = *tmp;
+
+                       if (ch == '"' || ch == '\\' ||
+                               ch == '{' || ch == '}' || ch == ',' ||
+                       /* these match array_isspace(): */
+                               ch == ' ' || ch == '\t' || ch == '\n' ||
+                               ch == '\r' || ch == '\v' || ch == '\f')
+                       {
+                               needquote = true;
+                               break;
+                       }
+               }
+       }
+
+       if (needquote)
+       {
+               appendPQExpBufferChar(buffer, '"');
+               for (tmp = value; *tmp; tmp++)
+               {
+                       char            ch = *tmp;
+
+                       if (ch == '"' || ch == '\\')
+                               appendPQExpBufferChar(buffer, '\\');
+                       appendPQExpBufferChar(buffer, ch);
+               }
+               appendPQExpBufferChar(buffer, '"');
+       }
+       else
+               appendPQExpBufferStr(buffer, value);
+}
+
+
 /*
  * Format a reloptions array and append it to the given buffer.
  *
diff --git a/src/include/fe_utils/string_utils.h 
b/src/include/fe_utils/string_utils.h
index 3bd6f26dcd4..4a25a959f00 100644
--- a/src/include/fe_utils/string_utils.h
+++ b/src/include/fe_utils/string_utils.h
@@ -52,6 +52,7 @@ extern void appendConnStrVal(PQExpBuffer buf, const char 
*str);
 extern void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname);
 
 extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems);
+extern void appendPGArray(PQExpBuffer buffer, const char *value);
 
 extern bool appendReloptionsArray(PQExpBuffer buffer, const char *reloptions,
                                                                  const char 
*prefix, int encoding, bool std_strings);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to