#include "pg_dump.h"
 #include "storage/block.h"
 
+typedef struct
+{
+   Oid         roleoid;        /* role's OID */
+   const char *rolename;       /* role's name */
+} RoleNameItem;
+
 typedef struct
 {
    const char *descr;          /* comment for an object */
 /* global decls */
 static bool dosync = true;     /* Issue fsync() to make dump durable on disk. */
 
-/* subquery used to convert user ID (eg, datdba) to user name */
-static const char *username_subquery;
-
 static Oid g_last_builtin_oid; /* value of the last builtin oid */
 
 /* The specified names/patterns should to match at least one entity */
 static bool have_extra_float_digits = false;
 static int extra_float_digits;
 
+/* sorted table of role names */
+static RoleNameItem *rolenames = NULL;
+static int nrolenames = 0;
+
 /* sorted table of comments */
 static CommentItem *comments = NULL;
 static int ncomments = 0;
 static NamespaceInfo *findNamespace(Oid nsoid);
 static void dumpTableData(Archive *fout, const TableDataInfo *tdinfo);
 static void refreshMatViewData(Archive *fout, const TableDataInfo *tdinfo);
+static const char *getRoleName(const char *roleoid_str);
+static void collectRoleNames(Archive *fout);
 static void getAdditionalACLs(Archive *fout);
 static void dumpCommentExtended(Archive *fout, const char *type,
                                const char *name, const char *namespace,
    if (fout->isStandby)
        dopt.no_unlogged_table_data = true;
 
-   /* Select the appropriate subquery to convert user IDs to names */
-   username_subquery = "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
-
    /*
     * Find the last built-in OID, if needed (prior to 8.1)
     *
    if (dopt.include_everything && !dopt.schemaOnly && !dopt.dontOutputBlobs)
        dopt.outputBlobs = true;
 
+   /*
+    * Collect role names so we can map object owner OIDs to names.
+    */
+   collectRoleNames(fout);
+
    /*
     * Now scan the database and create DumpableObject structs for all the
     * objects we intend to dump.
    int         i_tableoid,
                i_oid,
                i_datname,
-               i_dba,
+               i_datdba,
                i_encoding,
                i_collate,
                i_ctype,
    if (fout->remoteVersion >= 90300)
    {
        appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
-                         "(%s datdba) AS dba, "
+                         "datdba, "
                          "pg_encoding_to_char(encoding) AS encoding, "
                          "datcollate, datctype, datfrozenxid, datminmxid, "
                          "datacl, acldefault('d', datdba) AS acldefault, "
                          "shobj_description(oid, 'pg_database') AS description "
 
                          "FROM pg_database "
-                         "WHERE datname = current_database()",
-                         username_subquery);
+                         "WHERE datname = current_database()");
    }
    else
    {
        appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
-                         "(%s datdba) AS dba, "
+                         "datdba, "
                          "pg_encoding_to_char(encoding) AS encoding, "
                          "datcollate, datctype, datfrozenxid, 0 AS datminmxid, "
                          "datacl, acldefault('d', datdba) AS acldefault, "
                          "shobj_description(oid, 'pg_database') AS description "
 
                          "FROM pg_database "
-                         "WHERE datname = current_database()",
-                         username_subquery);
+                         "WHERE datname = current_database()");
    }
 
    res = ExecuteSqlQueryForSingleRow(fout, dbQry->data);
    i_tableoid = PQfnumber(res, "tableoid");
    i_oid = PQfnumber(res, "oid");
    i_datname = PQfnumber(res, "datname");
-   i_dba = PQfnumber(res, "dba");
+   i_datdba = PQfnumber(res, "datdba");
    i_encoding = PQfnumber(res, "encoding");
    i_collate = PQfnumber(res, "datcollate");
    i_ctype = PQfnumber(res, "datctype");
    dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
    dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
    datname = PQgetvalue(res, 0, i_datname);
-   dba = PQgetvalue(res, 0, i_dba);
+   dba = getRoleName(PQgetvalue(res, 0, i_datdba));
    encoding = PQgetvalue(res, 0, i_encoding);
    collate = PQgetvalue(res, 0, i_collate);
    ctype = PQgetvalue(res, 0, i_ctype);
 
    /* Fetch BLOB OIDs, and owner/ACL data */
    appendPQExpBuffer(blobQry,
-                     "SELECT oid, (%s lomowner) AS rolname, lomacl, "
+                     "SELECT oid, lomowner, lomacl, "
                      "acldefault('L', lomowner) AS acldefault "
-                     "FROM pg_largeobject_metadata",
-                     username_subquery);
+                     "FROM pg_largeobject_metadata");
 
    res = ExecuteSqlQuery(fout, blobQry->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
-   i_lomowner = PQfnumber(res, "rolname");
+   i_lomowner = PQfnumber(res, "lomowner");
    i_lomacl = PQfnumber(res, "lomacl");
    i_acldefault = PQfnumber(res, "acldefault");
 
        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].rolname = getRoleName(PQgetvalue(res, i, i_lomowner));
 
        /* Blobs have data */
        binfo[i].dobj.components |= DUMP_COMPONENT_DATA;
    int         i_tableoid;
    int         i_oid;
    int         i_pubname;
-   int         i_rolname;
+   int         i_pubowner;
    int         i_puballtables;
    int         i_pubinsert;
    int         i_pubupdate;
    if (fout->remoteVersion >= 130000)
        appendPQExpBuffer(query,
                          "SELECT p.tableoid, p.oid, p.pubname, "
-                         "(%s p.pubowner) AS rolname, "
+                         "p.pubowner, "
                          "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot "
-                         "FROM pg_publication p",
-                         username_subquery);
+                         "FROM pg_publication p");
    else if (fout->remoteVersion >= 110000)
        appendPQExpBuffer(query,
                          "SELECT p.tableoid, p.oid, p.pubname, "
-                         "(%s p.pubowner) AS rolname, "
+                         "p.pubowner, "
                          "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot "
-                         "FROM pg_publication p",
-                         username_subquery);
+                         "FROM pg_publication p");
    else
        appendPQExpBuffer(query,
                          "SELECT p.tableoid, p.oid, p.pubname, "
-                         "(%s p.pubowner) AS rolname, "
+                         "p.pubowner, "
                          "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot "
-                         "FROM pg_publication p",
-                         username_subquery);
+                         "FROM pg_publication p");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_tableoid = PQfnumber(res, "tableoid");
    i_oid = PQfnumber(res, "oid");
    i_pubname = PQfnumber(res, "pubname");
-   i_rolname = PQfnumber(res, "rolname");
+   i_pubowner = PQfnumber(res, "pubowner");
    i_puballtables = PQfnumber(res, "puballtables");
    i_pubinsert = PQfnumber(res, "pubinsert");
    i_pubupdate = PQfnumber(res, "pubupdate");
        pubinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
        AssignDumpId(&pubinfo[i].dobj);
        pubinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_pubname));
-       pubinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       pubinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_pubowner));
        pubinfo[i].puballtables =
            (strcmp(PQgetvalue(res, i, i_puballtables), "t") == 0);
        pubinfo[i].pubinsert =
        pubinfo[i].pubviaroot =
            (strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0);
 
-       if (strlen(pubinfo[i].rolname) == 0)
-           pg_log_warning("owner of publication \"%s\" appears to be invalid",
-                          pubinfo[i].dobj.name);
-
        /* Decide whether we want to dump it */
        selectDumpableObject(&(pubinfo[i].dobj), fout);
    }
    int         i_tableoid;
    int         i_oid;
    int         i_subname;
-   int         i_rolname;
+   int         i_subowner;
    int         i_substream;
    int         i_subtwophasestate;
    int         i_subconninfo;
    /* Get the subscriptions in current database. */
    appendPQExpBuffer(query,
                      "SELECT s.tableoid, s.oid, s.subname,\n"
-                     " (%s s.subowner) AS rolname,\n"
+                     " s.subowner,\n"
                      " s.subconninfo, s.subslotname, s.subsynccommit,\n"
-                     " s.subpublications,\n",
-                     username_subquery);
+                     " s.subpublications,\n");
 
    if (fout->remoteVersion >= 140000)
        appendPQExpBufferStr(query, " s.subbinary,\n");
    i_tableoid = PQfnumber(res, "tableoid");
    i_oid = PQfnumber(res, "oid");
    i_subname = PQfnumber(res, "subname");
-   i_rolname = PQfnumber(res, "rolname");
+   i_subowner = PQfnumber(res, "subowner");
    i_subconninfo = PQfnumber(res, "subconninfo");
    i_subslotname = PQfnumber(res, "subslotname");
    i_subsynccommit = PQfnumber(res, "subsynccommit");
        subinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
        AssignDumpId(&subinfo[i].dobj);
        subinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_subname));
-       subinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       subinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_subowner));
        subinfo[i].subconninfo = pg_strdup(PQgetvalue(res, i, i_subconninfo));
        if (PQgetisnull(res, i, i_subslotname))
            subinfo[i].subslotname = NULL;
        subinfo[i].subtwophasestate =
            pg_strdup(PQgetvalue(res, i, i_subtwophasestate));
 
-       if (strlen(subinfo[i].rolname) == 0)
-           pg_log_warning("owner of subscription \"%s\" appears to be invalid",
-                          subinfo[i].dobj.name);
-
        /* Decide whether we want to dump it */
        selectDumpableObject(&(subinfo[i].dobj), fout);
    }
    int         i_oid;
    int         i_nspname;
    int         i_nspowner;
-   int         i_rolname;
    int         i_nspacl;
    int         i_acldefault;
 
     */
    appendPQExpBuffer(query, "SELECT n.tableoid, n.oid, n.nspname, "
                      "n.nspowner, "
-                     "(%s nspowner) AS rolname, "
                      "n.nspacl, "
                      "acldefault('n', n.nspowner) AS acldefault "
-                     "FROM pg_namespace n",
-                     username_subquery);
+                     "FROM pg_namespace n");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_nspname = PQfnumber(res, "nspname");
    i_nspowner = PQfnumber(res, "nspowner");
-   i_rolname = PQfnumber(res, "rolname");
    i_nspacl = PQfnumber(res, "nspacl");
    i_acldefault = PQfnumber(res, "acldefault");
 
    for (i = 0; i < ntups; i++)
    {
+       const char *nspowner;
+
        nsinfo[i].dobj.objType = DO_NAMESPACE;
        nsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
        nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
        nsinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
        nsinfo[i].dacl.privtype = 0;
        nsinfo[i].dacl.initprivs = NULL;
-       nsinfo[i].nspowner = atooid(PQgetvalue(res, i, i_nspowner));
-       nsinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       nspowner = PQgetvalue(res, i, i_nspowner);
+       nsinfo[i].nspowner = atooid(nspowner);
+       nsinfo[i].rolname = getRoleName(nspowner);
 
        /* Decide whether to dump this namespace */
        selectDumpableNamespace(&nsinfo[i], fout);
            destroyPQExpBuffer(aclarray);
            destroyPQExpBuffer(aclitem);
        }
-
-       if (strlen(nsinfo[i].rolname) == 0)
-           pg_log_warning("owner of schema \"%s\" appears to be invalid",
-                          nsinfo[i].dobj.name);
    }
 
    PQclear(res);
    int         i_typnamespace;
    int         i_typacl;
    int         i_acldefault;
-   int         i_rolname;
+   int         i_typowner;
    int         i_typelem;
    int         i_typrelid;
    int         i_typrelkind;
    appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
                      "typnamespace, typacl, "
                      "acldefault('T', typowner) AS acldefault, "
-                     "(%s typowner) AS rolname, "
+                     "typowner, "
                      "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",
-                     username_subquery);
+                     "FROM pg_type");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_typnamespace = PQfnumber(res, "typnamespace");
    i_typacl = PQfnumber(res, "typacl");
    i_acldefault = PQfnumber(res, "acldefault");
-   i_rolname = PQfnumber(res, "rolname");
+   i_typowner = PQfnumber(res, "typowner");
    i_typelem = PQfnumber(res, "typelem");
    i_typrelid = PQfnumber(res, "typrelid");
    i_typrelkind = PQfnumber(res, "typrelkind");
        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].rolname = getRoleName(PQgetvalue(res, i, i_typowner));
        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);
             */
            stinfo->dobj.dump = DUMP_COMPONENT_NONE;
        }
-
-       if (strlen(tyinfo[i].rolname) == 0)
-           pg_log_warning("owner of data type \"%s\" appears to be invalid",
-                          tyinfo[i].dobj.name);
    }
 
    *numTypes = ntups;
    int         i_oid;
    int         i_oprname;
    int         i_oprnamespace;
-   int         i_rolname;
+   int         i_oprowner;
    int         i_oprkind;
    int         i_oprcode;
 
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
                      "oprnamespace, "
-                     "(%s oprowner) AS rolname, "
+                     "oprowner, "
                      "oprkind, "
                      "oprcode::oid AS oprcode "
-                     "FROM pg_operator",
-                     username_subquery);
+                     "FROM pg_operator");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_oprname = PQfnumber(res, "oprname");
    i_oprnamespace = PQfnumber(res, "oprnamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_oprowner = PQfnumber(res, "oprowner");
    i_oprkind = PQfnumber(res, "oprkind");
    i_oprcode = PQfnumber(res, "oprcode");
 
        oprinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oprname));
        oprinfo[i].dobj.namespace =
            findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace)));
-       oprinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       oprinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_oprowner));
        oprinfo[i].oprkind = (PQgetvalue(res, i, i_oprkind))[0];
        oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
 
        /* Decide whether we want to dump it */
        selectDumpableObject(&(oprinfo[i].dobj), fout);
-
-       if (strlen(oprinfo[i].rolname) == 0)
-           pg_log_warning("owner of operator \"%s\" appears to be invalid",
-                          oprinfo[i].dobj.name);
    }
 
    PQclear(res);
    int         i_oid;
    int         i_collname;
    int         i_collnamespace;
-   int         i_rolname;
+   int         i_collowner;
 
    query = createPQExpBuffer();
 
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, collname, "
                      "collnamespace, "
-                     "(%s collowner) AS rolname "
-                     "FROM pg_collation",
-                     username_subquery);
+                     "collowner "
+                     "FROM pg_collation");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_collname = PQfnumber(res, "collname");
    i_collnamespace = PQfnumber(res, "collnamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_collowner = PQfnumber(res, "collowner");
 
    for (i = 0; i < ntups; i++)
    {
        collinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_collname));
        collinfo[i].dobj.namespace =
            findNamespace(atooid(PQgetvalue(res, i, i_collnamespace)));
-       collinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       collinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_collowner));
 
        /* Decide whether we want to dump it */
        selectDumpableObject(&(collinfo[i].dobj), fout);
    int         i_oid;
    int         i_conname;
    int         i_connamespace;
-   int         i_rolname;
+   int         i_conowner;
 
    query = createPQExpBuffer();
 
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
                      "connamespace, "
-                     "(%s conowner) AS rolname "
-                     "FROM pg_conversion",
-                     username_subquery);
+                     "conowner "
+                     "FROM pg_conversion");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_conname = PQfnumber(res, "conname");
    i_connamespace = PQfnumber(res, "connamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_conowner = PQfnumber(res, "conowner");
 
    for (i = 0; i < ntups; i++)
    {
        convinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
        convinfo[i].dobj.namespace =
            findNamespace(atooid(PQgetvalue(res, i, i_connamespace)));
-       convinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       convinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_conowner));
 
        /* Decide whether we want to dump it */
        selectDumpableObject(&(convinfo[i].dobj), fout);
    int         i_oid;
    int         i_opcname;
    int         i_opcnamespace;
-   int         i_rolname;
+   int         i_opcowner;
 
    /*
     * find all opclasses, including builtin opclasses; we filter out
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
                      "opcnamespace, "
-                     "(%s opcowner) AS rolname "
-                     "FROM pg_opclass",
-                     username_subquery);
+                     "opcowner "
+                     "FROM pg_opclass");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_opcname = PQfnumber(res, "opcname");
    i_opcnamespace = PQfnumber(res, "opcnamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_opcowner = PQfnumber(res, "opcowner");
 
    for (i = 0; i < ntups; i++)
    {
        opcinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opcname));
        opcinfo[i].dobj.namespace =
            findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace)));
-       opcinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       opcinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_opcowner));
 
        /* Decide whether we want to dump it */
        selectDumpableObject(&(opcinfo[i].dobj), fout);
-
-       if (strlen(opcinfo[i].rolname) == 0)
-           pg_log_warning("owner of operator class \"%s\" appears to be invalid",
-                          opcinfo[i].dobj.name);
    }
 
    PQclear(res);
    int         i_oid;
    int         i_opfname;
    int         i_opfnamespace;
-   int         i_rolname;
+   int         i_opfowner;
 
    query = createPQExpBuffer();
 
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
                      "opfnamespace, "
-                     "(%s opfowner) AS rolname "
-                     "FROM pg_opfamily",
-                     username_subquery);
+                     "opfowner "
+                     "FROM pg_opfamily");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_opfname = PQfnumber(res, "opfname");
    i_opfnamespace = PQfnumber(res, "opfnamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_opfowner = PQfnumber(res, "opfowner");
 
    for (i = 0; i < ntups; i++)
    {
        opfinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opfname));
        opfinfo[i].dobj.namespace =
            findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace)));
-       opfinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       opfinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_opfowner));
 
        /* Decide whether we want to dump it */
        selectDumpableObject(&(opfinfo[i].dobj), fout);
-
-       if (strlen(opfinfo[i].rolname) == 0)
-           pg_log_warning("owner of operator family \"%s\" appears to be invalid",
-                          opfinfo[i].dobj.name);
    }
 
    PQclear(res);
    int         i_aggnamespace;
    int         i_pronargs;
    int         i_proargtypes;
-   int         i_rolname;
+   int         i_proowner;
    int         i_aggacl;
    int         i_acldefault;
 
                          "p.proname AS aggname, "
                          "p.pronamespace AS aggnamespace, "
                          "p.pronargs, p.proargtypes, "
-                         "(%s p.proowner) AS rolname, "
+                         "p.proowner, "
                          "p.proacl AS aggacl, "
                          "acldefault('f', p.proowner) AS acldefault "
                          "FROM pg_proc p "
                          "(SELECT oid FROM pg_namespace "
                          "WHERE nspname = 'pg_catalog') OR "
                          "p.proacl IS DISTINCT FROM pip.initprivs",
-                         username_subquery,
                          agg_check);
        if (dopt->binary_upgrade)
            appendPQExpBufferStr(query,
        appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
                          "pronamespace AS aggnamespace, "
                          "pronargs, proargtypes, "
-                         "(%s proowner) AS rolname, "
+                         "proowner, "
                          "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);
+                         "WHERE nspname = 'pg_catalog')");
        if (dopt->binary_upgrade)
            appendPQExpBufferStr(query,
                                 " OR EXISTS(SELECT 1 FROM pg_depend WHERE "
    i_aggnamespace = PQfnumber(res, "aggnamespace");
    i_pronargs = PQfnumber(res, "pronargs");
    i_proargtypes = PQfnumber(res, "proargtypes");
-   i_rolname = PQfnumber(res, "rolname");
+   i_proowner = PQfnumber(res, "proowner");
    i_aggacl = PQfnumber(res, "aggacl");
    i_acldefault = PQfnumber(res, "acldefault");
 
        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.rolname = getRoleName(PQgetvalue(res, i, i_proowner));
        agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */
        agginfo[i].aggfn.prorettype = InvalidOid;   /* not saved */
        agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
    int         i_oid;
    int         i_proname;
    int         i_pronamespace;
-   int         i_rolname;
+   int         i_proowner;
    int         i_prolang;
    int         i_pronargs;
    int         i_proargtypes;
                          "p.proacl, "
                          "acldefault('f', p.proowner) AS acldefault, "
                          "p.pronamespace, "
-                         "(%s p.proowner) AS rolname "
+                         "p.proowner "
                          "FROM pg_proc p "
                          "LEFT JOIN pg_init_privs pip ON "
                          "(p.oid = pip.objoid "
                          "\n  WHERE pg_transform.oid > %u AND "
                          "\n  (p.oid = pg_transform.trffromsql"
                          "\n  OR p.oid = pg_transform.trftosql))",
-                         username_subquery,
                          not_agg_check,
                          g_last_builtin_oid,
                          g_last_builtin_oid);
                          "pronargs, proargtypes, prorettype, proacl, "
                          "acldefault('f', proowner) AS acldefault, "
                          "pronamespace, "
-                         "(%s proowner) AS rolname "
+                         "proowner "
                          "FROM pg_proc p "
                          "WHERE NOT proisagg"
                          "\n  AND NOT EXISTS (SELECT 1 FROM pg_depend "
                          "\n  OR EXISTS (SELECT 1 FROM pg_cast"
                          "\n  WHERE pg_cast.oid > '%u'::oid"
                          "\n  AND p.oid = pg_cast.castfunc)",
-                         username_subquery,
                          g_last_builtin_oid);
 
        if (fout->remoteVersion >= 90500)
    i_oid = PQfnumber(res, "oid");
    i_proname = PQfnumber(res, "proname");
    i_pronamespace = PQfnumber(res, "pronamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_proowner = PQfnumber(res, "proowner");
    i_prolang = PQfnumber(res, "prolang");
    i_pronargs = PQfnumber(res, "pronargs");
    i_proargtypes = PQfnumber(res, "proargtypes");
        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].rolname = getRoleName(PQgetvalue(res, i, i_proowner));
        finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
        finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
        finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
        /* Mark whether function has an ACL */
        if (!PQgetisnull(res, i, i_proacl))
            finfo[i].dobj.components |= DUMP_COMPONENT_ACL;
-
-       if (strlen(finfo[i].rolname) == 0)
-           pg_log_warning("owner of function \"%s\" appears to be invalid",
-                          finfo[i].dobj.name);
    }
 
    PQclear(res);
    int         i_relnamespace;
    int         i_relkind;
    int         i_reltype;
-   int         i_rolname;
+   int         i_relowner;
    int         i_relchecks;
    int         i_relhasindex;
    int         i_relhasrules;
    appendPQExpBuffer(query,
                      "SELECT c.tableoid, c.oid, c.relname, "
                      "c.relnamespace, c.relkind, c.reltype, "
-                     "(%s c.relowner) AS rolname, "
+                     "c.relowner, "
                      "c.relchecks, "
                      "c.relhasindex, c.relhasrules, c.relpages, "
                      "c.relhastriggers, "
                      "tc.reloptions AS toast_reloptions, "
                      "d.refobjid AS owning_tab, "
                      "d.refobjsubid AS owning_col, "
-                     "tsp.spcname AS reltablespace, ",
-                     username_subquery);
+                     "tsp.spcname AS reltablespace, ");
 
    if (fout->remoteVersion >= 120000)
        appendPQExpBufferStr(query,
 
    if (fout->remoteVersion >= 90600)
        appendPQExpBufferStr(query,
-                            "c.relkind = " CppAsString2(RELKIND_SEQUENCE)
-                            " AND EXISTS (SELECT 1 FROM pg_depend "
-                            "WHERE classid = 'pg_class'::regclass AND "
-                            "objid = c.oid AND objsubid = 0 AND "
-                            "refclassid = 'pg_class'::regclass AND "
-                            "deptype = 'i') AS is_identity_sequence, ");
+                            "(d.deptype = 'i') IS TRUE AS is_identity_sequence, ");
    else
        appendPQExpBufferStr(query,
                             "false AS is_identity_sequence, ");
    i_relnamespace = PQfnumber(res, "relnamespace");
    i_relkind = PQfnumber(res, "relkind");
    i_reltype = PQfnumber(res, "reltype");
-   i_rolname = PQfnumber(res, "rolname");
+   i_relowner = PQfnumber(res, "relowner");
    i_relchecks = PQfnumber(res, "relchecks");
    i_relhasindex = PQfnumber(res, "relhasindex");
    i_relhasrules = PQfnumber(res, "relhasrules");
        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));
+       tblinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_relowner));
        tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
        tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
        tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0);
                              fmtQualifiedDumpable(&tblinfo[i]));
            ExecuteSqlStatement(fout, query->data);
        }
-
-       /* Emit notice if join for owner failed */
-       if (strlen(tblinfo[i].rolname) == 0)
-           pg_log_warning("owner of table \"%s\" appears to be invalid",
-                          tblinfo[i].dobj.name);
    }
 
    if (dopt->lockWaitTimeout)
    int         i_oid;
    int         i_stxname;
    int         i_stxnamespace;
-   int         i_rolname;
+   int         i_stxowner;
    int         i_stattarget;
    int         i;
 
 
    if (fout->remoteVersion < 130000)
        appendPQExpBuffer(query, "SELECT tableoid, oid, stxname, "
-                         "stxnamespace, (%s stxowner) AS rolname, (-1) AS stxstattarget "
-                         "FROM pg_catalog.pg_statistic_ext",
-                         username_subquery);
+                         "stxnamespace, stxowner, (-1) AS stxstattarget "
+                         "FROM pg_catalog.pg_statistic_ext");
    else
        appendPQExpBuffer(query, "SELECT tableoid, oid, stxname, "
-                         "stxnamespace, (%s stxowner) AS rolname, stxstattarget "
-                         "FROM pg_catalog.pg_statistic_ext",
-                         username_subquery);
+                         "stxnamespace, stxowner, stxstattarget "
+                         "FROM pg_catalog.pg_statistic_ext");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_stxname = PQfnumber(res, "stxname");
    i_stxnamespace = PQfnumber(res, "stxnamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_stxowner = PQfnumber(res, "stxowner");
    i_stattarget = PQfnumber(res, "stxstattarget");
 
    statsextinfo = (StatsExtInfo *) pg_malloc(ntups * sizeof(StatsExtInfo));
        statsextinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_stxname));
        statsextinfo[i].dobj.namespace =
            findNamespace(atooid(PQgetvalue(res, i, i_stxnamespace)));
-       statsextinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       statsextinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_stxowner));
        statsextinfo[i].stattarget = atoi(PQgetvalue(res, i, i_stattarget));
 
        /* Decide whether we want to dump it */
 
    appendPQExpBuffer(query,
                      "SELECT e.tableoid, e.oid, evtname, evtenabled, "
-                     "evtevent, (%s evtowner) AS evtowner, "
+                     "evtevent, evtowner, "
                      "array_to_string(array("
                      "select quote_literal(x) "
                      " from unnest(evttags) as t(x)), ', ') as evttags, "
                      "e.evtfoid::regproc as evtfname "
                      "FROM pg_event_trigger e "
-                     "ORDER BY e.oid",
-                     username_subquery);
+                     "ORDER BY e.oid");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
        evtinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_evtname));
        evtinfo[i].evtname = pg_strdup(PQgetvalue(res, i, i_evtname));
        evtinfo[i].evtevent = pg_strdup(PQgetvalue(res, i, i_evtevent));
-       evtinfo[i].evtowner = pg_strdup(PQgetvalue(res, i, i_evtowner));
+       evtinfo[i].evtowner = getRoleName(PQgetvalue(res, i, i_evtowner));
        evtinfo[i].evttags = pg_strdup(PQgetvalue(res, i, i_evttags));
        evtinfo[i].evtfname = pg_strdup(PQgetvalue(res, i, i_evtfname));
        evtinfo[i].evtenabled = *(PQgetvalue(res, i, i_evtenabled));
                      "laninline, lanvalidator, "
                      "lanacl, "
                      "acldefault('l', lanowner) AS acldefault, "
-                     "(%s lanowner) AS lanowner "
+                     "lanowner "
                      "FROM pg_language "
                      "WHERE lanispl "
-                     "ORDER BY oid",
-                     username_subquery);
+                     "ORDER BY oid");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
        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].lanowner = pg_strdup(PQgetvalue(res, i, i_lanowner));
+       planginfo[i].lanowner = getRoleName(PQgetvalue(res, i, i_lanowner));
 
        /* Decide whether we want to dump it */
        selectDumpableProcLang(&(planginfo[i]), fout);
    int         i_oid;
    int         i_dictname;
    int         i_dictnamespace;
-   int         i_rolname;
+   int         i_dictowner;
    int         i_dicttemplate;
    int         i_dictinitoption;
 
    query = createPQExpBuffer();
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, "
-                     "dictnamespace, (%s dictowner) AS rolname, "
+                     "dictnamespace, dictowner, "
                      "dicttemplate, dictinitoption "
-                     "FROM pg_ts_dict",
-                     username_subquery);
+                     "FROM pg_ts_dict");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_dictname = PQfnumber(res, "dictname");
    i_dictnamespace = PQfnumber(res, "dictnamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_dictowner = PQfnumber(res, "dictowner");
    i_dictinitoption = PQfnumber(res, "dictinitoption");
    i_dicttemplate = PQfnumber(res, "dicttemplate");
 
        dictinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_dictname));
        dictinfo[i].dobj.namespace =
            findNamespace(atooid(PQgetvalue(res, i, i_dictnamespace)));
-       dictinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       dictinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_dictowner));
        dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate));
        if (PQgetisnull(res, i, i_dictinitoption))
            dictinfo[i].dictinitoption = NULL;
    int         i_oid;
    int         i_cfgname;
    int         i_cfgnamespace;
-   int         i_rolname;
+   int         i_cfgowner;
    int         i_cfgparser;
 
    query = createPQExpBuffer();
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, "
-                     "cfgnamespace, (%s cfgowner) AS rolname, cfgparser "
-                     "FROM pg_ts_config",
-                     username_subquery);
+                     "cfgnamespace, cfgowner, cfgparser "
+                     "FROM pg_ts_config");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_oid = PQfnumber(res, "oid");
    i_cfgname = PQfnumber(res, "cfgname");
    i_cfgnamespace = PQfnumber(res, "cfgnamespace");
-   i_rolname = PQfnumber(res, "rolname");
+   i_cfgowner = PQfnumber(res, "cfgowner");
    i_cfgparser = PQfnumber(res, "cfgparser");
 
    for (i = 0; i < ntups; i++)
        cfginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_cfgname));
        cfginfo[i].dobj.namespace =
            findNamespace(atooid(PQgetvalue(res, i, i_cfgnamespace)));
-       cfginfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+       cfginfo[i].rolname = getRoleName(PQgetvalue(res, i, i_cfgowner));
        cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
 
        /* Decide whether we want to dump it */
    int         i_tableoid;
    int         i_oid;
    int         i_fdwname;
-   int         i_rolname;
+   int         i_fdwowner;
    int         i_fdwhandler;
    int         i_fdwvalidator;
    int         i_fdwacl;
    query = createPQExpBuffer();
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
-                     "(%s fdwowner) AS rolname, "
+                     "fdwowner, "
                      "fdwhandler::pg_catalog.regproc, "
                      "fdwvalidator::pg_catalog.regproc, "
                      "fdwacl, "
                      "FROM pg_options_to_table(fdwoptions) "
                      "ORDER BY option_name"
                      "), E',\n    ') AS fdwoptions "
-                     "FROM pg_foreign_data_wrapper",
-                     username_subquery);
+                     "FROM pg_foreign_data_wrapper");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_tableoid = PQfnumber(res, "tableoid");
    i_oid = PQfnumber(res, "oid");
    i_fdwname = PQfnumber(res, "fdwname");
-   i_rolname = PQfnumber(res, "rolname");
+   i_fdwowner = PQfnumber(res, "fdwowner");
    i_fdwhandler = PQfnumber(res, "fdwhandler");
    i_fdwvalidator = PQfnumber(res, "fdwvalidator");
    i_fdwacl = PQfnumber(res, "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].rolname = getRoleName(PQgetvalue(res, i, i_fdwowner));
        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));
    int         i_tableoid;
    int         i_oid;
    int         i_srvname;
-   int         i_rolname;
+   int         i_srvowner;
    int         i_srvfdw;
    int         i_srvtype;
    int         i_srvversion;
    query = createPQExpBuffer();
 
    appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
-                     "(%s srvowner) AS rolname, "
+                     "srvowner, "
                      "srvfdw, srvtype, srvversion, srvacl, "
                      "acldefault('S', srvowner) AS acldefault, "
                      "array_to_string(ARRAY("
                      "FROM pg_options_to_table(srvoptions) "
                      "ORDER BY option_name"
                      "), E',\n    ') AS srvoptions "
-                     "FROM pg_foreign_server",
-                     username_subquery);
+                     "FROM pg_foreign_server");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
    i_tableoid = PQfnumber(res, "tableoid");
    i_oid = PQfnumber(res, "oid");
    i_srvname = PQfnumber(res, "srvname");
-   i_rolname = PQfnumber(res, "rolname");
+   i_srvowner = PQfnumber(res, "srvowner");
    i_srvfdw = PQfnumber(res, "srvfdw");
    i_srvtype = PQfnumber(res, "srvtype");
    i_srvversion = PQfnumber(res, "srvversion");
        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].rolname = getRoleName(PQgetvalue(res, i, i_srvowner));
        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));
     */
    appendPQExpBuffer(query,
                      "SELECT oid, tableoid, "
-                     "(%s defaclrole) AS defaclrole, "
+                     "defaclrole, "
                      "defaclnamespace, "
                      "defaclobjtype, "
                      "defaclacl, "
                      "acldefault(CASE WHEN defaclobjtype = 'S' "
                      "THEN 's'::\"char\" ELSE defaclobjtype END, "
                      "defaclrole) ELSE '{}' END AS acldefault "
-                     "FROM pg_default_acl",
-                     username_subquery);
+                     "FROM pg_default_acl");
 
    res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
        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].defaclrole = getRoleName(PQgetvalue(res, i, i_defaclrole));
        daclinfo[i].defaclobjtype = *(PQgetvalue(res, i, i_defaclobjtype));
 
        /* Default ACLs are ACLs, of course */
    return daclinfo;
 }
 
+/*
+ * getRoleName -- look up the name of a role, given its OID
+ *
+ * In current usage, we don't expect failures, so error out for a bad OID.
+ */
+static const char *
+getRoleName(const char *roleoid_str)
+{
+   Oid         roleoid = atooid(roleoid_str);
+
+   /*
+    * Do binary search to find the appropriate item.
+    */
+   if (nrolenames > 0)
+   {
+       RoleNameItem *low = &rolenames[0];
+       RoleNameItem *high = &rolenames[nrolenames - 1];
+
+       while (low <= high)
+       {
+           RoleNameItem *middle = low + (high - low) / 2;
+
+           if (roleoid < middle->roleoid)
+               high = middle - 1;
+           else if (roleoid > middle->roleoid)
+               low = middle + 1;
+           else
+               return middle->rolename;    /* found a match */
+       }
+   }
+
+   fatal("role with OID %u does not exist", roleoid);
+   return NULL;                /* keep compiler quiet */
+}
+
+/*
+ * collectRoleNames --
+ *
+ * Construct a table of all known roles.
+ * The table is sorted by OID for speed in lookup.
+ */
+static void
+collectRoleNames(Archive *fout)
+{
+   PGresult   *res;
+   const char *query;
+   int         i;
+
+   query = "SELECT oid, rolname FROM pg_catalog.pg_roles ORDER BY 1";
+
+   res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
+
+   nrolenames = PQntuples(res);
+
+   rolenames = (RoleNameItem *) pg_malloc(nrolenames * sizeof(RoleNameItem));
+
+   for (i = 0; i < nrolenames; i++)
+   {
+       rolenames[i].roleoid = atooid(PQgetvalue(res, i, 0));
+       rolenames[i].rolename = pg_strdup(PQgetvalue(res, i, 1));
+   }
+
+   PQclear(res);
+}
+
 /*
  * getAdditionalACLs
  *