These patches take the dozens of mostly-duplicate pg_foo_ownercheck() and pg_foo_aclcheck() functions and replace (most of) them by common functions that are driven by the ObjectProperty table. All the required information is already in that table.

This is similar to the consolidation of the drop-by-OID functions that we did a while ago (b1d32d3e3230f00b5baba08f75b4f665c7d6dac6).
From fc98a7bdb9f2d1a47f67305c78aecc385cc10f21 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Fri, 14 Oct 2022 09:16:51 +0200
Subject: [PATCH] Refactor ownercheck functions

Instead of dozens of mostly-duplicate pg_foo_ownercheck() functions,
write one common function object_ownercheck() that can handle almost
all of them.  We already have all the information we need, such as
which system catalog corresponds to which catalog table, and which
column is the owner column.

I kept a few pg_foo_ownercheck() around as thin wrappers because they
are widely used through the code.  And there are also a couple that
don't work via the generic function, so those stay as is.
---
 src/backend/catalog/aclchk.c            | 517 ++----------------------
 src/backend/catalog/objectaddress.c     |  92 +----
 src/backend/commands/collationcmds.c    |   2 +-
 src/backend/commands/event_trigger.c    |   4 +-
 src/backend/commands/foreigncmds.c      |   6 +-
 src/backend/commands/proclang.c         |   2 +-
 src/backend/commands/publicationcmds.c  |   4 +-
 src/backend/commands/statscmds.c        |   2 +-
 src/backend/commands/subscriptioncmds.c |   6 +-
 src/backend/commands/tablespace.c       |   6 +-
 src/backend/commands/tsearchcmds.c      |   4 +-
 src/include/utils/acl.h                 |  22 +-
 12 files changed, 71 insertions(+), 596 deletions(-)

diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index aa5a2ed9483e..d67d3b522cef 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -32,6 +32,7 @@
 #include "catalog/pg_am.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_cast.h"
+#include "catalog/pg_class.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_conversion.h"
 #include "catalog/pg_database.h"
@@ -5111,25 +5112,30 @@ pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
 }
 
 /*
- * Ownership check for a relation (specified by OID).
+ * Generic ownership check for an object
  */
 bool
-pg_class_ownercheck(Oid class_oid, Oid roleid)
+object_ownercheck(Oid classid, Oid objectid, Oid roleid)
 {
        HeapTuple       tuple;
        Oid                     ownerId;
+       bool            isnull;
 
        /* Superusers bypass all permission checking. */
        if (superuser_arg(roleid))
                return true;
 
-       tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid));
+       tuple = SearchSysCache1(get_object_catcache_oid(classid), 
ObjectIdGetDatum(objectid));
        if (!HeapTupleIsValid(tuple))
                ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_TABLE),
-                                errmsg("relation with OID %u does not exist", 
class_oid)));
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("%s with OID %u does not exist", 
get_object_class_descr(classid), objectid)));
 
-       ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
+       ownerId = 
DatumGetObjectId(SysCacheGetAttr(get_object_catcache_oid(classid),
+                                                                               
           tuple,
+                                                                               
           get_object_attnum_owner(classid),
+                                                                               
           &isnull));
+       Assert(!isnull);
 
        ReleaseSysCache(tuple);
 
@@ -5137,107 +5143,43 @@ pg_class_ownercheck(Oid class_oid, Oid roleid)
 }
 
 /*
- * Ownership check for a type (specified by OID).
+ * Wrapper functions for commonly used cases
  */
+
 bool
-pg_type_ownercheck(Oid type_oid, Oid roleid)
+pg_class_ownercheck(Oid class_oid, Oid roleid)
 {
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("type with OID %u does not exist", 
type_oid)));
-
-       ownerId = ((Form_pg_type) GETSTRUCT(tuple))->typowner;
-
-       ReleaseSysCache(tuple);
+       return object_ownercheck(RelationRelationId, class_oid, roleid);
+}
 
-       return has_privs_of_role(roleid, ownerId);
+bool
+pg_type_ownercheck(Oid type_oid, Oid roleid)
+{
+       return object_ownercheck(TypeRelationId, type_oid, roleid);
 }
 
-/*
- * Ownership check for an operator (specified by OID).
- */
 bool
 pg_oper_ownercheck(Oid oper_oid, Oid roleid)
 {
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(oper_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                                errmsg("operator with OID %u does not exist", 
oper_oid)));
-
-       ownerId = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
+       return object_ownercheck(OperatorRelationId, oper_oid, roleid);
 }
 
-/*
- * Ownership check for a function (specified by OID).
- */
 bool
 pg_proc_ownercheck(Oid proc_oid, Oid roleid)
 {
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                                errmsg("function with OID %u does not exist", 
proc_oid)));
-
-       ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
+       return object_ownercheck(ProcedureRelationId, proc_oid, roleid);
 }
 
-/*
- * Ownership check for a procedural language (specified by OID)
- */
 bool
-pg_language_ownercheck(Oid lan_oid, Oid roleid)
+pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
 {
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lan_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                                errmsg("language with OID %u does not exist", 
lan_oid)));
-
-       ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
-
-       ReleaseSysCache(tuple);
+       return object_ownercheck(NamespaceRelationId, nsp_oid, roleid);
+}
 
-       return has_privs_of_role(roleid, ownerId);
+bool
+pg_database_ownercheck(Oid db_oid, Oid roleid)
+{
+       return object_ownercheck(DatabaseRelationId, db_oid, roleid);
 }
 
 /*
@@ -5286,326 +5228,6 @@ pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid)
        return has_privs_of_role(roleid, ownerId);
 }
 
-/*
- * Ownership check for a namespace (specified by OID).
- */
-bool
-pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_SCHEMA),
-                                errmsg("schema with OID %u does not exist", 
nsp_oid)));
-
-       ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a tablespace (specified by OID).
- */
-bool
-pg_tablespace_ownercheck(Oid spc_oid, Oid roleid)
-{
-       HeapTuple       spctuple;
-       Oid                     spcowner;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       /* Search syscache for pg_tablespace */
-       spctuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
-       if (!HeapTupleIsValid(spctuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("tablespace with OID %u does not 
exist", spc_oid)));
-
-       spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;
-
-       ReleaseSysCache(spctuple);
-
-       return has_privs_of_role(roleid, spcowner);
-}
-
-/*
- * Ownership check for an operator class (specified by OID).
- */
-bool
-pg_opclass_ownercheck(Oid opc_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opc_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("operator class with OID %u does not 
exist",
-                                               opc_oid)));
-
-       ownerId = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for an operator family (specified by OID).
- */
-bool
-pg_opfamily_ownercheck(Oid opf_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opf_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("operator family with OID %u does not 
exist",
-                                               opf_oid)));
-
-       ownerId = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a text search dictionary (specified by OID).
- */
-bool
-pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dict_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("text search dictionary with OID %u 
does not exist",
-                                               dict_oid)));
-
-       ownerId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a text search configuration (specified by OID).
- */
-bool
-pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfg_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("text search configuration with OID %u 
does not exist",
-                                               cfg_oid)));
-
-       ownerId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a foreign-data wrapper (specified by OID).
- */
-bool
-pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, 
ObjectIdGetDatum(srv_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("foreign-data wrapper with OID %u does 
not exist",
-                                               srv_oid)));
-
-       ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a foreign server (specified by OID).
- */
-bool
-pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("foreign server with OID %u does not 
exist",
-                                               srv_oid)));
-
-       ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for an event trigger (specified by OID).
- */
-bool
-pg_event_trigger_ownercheck(Oid et_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(et_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("event trigger with OID %u does not 
exist",
-                                               et_oid)));
-
-       ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a database (specified by OID).
- */
-bool
-pg_database_ownercheck(Oid db_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     dba;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_DATABASE),
-                                errmsg("database with OID %u does not exist", 
db_oid)));
-
-       dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, dba);
-}
-
-/*
- * Ownership check for a collation (specified by OID).
- */
-bool
-pg_collation_ownercheck(Oid coll_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("collation with OID %u does not exist", 
coll_oid)));
-
-       ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a conversion (specified by OID).
- */
-bool
-pg_conversion_ownercheck(Oid conv_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("conversion with OID %u does not 
exist", conv_oid)));
-
-       ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
 /*
  * Ownership check for an extension (specified by OID).
  */
@@ -5648,85 +5270,6 @@ pg_extension_ownercheck(Oid ext_oid, Oid roleid)
        return has_privs_of_role(roleid, ownerId);
 }
 
-/*
- * Ownership check for a publication (specified by OID).
- */
-bool
-pg_publication_ownercheck(Oid pub_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pub_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("publication with OID %u does not 
exist", pub_oid)));
-
-       ownerId = ((Form_pg_publication) GETSTRUCT(tuple))->pubowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a subscription (specified by OID).
- */
-bool
-pg_subscription_ownercheck(Oid sub_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(sub_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("subscription with OID %u does not 
exist", sub_oid)));
-
-       ownerId = ((Form_pg_subscription) GETSTRUCT(tuple))->subowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
-/*
- * Ownership check for a statistics object (specified by OID).
- */
-bool
-pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid)
-{
-       HeapTuple       tuple;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return true;
-
-       tuple = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stat_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("statistics object with OID %u does not 
exist",
-                                               stat_oid)));
-
-       ownerId = ((Form_pg_statistic_ext) GETSTRUCT(tuple))->stxowner;
-
-       ReleaseSysCache(tuple);
-
-       return has_privs_of_role(roleid, ownerId);
-}
-
 /*
  * Check whether specified role has CREATEROLE privilege (or is a superuser)
  *
diff --git a/src/backend/catalog/objectaddress.c 
b/src/backend/catalog/objectaddress.c
index 284ca55469e0..80c9110fd1a8 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -2443,11 +2443,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, 
ObjectAddress address,
                                aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
                                                           
RelationGetRelationName(relation));
                        break;
-               case OBJECT_DATABASE:
-                       if (!pg_database_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          strVal(object));
-                       break;
                case OBJECT_TYPE:
                case OBJECT_DOMAIN:
                case OBJECT_ATTRIBUTE:
@@ -2481,27 +2476,32 @@ check_object_ownership(Oid roleid, ObjectType objtype, 
ObjectAddress address,
                case OBJECT_FUNCTION:
                case OBJECT_PROCEDURE:
                case OBJECT_ROUTINE:
-                       if (!pg_proc_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          
NameListToString((castNode(ObjectWithArgs, object))->objname));
-                       break;
                case OBJECT_OPERATOR:
-                       if (!pg_oper_ownercheck(address.objectId, roleid))
+                       if (!object_ownercheck(address.classId, 
address.objectId, roleid))
                                aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
                                                           
NameListToString((castNode(ObjectWithArgs, object))->objname));
                        break;
+               case OBJECT_DATABASE:
+               case OBJECT_EVENT_TRIGGER:
+               case OBJECT_FDW:
+               case OBJECT_FOREIGN_SERVER:
+               case OBJECT_LANGUAGE:
+               case OBJECT_PUBLICATION:
                case OBJECT_SCHEMA:
-                       if (!pg_namespace_ownercheck(address.objectId, roleid))
+               case OBJECT_SUBSCRIPTION:
+               case OBJECT_TABLESPACE:
+                       if (!object_ownercheck(address.classId, 
address.objectId, roleid))
                                aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
                                                           strVal(object));
                        break;
                case OBJECT_COLLATION:
-                       if (!pg_collation_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          
NameListToString(castNode(List, object)));
-                       break;
                case OBJECT_CONVERSION:
-                       if (!pg_conversion_ownercheck(address.objectId, roleid))
+               case OBJECT_OPCLASS:
+               case OBJECT_OPFAMILY:
+               case OBJECT_STATISTIC_EXT:
+               case OBJECT_TSDICTIONARY:
+               case OBJECT_TSCONFIGURATION:
+                       if (!object_ownercheck(address.classId, 
address.objectId, roleid))
                                aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
                                                           
NameListToString(castNode(List, object)));
                        break;
@@ -2510,36 +2510,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, 
ObjectAddress address,
                                aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
                                                           strVal(object));
                        break;
-               case OBJECT_FDW:
-                       if 
(!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          strVal(object));
-                       break;
-               case OBJECT_FOREIGN_SERVER:
-                       if (!pg_foreign_server_ownercheck(address.objectId, 
roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          strVal(object));
-                       break;
-               case OBJECT_EVENT_TRIGGER:
-                       if (!pg_event_trigger_ownercheck(address.objectId, 
roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          strVal(object));
-                       break;
-               case OBJECT_LANGUAGE:
-                       if (!pg_language_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          strVal(object));
-                       break;
-               case OBJECT_OPCLASS:
-                       if (!pg_opclass_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          
NameListToString(castNode(List, object)));
-                       break;
-               case OBJECT_OPFAMILY:
-                       if (!pg_opfamily_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          
NameListToString(castNode(List, object)));
-                       break;
                case OBJECT_LARGEOBJECT:
                        if (!lo_compat_privileges &&
                                !pg_largeobject_ownercheck(address.objectId, 
roleid))
@@ -2565,16 +2535,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, 
ObjectAddress address,
                                                                        
format_type_be(targettypeid))));
                        }
                        break;
-               case OBJECT_PUBLICATION:
-                       if (!pg_publication_ownercheck(address.objectId, 
roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          strVal(object));
-                       break;
-               case OBJECT_SUBSCRIPTION:
-                       if (!pg_subscription_ownercheck(address.objectId, 
roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          strVal(object));
-                       break;
                case OBJECT_TRANSFORM:
                        {
                                TypeName   *typename = linitial_node(TypeName, 
castNode(List, object));
@@ -2584,21 +2544,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, 
ObjectAddress address,
                                        aclcheck_error_type(ACLCHECK_NOT_OWNER, 
typeid);
                        }
                        break;
-               case OBJECT_TABLESPACE:
-                       if (!pg_tablespace_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          strVal(object));
-                       break;
-               case OBJECT_TSDICTIONARY:
-                       if (!pg_ts_dict_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          
NameListToString(castNode(List, object)));
-                       break;
-               case OBJECT_TSCONFIGURATION:
-                       if (!pg_ts_config_ownercheck(address.objectId, roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          
NameListToString(castNode(List, object)));
-                       break;
                case OBJECT_ROLE:
 
                        /*
@@ -2630,11 +2575,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, 
ObjectAddress address,
                                                
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                                 errmsg("must be superuser")));
                        break;
-               case OBJECT_STATISTIC_EXT:
-                       if (!pg_statistics_object_ownercheck(address.objectId, 
roleid))
-                               aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
-                                                          
NameListToString(castNode(List, object)));
-                       break;
                default:
                        elog(ERROR, "unrecognized object type: %d",
                                 (int) objtype);
diff --git a/src/backend/commands/collationcmds.c 
b/src/backend/commands/collationcmds.c
index fcfc02d2aede..25c1e485c458 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -365,7 +365,7 @@ AlterCollation(AlterCollationStmt *stmt)
        rel = table_open(CollationRelationId, RowExclusiveLock);
        collOid = get_collation_oid(stmt->collname, false);
 
-       if (!pg_collation_ownercheck(collOid, GetUserId()))
+       if (!object_ownercheck(CollationRelationId, collOid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_COLLATION,
                                           NameListToString(stmt->collname));
 
diff --git a/src/backend/commands/event_trigger.c 
b/src/backend/commands/event_trigger.c
index 441f29d684ff..7ed9c80fc63c 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -379,7 +379,7 @@ AlterEventTrigger(AlterEventTrigStmt *stmt)
        evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
        trigoid = evtForm->oid;
 
-       if (!pg_event_trigger_ownercheck(trigoid, GetUserId()))
+       if (!object_ownercheck(EventTriggerRelationId, trigoid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER,
                                           stmt->trigname);
 
@@ -471,7 +471,7 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple 
tup, Oid newOwnerId)
        if (form->evtowner == newOwnerId)
                return;
 
-       if (!pg_event_trigger_ownercheck(form->oid, GetUserId()))
+       if (!object_ownercheck(EventTriggerRelationId, form->oid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER,
                                           NameStr(form->evtname));
 
diff --git a/src/backend/commands/foreigncmds.c 
b/src/backend/commands/foreigncmds.c
index 91f4dd30de18..e6e6d128d11a 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -358,7 +358,7 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple 
tup, Oid newOwnerId)
                        srvId = form->oid;
 
                        /* Must be owner */
-                       if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
+                       if (!object_ownercheck(ForeignServerRelationId, srvId, 
GetUserId()))
                                aclcheck_error(ACLCHECK_NOT_OWNER, 
OBJECT_FOREIGN_SERVER,
                                                           
NameStr(form->srvname));
 
@@ -998,7 +998,7 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
        /*
         * Only owner or a superuser can ALTER a SERVER.
         */
-       if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
+       if (!object_ownercheck(ForeignServerRelationId, srvId, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FOREIGN_SERVER,
                                           stmt->servername);
 
@@ -1076,7 +1076,7 @@ user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, 
const char *servername)
 {
        Oid                     curuserid = GetUserId();
 
-       if (!pg_foreign_server_ownercheck(serverid, curuserid))
+       if (!object_ownercheck(ForeignServerRelationId, serverid, curuserid))
        {
                if (umuserid == curuserid)
                {
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 4a093f45d85a..96a524be36aa 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -134,7 +134,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 
                /* This is currently pointless, since we already checked 
superuser */
 #ifdef NOT_USED
-               if (!pg_language_ownercheck(oldform->oid, languageOwner))
+               if (!object_ownercheck(LanguageRelationId, oldform->oid, 
languageOwner))
                        aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_LANGUAGE,
                                                   languageName);
 #endif
diff --git a/src/backend/commands/publicationcmds.c 
b/src/backend/commands/publicationcmds.c
index a8b75eb1be8b..3d0f712a4faf 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -1394,7 +1394,7 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt 
*stmt)
        pubform = (Form_pg_publication) GETSTRUCT(tup);
 
        /* must be owner */
-       if (!pg_publication_ownercheck(pubform->oid, GetUserId()))
+       if (!object_ownercheck(PublicationRelationId, pubform->oid, 
GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
                                           stmt->pubname);
 
@@ -1905,7 +1905,7 @@ AlterPublicationOwner_internal(Relation rel, HeapTuple 
tup, Oid newOwnerId)
                AclResult       aclresult;
 
                /* Must be owner */
-               if (!pg_publication_ownercheck(form->oid, GetUserId()))
+               if (!object_ownercheck(PublicationRelationId, form->oid, 
GetUserId()))
                        aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
                                                   NameStr(form->pubname));
 
diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
index 55216d28916b..0d87318e0233 100644
--- a/src/backend/commands/statscmds.c
+++ b/src/backend/commands/statscmds.c
@@ -665,7 +665,7 @@ AlterStatistics(AlterStatsStmt *stmt)
                elog(ERROR, "cache lookup failed for extended statistics object 
%u", stxoid);
 
        /* Must be owner of the existing statistics object */
-       if (!pg_statistics_object_ownercheck(stxoid, GetUserId()))
+       if (!object_ownercheck(StatisticExtRelationId, stxoid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_STATISTIC_EXT,
                                           NameListToString(stmt->defnames));
 
diff --git a/src/backend/commands/subscriptioncmds.c 
b/src/backend/commands/subscriptioncmds.c
index 8fb89a9392c8..a69b9a38bdcf 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1032,7 +1032,7 @@ AlterSubscription(ParseState *pstate, 
AlterSubscriptionStmt *stmt,
        subid = form->oid;
 
        /* must be owner */
-       if (!pg_subscription_ownercheck(subid, GetUserId()))
+       if (!object_ownercheck(SubscriptionRelationId, subid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION,
                                           stmt->subname);
 
@@ -1413,7 +1413,7 @@ DropSubscription(DropSubscriptionStmt *stmt, bool 
isTopLevel)
        subid = form->oid;
 
        /* must be owner */
-       if (!pg_subscription_ownercheck(subid, GetUserId()))
+       if (!object_ownercheck(SubscriptionRelationId, subid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION,
                                           stmt->subname);
 
@@ -1704,7 +1704,7 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple 
tup, Oid newOwnerId)
        if (form->subowner == newOwnerId)
                return;
 
-       if (!pg_subscription_ownercheck(form->oid, GetUserId()))
+       if (!object_ownercheck(SubscriptionRelationId, form->oid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION,
                                           NameStr(form->subname));
 
diff --git a/src/backend/commands/tablespace.c 
b/src/backend/commands/tablespace.c
index b69ff37dbbdc..12c7993b15aa 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -446,7 +446,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
        tablespaceoid = spcform->oid;
 
        /* Must be tablespace owner */
-       if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId()))
+       if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, 
GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
                                           tablespacename);
 
@@ -966,7 +966,7 @@ RenameTableSpace(const char *oldname, const char *newname)
        table_endscan(scan);
 
        /* Must be owner */
-       if (!pg_tablespace_ownercheck(tspId, GetUserId()))
+       if (!object_ownercheck(TableSpaceRelationId, tspId, GetUserId()))
                aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE, oldname);
 
        /* Validate new name */
@@ -1051,7 +1051,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
        tablespaceoid = ((Form_pg_tablespace) GETSTRUCT(tup))->oid;
 
        /* Must be owner of the existing object */
-       if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId()))
+       if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, 
GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
                                           stmt->tablespacename);
 
diff --git a/src/backend/commands/tsearchcmds.c 
b/src/backend/commands/tsearchcmds.c
index 4cc4e3c00f8e..365bfd30fdfe 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -510,7 +510,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
                         dictId);
 
        /* must be owner */
-       if (!pg_ts_dict_ownercheck(dictId, GetUserId()))
+       if (!object_ownercheck(TSDictionaryRelationId, dictId, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TSDICTIONARY,
                                           NameListToString(stmt->dictname));
 
@@ -1124,7 +1124,7 @@ AlterTSConfiguration(AlterTSConfigurationStmt *stmt)
        cfgId = ((Form_pg_ts_config) GETSTRUCT(tup))->oid;
 
        /* must be owner */
-       if (!pg_ts_config_ownercheck(cfgId, GetUserId()))
+       if (!object_ownercheck(TSConfigRelationId, cfgId, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TSCONFIGURATION,
                                           NameListToString(stmt->cfgname));
 
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 9a4df3a5dacc..bf461f24fde7 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -306,28 +306,20 @@ extern void removeExtObjInitPriv(Oid objoid, Oid 
classoid);
 
 
 /* ownercheck routines just return true (owner) or false (not) */
+extern bool object_ownercheck(Oid classid, Oid objectid, Oid roleid);
+
+/* wrapper functions for commonly used cases */
 extern bool pg_class_ownercheck(Oid class_oid, Oid roleid);
 extern bool pg_type_ownercheck(Oid type_oid, Oid roleid);
 extern bool pg_oper_ownercheck(Oid oper_oid, Oid roleid);
 extern bool pg_proc_ownercheck(Oid proc_oid, Oid roleid);
-extern bool pg_language_ownercheck(Oid lan_oid, Oid roleid);
-extern bool pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid);
 extern bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid);
-extern bool pg_tablespace_ownercheck(Oid spc_oid, Oid roleid);
-extern bool pg_opclass_ownercheck(Oid opc_oid, Oid roleid);
-extern bool pg_opfamily_ownercheck(Oid opf_oid, Oid roleid);
 extern bool pg_database_ownercheck(Oid db_oid, Oid roleid);
-extern bool pg_collation_ownercheck(Oid coll_oid, Oid roleid);
-extern bool pg_conversion_ownercheck(Oid conv_oid, Oid roleid);
-extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid);
-extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid);
-extern bool pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid);
-extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid);
-extern bool pg_event_trigger_ownercheck(Oid et_oid, Oid roleid);
+
+/* special cases */
+extern bool pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid);
 extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid);
-extern bool pg_publication_ownercheck(Oid pub_oid, Oid roleid);
-extern bool pg_subscription_ownercheck(Oid sub_oid, Oid roleid);
-extern bool pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid);
+
 extern bool has_createrole_privilege(Oid roleid);
 extern bool has_bypassrls_privilege(Oid roleid);
 
-- 
2.37.3

From 15c6a6dd5ab08027a324eeb11c0a9b519c4b3d94 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Fri, 14 Oct 2022 09:16:51 +0200
Subject: [PATCH] Refactor aclcheck functions

Instead of dozens of mostly-duplicate pg_foo_aclcheck() functions,
write one common function object_aclcheck() that can handle almost all
of them.  We already have all the information we need, such as which
system catalog corresponds to which catalog table, and which column is
the ACL column.

I kept a few pg_foo_aclcheck() around as thin wrappers because they
are widely used through the code.  And there are also a few that don't
work via the generic function, so those stay as is.

I also changed most pg_foo_aclmask() functions to static functions,
since they are not used outside of aclchk.c.
---
 contrib/dblink/dblink.c             |   2 +-
 src/backend/catalog/aclchk.c        | 601 +++++++---------------------
 src/backend/commands/foreigncmds.c  |  10 +-
 src/backend/commands/functioncmds.c |   6 +-
 src/backend/utils/adt/acl.c         |  52 +--
 src/backend/utils/fmgr/fmgr.c       |   2 +-
 src/include/utils/acl.h             |  47 +--
 7 files changed, 188 insertions(+), 532 deletions(-)

diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 9eef417c47b7..f8b017fd3a29 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2838,7 +2838,7 @@ get_connect_string(const char *servername)
                fdw = GetForeignDataWrapper(fdwid);
 
                /* Check permissions, user must have usage on the server. */
-               aclresult = pg_foreign_server_aclcheck(serverid, userid, 
ACL_USAGE);
+               aclresult = object_aclcheck(ForeignServerRelationId, serverid, 
userid, ACL_USAGE);
                if (aclresult != ACLCHECK_OK)
                        aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, 
foreign_server->servername);
 
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index d67d3b522cef..9e8ec306f639 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -139,8 +139,26 @@ static AclMode restrict_and_check_grant(bool is_grant, 
AclMode avail_goptions,
                                                                                
Oid objectId, Oid grantorId,
                                                                                
ObjectType objtype, const char *objname,
                                                                                
AttrNumber att_number, const char *colname);
-static AclMode pg_aclmask(ObjectType objtype, Oid table_oid, AttrNumber attnum,
+static AclMode pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber 
attnum,
                                                  Oid roleid, AclMode mask, 
AclMaskHow how);
+static AclMode object_aclmask(Oid classid, Oid objectid, Oid roleid,
+                                                         AclMode mask, 
AclMaskHow how);
+static AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum,
+                                                                       Oid 
roleid, AclMode mask, AclMaskHow how);
+static AclMode pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum,
+                                                                               
Oid roleid, AclMode mask,
+                                                                               
AclMaskHow how, bool *is_missing);
+static AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid,
+                                                                       AclMode 
mask, AclMaskHow how,
+                                                                       bool 
*is_missing);
+static AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid,
+                                                                               
AclMode mask, AclMaskHow how);
+static AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
+                                                                               
           AclMode mask, AclMaskHow how, Snapshot snapshot);
+static AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
+                                                                       AclMode 
mask, AclMaskHow how);
+static AclMode pg_type_aclmask(Oid type_oid, Oid roleid,
+                                                          AclMode mask, 
AclMaskHow how);
 static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
                                                                        Acl 
*new_acl);
 static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int 
objsubid,
@@ -3787,47 +3805,47 @@ aclcheck_error_type(AclResult aclerr, Oid typeOid)
  * Relay for the various pg_*_mask routines depending on object kind
  */
 static AclMode
-pg_aclmask(ObjectType objtype, Oid table_oid, AttrNumber attnum, Oid roleid,
+pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid,
                   AclMode mask, AclMaskHow how)
 {
        switch (objtype)
        {
                case OBJECT_COLUMN:
                        return
-                               pg_class_aclmask(table_oid, roleid, mask, how) |
-                               pg_attribute_aclmask(table_oid, attnum, roleid, 
mask, how);
+                               pg_class_aclmask(object_oid, roleid, mask, how) 
|
+                               pg_attribute_aclmask(object_oid, attnum, 
roleid, mask, how);
                case OBJECT_TABLE:
                case OBJECT_SEQUENCE:
-                       return pg_class_aclmask(table_oid, roleid, mask, how);
+                       return pg_class_aclmask(object_oid, roleid, mask, how);
                case OBJECT_DATABASE:
-                       return pg_database_aclmask(table_oid, roleid, mask, 
how);
+                       return object_aclmask(DatabaseRelationId, object_oid, 
roleid, mask, how);
                case OBJECT_FUNCTION:
-                       return pg_proc_aclmask(table_oid, roleid, mask, how);
+                       return object_aclmask(ProcedureRelationId, object_oid, 
roleid, mask, how);
                case OBJECT_LANGUAGE:
-                       return pg_language_aclmask(table_oid, roleid, mask, 
how);
+                       return object_aclmask(LanguageRelationId, object_oid, 
roleid, mask, how);
                case OBJECT_LARGEOBJECT:
-                       return pg_largeobject_aclmask_snapshot(table_oid, 
roleid,
+                       return pg_largeobject_aclmask_snapshot(object_oid, 
roleid,
                                                                                
                   mask, how, NULL);
                case OBJECT_PARAMETER_ACL:
-                       return pg_parameter_acl_aclmask(table_oid, roleid, 
mask, how);
+                       return pg_parameter_acl_aclmask(object_oid, roleid, 
mask, how);
                case OBJECT_SCHEMA:
-                       return pg_namespace_aclmask(table_oid, roleid, mask, 
how);
+                       return pg_namespace_aclmask(object_oid, roleid, mask, 
how);
                case OBJECT_STATISTIC_EXT:
                        elog(ERROR, "grantable rights not supported for 
statistics objects");
                        /* not reached, but keep compiler quiet */
                        return ACL_NO_RIGHTS;
                case OBJECT_TABLESPACE:
-                       return pg_tablespace_aclmask(table_oid, roleid, mask, 
how);
+                       return object_aclmask(TableSpaceRelationId, object_oid, 
roleid, mask, how);
                case OBJECT_FDW:
-                       return pg_foreign_data_wrapper_aclmask(table_oid, 
roleid, mask, how);
+                       return object_aclmask(ForeignDataWrapperRelationId, 
object_oid, roleid, mask, how);
                case OBJECT_FOREIGN_SERVER:
-                       return pg_foreign_server_aclmask(table_oid, roleid, 
mask, how);
+                       return object_aclmask(ForeignServerRelationId, 
object_oid, roleid, mask, how);
                case OBJECT_EVENT_TRIGGER:
                        elog(ERROR, "grantable rights not supported for event 
triggers");
                        /* not reached, but keep compiler quiet */
                        return ACL_NO_RIGHTS;
                case OBJECT_TYPE:
-                       return pg_type_aclmask(table_oid, roleid, mask, how);
+                       return pg_type_aclmask(object_oid, roleid, mask, how);
                default:
                        elog(ERROR, "unrecognized objtype: %d",
                                 (int) objtype);
@@ -3849,14 +3867,72 @@ pg_aclmask(ObjectType objtype, Oid table_oid, 
AttrNumber attnum, Oid roleid,
  */
 
 /*
- * Exported routine for examining a user's privileges for a column
+ * Generic routine for examining a user's privileges for an object
+ */
+static AclMode
+object_aclmask(Oid classid, Oid objectid, Oid roleid,
+                          AclMode mask, AclMaskHow how)
+{
+       AclMode         result;
+       HeapTuple       tuple;
+       Datum           aclDatum;
+       bool            isNull;
+       Acl                *acl;
+       Oid                     ownerId;
+
+       /* Superusers bypass all permission checking. */
+       if (superuser_arg(roleid))
+               return mask;
+
+       /*
+        * Get the objects's ACL from its catalog
+        */
+       tuple = SearchSysCache1(get_object_catcache_oid(classid), 
ObjectIdGetDatum(objectid));
+       if (!HeapTupleIsValid(tuple))
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_DATABASE),
+                                errmsg("%s with OID %u does not exist", 
get_object_class_descr(classid), objectid)));
+
+       ownerId = 
DatumGetObjectId(SysCacheGetAttr(get_object_catcache_oid(classid),
+                                                                               
           tuple,
+                                                                               
           get_object_attnum_owner(classid),
+                                                                               
           &isNull));
+       Assert(!isNull);
+
+       aclDatum = SysCacheGetAttr(get_object_catcache_oid(classid), tuple, 
get_object_attnum_acl(classid),
+                                                          &isNull);
+       if (isNull)
+       {
+               /* No ACL, so build default ACL */
+               acl = acldefault(get_object_type(classid, objectid), ownerId);
+               aclDatum = (Datum) 0;
+       }
+       else
+       {
+               /* detoast ACL if necessary */
+               acl = DatumGetAclP(aclDatum);
+       }
+
+       result = aclmask(acl, roleid, ownerId, mask, how);
+
+       /* if we have a detoasted copy, free it */
+       if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+               pfree(acl);
+
+       ReleaseSysCache(tuple);
+
+       return result;
+}
+
+/*
+ * Routine for examining a user's privileges for a column
  *
  * Note: this considers only privileges granted specifically on the column.
  * It is caller's responsibility to take relation-level privileges into account
  * as appropriate.  (For the same reason, we have no special case for
  * superuser-ness here.)
  */
-AclMode
+static AclMode
 pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid,
                                         AclMode mask, AclMaskHow how)
 {
@@ -3865,12 +3941,12 @@ pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, 
Oid roleid,
 }
 
 /*
- * Exported routine for examining a user's privileges for a column
+ * Routine for examining a user's privileges for a column
  *
  * Does the bulk of the work for pg_attribute_aclmask(), and allows other
  * callers to avoid the missing attribute ERROR when is_missing is non-NULL.
  */
-AclMode
+static AclMode
 pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum, Oid roleid,
                                                 AclMode mask, AclMaskHow how, 
bool *is_missing)
 {
@@ -3983,12 +4059,12 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
 }
 
 /*
- * Exported routine for examining a user's privileges for a table
+ * Routine for examining a user's privileges for a table
  *
  * Does the bulk of the work for pg_class_aclmask(), and allows other
  * callers to avoid the missing relation ERROR when is_missing is non-NULL.
  */
-AclMode
+static AclMode
 pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask,
                                         AclMaskHow how, bool *is_missing)
 {
@@ -4104,64 +4180,10 @@ pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode 
mask,
 }
 
 /*
- * Exported routine for examining a user's privileges for a database
- */
-AclMode
-pg_database_aclmask(Oid db_oid, Oid roleid,
-                                       AclMode mask, AclMaskHow how)
-{
-       AclMode         result;
-       HeapTuple       tuple;
-       Datum           aclDatum;
-       bool            isNull;
-       Acl                *acl;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return mask;
-
-       /*
-        * Get the database's ACL from pg_database
-        */
-       tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_DATABASE),
-                                errmsg("database with OID %u does not exist", 
db_oid)));
-
-       ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
-
-       aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
-                                                          &isNull);
-       if (isNull)
-       {
-               /* No ACL, so build default ACL */
-               acl = acldefault(OBJECT_DATABASE, ownerId);
-               aclDatum = (Datum) 0;
-       }
-       else
-       {
-               /* detoast ACL if necessary */
-               acl = DatumGetAclP(aclDatum);
-       }
-
-       result = aclmask(acl, roleid, ownerId, mask, how);
-
-       /* if we have a detoasted copy, free it */
-       if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
-               pfree(acl);
-
-       ReleaseSysCache(tuple);
-
-       return result;
-}
-
-/*
- * Exported routine for examining a user's privileges for a configuration
+ * Routine for examining a user's privileges for a configuration
  * parameter (GUC), identified by GUC name.
  */
-AclMode
+static AclMode
 pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow 
how)
 {
        AclMode         result;
@@ -4222,10 +4244,10 @@ pg_parameter_aclmask(const char *name, Oid roleid, 
AclMode mask, AclMaskHow how)
 }
 
 /*
- * Exported routine for examining a user's privileges for a configuration
+ * Routine for examining a user's privileges for a configuration
  * parameter (GUC), identified by the OID of its pg_parameter_acl entry.
  */
-AclMode
+static AclMode
 pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
 {
        AclMode         result;
@@ -4273,115 +4295,7 @@ pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, 
AclMode mask, AclMaskHow how)
 }
 
 /*
- * Exported routine for examining a user's privileges for a function
- */
-AclMode
-pg_proc_aclmask(Oid proc_oid, Oid roleid,
-                               AclMode mask, AclMaskHow how)
-{
-       AclMode         result;
-       HeapTuple       tuple;
-       Datum           aclDatum;
-       bool            isNull;
-       Acl                *acl;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return mask;
-
-       /*
-        * Get the function's ACL from pg_proc
-        */
-       tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                                errmsg("function with OID %u does not exist", 
proc_oid)));
-
-       ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
-
-       aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
-                                                          &isNull);
-       if (isNull)
-       {
-               /* No ACL, so build default ACL */
-               acl = acldefault(OBJECT_FUNCTION, ownerId);
-               aclDatum = (Datum) 0;
-       }
-       else
-       {
-               /* detoast ACL if necessary */
-               acl = DatumGetAclP(aclDatum);
-       }
-
-       result = aclmask(acl, roleid, ownerId, mask, how);
-
-       /* if we have a detoasted copy, free it */
-       if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
-               pfree(acl);
-
-       ReleaseSysCache(tuple);
-
-       return result;
-}
-
-/*
- * Exported routine for examining a user's privileges for a language
- */
-AclMode
-pg_language_aclmask(Oid lang_oid, Oid roleid,
-                                       AclMode mask, AclMaskHow how)
-{
-       AclMode         result;
-       HeapTuple       tuple;
-       Datum           aclDatum;
-       bool            isNull;
-       Acl                *acl;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return mask;
-
-       /*
-        * Get the language's ACL from pg_language
-        */
-       tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lang_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("language with OID %u does not exist", 
lang_oid)));
-
-       ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
-
-       aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
-                                                          &isNull);
-       if (isNull)
-       {
-               /* No ACL, so build default ACL */
-               acl = acldefault(OBJECT_LANGUAGE, ownerId);
-               aclDatum = (Datum) 0;
-       }
-       else
-       {
-               /* detoast ACL if necessary */
-               acl = DatumGetAclP(aclDatum);
-       }
-
-       result = aclmask(acl, roleid, ownerId, mask, how);
-
-       /* if we have a detoasted copy, free it */
-       if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
-               pfree(acl);
-
-       ReleaseSysCache(tuple);
-
-       return result;
-}
-
-/*
- * Exported routine for examining a user's privileges for a largeobject
+ * Routine for examining a user's privileges for a largeobject
  *
  * When a large object is opened for reading, it is opened relative to the
  * caller's snapshot, but when it is opened for writing, a current
@@ -4392,7 +4306,7 @@ pg_language_aclmask(Oid lang_oid, Oid roleid,
  * snapshot, since all we do with the snapshot argument is pass it through
  * to systable_beginscan().
  */
-AclMode
+static AclMode
 pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
                                                                AclMode mask, 
AclMaskHow how,
                                                                Snapshot 
snapshot)
@@ -4463,9 +4377,9 @@ pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
 }
 
 /*
- * Exported routine for examining a user's privileges for a namespace
+ * Routine for examining a user's privileges for a namespace
  */
-AclMode
+static AclMode
 pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
                                         AclMode mask, AclMaskHow how)
 {
@@ -4555,189 +4469,9 @@ pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
 }
 
 /*
- * Exported routine for examining a user's privileges for a tablespace
+ * Routine for examining a user's privileges for a type.
  */
-AclMode
-pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
-                                         AclMode mask, AclMaskHow how)
-{
-       AclMode         result;
-       HeapTuple       tuple;
-       Datum           aclDatum;
-       bool            isNull;
-       Acl                *acl;
-       Oid                     ownerId;
-
-       /* Superusers bypass all permission checking. */
-       if (superuser_arg(roleid))
-               return mask;
-
-       /*
-        * Get the tablespace's ACL from pg_tablespace
-        */
-       tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("tablespace with OID %u does not 
exist", spc_oid)));
-
-       ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;
-
-       aclDatum = SysCacheGetAttr(TABLESPACEOID, tuple,
-                                                          
Anum_pg_tablespace_spcacl,
-                                                          &isNull);
-
-       if (isNull)
-       {
-               /* No ACL, so build default ACL */
-               acl = acldefault(OBJECT_TABLESPACE, ownerId);
-               aclDatum = (Datum) 0;
-       }
-       else
-       {
-               /* detoast ACL if necessary */
-               acl = DatumGetAclP(aclDatum);
-       }
-
-       result = aclmask(acl, roleid, ownerId, mask, how);
-
-       /* if we have a detoasted copy, free it */
-       if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
-               pfree(acl);
-
-       ReleaseSysCache(tuple);
-
-       return result;
-}
-
-/*
- * Exported routine for examining a user's privileges for a foreign
- * data wrapper
- */
-AclMode
-pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
-                                                               AclMode mask, 
AclMaskHow how)
-{
-       AclMode         result;
-       HeapTuple       tuple;
-       Datum           aclDatum;
-       bool            isNull;
-       Acl                *acl;
-       Oid                     ownerId;
-
-       Form_pg_foreign_data_wrapper fdwForm;
-
-       /* Bypass permission checks for superusers */
-       if (superuser_arg(roleid))
-               return mask;
-
-       /*
-        * Must get the FDW's tuple from pg_foreign_data_wrapper
-        */
-       tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, 
ObjectIdGetDatum(fdw_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("foreign-data wrapper with OID %u does 
not exist",
-                                               fdw_oid)));
-       fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
-
-       /*
-        * Normal case: get the FDW's ACL from pg_foreign_data_wrapper
-        */
-       ownerId = fdwForm->fdwowner;
-
-       aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
-                                                          
Anum_pg_foreign_data_wrapper_fdwacl, &isNull);
-       if (isNull)
-       {
-               /* No ACL, so build default ACL */
-               acl = acldefault(OBJECT_FDW, ownerId);
-               aclDatum = (Datum) 0;
-       }
-       else
-       {
-               /* detoast rel's ACL if necessary */
-               acl = DatumGetAclP(aclDatum);
-       }
-
-       result = aclmask(acl, roleid, ownerId, mask, how);
-
-       /* if we have a detoasted copy, free it */
-       if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
-               pfree(acl);
-
-       ReleaseSysCache(tuple);
-
-       return result;
-}
-
-/*
- * Exported routine for examining a user's privileges for a foreign
- * server.
- */
-AclMode
-pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
-                                                 AclMode mask, AclMaskHow how)
-{
-       AclMode         result;
-       HeapTuple       tuple;
-       Datum           aclDatum;
-       bool            isNull;
-       Acl                *acl;
-       Oid                     ownerId;
-
-       Form_pg_foreign_server srvForm;
-
-       /* Bypass permission checks for superusers */
-       if (superuser_arg(roleid))
-               return mask;
-
-       /*
-        * Must get the FDW's tuple from pg_foreign_data_wrapper
-        */
-       tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
-       if (!HeapTupleIsValid(tuple))
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("foreign server with OID %u does not 
exist",
-                                               srv_oid)));
-       srvForm = (Form_pg_foreign_server) GETSTRUCT(tuple);
-
-       /*
-        * Normal case: get the foreign server's ACL from pg_foreign_server
-        */
-       ownerId = srvForm->srvowner;
-
-       aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
-                                                          
Anum_pg_foreign_server_srvacl, &isNull);
-       if (isNull)
-       {
-               /* No ACL, so build default ACL */
-               acl = acldefault(OBJECT_FOREIGN_SERVER, ownerId);
-               aclDatum = (Datum) 0;
-       }
-       else
-       {
-               /* detoast rel's ACL if necessary */
-               acl = DatumGetAclP(aclDatum);
-       }
-
-       result = aclmask(acl, roleid, ownerId, mask, how);
-
-       /* if we have a detoasted copy, free it */
-       if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
-               pfree(acl);
-
-       ReleaseSysCache(tuple);
-
-       return result;
-}
-
-/*
- * Exported routine for examining a user's privileges for a type.
- */
-AclMode
+static AclMode
 pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
 {
        AclMode         result;
@@ -4811,6 +4545,40 @@ pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, 
AclMaskHow how)
        return result;
 }
 
+/*
+ * Exported generic routine for checking a user's access privileges to an 
object
+ */
+AclResult
+object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
+{
+       if (object_aclmask(classid, objectid, roleid, mode, ACLMASK_ANY) != 0)
+               return ACLCHECK_OK;
+       else
+               return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Wrapper functions for commonly used cases
+ */
+
+AclResult
+pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
+{
+       return object_aclcheck(DatabaseRelationId, db_oid, roleid, mode);
+}
+
+AclResult
+pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
+{
+       return object_aclcheck(ProcedureRelationId, proc_oid, roleid, mode);
+}
+
+AclResult
+pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
+{
+       return object_aclcheck(TableSpaceRelationId, spc_oid, roleid, mode);
+}
+
 /*
  * Exported routine for checking a user's access privileges to a column
  *
@@ -4973,18 +4741,6 @@ pg_class_aclcheck_ext(Oid table_oid, Oid roleid,
                return ACLCHECK_NO_PRIV;
 }
 
-/*
- * Exported routine for checking a user's access privileges to a database
- */
-AclResult
-pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
-{
-       if (pg_database_aclmask(db_oid, roleid, mode, ACLMASK_ANY) != 0)
-               return ACLCHECK_OK;
-       else
-               return ACLCHECK_NO_PRIV;
-}
-
 /*
  * Exported routine for checking a user's access privileges to a configuration
  * parameter (GUC), identified by GUC name.
@@ -4998,43 +4754,6 @@ pg_parameter_aclcheck(const char *name, Oid roleid, 
AclMode mode)
                return ACLCHECK_NO_PRIV;
 }
 
-/*
- * Exported routine for checking a user's access privileges to a configuration
- * parameter (GUC), identified by the OID of its pg_parameter_acl entry.
- */
-AclResult
-pg_parameter_acl_aclcheck(Oid acl_oid, Oid roleid, AclMode mode)
-{
-       if (pg_parameter_acl_aclmask(acl_oid, roleid, mode, ACLMASK_ANY) != 0)
-               return ACLCHECK_OK;
-       else
-               return ACLCHECK_NO_PRIV;
-}
-
-/*
- * Exported routine for checking a user's access privileges to a function
- */
-AclResult
-pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
-{
-       if (pg_proc_aclmask(proc_oid, roleid, mode, ACLMASK_ANY) != 0)
-               return ACLCHECK_OK;
-       else
-               return ACLCHECK_NO_PRIV;
-}
-
-/*
- * Exported routine for checking a user's access privileges to a language
- */
-AclResult
-pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
-{
-       if (pg_language_aclmask(lang_oid, roleid, mode, ACLMASK_ANY) != 0)
-               return ACLCHECK_OK;
-       else
-               return ACLCHECK_NO_PRIV;
-}
-
 /*
  * Exported routine for checking a user's access privileges to a largeobject
  */
@@ -5061,44 +4780,6 @@ pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode 
mode)
                return ACLCHECK_NO_PRIV;
 }
 
-/*
- * Exported routine for checking a user's access privileges to a tablespace
- */
-AclResult
-pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
-{
-       if (pg_tablespace_aclmask(spc_oid, roleid, mode, ACLMASK_ANY) != 0)
-               return ACLCHECK_OK;
-       else
-               return ACLCHECK_NO_PRIV;
-}
-
-/*
- * Exported routine for checking a user's access privileges to a foreign
- * data wrapper
- */
-AclResult
-pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
-{
-       if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) 
!= 0)
-               return ACLCHECK_OK;
-       else
-               return ACLCHECK_NO_PRIV;
-}
-
-/*
- * Exported routine for checking a user's access privileges to a foreign
- * server
- */
-AclResult
-pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
-{
-       if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0)
-               return ACLCHECK_OK;
-       else
-               return ACLCHECK_NO_PRIV;
-}
-
 /*
  * Exported routine for checking a user's access privileges to a type
  */
diff --git a/src/backend/commands/foreigncmds.c 
b/src/backend/commands/foreigncmds.c
index e6e6d128d11a..55b0be9e1d11 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -366,7 +366,7 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple 
tup, Oid newOwnerId)
                        check_is_member_of_role(GetUserId(), newOwnerId);
 
                        /* New owner must have USAGE privilege on foreign-data 
wrapper */
-                       aclresult = 
pg_foreign_data_wrapper_aclcheck(form->srvfdw, newOwnerId, ACL_USAGE);
+                       aclresult = 
object_aclcheck(ForeignDataWrapperRelationId, form->srvfdw, newOwnerId, 
ACL_USAGE);
                        if (aclresult != ACLCHECK_OK)
                        {
                                ForeignDataWrapper *fdw = 
GetForeignDataWrapper(form->srvfdw);
@@ -891,7 +891,7 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
         */
        fdw = GetForeignDataWrapperByName(stmt->fdwname, false);
 
-       aclresult = pg_foreign_data_wrapper_aclcheck(fdw->fdwid, ownerId, 
ACL_USAGE);
+       aclresult = object_aclcheck(ForeignDataWrapperRelationId, fdw->fdwid, 
ownerId, ACL_USAGE);
        if (aclresult != ACLCHECK_OK)
                aclcheck_error(aclresult, OBJECT_FDW, fdw->fdwname);
 
@@ -1082,7 +1082,7 @@ user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, 
const char *servername)
                {
                        AclResult       aclresult;
 
-                       aclresult = pg_foreign_server_aclcheck(serverid, 
curuserid, ACL_USAGE);
+                       aclresult = object_aclcheck(ForeignServerRelationId, 
serverid, curuserid, ACL_USAGE);
                        if (aclresult != ACLCHECK_OK)
                                aclcheck_error(aclresult, 
OBJECT_FOREIGN_SERVER, servername);
                }
@@ -1433,7 +1433,7 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid 
relid)
         * get the actual FDW for option validation etc.
         */
        server = GetForeignServerByName(stmt->servername, false);
-       aclresult = pg_foreign_server_aclcheck(server->serverid, ownerId, 
ACL_USAGE);
+       aclresult = object_aclcheck(ForeignServerRelationId, server->serverid, 
ownerId, ACL_USAGE);
        if (aclresult != ACLCHECK_OK)
                aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, 
server->servername);
 
@@ -1492,7 +1492,7 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt)
 
        /* Check that the foreign server exists and that we have USAGE on it */
        server = GetForeignServerByName(stmt->server_name, false);
-       aclresult = pg_foreign_server_aclcheck(server->serverid, GetUserId(), 
ACL_USAGE);
+       aclresult = object_aclcheck(ForeignServerRelationId, server->serverid, 
GetUserId(), ACL_USAGE);
        if (aclresult != ACLCHECK_OK)
                aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, 
server->servername);
 
diff --git a/src/backend/commands/functioncmds.c 
b/src/backend/commands/functioncmds.c
index e6fcfc23b931..e006033bd845 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1111,7 +1111,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt 
*stmt)
        if (languageStruct->lanpltrusted)
        {
                /* if trusted language, need USAGE privilege */
-               aclresult = pg_language_aclcheck(languageOid, GetUserId(), 
ACL_USAGE);
+               aclresult = object_aclcheck(LanguageRelationId, languageOid, 
GetUserId(), ACL_USAGE);
                if (aclresult != ACLCHECK_OK)
                        aclcheck_error(aclresult, OBJECT_LANGUAGE,
                                                   
NameStr(languageStruct->lanname));
@@ -1844,7 +1844,7 @@ CreateTransform(CreateTransformStmt *stmt)
         */
        langid = get_language_oid(stmt->lang, false);
 
-       aclresult = pg_language_aclcheck(langid, GetUserId(), ACL_USAGE);
+       aclresult = object_aclcheck(LanguageRelationId, langid, GetUserId(), 
ACL_USAGE);
        if (aclresult != ACLCHECK_OK)
                aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
 
@@ -2110,7 +2110,7 @@ ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool 
atomic)
                /* if trusted language, need USAGE privilege */
                AclResult       aclresult;
 
-               aclresult = pg_language_aclcheck(codeblock->langOid, 
GetUserId(),
+               aclresult = object_aclcheck(LanguageRelationId, 
codeblock->langOid, GetUserId(),
                                                                                
 ACL_USAGE);
                if (aclresult != ACLCHECK_OK)
                        aclcheck_error(aclresult, OBJECT_LANGUAGE,
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 4fac402e5b64..01862e26a916 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -23,7 +23,11 @@
 #include "catalog/pg_authid.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_database.h"
+#include "catalog/pg_foreign_data_wrapper.h"
+#include "catalog/pg_foreign_server.h"
+#include "catalog/pg_language.h"
 #include "catalog/pg_parameter_acl.h"
+#include "catalog/pg_tablespace.h"
 #include "catalog/pg_type.h"
 #include "commands/dbcommands.h"
 #include "commands/proclang.h"
@@ -3099,7 +3103,7 @@ 
has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
        fdwid = convert_foreign_data_wrapper_name(fdwname);
        mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
 
-       aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
+       aclresult = object_aclcheck(ForeignDataWrapperRelationId, fdwid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3124,7 +3128,7 @@ has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS)
        fdwid = convert_foreign_data_wrapper_name(fdwname);
        mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
 
-       aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
+       aclresult = object_aclcheck(ForeignDataWrapperRelationId, fdwid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3150,7 +3154,7 @@ 
has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(FOREIGNDATAWRAPPEROID, 
ObjectIdGetDatum(fdwid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
+       aclresult = object_aclcheck(ForeignDataWrapperRelationId, fdwid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3176,7 +3180,7 @@ has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(FOREIGNDATAWRAPPEROID, 
ObjectIdGetDatum(fdwid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
+       aclresult = object_aclcheck(ForeignDataWrapperRelationId, fdwid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3199,7 +3203,7 @@ 
has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS)
        fdwid = convert_foreign_data_wrapper_name(fdwname);
        mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
 
-       aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
+       aclresult = object_aclcheck(ForeignDataWrapperRelationId, fdwid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3223,7 +3227,7 @@ has_foreign_data_wrapper_privilege_id_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(FOREIGNDATAWRAPPEROID, 
ObjectIdGetDatum(fdwid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
+       aclresult = object_aclcheck(ForeignDataWrapperRelationId, fdwid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3490,7 +3494,7 @@ has_language_privilege_name_name(PG_FUNCTION_ARGS)
        languageoid = convert_language_name(languagename);
        mode = convert_language_priv_string(priv_type_text);
 
-       aclresult = pg_language_aclcheck(languageoid, roleid, mode);
+       aclresult = object_aclcheck(LanguageRelationId, languageoid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3515,7 +3519,7 @@ has_language_privilege_name(PG_FUNCTION_ARGS)
        languageoid = convert_language_name(languagename);
        mode = convert_language_priv_string(priv_type_text);
 
-       aclresult = pg_language_aclcheck(languageoid, roleid, mode);
+       aclresult = object_aclcheck(LanguageRelationId, languageoid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3541,7 +3545,7 @@ has_language_privilege_name_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_language_aclcheck(languageoid, roleid, mode);
+       aclresult = object_aclcheck(LanguageRelationId, languageoid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3567,7 +3571,7 @@ has_language_privilege_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_language_aclcheck(languageoid, roleid, mode);
+       aclresult = object_aclcheck(LanguageRelationId, languageoid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3590,7 +3594,7 @@ has_language_privilege_id_name(PG_FUNCTION_ARGS)
        languageoid = convert_language_name(languagename);
        mode = convert_language_priv_string(priv_type_text);
 
-       aclresult = pg_language_aclcheck(languageoid, roleid, mode);
+       aclresult = object_aclcheck(LanguageRelationId, languageoid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3614,7 +3618,7 @@ has_language_privilege_id_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_language_aclcheck(languageoid, roleid, mode);
+       aclresult = object_aclcheck(LanguageRelationId, languageoid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3874,7 +3878,7 @@ has_server_privilege_name_name(PG_FUNCTION_ARGS)
        serverid = convert_server_name(servername);
        mode = convert_server_priv_string(priv_type_text);
 
-       aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
+       aclresult = object_aclcheck(ForeignServerRelationId, serverid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3899,7 +3903,7 @@ has_server_privilege_name(PG_FUNCTION_ARGS)
        serverid = convert_server_name(servername);
        mode = convert_server_priv_string(priv_type_text);
 
-       aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
+       aclresult = object_aclcheck(ForeignServerRelationId, serverid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3925,7 +3929,7 @@ has_server_privilege_name_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(FOREIGNSERVEROID, 
ObjectIdGetDatum(serverid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
+       aclresult = object_aclcheck(ForeignServerRelationId, serverid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3951,7 +3955,7 @@ has_server_privilege_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(FOREIGNSERVEROID, 
ObjectIdGetDatum(serverid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
+       aclresult = object_aclcheck(ForeignServerRelationId, serverid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3974,7 +3978,7 @@ has_server_privilege_id_name(PG_FUNCTION_ARGS)
        serverid = convert_server_name(servername);
        mode = convert_server_priv_string(priv_type_text);
 
-       aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
+       aclresult = object_aclcheck(ForeignServerRelationId, serverid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -3998,7 +4002,7 @@ has_server_privilege_id_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(FOREIGNSERVEROID, 
ObjectIdGetDatum(serverid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
+       aclresult = object_aclcheck(ForeignServerRelationId, serverid, roleid, 
mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -4065,7 +4069,7 @@ has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
        tablespaceoid = convert_tablespace_name(tablespacename);
        mode = convert_tablespace_priv_string(priv_type_text);
 
-       aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
+       aclresult = object_aclcheck(TableSpaceRelationId, tablespaceoid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -4090,7 +4094,7 @@ has_tablespace_privilege_name(PG_FUNCTION_ARGS)
        tablespaceoid = convert_tablespace_name(tablespacename);
        mode = convert_tablespace_priv_string(priv_type_text);
 
-       aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
+       aclresult = object_aclcheck(TableSpaceRelationId, tablespaceoid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -4116,7 +4120,7 @@ has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(TABLESPACEOID, 
ObjectIdGetDatum(tablespaceoid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
+       aclresult = object_aclcheck(TableSpaceRelationId, tablespaceoid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -4142,7 +4146,7 @@ has_tablespace_privilege_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(TABLESPACEOID, 
ObjectIdGetDatum(tablespaceoid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
+       aclresult = object_aclcheck(TableSpaceRelationId, tablespaceoid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -4165,7 +4169,7 @@ has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
        tablespaceoid = convert_tablespace_name(tablespacename);
        mode = convert_tablespace_priv_string(priv_type_text);
 
-       aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
+       aclresult = object_aclcheck(TableSpaceRelationId, tablespaceoid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
@@ -4189,7 +4193,7 @@ has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
        if (!SearchSysCacheExists1(TABLESPACEOID, 
ObjectIdGetDatum(tablespaceoid)))
                PG_RETURN_NULL();
 
-       aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
+       aclresult = object_aclcheck(TableSpaceRelationId, tablespaceoid, 
roleid, mode);
 
        PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
 }
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index a9dd068095bf..b38bd1003ea0 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -2054,7 +2054,7 @@ CheckFunctionValidatorAccess(Oid validatorOid, Oid 
functionOid)
                                                langStruct->lanvalidator)));
 
        /* first validate that we have permissions to use the language */
-       aclresult = pg_language_aclcheck(procStruct->prolang, GetUserId(),
+       aclresult = object_aclcheck(LanguageRelationId, procStruct->prolang, 
GetUserId(),
                                                                         
ACL_USAGE);
        if (aclresult != ACLCHECK_OK)
                aclcheck_error(aclresult, OBJECT_LANGUAGE,
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index bf461f24fde7..dac9993a0fbe 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -235,39 +235,18 @@ extern void ExecAlterDefaultPrivilegesStmt(ParseState 
*pstate, AlterDefaultPrivi
 
 extern void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid);
 
-extern AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum,
-                                                                       Oid 
roleid, AclMode mask, AclMaskHow how);
-extern AclMode pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum,
-                                                                               
Oid roleid, AclMode mask,
-                                                                               
AclMaskHow how, bool *is_missing);
 extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
                                                                AclMode mask, 
AclMaskHow how);
-extern AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid,
-                                                                       AclMode 
mask, AclMaskHow how,
-                                                                       bool 
*is_missing);
-extern AclMode pg_database_aclmask(Oid db_oid, Oid roleid,
-                                                                  AclMode 
mask, AclMaskHow how);
-extern AclMode pg_parameter_aclmask(const char *name, Oid roleid,
-                                                                       AclMode 
mask, AclMaskHow how);
-extern AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid,
-                                                                               
AclMode mask, AclMaskHow how);
-extern AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid,
-                                                          AclMode mask, 
AclMaskHow how);
-extern AclMode pg_language_aclmask(Oid lang_oid, Oid roleid,
-                                                                  AclMode 
mask, AclMaskHow how);
-extern AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
-                                                                               
           AclMode mask, AclMaskHow how, Snapshot snapshot);
-extern AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
-                                                                       AclMode 
mask, AclMaskHow how);
-extern AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
-                                                                        
AclMode mask, AclMaskHow how);
-extern AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
-                                                                               
           AclMode mask, AclMaskHow how);
-extern AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
-                                                                               
 AclMode mask, AclMaskHow how);
-extern AclMode pg_type_aclmask(Oid type_oid, Oid roleid,
-                                                          AclMode mask, 
AclMaskHow how);
 
+/* generic function */
+extern AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, 
AclMode mode);
+
+/* wrapper functions for commonly used cases */
+extern AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode);
+extern AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode);
+extern AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode);
+
+/* special cases */
 extern AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
                                                                           Oid 
roleid, AclMode mode);
 extern AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum,
@@ -278,19 +257,11 @@ extern AclResult pg_attribute_aclcheck_all(Oid table_oid, 
Oid roleid,
 extern AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode);
 extern AclResult pg_class_aclcheck_ext(Oid table_oid, Oid roleid,
                                                                           
AclMode mode, bool *is_missing);
-extern AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode);
 extern AclResult pg_parameter_aclcheck(const char *name, Oid roleid,
                                                                           
AclMode mode);
-extern AclResult pg_parameter_acl_aclcheck(Oid acl_oid, Oid roleid,
-                                                                               
   AclMode mode);
-extern AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode);
-extern AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode);
 extern AclResult pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid,
                                                                                
                  AclMode mode, Snapshot snapshot);
 extern AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode);
-extern AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode);
-extern AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, 
AclMode mode);
-extern AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode 
mode);
 extern AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode);
 
 extern void aclcheck_error(AclResult aclerr, ObjectType objtype,
-- 
2.37.3

Reply via email to