LCOV - differential code coverage report
Current view: top level - src/backend/catalog - aclchk.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 81.3 % 1772 1441 21 99 193 18 69 855 130 387 95 633 149 322
Current Date: 2023-04-08 15:15:32 Functions: 96.3 % 54 52 2 45 7 1 35 1 17
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * aclchk.c
       4                 :  *    Routines to check access control permissions.
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/backend/catalog/aclchk.c
      12                 :  *
      13                 :  * NOTES
      14                 :  *    See acl.h.
      15                 :  *
      16                 :  *-------------------------------------------------------------------------
      17                 :  */
      18                 : #include "postgres.h"
      19                 : 
      20                 : #include "access/genam.h"
      21                 : #include "access/heapam.h"
      22                 : #include "access/htup_details.h"
      23                 : #include "access/sysattr.h"
      24                 : #include "access/tableam.h"
      25                 : #include "access/xact.h"
      26                 : #include "catalog/binary_upgrade.h"
      27                 : #include "catalog/catalog.h"
      28                 : #include "catalog/dependency.h"
      29                 : #include "catalog/indexing.h"
      30                 : #include "catalog/objectaccess.h"
      31                 : #include "catalog/pg_aggregate.h"
      32                 : #include "catalog/pg_am.h"
      33                 : #include "catalog/pg_authid.h"
      34                 : #include "catalog/pg_cast.h"
      35                 : #include "catalog/pg_class.h"
      36                 : #include "catalog/pg_collation.h"
      37                 : #include "catalog/pg_conversion.h"
      38                 : #include "catalog/pg_database.h"
      39                 : #include "catalog/pg_default_acl.h"
      40                 : #include "catalog/pg_event_trigger.h"
      41                 : #include "catalog/pg_extension.h"
      42                 : #include "catalog/pg_foreign_data_wrapper.h"
      43                 : #include "catalog/pg_foreign_server.h"
      44                 : #include "catalog/pg_init_privs.h"
      45                 : #include "catalog/pg_language.h"
      46                 : #include "catalog/pg_largeobject.h"
      47                 : #include "catalog/pg_largeobject_metadata.h"
      48                 : #include "catalog/pg_namespace.h"
      49                 : #include "catalog/pg_opclass.h"
      50                 : #include "catalog/pg_operator.h"
      51                 : #include "catalog/pg_opfamily.h"
      52                 : #include "catalog/pg_parameter_acl.h"
      53                 : #include "catalog/pg_proc.h"
      54                 : #include "catalog/pg_statistic_ext.h"
      55                 : #include "catalog/pg_subscription.h"
      56                 : #include "catalog/pg_tablespace.h"
      57                 : #include "catalog/pg_transform.h"
      58                 : #include "catalog/pg_ts_config.h"
      59                 : #include "catalog/pg_ts_dict.h"
      60                 : #include "catalog/pg_ts_parser.h"
      61                 : #include "catalog/pg_ts_template.h"
      62                 : #include "catalog/pg_type.h"
      63                 : #include "commands/dbcommands.h"
      64                 : #include "commands/defrem.h"
      65                 : #include "commands/event_trigger.h"
      66                 : #include "commands/extension.h"
      67                 : #include "commands/proclang.h"
      68                 : #include "commands/tablespace.h"
      69                 : #include "foreign/foreign.h"
      70                 : #include "miscadmin.h"
      71                 : #include "nodes/makefuncs.h"
      72                 : #include "parser/parse_func.h"
      73                 : #include "parser/parse_type.h"
      74                 : #include "utils/acl.h"
      75                 : #include "utils/aclchk_internal.h"
      76                 : #include "utils/builtins.h"
      77                 : #include "utils/fmgroids.h"
      78                 : #include "utils/guc.h"
      79                 : #include "utils/lsyscache.h"
      80                 : #include "utils/rel.h"
      81                 : #include "utils/syscache.h"
      82                 : 
      83                 : /*
      84                 :  * Internal format used by ALTER DEFAULT PRIVILEGES.
      85                 :  */
      86                 : typedef struct
      87                 : {
      88                 :     Oid         roleid;         /* owning role */
      89                 :     Oid         nspid;          /* namespace, or InvalidOid if none */
      90                 :     /* remaining fields are same as in InternalGrant: */
      91                 :     bool        is_grant;
      92                 :     ObjectType  objtype;
      93                 :     bool        all_privs;
      94                 :     AclMode     privileges;
      95                 :     List       *grantees;
      96                 :     bool        grant_option;
      97                 :     DropBehavior behavior;
      98                 : } InternalDefaultACL;
      99                 : 
     100                 : /*
     101                 :  * When performing a binary-upgrade, pg_dump will call a function to set
     102                 :  * this variable to let us know that we need to populate the pg_init_privs
     103                 :  * table for the GRANT/REVOKE commands while this variable is set to true.
     104                 :  */
     105                 : bool        binary_upgrade_record_init_privs = false;
     106                 : 
     107                 : static void ExecGrantStmt_oids(InternalGrant *istmt);
     108                 : static void ExecGrant_Relation(InternalGrant *istmt);
     109                 : static void ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs,
     110                 :                              void (*object_check) (InternalGrant *istmt, HeapTuple tuple));
     111                 : static void ExecGrant_Language_check(InternalGrant *istmt, HeapTuple tuple);
     112                 : static void ExecGrant_Largeobject(InternalGrant *istmt);
     113                 : static void ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple);
     114                 : static void ExecGrant_Parameter(InternalGrant *istmt);
     115                 : 
     116                 : static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames);
     117                 : static void SetDefaultACL(InternalDefaultACL *iacls);
     118                 : 
     119                 : static List *objectNamesToOids(ObjectType objtype, List *objnames,
     120                 :                                bool is_grant);
     121                 : static List *objectsInSchemaToOids(ObjectType objtype, List *nspnames);
     122                 : static List *getRelationsInNamespace(Oid namespaceId, char relkind);
     123                 : static void expand_col_privileges(List *colnames, Oid table_oid,
     124                 :                                   AclMode this_privileges,
     125                 :                                   AclMode *col_privileges,
     126                 :                                   int num_col_privileges);
     127                 : static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
     128                 :                                       AclMode this_privileges,
     129                 :                                       AclMode *col_privileges,
     130                 :                                       int num_col_privileges);
     131                 : static AclMode string_to_privilege(const char *privname);
     132                 : static const char *privilege_to_string(AclMode privilege);
     133                 : static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
     134                 :                                         bool all_privs, AclMode privileges,
     135                 :                                         Oid objectId, Oid grantorId,
     136                 :                                         ObjectType objtype, const char *objname,
     137                 :                                         AttrNumber att_number, const char *colname);
     138                 : static AclMode pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum,
     139                 :                           Oid roleid, AclMode mask, AclMaskHow how);
     140                 : static AclMode object_aclmask(Oid classid, Oid objectid, Oid roleid,
     141                 :                               AclMode mask, AclMaskHow how);
     142                 : static AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum,
     143                 :                                     Oid roleid, AclMode mask, AclMaskHow how);
     144                 : static AclMode pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum,
     145                 :                                         Oid roleid, AclMode mask,
     146                 :                                         AclMaskHow how, bool *is_missing);
     147                 : static AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid,
     148                 :                                     AclMode mask, AclMaskHow how,
     149                 :                                     bool *is_missing);
     150                 : static AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid,
     151                 :                                         AclMode mask, AclMaskHow how);
     152                 : static AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
     153                 :                                                AclMode mask, AclMaskHow how, Snapshot snapshot);
     154                 : static AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
     155                 :                                     AclMode mask, AclMaskHow how);
     156                 : static AclMode pg_type_aclmask(Oid type_oid, Oid roleid,
     157                 :                                AclMode mask, AclMaskHow how);
     158                 : static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
     159                 :                                     Acl *new_acl);
     160                 : static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
     161                 :                                           Acl *new_acl);
     162                 : 
     163                 : 
     164                 : /*
     165                 :  * If is_grant is true, adds the given privileges for the list of
     166                 :  * grantees to the existing old_acl.  If is_grant is false, the
     167                 :  * privileges for the given grantees are removed from old_acl.
     168                 :  *
     169                 :  * NB: the original old_acl is pfree'd.
     170                 :  */
     171                 : static Acl *
     172 GIC      104765 : merge_acl_with_grant(Acl *old_acl, bool is_grant,
     173                 :                      bool grant_option, DropBehavior behavior,
     174                 :                      List *grantees, AclMode privileges,
     175                 :                      Oid grantorId, Oid ownerId)
     176                 : {
     177                 :     unsigned    modechg;
     178                 :     ListCell   *j;
     179                 :     Acl        *new_acl;
     180                 : 
     181          104765 :     modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
     182                 : 
     183          104765 :     new_acl = old_acl;
     184                 : 
     185          209569 :     foreach(j, grantees)
     186                 :     {
     187                 :         AclItem     aclitem;
     188 ECB             :         Acl        *newer_acl;
     189                 : 
     190 GIC      104810 :         aclitem.ai_grantee = lfirst_oid(j);
     191                 : 
     192                 :         /*
     193                 :          * Grant options can only be granted to individual roles, not PUBLIC.
     194                 :          * The reason is that if a user would re-grant a privilege that he
     195                 :          * held through PUBLIC, and later the user is removed, the situation
     196                 :          * is impossible to clean up.
     197 ECB             :          */
     198 GIC      104810 :         if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
     199 LBC           0 :             ereport(ERROR,
     200                 :                     (errcode(ERRCODE_INVALID_GRANT_OPERATION),
     201 ECB             :                      errmsg("grant options can only be granted to roles")));
     202                 : 
     203 GIC      104810 :         aclitem.ai_grantor = grantorId;
     204                 : 
     205                 :         /*
     206 ECB             :          * The asymmetry in the conditions here comes from the spec.  In
     207                 :          * GRANT, the grant_option flag signals WITH GRANT OPTION, which means
     208                 :          * to grant both the basic privilege and its grant option. But in
     209                 :          * REVOKE, plain revoke revokes both the basic privilege and its grant
     210                 :          * option, while REVOKE GRANT OPTION revokes only the option.
     211                 :          */
     212 GIC      104810 :         ACLITEM_SET_PRIVS_GOPTIONS(aclitem,
     213                 :                                    (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
     214 ECB             :                                    (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
     215 EUB             : 
     216 GIC      104810 :         newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
     217                 : 
     218                 :         /* avoid memory leak when there are many grantees */
     219 CBC      104804 :         pfree(new_acl);
     220 GIC      104804 :         new_acl = newer_acl;
     221                 :     }
     222                 : 
     223          104759 :     return new_acl;
     224                 : }
     225                 : 
     226                 : /*
     227                 :  * Restrict the privileges to what we can actually grant, and emit
     228 ECB             :  * the standards-mandated warning and error messages.
     229                 :  */
     230                 : static AclMode
     231 GIC      104685 : restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
     232 ECB             :                          AclMode privileges, Oid objectId, Oid grantorId,
     233                 :                          ObjectType objtype, const char *objname,
     234                 :                          AttrNumber att_number, const char *colname)
     235                 : {
     236                 :     AclMode     this_privileges;
     237                 :     AclMode     whole_mask;
     238                 : 
     239 CBC      104685 :     switch (objtype)
     240                 :     {
     241 GIC       55894 :         case OBJECT_COLUMN:
     242           55894 :             whole_mask = ACL_ALL_RIGHTS_COLUMN;
     243           55894 :             break;
     244           24608 :         case OBJECT_TABLE:
     245           24608 :             whole_mask = ACL_ALL_RIGHTS_RELATION;
     246           24608 :             break;
     247 CBC          76 :         case OBJECT_SEQUENCE:
     248 GIC          76 :             whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
     249              76 :             break;
     250             659 :         case OBJECT_DATABASE:
     251             659 :             whole_mask = ACL_ALL_RIGHTS_DATABASE;
     252             659 :             break;
     253           22206 :         case OBJECT_FUNCTION:
     254           22206 :             whole_mask = ACL_ALL_RIGHTS_FUNCTION;
     255 CBC       22206 :             break;
     256 GIC          18 :         case OBJECT_LANGUAGE:
     257 CBC          18 :             whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
     258              18 :             break;
     259              40 :         case OBJECT_LARGEOBJECT:
     260              40 :             whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
     261              40 :             break;
     262             978 :         case OBJECT_SCHEMA:
     263             978 :             whole_mask = ACL_ALL_RIGHTS_SCHEMA;
     264             978 :             break;
     265 LBC           0 :         case OBJECT_TABLESPACE:
     266               0 :             whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
     267               0 :             break;
     268 CBC          47 :         case OBJECT_FDW:
     269              47 :             whole_mask = ACL_ALL_RIGHTS_FDW;
     270              47 :             break;
     271              44 :         case OBJECT_FOREIGN_SERVER:
     272              44 :             whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
     273              44 :             break;
     274 LBC           0 :         case OBJECT_EVENT_TRIGGER:
     275               0 :             elog(ERROR, "grantable rights not supported for event triggers");
     276 ECB             :             /* not reached, but keep compiler quiet */
     277                 :             return ACL_NO_RIGHTS;
     278 CBC          47 :         case OBJECT_TYPE:
     279              47 :             whole_mask = ACL_ALL_RIGHTS_TYPE;
     280              47 :             break;
     281 GBC          68 :         case OBJECT_PARAMETER_ACL:
     282              68 :             whole_mask = ACL_ALL_RIGHTS_PARAMETER_ACL;
     283              68 :             break;
     284 LBC           0 :         default:
     285               0 :             elog(ERROR, "unrecognized object type: %d", objtype);
     286 ECB             :             /* not reached, but keep compiler quiet */
     287                 :             return ACL_NO_RIGHTS;
     288                 :     }
     289                 : 
     290 EUB             :     /*
     291                 :      * If we found no grant options, consider whether to issue a hard error.
     292                 :      * Per spec, having any privilege at all on the object will get you by
     293                 :      * here.
     294 ECB             :      */
     295 CBC      104685 :     if (avail_goptions == ACL_NO_RIGHTS)
     296 ECB             :     {
     297 CBC          33 :         if (pg_aclmask(objtype, objectId, att_number, grantorId,
     298              33 :                        whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
     299 ECB             :                        ACLMASK_ANY) == ACL_NO_RIGHTS)
     300 EUB             :         {
     301 GBC          15 :             if (objtype == OBJECT_COLUMN && colname)
     302 UIC           0 :                 aclcheck_error_col(ACLCHECK_NO_PRIV, objtype, objname, colname);
     303                 :             else
     304 GIC          15 :                 aclcheck_error(ACLCHECK_NO_PRIV, objtype, objname);
     305                 :         }
     306                 :     }
     307                 : 
     308                 :     /*
     309                 :      * Restrict the operation to what we can actually grant or revoke, and
     310                 :      * issue a warning if appropriate.  (For REVOKE this isn't quite what the
     311 ECB             :      * spec says to do: the spec seems to want a warning only if no privilege
     312                 :      * bits actually change in the ACL. In practice that behavior seems much
     313                 :      * too noisy, as well as inconsistent with the GRANT case.)
     314                 :      */
     315 GIC      104670 :     this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
     316          104670 :     if (is_grant)
     317 ECB             :     {
     318 GBC       29688 :         if (this_privileges == 0)
     319                 :         {
     320 CBC          15 :             if (objtype == OBJECT_COLUMN && colname)
     321 UIC           0 :                 ereport(WARNING,
     322                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
     323                 :                          errmsg("no privileges were granted for column \"%s\" of relation \"%s\"",
     324                 :                                 colname, objname)));
     325                 :             else
     326 GIC          15 :                 ereport(WARNING,
     327                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
     328                 :                          errmsg("no privileges were granted for \"%s\"",
     329                 :                                 objname)));
     330                 :         }
     331 CBC       29673 :         else if (!all_privs && this_privileges != privileges)
     332 ECB             :         {
     333 UIC           0 :             if (objtype == OBJECT_COLUMN && colname)
     334 LBC           0 :                 ereport(WARNING,
     335                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
     336 ECB             :                          errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
     337 EUB             :                                 colname, objname)));
     338                 :             else
     339 UIC           0 :                 ereport(WARNING,
     340                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
     341                 :                          errmsg("not all privileges were granted for \"%s\"",
     342 ECB             :                                 objname)));
     343                 :         }
     344                 :     }
     345                 :     else
     346                 :     {
     347 CBC       74982 :         if (this_privileges == 0)
     348                 :         {
     349 GBC           3 :             if (objtype == OBJECT_COLUMN && colname)
     350 UBC           0 :                 ereport(WARNING,
     351                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
     352                 :                          errmsg("no privileges could be revoked for column \"%s\" of relation \"%s\"",
     353                 :                                 colname, objname)));
     354                 :             else
     355 GBC           3 :                 ereport(WARNING,
     356                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
     357                 :                          errmsg("no privileges could be revoked for \"%s\"",
     358                 :                                 objname)));
     359                 :         }
     360 GIC       74979 :         else if (!all_privs && this_privileges != privileges)
     361                 :         {
     362 UIC           0 :             if (objtype == OBJECT_COLUMN && colname)
     363 LBC           0 :                 ereport(WARNING,
     364                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
     365 ECB             :                          errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
     366 EUB             :                                 colname, objname)));
     367                 :             else
     368 UIC           0 :                 ereport(WARNING,
     369                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
     370                 :                          errmsg("not all privileges could be revoked for \"%s\"",
     371 ECB             :                                 objname)));
     372                 :         }
     373                 :     }
     374                 : 
     375 GIC      104670 :     return this_privileges;
     376 ECB             : }
     377                 : 
     378 EUB             : /*
     379                 :  * Called to execute the utility commands GRANT and REVOKE
     380                 :  */
     381                 : void
     382 GIC       48822 : ExecuteGrantStmt(GrantStmt *stmt)
     383                 : {
     384 EUB             :     InternalGrant istmt;
     385                 :     ListCell   *cell;
     386                 :     const char *errormsg;
     387                 :     AclMode     all_privileges;
     388                 : 
     389 GIC       48822 :     if (stmt->grantor)
     390                 :     {
     391 ECB             :         Oid         grantor;
     392                 : 
     393 GIC           9 :         grantor = get_rolespec_oid(stmt->grantor, false);
     394                 : 
     395                 :         /*
     396                 :          * Currently, this clause is only for SQL compatibility, not very
     397                 :          * interesting otherwise.
     398 ECB             :          */
     399 GIC           9 :         if (grantor != GetUserId())
     400               3 :             ereport(ERROR,
     401                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     402                 :                      errmsg("grantor must be current user")));
     403                 :     }
     404                 : 
     405 ECB             :     /*
     406                 :      * Turn the regular GrantStmt into the InternalGrant form.
     407                 :      */
     408 GIC       48819 :     istmt.is_grant = stmt->is_grant;
     409 CBC       48819 :     istmt.objtype = stmt->objtype;
     410                 : 
     411                 :     /* Collect the OIDs of the target objects */
     412 GIC       48819 :     switch (stmt->targtype)
     413                 :     {
     414           48804 :         case ACL_TARGET_OBJECT:
     415 CBC       97595 :             istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects,
     416           48804 :                                               stmt->is_grant);
     417 GIC       48791 :             break;
     418              15 :         case ACL_TARGET_ALL_IN_SCHEMA:
     419              15 :             istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
     420              15 :             break;
     421                 :             /* ACL_TARGET_DEFAULTS should not be seen here */
     422 UIC           0 :         default:
     423               0 :             elog(ERROR, "unrecognized GrantStmt.targtype: %d",
     424 ECB             :                  (int) stmt->targtype);
     425                 :     }
     426                 : 
     427                 :     /* all_privs to be filled below */
     428                 :     /* privileges to be filled below */
     429 GIC       48806 :     istmt.col_privs = NIL;      /* may get filled below */
     430 CBC       48806 :     istmt.grantees = NIL;       /* filled below */
     431           48806 :     istmt.grant_option = stmt->grant_option;
     432           48806 :     istmt.behavior = stmt->behavior;
     433 ECB             : 
     434                 :     /*
     435                 :      * Convert the RoleSpec list into an Oid list.  Note that at this point we
     436                 :      * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
     437                 :      * there shouldn't be any additional work needed to support this case.
     438 EUB             :      */
     439 GBC       97639 :     foreach(cell, stmt->grantees)
     440                 :     {
     441 GIC       48836 :         RoleSpec   *grantee = (RoleSpec *) lfirst(cell);
     442                 :         Oid         grantee_uid;
     443                 : 
     444           48836 :         switch (grantee->roletype)
     445 ECB             :         {
     446 CBC       44015 :             case ROLESPEC_PUBLIC:
     447           44015 :                 grantee_uid = ACL_ID_PUBLIC;
     448           44015 :                 break;
     449 GIC        4821 :             default:
     450            4821 :                 grantee_uid = get_rolespec_oid(grantee, false);
     451            4818 :                 break;
     452                 :         }
     453           48833 :         istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
     454                 :     }
     455 ECB             : 
     456                 :     /*
     457                 :      * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
     458                 :      * bitmask.  Note: objtype can't be OBJECT_COLUMN.
     459                 :      */
     460 CBC       48803 :     switch (stmt->objtype)
     461                 :     {
     462           25070 :         case OBJECT_TABLE:
     463 ECB             : 
     464                 :             /*
     465                 :              * Because this might be a sequence, we test both relation and
     466                 :              * sequence bits, and later do a more limited test when we know
     467                 :              * the object type.
     468                 :              */
     469 CBC       25070 :             all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE;
     470 GIC       25070 :             errormsg = gettext_noop("invalid privilege type %s for relation");
     471           25070 :             break;
     472               6 :         case OBJECT_SEQUENCE:
     473               6 :             all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
     474               6 :             errormsg = gettext_noop("invalid privilege type %s for sequence");
     475               6 :             break;
     476 CBC         655 :         case OBJECT_DATABASE:
     477 GIC         655 :             all_privileges = ACL_ALL_RIGHTS_DATABASE;
     478 CBC         655 :             errormsg = gettext_noop("invalid privilege type %s for database");
     479 GIC         655 :             break;
     480              10 :         case OBJECT_DOMAIN:
     481              10 :             all_privileges = ACL_ALL_RIGHTS_TYPE;
     482              10 :             errormsg = gettext_noop("invalid privilege type %s for domain");
     483              10 :             break;
     484           22156 :         case OBJECT_FUNCTION:
     485 CBC       22156 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
     486           22156 :             errormsg = gettext_noop("invalid privilege type %s for function");
     487           22156 :             break;
     488              21 :         case OBJECT_LANGUAGE:
     489              21 :             all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
     490              21 :             errormsg = gettext_noop("invalid privilege type %s for language");
     491              21 :             break;
     492              31 :         case OBJECT_LARGEOBJECT:
     493              31 :             all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
     494              31 :             errormsg = gettext_noop("invalid privilege type %s for large object");
     495              31 :             break;
     496             666 :         case OBJECT_SCHEMA:
     497             666 :             all_privileges = ACL_ALL_RIGHTS_SCHEMA;
     498             666 :             errormsg = gettext_noop("invalid privilege type %s for schema");
     499             666 :             break;
     500              21 :         case OBJECT_PROCEDURE:
     501              21 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
     502              21 :             errormsg = gettext_noop("invalid privilege type %s for procedure");
     503              21 :             break;
     504               3 :         case OBJECT_ROUTINE:
     505               3 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
     506               3 :             errormsg = gettext_noop("invalid privilege type %s for routine");
     507               3 :             break;
     508 LBC           0 :         case OBJECT_TABLESPACE:
     509               0 :             all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
     510               0 :             errormsg = gettext_noop("invalid privilege type %s for tablespace");
     511               0 :             break;
     512 CBC          43 :         case OBJECT_TYPE:
     513              43 :             all_privileges = ACL_ALL_RIGHTS_TYPE;
     514              43 :             errormsg = gettext_noop("invalid privilege type %s for type");
     515              43 :             break;
     516              46 :         case OBJECT_FDW:
     517              46 :             all_privileges = ACL_ALL_RIGHTS_FDW;
     518              46 :             errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
     519              46 :             break;
     520              38 :         case OBJECT_FOREIGN_SERVER:
     521              38 :             all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
     522              38 :             errormsg = gettext_noop("invalid privilege type %s for foreign server");
     523              38 :             break;
     524 GBC          37 :         case OBJECT_PARAMETER_ACL:
     525              37 :             all_privileges = ACL_ALL_RIGHTS_PARAMETER_ACL;
     526              37 :             errormsg = gettext_noop("invalid privilege type %s for parameter");
     527              37 :             break;
     528 LBC           0 :         default:
     529               0 :             elog(ERROR, "unrecognized GrantStmt.objtype: %d",
     530 ECB             :                  (int) stmt->objtype);
     531                 :             /* keep compiler quiet */
     532                 :             all_privileges = ACL_NO_RIGHTS;
     533                 :             errormsg = NULL;
     534                 :     }
     535                 : 
     536 CBC       48803 :     if (stmt->privileges == NIL)
     537 ECB             :     {
     538 CBC        4646 :         istmt.all_privs = true;
     539 ECB             : 
     540                 :         /*
     541                 :          * will be turned into ACL_ALL_RIGHTS_* by the internal routines
     542                 :          * depending on the object type
     543                 :          */
     544 GBC        4646 :         istmt.privileges = ACL_NO_RIGHTS;
     545 EUB             :     }
     546                 :     else
     547                 :     {
     548 GIC       44157 :         istmt.all_privs = false;
     549           44157 :         istmt.privileges = ACL_NO_RIGHTS;
     550                 : 
     551           89310 :         foreach(cell, stmt->privileges)
     552 ECB             :         {
     553 GIC       45165 :             AccessPriv *privnode = (AccessPriv *) lfirst(cell);
     554 ECB             :             AclMode     priv;
     555                 : 
     556                 :             /*
     557                 :              * If it's a column-level specification, we just set it aside in
     558                 :              * col_privs for the moment; but insist it's for a relation.
     559                 :              */
     560 CBC       45165 :             if (privnode->cols)
     561                 :             {
     562 GIC         469 :                 if (stmt->objtype != OBJECT_TABLE)
     563 UIC           0 :                     ereport(ERROR,
     564 ECB             :                             (errcode(ERRCODE_INVALID_GRANT_OPERATION),
     565                 :                              errmsg("column privileges are only valid for relations")));
     566 GIC         469 :                 istmt.col_privs = lappend(istmt.col_privs, privnode);
     567 CBC         469 :                 continue;
     568                 :             }
     569 ECB             : 
     570 GIC       44696 :             if (privnode->priv_name == NULL) /* parser mistake? */
     571 UIC           0 :                 elog(ERROR, "AccessPriv node must specify privilege or columns");
     572 GIC       44696 :             priv = string_to_privilege(privnode->priv_name);
     573                 : 
     574           44696 :             if (priv & ~((AclMode) all_privileges))
     575              12 :                 ereport(ERROR,
     576 ECB             :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
     577                 :                          errmsg(errormsg, privilege_to_string(priv))));
     578                 : 
     579 GBC       44684 :             istmt.privileges |= priv;
     580                 :         }
     581                 :     }
     582 ECB             : 
     583 CBC       48791 :     ExecGrantStmt_oids(&istmt);
     584 GIC       48761 : }
     585                 : 
     586 ECB             : /*
     587 EUB             :  * ExecGrantStmt_oids
     588 ECB             :  *
     589                 :  * Internal entry point for granting and revoking privileges.
     590                 :  */
     591                 : static void
     592 GIC       48881 : ExecGrantStmt_oids(InternalGrant *istmt)
     593                 : {
     594           48881 :     switch (istmt->objtype)
     595 ECB             :     {
     596 GIC       25114 :         case OBJECT_TABLE:
     597                 :         case OBJECT_SEQUENCE:
     598           25114 :             ExecGrant_Relation(istmt);
     599 CBC       25111 :             break;
     600             659 :         case OBJECT_DATABASE:
     601 GNC         659 :             ExecGrant_common(istmt, DatabaseRelationId, ACL_ALL_RIGHTS_DATABASE, NULL);
     602 GIC         659 :             break;
     603              53 :         case OBJECT_DOMAIN:
     604                 :         case OBJECT_TYPE:
     605 GNC          53 :             ExecGrant_common(istmt, TypeRelationId, ACL_ALL_RIGHTS_TYPE, ExecGrant_Type_check);
     606 GIC          44 :             break;
     607              47 :         case OBJECT_FDW:
     608 GNC          47 :             ExecGrant_common(istmt, ForeignDataWrapperRelationId, ACL_ALL_RIGHTS_FDW, NULL);
     609 GIC          38 :             break;
     610 CBC          44 :         case OBJECT_FOREIGN_SERVER:
     611 GNC          44 :             ExecGrant_common(istmt, ForeignServerRelationId, ACL_ALL_RIGHTS_FOREIGN_SERVER, NULL);
     612 CBC          38 :             break;
     613 GIC       22185 :         case OBJECT_FUNCTION:
     614 ECB             :         case OBJECT_PROCEDURE:
     615                 :         case OBJECT_ROUTINE:
     616 GNC       22185 :             ExecGrant_common(istmt, ProcedureRelationId, ACL_ALL_RIGHTS_FUNCTION, NULL);
     617 CBC       22185 :             break;
     618              21 :         case OBJECT_LANGUAGE:
     619 GNC          21 :             ExecGrant_common(istmt, LanguageRelationId, ACL_ALL_RIGHTS_LANGUAGE, ExecGrant_Language_check);
     620 GIC          18 :             break;
     621 CBC          37 :         case OBJECT_LARGEOBJECT:
     622              37 :             ExecGrant_Largeobject(istmt);
     623              37 :             break;
     624             672 :         case OBJECT_SCHEMA:
     625 GNC         672 :             ExecGrant_common(istmt, NamespaceRelationId, ACL_ALL_RIGHTS_SCHEMA, NULL);
     626 CBC         672 :             break;
     627 LBC           0 :         case OBJECT_TABLESPACE:
     628 UNC           0 :             ExecGrant_common(istmt, TableSpaceRelationId, ACL_ALL_RIGHTS_TABLESPACE, NULL);
     629 LBC           0 :             break;
     630 GIC          49 :         case OBJECT_PARAMETER_ACL:
     631              49 :             ExecGrant_Parameter(istmt);
     632 CBC          49 :             break;
     633 LBC           0 :         default:
     634               0 :             elog(ERROR, "unrecognized GrantStmt.objtype: %d",
     635 ECB             :                  (int) istmt->objtype);
     636                 :     }
     637                 : 
     638                 :     /*
     639                 :      * Pass the info to event triggers about the just-executed GRANT.  Note
     640                 :      * that we prefer to do it after actually executing it, because that gives
     641                 :      * the functions a chance to adjust the istmt with privileges actually
     642                 :      * granted.
     643 EUB             :      */
     644 GBC       48851 :     if (EventTriggerSupportsObjectType(istmt->objtype))
     645           48143 :         EventTriggerCollectGrant(istmt);
     646 CBC       48851 : }
     647 ECB             : 
     648                 : /*
     649 EUB             :  * objectNamesToOids
     650                 :  *
     651                 :  * Turn a list of object names of a given type into an Oid list.
     652                 :  *
     653                 :  * XXX: This function doesn't take any sort of locks on the objects whose
     654                 :  * names it looks up.  In the face of concurrent DDL, we might easily latch
     655                 :  * onto an old version of an object, causing the GRANT or REVOKE statement
     656                 :  * to fail.
     657                 :  */
     658                 : static List *
     659 GIC       48804 : objectNamesToOids(ObjectType objtype, List *objnames, bool is_grant)
     660 ECB             : {
     661 CBC       48804 :     List       *objects = NIL;
     662 ECB             :     ListCell   *cell;
     663                 : 
     664 GIC       48804 :     Assert(objnames != NIL);
     665                 : 
     666           48804 :     switch (objtype)
     667                 :     {
     668           25070 :         case OBJECT_TABLE:
     669                 :         case OBJECT_SEQUENCE:
     670           50167 :             foreach(cell, objnames)
     671                 :             {
     672           25097 :                 RangeVar   *relvar = (RangeVar *) lfirst(cell);
     673                 :                 Oid         relOid;
     674                 : 
     675 CBC       25097 :                 relOid = RangeVarGetRelid(relvar, NoLock, false);
     676 GIC       25097 :                 objects = lappend_oid(objects, relOid);
     677 ECB             :             }
     678 GIC       25070 :             break;
     679             655 :         case OBJECT_DATABASE:
     680 CBC        1310 :             foreach(cell, objnames)
     681                 :             {
     682             655 :                 char       *dbname = strVal(lfirst(cell));
     683                 :                 Oid         dbid;
     684 ECB             : 
     685 GIC         655 :                 dbid = get_database_oid(dbname, false);
     686 CBC         655 :                 objects = lappend_oid(objects, dbid);
     687                 :             }
     688             655 :             break;
     689 GIC          53 :         case OBJECT_DOMAIN:
     690                 :         case OBJECT_TYPE:
     691 CBC         106 :             foreach(cell, objnames)
     692 ECB             :             {
     693 GIC          53 :                 List       *typname = (List *) lfirst(cell);
     694 ECB             :                 Oid         oid;
     695                 : 
     696 CBC          53 :                 oid = typenameTypeId(NULL, makeTypeNameFromNameList(typname));
     697 GIC          53 :                 objects = lappend_oid(objects, oid);
     698 ECB             :             }
     699 GIC          53 :             break;
     700           22159 :         case OBJECT_FUNCTION:
     701 CBC       44324 :             foreach(cell, objnames)
     702 ECB             :             {
     703 GIC       22171 :                 ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
     704 ECB             :                 Oid         funcid;
     705                 : 
     706 GIC       22171 :                 funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false);
     707 CBC       22165 :                 objects = lappend_oid(objects, funcid);
     708                 :             }
     709           22153 :             break;
     710 GIC          21 :         case OBJECT_LANGUAGE:
     711              42 :             foreach(cell, objnames)
     712 ECB             :             {
     713 CBC          21 :                 char       *langname = strVal(lfirst(cell));
     714                 :                 Oid         oid;
     715 ECB             : 
     716 CBC          21 :                 oid = get_language_oid(langname, false);
     717              21 :                 objects = lappend_oid(objects, oid);
     718                 :             }
     719              21 :             break;
     720 GIC          40 :         case OBJECT_LARGEOBJECT:
     721              77 :             foreach(cell, objnames)
     722 ECB             :             {
     723 CBC          43 :                 Oid         lobjOid = oidparse(lfirst(cell));
     724                 : 
     725              43 :                 if (!LargeObjectExists(lobjOid))
     726               6 :                     ereport(ERROR,
     727 ECB             :                             (errcode(ERRCODE_UNDEFINED_OBJECT),
     728                 :                              errmsg("large object %u does not exist",
     729                 :                                     lobjOid)));
     730                 : 
     731 GIC          37 :                 objects = lappend_oid(objects, lobjOid);
     732 ECB             :             }
     733 CBC          34 :             break;
     734 GIC         666 :         case OBJECT_SCHEMA:
     735 CBC        1638 :             foreach(cell, objnames)
     736 ECB             :             {
     737 CBC         972 :                 char       *nspname = strVal(lfirst(cell));
     738                 :                 Oid         oid;
     739 ECB             : 
     740 GIC         972 :                 oid = get_namespace_oid(nspname, false);
     741 CBC         972 :                 objects = lappend_oid(objects, oid);
     742 ECB             :             }
     743 GIC         666 :             break;
     744              18 :         case OBJECT_PROCEDURE:
     745              36 :             foreach(cell, objnames)
     746                 :             {
     747 CBC          18 :                 ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
     748                 :                 Oid         procid;
     749 ECB             : 
     750 CBC          18 :                 procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false);
     751              18 :                 objects = lappend_oid(objects, procid);
     752                 :             }
     753              18 :             break;
     754 UIC           0 :         case OBJECT_ROUTINE:
     755               0 :             foreach(cell, objnames)
     756 ECB             :             {
     757 LBC           0 :                 ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
     758                 :                 Oid         routid;
     759 ECB             : 
     760 LBC           0 :                 routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false);
     761               0 :                 objects = lappend_oid(objects, routid);
     762                 :             }
     763               0 :             break;
     764 UIC           0 :         case OBJECT_TABLESPACE:
     765               0 :             foreach(cell, objnames)
     766 ECB             :             {
     767 LBC           0 :                 char       *spcname = strVal(lfirst(cell));
     768                 :                 Oid         spcoid;
     769 ECB             : 
     770 UBC           0 :                 spcoid = get_tablespace_oid(spcname, false);
     771               0 :                 objects = lappend_oid(objects, spcoid);
     772                 :             }
     773               0 :             break;
     774 GIC          46 :         case OBJECT_FDW:
     775              92 :             foreach(cell, objnames)
     776 EUB             :             {
     777 GBC          46 :                 char       *fdwname = strVal(lfirst(cell));
     778 GIC          46 :                 Oid         fdwid = get_foreign_data_wrapper_oid(fdwname, false);
     779 EUB             : 
     780 GBC          46 :                 objects = lappend_oid(objects, fdwid);
     781 EUB             :             }
     782 GIC          46 :             break;
     783 GBC          38 :         case OBJECT_FOREIGN_SERVER:
     784 GIC          76 :             foreach(cell, objnames)
     785                 :             {
     786 GBC          38 :                 char       *srvname = strVal(lfirst(cell));
     787              38 :                 Oid         srvid = get_foreign_server_oid(srvname, false);
     788                 : 
     789              38 :                 objects = lappend_oid(objects, srvid);
     790 ECB             :             }
     791 CBC          38 :             break;
     792 GIC          38 :         case OBJECT_PARAMETER_ACL:
     793 CBC         100 :             foreach(cell, objnames)
     794 ECB             :             {
     795                 :                 /*
     796                 :                  * In this code we represent a GUC by the OID of its entry in
     797                 :                  * pg_parameter_acl, which we have to manufacture here if it
     798                 :                  * doesn't exist yet.  (That's a hack for sure, but it avoids
     799                 :                  * messing with all the GRANT/REVOKE infrastructure that
     800                 :                  * expects to use OIDs for object identities.)  However, if
     801                 :                  * this is a REVOKE, we can instead just ignore any GUCs that
     802                 :                  * don't have such an entry, as they must not have any
     803                 :                  * privileges needing removal.
     804                 :                  */
     805 CBC          63 :                 char       *parameter = strVal(lfirst(cell));
     806 GIC          63 :                 Oid         parameterId = ParameterAclLookup(parameter, true);
     807 ECB             : 
     808 CBC          63 :                 if (!OidIsValid(parameterId) && is_grant)
     809 ECB             :                 {
     810 GIC          35 :                     parameterId = ParameterAclCreate(parameter);
     811                 : 
     812                 :                     /*
     813                 :                      * Prevent error when processing duplicate objects, and
     814                 :                      * make this new entry visible so that ExecGrant_Parameter
     815                 :                      * can update it.
     816                 :                      */
     817              34 :                     CommandCounterIncrement();
     818                 :                 }
     819              62 :                 if (OidIsValid(parameterId))
     820              56 :                     objects = lappend_oid(objects, parameterId);
     821 ECB             :             }
     822 CBC          37 :             break;
     823 UIC           0 :         default:
     824 LBC           0 :             elog(ERROR, "unrecognized GrantStmt.objtype: %d",
     825                 :                  (int) objtype);
     826 ECB             :     }
     827                 : 
     828 GIC       48791 :     return objects;
     829                 : }
     830                 : 
     831                 : /*
     832                 :  * objectsInSchemaToOids
     833 ECB             :  *
     834                 :  * Find all objects of a given type in specified schemas, and make a list
     835                 :  * of their Oids.  We check USAGE privilege on the schemas, but there is
     836                 :  * no privilege checking on the individual objects here.
     837                 :  */
     838                 : static List *
     839 GBC          15 : objectsInSchemaToOids(ObjectType objtype, List *nspnames)
     840 EUB             : {
     841 GIC          15 :     List       *objects = NIL;
     842                 :     ListCell   *cell;
     843                 : 
     844 CBC          30 :     foreach(cell, nspnames)
     845                 :     {
     846 GIC          15 :         char       *nspname = strVal(lfirst(cell));
     847                 :         Oid         namespaceId;
     848                 :         List       *objs;
     849                 : 
     850              15 :         namespaceId = LookupExplicitNamespace(nspname, false);
     851                 : 
     852              15 :         switch (objtype)
     853                 :         {
     854               6 :             case OBJECT_TABLE:
     855 CBC           6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
     856 GIC           6 :                 objects = list_concat(objects, objs);
     857 CBC           6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
     858 GIC           6 :                 objects = list_concat(objects, objs);
     859               6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
     860 CBC           6 :                 objects = list_concat(objects, objs);
     861 GIC           6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
     862 CBC           6 :                 objects = list_concat(objects, objs);
     863 GIC           6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE);
     864               6 :                 objects = list_concat(objects, objs);
     865               6 :                 break;
     866 LBC           0 :             case OBJECT_SEQUENCE:
     867 UIC           0 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
     868 LBC           0 :                 objects = list_concat(objects, objs);
     869 UIC           0 :                 break;
     870 CBC           9 :             case OBJECT_FUNCTION:
     871 ECB             :             case OBJECT_PROCEDURE:
     872                 :             case OBJECT_ROUTINE:
     873                 :                 {
     874                 :                     ScanKeyData key[2];
     875                 :                     int         keycount;
     876                 :                     Relation    rel;
     877                 :                     TableScanDesc scan;
     878                 :                     HeapTuple   tuple;
     879                 : 
     880 CBC           9 :                     keycount = 0;
     881               9 :                     ScanKeyInit(&key[keycount++],
     882 EUB             :                                 Anum_pg_proc_pronamespace,
     883                 :                                 BTEqualStrategyNumber, F_OIDEQ,
     884                 :                                 ObjectIdGetDatum(namespaceId));
     885                 : 
     886 CBC           9 :                     if (objtype == OBJECT_FUNCTION)
     887                 :                         /* includes aggregates and window functions */
     888 GIC           3 :                         ScanKeyInit(&key[keycount++],
     889                 :                                     Anum_pg_proc_prokind,
     890                 :                                     BTEqualStrategyNumber, F_CHARNE,
     891                 :                                     CharGetDatum(PROKIND_PROCEDURE));
     892               6 :                     else if (objtype == OBJECT_PROCEDURE)
     893               3 :                         ScanKeyInit(&key[keycount++],
     894                 :                                     Anum_pg_proc_prokind,
     895                 :                                     BTEqualStrategyNumber, F_CHAREQ,
     896 ECB             :                                     CharGetDatum(PROKIND_PROCEDURE));
     897                 : 
     898 GIC           9 :                     rel = table_open(ProcedureRelationId, AccessShareLock);
     899               9 :                     scan = table_beginscan_catalog(rel, keycount, key);
     900                 : 
     901              27 :                     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
     902 ECB             :                     {
     903 GIC          18 :                         Oid         oid = ((Form_pg_proc) GETSTRUCT(tuple))->oid;
     904 ECB             : 
     905 GIC          18 :                         objects = lappend_oid(objects, oid);
     906                 :                     }
     907                 : 
     908 CBC           9 :                     table_endscan(scan);
     909               9 :                     table_close(rel, AccessShareLock);
     910                 :                 }
     911 GIC           9 :                 break;
     912 UIC           0 :             default:
     913                 :                 /* should not happen */
     914 LBC           0 :                 elog(ERROR, "unrecognized GrantStmt.objtype: %d",
     915 ECB             :                      (int) objtype);
     916                 :         }
     917                 :     }
     918                 : 
     919 CBC          15 :     return objects;
     920                 : }
     921 ECB             : 
     922                 : /*
     923                 :  * getRelationsInNamespace
     924                 :  *
     925                 :  * Return Oid list of relations in given namespace filtered by relation kind
     926                 :  */
     927                 : static List *
     928 GBC          30 : getRelationsInNamespace(Oid namespaceId, char relkind)
     929                 : {
     930              30 :     List       *relations = NIL;
     931                 :     ScanKeyData key[2];
     932                 :     Relation    rel;
     933                 :     TableScanDesc scan;
     934                 :     HeapTuple   tuple;
     935 ECB             : 
     936 GIC          30 :     ScanKeyInit(&key[0],
     937                 :                 Anum_pg_class_relnamespace,
     938                 :                 BTEqualStrategyNumber, F_OIDEQ,
     939                 :                 ObjectIdGetDatum(namespaceId));
     940              30 :     ScanKeyInit(&key[1],
     941                 :                 Anum_pg_class_relkind,
     942                 :                 BTEqualStrategyNumber, F_CHAREQ,
     943                 :                 CharGetDatum(relkind));
     944 ECB             : 
     945 GIC          30 :     rel = table_open(RelationRelationId, AccessShareLock);
     946 CBC          30 :     scan = table_beginscan_catalog(rel, 2, key);
     947                 : 
     948 GIC          42 :     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
     949                 :     {
     950              12 :         Oid         oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
     951                 : 
     952 CBC          12 :         relations = lappend_oid(relations, oid);
     953                 :     }
     954                 : 
     955 GIC          30 :     table_endscan(scan);
     956 CBC          30 :     table_close(rel, AccessShareLock);
     957                 : 
     958 GIC          30 :     return relations;
     959                 : }
     960                 : 
     961 ECB             : 
     962                 : /*
     963                 :  * ALTER DEFAULT PRIVILEGES statement
     964                 :  */
     965                 : void
     966 CBC          80 : ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
     967                 : {
     968              80 :     GrantStmt  *action = stmt->action;
     969                 :     InternalDefaultACL iacls;
     970                 :     ListCell   *cell;
     971              80 :     List       *rolespecs = NIL;
     972              80 :     List       *nspnames = NIL;
     973 GIC          80 :     DefElem    *drolespecs = NULL;
     974 CBC          80 :     DefElem    *dnspnames = NULL;
     975                 :     AclMode     all_privileges;
     976                 :     const char *errormsg;
     977                 : 
     978                 :     /* Deconstruct the "options" part of the statement */
     979 GIC         141 :     foreach(cell, stmt->options)
     980                 :     {
     981              61 :         DefElem    *defel = (DefElem *) lfirst(cell);
     982 ECB             : 
     983 GIC          61 :         if (strcmp(defel->defname, "schemas") == 0)
     984 ECB             :         {
     985 GIC          27 :             if (dnspnames)
     986 UIC           0 :                 errorConflictingDefElem(defel, pstate);
     987 CBC          27 :             dnspnames = defel;
     988 ECB             :         }
     989 CBC          34 :         else if (strcmp(defel->defname, "roles") == 0)
     990 ECB             :         {
     991 GIC          34 :             if (drolespecs)
     992 UIC           0 :                 errorConflictingDefElem(defel, pstate);
     993 GIC          34 :             drolespecs = defel;
     994                 :         }
     995 ECB             :         else
     996 UIC           0 :             elog(ERROR, "option \"%s\" not recognized", defel->defname);
     997 ECB             :     }
     998                 : 
     999 CBC          80 :     if (dnspnames)
    1000 GIC          27 :         nspnames = (List *) dnspnames->arg;
    1001 CBC          80 :     if (drolespecs)
    1002 GBC          34 :         rolespecs = (List *) drolespecs->arg;
    1003 ECB             : 
    1004                 :     /* Prepare the InternalDefaultACL representation of the statement */
    1005                 :     /* roleid to be filled below */
    1006                 :     /* nspid to be filled in SetDefaultACLsInSchemas */
    1007 CBC          80 :     iacls.is_grant = action->is_grant;
    1008 GBC          80 :     iacls.objtype = action->objtype;
    1009 ECB             :     /* all_privs to be filled below */
    1010                 :     /* privileges to be filled below */
    1011 GIC          80 :     iacls.grantees = NIL;       /* filled below */
    1012 GBC          80 :     iacls.grant_option = action->grant_option;
    1013 GIC          80 :     iacls.behavior = action->behavior;
    1014                 : 
    1015 ECB             :     /*
    1016                 :      * Convert the RoleSpec list into an Oid list.  Note that at this point we
    1017                 :      * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
    1018                 :      * there shouldn't be any additional work needed to support this case.
    1019                 :      */
    1020 GIC         163 :     foreach(cell, action->grantees)
    1021                 :     {
    1022              83 :         RoleSpec   *grantee = (RoleSpec *) lfirst(cell);
    1023 ECB             :         Oid         grantee_uid;
    1024                 : 
    1025 GIC          83 :         switch (grantee->roletype)
    1026                 :         {
    1027 CBC          20 :             case ROLESPEC_PUBLIC:
    1028              20 :                 grantee_uid = ACL_ID_PUBLIC;
    1029              20 :                 break;
    1030 GIC          63 :             default:
    1031              63 :                 grantee_uid = get_rolespec_oid(grantee, false);
    1032              63 :                 break;
    1033                 :         }
    1034              83 :         iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
    1035                 :     }
    1036 ECB             : 
    1037                 :     /*
    1038                 :      * Convert action->privileges, a list of privilege strings, into an
    1039                 :      * AclMode bitmask.
    1040                 :      */
    1041 CBC          80 :     switch (action->objtype)
    1042                 :     {
    1043              39 :         case OBJECT_TABLE:
    1044              39 :             all_privileges = ACL_ALL_RIGHTS_RELATION;
    1045              39 :             errormsg = gettext_noop("invalid privilege type %s for relation");
    1046              39 :             break;
    1047               3 :         case OBJECT_SEQUENCE:
    1048               3 :             all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
    1049 GIC           3 :             errormsg = gettext_noop("invalid privilege type %s for sequence");
    1050 CBC           3 :             break;
    1051 GIC          11 :         case OBJECT_FUNCTION:
    1052              11 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
    1053              11 :             errormsg = gettext_noop("invalid privilege type %s for function");
    1054              11 :             break;
    1055 UIC           0 :         case OBJECT_PROCEDURE:
    1056               0 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
    1057 LBC           0 :             errormsg = gettext_noop("invalid privilege type %s for procedure");
    1058 UIC           0 :             break;
    1059 LBC           0 :         case OBJECT_ROUTINE:
    1060               0 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
    1061               0 :             errormsg = gettext_noop("invalid privilege type %s for routine");
    1062               0 :             break;
    1063 CBC           9 :         case OBJECT_TYPE:
    1064               9 :             all_privileges = ACL_ALL_RIGHTS_TYPE;
    1065               9 :             errormsg = gettext_noop("invalid privilege type %s for type");
    1066               9 :             break;
    1067              18 :         case OBJECT_SCHEMA:
    1068              18 :             all_privileges = ACL_ALL_RIGHTS_SCHEMA;
    1069              18 :             errormsg = gettext_noop("invalid privilege type %s for schema");
    1070              18 :             break;
    1071 UBC           0 :         default:
    1072               0 :             elog(ERROR, "unrecognized GrantStmt.objtype: %d",
    1073 EUB             :                  (int) action->objtype);
    1074                 :             /* keep compiler quiet */
    1075                 :             all_privileges = ACL_NO_RIGHTS;
    1076                 :             errormsg = NULL;
    1077                 :     }
    1078                 : 
    1079 CBC          80 :     if (action->privileges == NIL)
    1080 ECB             :     {
    1081 CBC          28 :         iacls.all_privs = true;
    1082 ECB             : 
    1083                 :         /*
    1084                 :          * will be turned into ACL_ALL_RIGHTS_* by the internal routines
    1085                 :          * depending on the object type
    1086                 :          */
    1087 GBC          28 :         iacls.privileges = ACL_NO_RIGHTS;
    1088 EUB             :     }
    1089                 :     else
    1090                 :     {
    1091 GIC          52 :         iacls.all_privs = false;
    1092              52 :         iacls.privileges = ACL_NO_RIGHTS;
    1093                 : 
    1094             104 :         foreach(cell, action->privileges)
    1095 ECB             :         {
    1096 GIC          52 :             AccessPriv *privnode = (AccessPriv *) lfirst(cell);
    1097 ECB             :             AclMode     priv;
    1098                 : 
    1099 GIC          52 :             if (privnode->cols)
    1100 UIC           0 :                 ereport(ERROR,
    1101                 :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
    1102                 :                          errmsg("default privileges cannot be set for columns")));
    1103 ECB             : 
    1104 GIC          52 :             if (privnode->priv_name == NULL) /* parser mistake? */
    1105 UIC           0 :                 elog(ERROR, "AccessPriv node must specify privilege");
    1106 GIC          52 :             priv = string_to_privilege(privnode->priv_name);
    1107 ECB             : 
    1108 CBC          52 :             if (priv & ~((AclMode) all_privileges))
    1109 UIC           0 :                 ereport(ERROR,
    1110 ECB             :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
    1111                 :                          errmsg(errormsg, privilege_to_string(priv))));
    1112                 : 
    1113 GIC          52 :             iacls.privileges |= priv;
    1114                 :         }
    1115 ECB             :     }
    1116 EUB             : 
    1117 GIC          80 :     if (rolespecs == NIL)
    1118                 :     {
    1119                 :         /* Set permissions for myself */
    1120 CBC          46 :         iacls.roleid = GetUserId();
    1121 EUB             : 
    1122 CBC          46 :         SetDefaultACLsInSchemas(&iacls, nspnames);
    1123                 :     }
    1124 ECB             :     else
    1125 EUB             :     {
    1126                 :         /* Look up the role OIDs and do permissions checks */
    1127                 :         ListCell   *rolecell;
    1128                 : 
    1129 CBC          68 :         foreach(rolecell, rolespecs)
    1130                 :         {
    1131 GIC          34 :             RoleSpec   *rolespec = lfirst(rolecell);
    1132                 : 
    1133 CBC          34 :             iacls.roleid = get_rolespec_oid(rolespec, false);
    1134                 : 
    1135 GNC          34 :             if (!has_privs_of_role(GetUserId(), iacls.roleid))
    1136 UNC           0 :                 ereport(ERROR,
    1137                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    1138                 :                          errmsg("permission denied to change default privileges")));
    1139                 : 
    1140 GIC          34 :             SetDefaultACLsInSchemas(&iacls, nspnames);
    1141                 :         }
    1142 ECB             :     }
    1143 GIC          77 : }
    1144 ECB             : 
    1145                 : /*
    1146                 :  * Process ALTER DEFAULT PRIVILEGES for a list of target schemas
    1147                 :  *
    1148                 :  * All fields of *iacls except nspid were filled already
    1149 EUB             :  */
    1150                 : static void
    1151 GIC          80 : SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
    1152                 : {
    1153 CBC          80 :     if (nspnames == NIL)
    1154                 :     {
    1155                 :         /* Set database-wide permissions if no schema was specified */
    1156              53 :         iacls->nspid = InvalidOid;
    1157                 : 
    1158 GIC          53 :         SetDefaultACL(iacls);
    1159                 :     }
    1160                 :     else
    1161                 :     {
    1162                 :         /* Look up the schema OIDs and set permissions for each one */
    1163                 :         ListCell   *nspcell;
    1164 ECB             : 
    1165 GIC          54 :         foreach(nspcell, nspnames)
    1166 ECB             :         {
    1167 GIC          30 :             char       *nspname = strVal(lfirst(nspcell));
    1168                 : 
    1169 CBC          30 :             iacls->nspid = get_namespace_oid(nspname, false);
    1170                 : 
    1171 ECB             :             /*
    1172                 :              * We used to insist that the target role have CREATE privileges
    1173                 :              * on the schema, since without that it wouldn't be able to create
    1174                 :              * an object for which these default privileges would apply.
    1175                 :              * However, this check proved to be more confusing than helpful,
    1176                 :              * and it also caused certain database states to not be
    1177                 :              * dumpable/restorable, since revoking CREATE doesn't cause
    1178                 :              * default privileges for the schema to go away.  So now, we just
    1179                 :              * allow the ALTER; if the user lacks CREATE he'll find out when
    1180                 :              * he tries to create an object.
    1181                 :              */
    1182                 : 
    1183 GIC          30 :             SetDefaultACL(iacls);
    1184                 :         }
    1185                 :     }
    1186              77 : }
    1187                 : 
    1188                 : 
    1189                 : /*
    1190                 :  * Create or update a pg_default_acl entry
    1191                 :  */
    1192                 : static void
    1193              98 : SetDefaultACL(InternalDefaultACL *iacls)
    1194                 : {
    1195              98 :     AclMode     this_privileges = iacls->privileges;
    1196 ECB             :     char        objtype;
    1197                 :     Relation    rel;
    1198                 :     HeapTuple   tuple;
    1199                 :     bool        isNew;
    1200                 :     Acl        *def_acl;
    1201                 :     Acl        *old_acl;
    1202                 :     Acl        *new_acl;
    1203                 :     HeapTuple   newtuple;
    1204                 :     int         noldmembers;
    1205                 :     int         nnewmembers;
    1206                 :     Oid        *oldmembers;
    1207                 :     Oid        *newmembers;
    1208                 : 
    1209 GIC          98 :     rel = table_open(DefaultAclRelationId, RowExclusiveLock);
    1210                 : 
    1211                 :     /*
    1212                 :      * The default for a global entry is the hard-wired default ACL for the
    1213                 :      * particular object type.  The default for non-global entries is an empty
    1214                 :      * ACL.  This must be so because global entries replace the hard-wired
    1215                 :      * defaults, while others are added on.
    1216                 :      */
    1217              98 :     if (!OidIsValid(iacls->nspid))
    1218              68 :         def_acl = acldefault(iacls->objtype, iacls->roleid);
    1219 ECB             :     else
    1220 GIC          30 :         def_acl = make_empty_acl();
    1221                 : 
    1222                 :     /*
    1223                 :      * Convert ACL object type to pg_default_acl object type and handle
    1224                 :      * all_privs option
    1225                 :      */
    1226              98 :     switch (iacls->objtype)
    1227 ECB             :     {
    1228 CBC          45 :         case OBJECT_TABLE:
    1229 GIC          45 :             objtype = DEFACLOBJ_RELATION;
    1230 CBC          45 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
    1231 GIC          13 :                 this_privileges = ACL_ALL_RIGHTS_RELATION;
    1232              45 :             break;
    1233                 : 
    1234               6 :         case OBJECT_SEQUENCE:
    1235               6 :             objtype = DEFACLOBJ_SEQUENCE;
    1236 CBC           6 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
    1237 GIC           6 :                 this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
    1238 CBC           6 :             break;
    1239 ECB             : 
    1240 CBC          14 :         case OBJECT_FUNCTION:
    1241              14 :             objtype = DEFACLOBJ_FUNCTION;
    1242              14 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
    1243 GIC           6 :                 this_privileges = ACL_ALL_RIGHTS_FUNCTION;
    1244 CBC          14 :             break;
    1245 ECB             : 
    1246 CBC          12 :         case OBJECT_TYPE:
    1247              12 :             objtype = DEFACLOBJ_TYPE;
    1248              12 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
    1249 GIC           6 :                 this_privileges = ACL_ALL_RIGHTS_TYPE;
    1250 CBC          12 :             break;
    1251 ECB             : 
    1252 CBC          21 :         case OBJECT_SCHEMA:
    1253              21 :             if (OidIsValid(iacls->nspid))
    1254               3 :                 ereport(ERROR,
    1255                 :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
    1256 ECB             :                          errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS")));
    1257 CBC          18 :             objtype = DEFACLOBJ_NAMESPACE;
    1258              18 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
    1259              12 :                 this_privileges = ACL_ALL_RIGHTS_SCHEMA;
    1260              18 :             break;
    1261                 : 
    1262 LBC           0 :         default:
    1263 UNC           0 :             elog(ERROR, "unrecognized object type: %d",
    1264 ECB             :                  (int) iacls->objtype);
    1265                 :             objtype = 0;        /* keep compiler quiet */
    1266                 :             break;
    1267                 :     }
    1268                 : 
    1269                 :     /* Search for existing row for this object type in catalog */
    1270 CBC          95 :     tuple = SearchSysCache3(DEFACLROLENSPOBJ,
    1271                 :                             ObjectIdGetDatum(iacls->roleid),
    1272 EUB             :                             ObjectIdGetDatum(iacls->nspid),
    1273                 :                             CharGetDatum(objtype));
    1274                 : 
    1275 GIC          95 :     if (HeapTupleIsValid(tuple))
    1276                 :     {
    1277                 :         Datum       aclDatum;
    1278                 :         bool        isNull;
    1279                 : 
    1280 CBC          36 :         aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
    1281                 :                                    Anum_pg_default_acl_defaclacl,
    1282                 :                                    &isNull);
    1283 GIC          36 :         if (!isNull)
    1284              36 :             old_acl = DatumGetAclPCopy(aclDatum);
    1285 ECB             :         else
    1286 UIC           0 :             old_acl = NULL;     /* this case shouldn't happen, probably */
    1287 GIC          36 :         isNew = false;
    1288                 :     }
    1289                 :     else
    1290 ECB             :     {
    1291 GIC          59 :         old_acl = NULL;
    1292              59 :         isNew = true;
    1293 ECB             :     }
    1294                 : 
    1295 GIC          95 :     if (old_acl != NULL)
    1296 EUB             :     {
    1297 ECB             :         /*
    1298                 :          * We need the members of both old and new ACLs so we can correct the
    1299                 :          * shared dependency information.  Collect data before
    1300                 :          * merge_acl_with_grant throws away old_acl.
    1301                 :          */
    1302 CBC          36 :         noldmembers = aclmembers(old_acl, &oldmembers);
    1303                 :     }
    1304                 :     else
    1305 ECB             :     {
    1306                 :         /* If no or null entry, start with the default ACL value */
    1307 GIC          59 :         old_acl = aclcopy(def_acl);
    1308                 :         /* There are no old member roles according to the catalogs */
    1309              59 :         noldmembers = 0;
    1310              59 :         oldmembers = NULL;
    1311                 :     }
    1312 ECB             : 
    1313                 :     /*
    1314                 :      * Generate new ACL.  Grantor of rights is always the same as the target
    1315                 :      * role.
    1316                 :      */
    1317 CBC          95 :     new_acl = merge_acl_with_grant(old_acl,
    1318 GIC          95 :                                    iacls->is_grant,
    1319 CBC          95 :                                    iacls->grant_option,
    1320 ECB             :                                    iacls->behavior,
    1321                 :                                    iacls->grantees,
    1322                 :                                    this_privileges,
    1323                 :                                    iacls->roleid,
    1324                 :                                    iacls->roleid);
    1325                 : 
    1326                 :     /*
    1327                 :      * If the result is the same as the default value, we do not need an
    1328                 :      * explicit pg_default_acl entry, and should in fact remove the entry if
    1329                 :      * it exists.  Must sort both arrays to compare properly.
    1330                 :      */
    1331 GIC          95 :     aclitemsort(new_acl);
    1332              95 :     aclitemsort(def_acl);
    1333              95 :     if (aclequal(new_acl, def_acl))
    1334                 :     {
    1335                 :         /* delete old entry, if indeed there is one */
    1336              28 :         if (!isNew)
    1337                 :         {
    1338                 :             ObjectAddress myself;
    1339                 : 
    1340                 :             /*
    1341 ECB             :              * The dependency machinery will take care of removing all
    1342                 :              * associated dependency entries.  We use DROP_RESTRICT since
    1343                 :              * there shouldn't be anything depending on this entry.
    1344                 :              */
    1345 GIC          27 :             myself.classId = DefaultAclRelationId;
    1346 CBC          27 :             myself.objectId = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
    1347 GIC          27 :             myself.objectSubId = 0;
    1348                 : 
    1349              27 :             performDeletion(&myself, DROP_RESTRICT, 0);
    1350                 :         }
    1351                 :     }
    1352                 :     else
    1353                 :     {
    1354 GNC          67 :         Datum       values[Natts_pg_default_acl] = {0};
    1355              67 :         bool        nulls[Natts_pg_default_acl] = {0};
    1356              67 :         bool        replaces[Natts_pg_default_acl] = {0};
    1357                 :         Oid         defAclOid;
    1358 ECB             : 
    1359 GIC          67 :         if (isNew)
    1360                 :         {
    1361                 :             /* insert new entry */
    1362 CBC          58 :             defAclOid = GetNewOidWithIndex(rel, DefaultAclOidIndexId,
    1363 ECB             :                                            Anum_pg_default_acl_oid);
    1364 CBC          58 :             values[Anum_pg_default_acl_oid - 1] = ObjectIdGetDatum(defAclOid);
    1365 GIC          58 :             values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid);
    1366              58 :             values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid);
    1367 CBC          58 :             values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
    1368 GIC          58 :             values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
    1369                 : 
    1370 CBC          58 :             newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
    1371 GIC          58 :             CatalogTupleInsert(rel, newtuple);
    1372 ECB             :         }
    1373                 :         else
    1374                 :         {
    1375 CBC           9 :             defAclOid = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
    1376 ECB             : 
    1377                 :             /* update existing entry */
    1378 CBC           9 :             values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
    1379               9 :             replaces[Anum_pg_default_acl_defaclacl - 1] = true;
    1380                 : 
    1381 GIC           9 :             newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
    1382                 :                                          values, nulls, replaces);
    1383 CBC           9 :             CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
    1384                 :         }
    1385                 : 
    1386 ECB             :         /* these dependencies don't change in an update */
    1387 CBC          67 :         if (isNew)
    1388                 :         {
    1389 ECB             :             /* dependency on role */
    1390 GIC          58 :             recordDependencyOnOwner(DefaultAclRelationId, defAclOid,
    1391 ECB             :                                     iacls->roleid);
    1392                 : 
    1393                 :             /* dependency on namespace */
    1394 GIC          58 :             if (OidIsValid(iacls->nspid))
    1395 ECB             :             {
    1396                 :                 ObjectAddress myself,
    1397                 :                             referenced;
    1398                 : 
    1399 GIC          17 :                 myself.classId = DefaultAclRelationId;
    1400              17 :                 myself.objectId = defAclOid;
    1401              17 :                 myself.objectSubId = 0;
    1402 ECB             : 
    1403 GIC          17 :                 referenced.classId = NamespaceRelationId;
    1404              17 :                 referenced.objectId = iacls->nspid;
    1405              17 :                 referenced.objectSubId = 0;
    1406                 : 
    1407 CBC          17 :                 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
    1408 ECB             :             }
    1409                 :         }
    1410                 : 
    1411                 :         /*
    1412                 :          * Update the shared dependency ACL info
    1413                 :          */
    1414 GIC          67 :         nnewmembers = aclmembers(new_acl, &newmembers);
    1415 ECB             : 
    1416 GIC          67 :         updateAclDependencies(DefaultAclRelationId,
    1417                 :                               defAclOid, 0,
    1418                 :                               iacls->roleid,
    1419                 :                               noldmembers, oldmembers,
    1420                 :                               nnewmembers, newmembers);
    1421                 : 
    1422 CBC          67 :         if (isNew)
    1423 GIC          58 :             InvokeObjectPostCreateHook(DefaultAclRelationId, defAclOid, 0);
    1424 ECB             :         else
    1425 GIC           9 :             InvokeObjectPostAlterHook(DefaultAclRelationId, defAclOid, 0);
    1426                 :     }
    1427                 : 
    1428              95 :     if (HeapTupleIsValid(tuple))
    1429              36 :         ReleaseSysCache(tuple);
    1430 ECB             : 
    1431 CBC          95 :     table_close(rel, RowExclusiveLock);
    1432                 : 
    1433 ECB             :     /* prevent error when processing duplicate objects */
    1434 GIC          95 :     CommandCounterIncrement();
    1435              95 : }
    1436 ECB             : 
    1437                 : 
    1438                 : /*
    1439                 :  * RemoveRoleFromObjectACL
    1440                 :  *
    1441                 :  * Used by shdepDropOwned to remove mentions of a role in ACLs
    1442                 :  */
    1443                 : void
    1444 GIC         105 : RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
    1445                 : {
    1446             105 :     if (classid == DefaultAclRelationId)
    1447                 :     {
    1448                 :         InternalDefaultACL iacls;
    1449                 :         Form_pg_default_acl pg_default_acl_tuple;
    1450                 :         Relation    rel;
    1451                 :         ScanKeyData skey[1];
    1452 ECB             :         SysScanDesc scan;
    1453                 :         HeapTuple   tuple;
    1454                 : 
    1455                 :         /* first fetch info needed by SetDefaultACL */
    1456 GIC          15 :         rel = table_open(DefaultAclRelationId, AccessShareLock);
    1457                 : 
    1458              15 :         ScanKeyInit(&skey[0],
    1459                 :                     Anum_pg_default_acl_oid,
    1460                 :                     BTEqualStrategyNumber, F_OIDEQ,
    1461                 :                     ObjectIdGetDatum(objid));
    1462                 : 
    1463              15 :         scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
    1464 ECB             :                                   NULL, 1, skey);
    1465                 : 
    1466 CBC          15 :         tuple = systable_getnext(scan);
    1467                 : 
    1468 GIC          15 :         if (!HeapTupleIsValid(tuple))
    1469 UIC           0 :             elog(ERROR, "could not find tuple for default ACL %u", objid);
    1470                 : 
    1471 CBC          15 :         pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
    1472                 : 
    1473 GIC          15 :         iacls.roleid = pg_default_acl_tuple->defaclrole;
    1474 CBC          15 :         iacls.nspid = pg_default_acl_tuple->defaclnamespace;
    1475                 : 
    1476              15 :         switch (pg_default_acl_tuple->defaclobjtype)
    1477 EUB             :         {
    1478 GIC           3 :             case DEFACLOBJ_RELATION:
    1479 CBC           3 :                 iacls.objtype = OBJECT_TABLE;
    1480 GIC           3 :                 break;
    1481 CBC           3 :             case DEFACLOBJ_SEQUENCE:
    1482               3 :                 iacls.objtype = OBJECT_SEQUENCE;
    1483 GIC           3 :                 break;
    1484 CBC           3 :             case DEFACLOBJ_FUNCTION:
    1485 GIC           3 :                 iacls.objtype = OBJECT_FUNCTION;
    1486 CBC           3 :                 break;
    1487               3 :             case DEFACLOBJ_TYPE:
    1488               3 :                 iacls.objtype = OBJECT_TYPE;
    1489               3 :                 break;
    1490               3 :             case DEFACLOBJ_NAMESPACE:
    1491               3 :                 iacls.objtype = OBJECT_SCHEMA;
    1492               3 :                 break;
    1493 LBC           0 :             default:
    1494 ECB             :                 /* Shouldn't get here */
    1495 LBC           0 :                 elog(ERROR, "unexpected default ACL type: %d",
    1496 ECB             :                      (int) pg_default_acl_tuple->defaclobjtype);
    1497                 :                 break;
    1498                 :         }
    1499                 : 
    1500 CBC          15 :         systable_endscan(scan);
    1501 GBC          15 :         table_close(rel, AccessShareLock);
    1502                 : 
    1503              15 :         iacls.is_grant = false;
    1504 GIC          15 :         iacls.all_privs = true;
    1505              15 :         iacls.privileges = ACL_NO_RIGHTS;
    1506              15 :         iacls.grantees = list_make1_oid(roleid);
    1507              15 :         iacls.grant_option = false;
    1508 CBC          15 :         iacls.behavior = DROP_CASCADE;
    1509 ECB             : 
    1510                 :         /* Do it */
    1511 CBC          15 :         SetDefaultACL(&iacls);
    1512 ECB             :     }
    1513                 :     else
    1514                 :     {
    1515                 :         InternalGrant istmt;
    1516                 : 
    1517 GIC          90 :         switch (classid)
    1518                 :         {
    1519 CBC          38 :             case RelationRelationId:
    1520                 :                 /* it's OK to use TABLE for a sequence */
    1521 GIC          38 :                 istmt.objtype = OBJECT_TABLE;
    1522              38 :                 break;
    1523               4 :             case DatabaseRelationId:
    1524               4 :                 istmt.objtype = OBJECT_DATABASE;
    1525 CBC           4 :                 break;
    1526 UIC           0 :             case TypeRelationId:
    1527 LBC           0 :                 istmt.objtype = OBJECT_TYPE;
    1528 UIC           0 :                 break;
    1529 CBC          14 :             case ProcedureRelationId:
    1530              14 :                 istmt.objtype = OBJECT_ROUTINE;
    1531              14 :                 break;
    1532 LBC           0 :             case LanguageRelationId:
    1533               0 :                 istmt.objtype = OBJECT_LANGUAGE;
    1534 UBC           0 :                 break;
    1535 GBC           9 :             case LargeObjectRelationId:
    1536               9 :                 istmt.objtype = OBJECT_LARGEOBJECT;
    1537 CBC           9 :                 break;
    1538               6 :             case NamespaceRelationId:
    1539               6 :                 istmt.objtype = OBJECT_SCHEMA;
    1540 GBC           6 :                 break;
    1541 UBC           0 :             case TableSpaceRelationId:
    1542               0 :                 istmt.objtype = OBJECT_TABLESPACE;
    1543 LBC           0 :                 break;
    1544 CBC           6 :             case ForeignServerRelationId:
    1545               6 :                 istmt.objtype = OBJECT_FOREIGN_SERVER;
    1546               6 :                 break;
    1547               1 :             case ForeignDataWrapperRelationId:
    1548               1 :                 istmt.objtype = OBJECT_FDW;
    1549 GBC           1 :                 break;
    1550              12 :             case ParameterAclRelationId:
    1551              12 :                 istmt.objtype = OBJECT_PARAMETER_ACL;
    1552 CBC          12 :                 break;
    1553 LBC           0 :             default:
    1554               0 :                 elog(ERROR, "unexpected object class %u", classid);
    1555 ECB             :                 break;
    1556                 :         }
    1557 CBC          90 :         istmt.is_grant = false;
    1558              90 :         istmt.objects = list_make1_oid(objid);
    1559              90 :         istmt.all_privs = true;
    1560              90 :         istmt.privileges = ACL_NO_RIGHTS;
    1561 GBC          90 :         istmt.col_privs = NIL;
    1562              90 :         istmt.grantees = list_make1_oid(roleid);
    1563 GIC          90 :         istmt.grant_option = false;
    1564              90 :         istmt.behavior = DROP_CASCADE;
    1565 ECB             : 
    1566 CBC          90 :         ExecGrantStmt_oids(&istmt);
    1567 ECB             :     }
    1568 CBC         105 : }
    1569 ECB             : 
    1570                 : 
    1571                 : /*
    1572                 :  * expand_col_privileges
    1573                 :  *
    1574                 :  * OR the specified privilege(s) into per-column array entries for each
    1575                 :  * specified attribute.  The per-column array is indexed starting at
    1576                 :  * FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
    1577                 :  */
    1578                 : static void
    1579 GIC         469 : expand_col_privileges(List *colnames, Oid table_oid,
    1580                 :                       AclMode this_privileges,
    1581                 :                       AclMode *col_privileges,
    1582                 :                       int num_col_privileges)
    1583                 : {
    1584                 :     ListCell   *cell;
    1585                 : 
    1586            5620 :     foreach(cell, colnames)
    1587 ECB             :     {
    1588 GIC        5151 :         char       *colname = strVal(lfirst(cell));
    1589                 :         AttrNumber  attnum;
    1590                 : 
    1591            5151 :         attnum = get_attnum(table_oid, colname);
    1592            5151 :         if (attnum == InvalidAttrNumber)
    1593 UIC           0 :             ereport(ERROR,
    1594 ECB             :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    1595                 :                      errmsg("column \"%s\" of relation \"%s\" does not exist",
    1596                 :                             colname, get_rel_name(table_oid))));
    1597 GIC        5151 :         attnum -= FirstLowInvalidHeapAttributeNumber;
    1598            5151 :         if (attnum <= 0 || attnum >= num_col_privileges)
    1599 LBC           0 :             elog(ERROR, "column number out of range");    /* safety check */
    1600 CBC        5151 :         col_privileges[attnum] |= this_privileges;
    1601 EUB             :     }
    1602 GIC         469 : }
    1603                 : 
    1604                 : /*
    1605 ECB             :  * expand_all_col_privileges
    1606                 :  *
    1607 EUB             :  * OR the specified privilege(s) into per-column array entries for each valid
    1608 ECB             :  * attribute of a relation.  The per-column array is indexed starting at
    1609                 :  * FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
    1610                 :  */
    1611                 : static void
    1612 GIC        4456 : expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
    1613                 :                           AclMode this_privileges,
    1614                 :                           AclMode *col_privileges,
    1615                 :                           int num_col_privileges)
    1616                 : {
    1617                 :     AttrNumber  curr_att;
    1618                 : 
    1619            4456 :     Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
    1620 CBC        4456 :     for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
    1621 GIC       74307 :          curr_att <= classForm->relnatts;
    1622           69851 :          curr_att++)
    1623                 :     {
    1624                 :         HeapTuple   attTuple;
    1625                 :         bool        isdropped;
    1626                 : 
    1627 CBC       69851 :         if (curr_att == InvalidAttrNumber)
    1628            4456 :             continue;
    1629 ECB             : 
    1630                 :         /* Views don't have any system columns at all */
    1631 GIC       65395 :         if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
    1632           14628 :             continue;
    1633                 : 
    1634           50767 :         attTuple = SearchSysCache2(ATTNUM,
    1635 ECB             :                                    ObjectIdGetDatum(table_oid),
    1636                 :                                    Int16GetDatum(curr_att));
    1637 GIC       50767 :         if (!HeapTupleIsValid(attTuple))
    1638 UIC           0 :             elog(ERROR, "cache lookup failed for attribute %d of relation %u",
    1639 ECB             :                  curr_att, table_oid);
    1640                 : 
    1641 GIC       50767 :         isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
    1642 ECB             : 
    1643 GIC       50767 :         ReleaseSysCache(attTuple);
    1644                 : 
    1645 ECB             :         /* ignore dropped columns */
    1646 GBC       50767 :         if (isdropped)
    1647 GIC           3 :             continue;
    1648                 : 
    1649 CBC       50764 :         col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
    1650                 :     }
    1651            4456 : }
    1652                 : 
    1653                 : /*
    1654 ECB             :  *  This processes attributes, but expects to be called from
    1655                 :  *  ExecGrant_Relation, not directly from ExecuteGrantStmt.
    1656                 :  */
    1657                 : static void
    1658 GIC       55894 : ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
    1659 ECB             :                     AttrNumber attnum, Oid ownerId, AclMode col_privileges,
    1660                 :                     Relation attRelation, const Acl *old_rel_acl)
    1661                 : {
    1662                 :     HeapTuple   attr_tuple;
    1663                 :     Form_pg_attribute pg_attribute_tuple;
    1664                 :     Acl        *old_acl;
    1665                 :     Acl        *new_acl;
    1666                 :     Acl        *merged_acl;
    1667                 :     Datum       aclDatum;
    1668                 :     bool        isNull;
    1669                 :     Oid         grantorId;
    1670                 :     AclMode     avail_goptions;
    1671                 :     bool        need_update;
    1672                 :     HeapTuple   newtuple;
    1673 GNC       55894 :     Datum       values[Natts_pg_attribute] = {0};
    1674           55894 :     bool        nulls[Natts_pg_attribute] = {0};
    1675           55894 :     bool        replaces[Natts_pg_attribute] = {0};
    1676                 :     int         noldmembers;
    1677                 :     int         nnewmembers;
    1678                 :     Oid        *oldmembers;
    1679                 :     Oid        *newmembers;
    1680                 : 
    1681 CBC       55894 :     attr_tuple = SearchSysCache2(ATTNUM,
    1682 ECB             :                                  ObjectIdGetDatum(relOid),
    1683                 :                                  Int16GetDatum(attnum));
    1684 GIC       55894 :     if (!HeapTupleIsValid(attr_tuple))
    1685 UIC           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
    1686                 :              attnum, relOid);
    1687 GIC       55894 :     pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
    1688                 : 
    1689 ECB             :     /*
    1690                 :      * Get working copy of existing ACL. If there's no ACL, substitute the
    1691                 :      * proper default.
    1692                 :      */
    1693 GBC       55894 :     aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
    1694                 :                                &isNull);
    1695 CBC       55894 :     if (isNull)
    1696                 :     {
    1697 GIC       55743 :         old_acl = acldefault(OBJECT_COLUMN, ownerId);
    1698                 :         /* There are no old member roles according to the catalogs */
    1699           55743 :         noldmembers = 0;
    1700           55743 :         oldmembers = NULL;
    1701 ECB             :     }
    1702                 :     else
    1703                 :     {
    1704 GIC         151 :         old_acl = DatumGetAclPCopy(aclDatum);
    1705 ECB             :         /* Get the roles mentioned in the existing ACL */
    1706 GIC         151 :         noldmembers = aclmembers(old_acl, &oldmembers);
    1707 ECB             :     }
    1708                 : 
    1709                 :     /*
    1710                 :      * In select_best_grantor we should consider existing table-level ACL bits
    1711                 :      * as well as the per-column ACL.  Build a new ACL that is their
    1712                 :      * concatenation.  (This is a bit cheap and dirty compared to merging them
    1713                 :      * properly with no duplications, but it's all we need here.)
    1714                 :      */
    1715 GIC       55894 :     merged_acl = aclconcat(old_rel_acl, old_acl);
    1716                 : 
    1717                 :     /* Determine ID to do the grant as, and available grant options */
    1718           55894 :     select_best_grantor(GetUserId(), col_privileges,
    1719                 :                         merged_acl, ownerId,
    1720                 :                         &grantorId, &avail_goptions);
    1721                 : 
    1722           55894 :     pfree(merged_acl);
    1723 ECB             : 
    1724                 :     /*
    1725                 :      * Restrict the privileges to what we can actually grant, and emit the
    1726                 :      * standards-mandated warning and error messages.  Note: we don't track
    1727                 :      * whether the user actually used the ALL PRIVILEGES(columns) syntax for
    1728                 :      * each column; we just approximate it by whether all the possible
    1729                 :      * privileges are specified now.  Since the all_privs flag only determines
    1730                 :      * whether a warning is issued, this seems close enough.
    1731                 :      */
    1732                 :     col_privileges =
    1733 GIC       55894 :         restrict_and_check_grant(istmt->is_grant, avail_goptions,
    1734                 :                                  (col_privileges == ACL_ALL_RIGHTS_COLUMN),
    1735                 :                                  col_privileges,
    1736                 :                                  relOid, grantorId, OBJECT_COLUMN,
    1737                 :                                  relname, attnum,
    1738           55894 :                                  NameStr(pg_attribute_tuple->attname));
    1739                 : 
    1740                 :     /*
    1741 ECB             :      * Generate new ACL.
    1742                 :      */
    1743 GIC       55894 :     new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
    1744           55894 :                                    istmt->grant_option,
    1745                 :                                    istmt->behavior, istmt->grantees,
    1746 ECB             :                                    col_privileges, grantorId,
    1747                 :                                    ownerId);
    1748                 : 
    1749                 :     /*
    1750                 :      * We need the members of both old and new ACLs so we can correct the
    1751                 :      * shared dependency information.
    1752                 :      */
    1753 GIC       55894 :     nnewmembers = aclmembers(new_acl, &newmembers);
    1754                 : 
    1755                 :     /* finished building new ACL value, now insert it */
    1756                 : 
    1757                 :     /*
    1758 ECB             :      * If the updated ACL is empty, we can set attacl to null, and maybe even
    1759                 :      * avoid an update of the pg_attribute row.  This is worth testing because
    1760                 :      * we'll come through here multiple times for any relation-level REVOKE,
    1761                 :      * even if there were never any column GRANTs.  Note we are assuming that
    1762                 :      * the "default" ACL state for columns is empty.
    1763                 :      */
    1764 GIC       55894 :     if (ACL_NUM(new_acl) > 0)
    1765                 :     {
    1766            5162 :         values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
    1767            5162 :         need_update = true;
    1768                 :     }
    1769 ECB             :     else
    1770                 :     {
    1771 CBC       50732 :         nulls[Anum_pg_attribute_attacl - 1] = true;
    1772           50732 :         need_update = !isNull;
    1773                 :     }
    1774 GIC       55894 :     replaces[Anum_pg_attribute_attacl - 1] = true;
    1775                 : 
    1776 CBC       55894 :     if (need_update)
    1777 ECB             :     {
    1778 GIC        5208 :         newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
    1779 ECB             :                                      values, nulls, replaces);
    1780                 : 
    1781 CBC        5208 :         CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
    1782                 : 
    1783 ECB             :         /* Update initial privileges for extensions */
    1784 GIC        5208 :         recordExtensionInitPriv(relOid, RelationRelationId, attnum,
    1785            5208 :                                 ACL_NUM(new_acl) > 0 ? new_acl : NULL);
    1786 ECB             : 
    1787                 :         /* Update the shared dependency ACL info */
    1788 GIC        5208 :         updateAclDependencies(RelationRelationId, relOid, attnum,
    1789 ECB             :                               ownerId,
    1790                 :                               noldmembers, oldmembers,
    1791                 :                               nnewmembers, newmembers);
    1792                 :     }
    1793                 : 
    1794 GIC       55894 :     pfree(new_acl);
    1795                 : 
    1796           55894 :     ReleaseSysCache(attr_tuple);
    1797           55894 : }
    1798                 : 
    1799 ECB             : /*
    1800                 :  *  This processes both sequences and non-sequences.
    1801                 :  */
    1802                 : static void
    1803 GIC       25114 : ExecGrant_Relation(InternalGrant *istmt)
    1804                 : {
    1805                 :     Relation    relation;
    1806                 :     Relation    attRelation;
    1807                 :     ListCell   *cell;
    1808 ECB             : 
    1809 GIC       25114 :     relation = table_open(RelationRelationId, RowExclusiveLock);
    1810           25114 :     attRelation = table_open(AttributeRelationId, RowExclusiveLock);
    1811                 : 
    1812           50258 :     foreach(cell, istmt->objects)
    1813                 :     {
    1814 CBC       25147 :         Oid         relOid = lfirst_oid(cell);
    1815 ECB             :         Datum       aclDatum;
    1816                 :         Form_pg_class pg_class_tuple;
    1817                 :         bool        isNull;
    1818                 :         AclMode     this_privileges;
    1819                 :         AclMode    *col_privileges;
    1820                 :         int         num_col_privileges;
    1821                 :         bool        have_col_privileges;
    1822                 :         Acl        *old_acl;
    1823                 :         Acl        *old_rel_acl;
    1824                 :         int         noldmembers;
    1825                 :         Oid        *oldmembers;
    1826                 :         Oid         ownerId;
    1827                 :         HeapTuple   tuple;
    1828                 :         ListCell   *cell_colprivs;
    1829                 : 
    1830 GIC       25147 :         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
    1831           25147 :         if (!HeapTupleIsValid(tuple))
    1832 UIC           0 :             elog(ERROR, "cache lookup failed for relation %u", relOid);
    1833 GIC       25147 :         pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
    1834                 : 
    1835 ECB             :         /* Not sensible to grant on an index */
    1836 CBC       25147 :         if (pg_class_tuple->relkind == RELKIND_INDEX ||
    1837 GBC       25147 :             pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX)
    1838 LBC           0 :             ereport(ERROR,
    1839                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1840                 :                      errmsg("\"%s\" is an index",
    1841 ECB             :                             NameStr(pg_class_tuple->relname))));
    1842                 : 
    1843 EUB             :         /* Composite types aren't tables either */
    1844 GIC       25147 :         if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
    1845 UIC           0 :             ereport(ERROR,
    1846                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1847                 :                      errmsg("\"%s\" is a composite type",
    1848                 :                             NameStr(pg_class_tuple->relname))));
    1849 ECB             : 
    1850 EUB             :         /* Used GRANT SEQUENCE on a non-sequence? */
    1851 GIC       25147 :         if (istmt->objtype == OBJECT_SEQUENCE &&
    1852               6 :             pg_class_tuple->relkind != RELKIND_SEQUENCE)
    1853 UIC           0 :             ereport(ERROR,
    1854                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1855                 :                      errmsg("\"%s\" is not a sequence",
    1856 ECB             :                             NameStr(pg_class_tuple->relname))));
    1857                 : 
    1858 EUB             :         /* Adjust the default permissions based on object type */
    1859 GIC       25147 :         if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
    1860                 :         {
    1861            4483 :             if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
    1862              35 :                 this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
    1863                 :             else
    1864 CBC        4448 :                 this_privileges = ACL_ALL_RIGHTS_RELATION;
    1865                 :         }
    1866 ECB             :         else
    1867 CBC       20664 :             this_privileges = istmt->privileges;
    1868                 : 
    1869 ECB             :         /*
    1870                 :          * The GRANT TABLE syntax can be used for sequences and non-sequences,
    1871                 :          * so we have to look at the relkind to determine the supported
    1872                 :          * permissions.  The OR of table and sequence permissions were already
    1873                 :          * checked.
    1874                 :          */
    1875 GIC       25147 :         if (istmt->objtype == OBJECT_TABLE)
    1876                 :         {
    1877           25141 :             if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
    1878                 :             {
    1879                 :                 /*
    1880 ECB             :                  * For backward compatibility, just throw a warning for
    1881                 :                  * invalid sequence permissions when using the non-sequence
    1882                 :                  * GRANT syntax.
    1883                 :                  */
    1884 GIC          70 :                 if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
    1885                 :                 {
    1886                 :                     /*
    1887                 :                      * Mention the object name because the user needs to know
    1888                 :                      * which operations succeeded.  This is required because
    1889 ECB             :                      * WARNING allows the command to continue.
    1890                 :                      */
    1891 UIC           0 :                     ereport(WARNING,
    1892                 :                             (errcode(ERRCODE_INVALID_GRANT_OPERATION),
    1893                 :                              errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
    1894                 :                                     NameStr(pg_class_tuple->relname))));
    1895               0 :                     this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
    1896 EUB             :                 }
    1897                 :             }
    1898                 :             else
    1899                 :             {
    1900 GBC       25071 :                 if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
    1901                 :                 {
    1902                 :                     /*
    1903                 :                      * USAGE is the only permission supported by sequences but
    1904                 :                      * not by non-sequences.  Don't mention the object name
    1905 ECB             :                      * because we didn't in the combined TABLE | SEQUENCE
    1906                 :                      * check.
    1907                 :                      */
    1908 UIC           0 :                     ereport(ERROR,
    1909                 :                             (errcode(ERRCODE_INVALID_GRANT_OPERATION),
    1910                 :                              errmsg("invalid privilege type %s for table",
    1911                 :                                     "USAGE")));
    1912                 :                 }
    1913 EUB             :             }
    1914                 :         }
    1915                 : 
    1916                 :         /*
    1917                 :          * Set up array in which we'll accumulate any column privilege bits
    1918                 :          * that need modification.  The array is indexed such that entry [0]
    1919                 :          * corresponds to FirstLowInvalidHeapAttributeNumber.
    1920                 :          */
    1921 GIC       25147 :         num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
    1922           25147 :         col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
    1923           25147 :         have_col_privileges = false;
    1924                 : 
    1925                 :         /*
    1926 ECB             :          * If we are revoking relation privileges that are also column
    1927                 :          * privileges, we must implicitly revoke them from each column too,
    1928                 :          * per SQL spec.  (We don't need to implicitly add column privileges
    1929                 :          * during GRANT because the permissions-checking code always checks
    1930                 :          * both relation and per-column privileges.)
    1931                 :          */
    1932 GIC       25147 :         if (!istmt->is_grant &&
    1933            4484 :             (this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
    1934                 :         {
    1935            4456 :             expand_all_col_privileges(relOid, pg_class_tuple,
    1936                 :                                       this_privileges & ACL_ALL_RIGHTS_COLUMN,
    1937 ECB             :                                       col_privileges,
    1938                 :                                       num_col_privileges);
    1939 GIC        4456 :             have_col_privileges = true;
    1940 ECB             :         }
    1941                 : 
    1942                 :         /*
    1943                 :          * Get owner ID and working copy of existing ACL. If there's no ACL,
    1944                 :          * substitute the proper default.
    1945                 :          */
    1946 GIC       25147 :         ownerId = pg_class_tuple->relowner;
    1947           25147 :         aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
    1948                 :                                    &isNull);
    1949           25147 :         if (isNull)
    1950                 :         {
    1951 CBC       23554 :             switch (pg_class_tuple->relkind)
    1952 ECB             :             {
    1953 GIC          40 :                 case RELKIND_SEQUENCE:
    1954 CBC          40 :                     old_acl = acldefault(OBJECT_SEQUENCE, ownerId);
    1955 GIC          40 :                     break;
    1956 CBC       23514 :                 default:
    1957 GIC       23514 :                     old_acl = acldefault(OBJECT_TABLE, ownerId);
    1958 CBC       23514 :                     break;
    1959 ECB             :             }
    1960                 :             /* There are no old member roles according to the catalogs */
    1961 CBC       23554 :             noldmembers = 0;
    1962           23554 :             oldmembers = NULL;
    1963 ECB             :         }
    1964                 :         else
    1965                 :         {
    1966 CBC        1593 :             old_acl = DatumGetAclPCopy(aclDatum);
    1967 ECB             :             /* Get the roles mentioned in the existing ACL */
    1968 GIC        1593 :             noldmembers = aclmembers(old_acl, &oldmembers);
    1969                 :         }
    1970                 : 
    1971 ECB             :         /* Need an extra copy of original rel ACL for column handling */
    1972 GIC       25147 :         old_rel_acl = aclcopy(old_acl);
    1973 ECB             : 
    1974                 :         /*
    1975                 :          * Handle relation-level privileges, if any were specified
    1976                 :          */
    1977 CBC       25147 :         if (this_privileges != ACL_NO_RIGHTS)
    1978                 :         {
    1979                 :             AclMode     avail_goptions;
    1980                 :             Acl        *new_acl;
    1981                 :             Oid         grantorId;
    1982 ECB             :             HeapTuple   newtuple;
    1983 GNC       24684 :             Datum       values[Natts_pg_class] = {0};
    1984           24684 :             bool        nulls[Natts_pg_class] = {0};
    1985           24684 :             bool        replaces[Natts_pg_class] = {0};
    1986                 :             int         nnewmembers;
    1987                 :             Oid        *newmembers;
    1988 ECB             :             ObjectType  objtype;
    1989                 : 
    1990                 :             /* Determine ID to do the grant as, and available grant options */
    1991 GIC       24684 :             select_best_grantor(GetUserId(), this_privileges,
    1992                 :                                 old_acl, ownerId,
    1993                 :                                 &grantorId, &avail_goptions);
    1994                 : 
    1995           24684 :             switch (pg_class_tuple->relkind)
    1996 ECB             :             {
    1997 GIC          76 :                 case RELKIND_SEQUENCE:
    1998              76 :                     objtype = OBJECT_SEQUENCE;
    1999              76 :                     break;
    2000 CBC       24608 :                 default:
    2001 GIC       24608 :                     objtype = OBJECT_TABLE;
    2002 CBC       24608 :                     break;
    2003 ECB             :             }
    2004                 : 
    2005                 :             /*
    2006                 :              * Restrict the privileges to what we can actually grant, and emit
    2007                 :              * the standards-mandated warning and error messages.
    2008                 :              */
    2009                 :             this_privileges =
    2010 GIC       24684 :                 restrict_and_check_grant(istmt->is_grant, avail_goptions,
    2011           24684 :                                          istmt->all_privs, this_privileges,
    2012                 :                                          relOid, grantorId, objtype,
    2013           24684 :                                          NameStr(pg_class_tuple->relname),
    2014                 :                                          0, NULL);
    2015 ECB             : 
    2016                 :             /*
    2017                 :              * Generate new ACL.
    2018                 :              */
    2019 GIC       24684 :             new_acl = merge_acl_with_grant(old_acl,
    2020           24684 :                                            istmt->is_grant,
    2021           24684 :                                            istmt->grant_option,
    2022                 :                                            istmt->behavior,
    2023                 :                                            istmt->grantees,
    2024 ECB             :                                            this_privileges,
    2025                 :                                            grantorId,
    2026                 :                                            ownerId);
    2027                 : 
    2028                 :             /*
    2029                 :              * We need the members of both old and new ACLs so we can correct
    2030                 :              * the shared dependency information.
    2031                 :              */
    2032 GIC       24681 :             nnewmembers = aclmembers(new_acl, &newmembers);
    2033                 : 
    2034                 :             /* finished building new ACL value, now insert it */
    2035           24681 :             replaces[Anum_pg_class_relacl - 1] = true;
    2036 CBC       24681 :             values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
    2037 ECB             : 
    2038 GIC       24681 :             newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
    2039 ECB             :                                          values, nulls, replaces);
    2040                 : 
    2041 GIC       24681 :             CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
    2042 ECB             : 
    2043                 :             /* Update initial privileges for extensions */
    2044 GIC       24681 :             recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
    2045 ECB             : 
    2046                 :             /* Update the shared dependency ACL info */
    2047 GIC       24681 :             updateAclDependencies(RelationRelationId, relOid, 0,
    2048 ECB             :                                   ownerId,
    2049                 :                                   noldmembers, oldmembers,
    2050                 :                                   nnewmembers, newmembers);
    2051                 : 
    2052 GIC       24681 :             pfree(new_acl);
    2053 ECB             :         }
    2054                 : 
    2055                 :         /*
    2056                 :          * Handle column-level privileges, if any were specified or implied.
    2057                 :          * We first expand the user-specified column privileges into the
    2058                 :          * array, and then iterate over all nonempty array entries.
    2059                 :          */
    2060 GIC       25613 :         foreach(cell_colprivs, istmt->col_privs)
    2061 ECB             :         {
    2062 GIC         469 :             AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
    2063 ECB             : 
    2064 GIC         469 :             if (col_privs->priv_name == NULL)
    2065 CBC           9 :                 this_privileges = ACL_ALL_RIGHTS_COLUMN;
    2066 ECB             :             else
    2067 GIC         460 :                 this_privileges = string_to_privilege(col_privs->priv_name);
    2068 ECB             : 
    2069 GIC         469 :             if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
    2070 LBC           0 :                 ereport(ERROR,
    2071 EUB             :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
    2072                 :                          errmsg("invalid privilege type %s for column",
    2073                 :                                 privilege_to_string(this_privileges))));
    2074                 : 
    2075 GIC         469 :             if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
    2076 LBC           0 :                 this_privileges & ~((AclMode) ACL_SELECT))
    2077 EUB             :             {
    2078                 :                 /*
    2079                 :                  * The only column privilege allowed on sequences is SELECT.
    2080                 :                  * This is a warning not error because we do it that way for
    2081                 :                  * relation-level privileges.
    2082                 :                  */
    2083 UIC           0 :                 ereport(WARNING,
    2084 EUB             :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
    2085                 :                          errmsg("sequence \"%s\" only supports SELECT column privileges",
    2086                 :                                 NameStr(pg_class_tuple->relname))));
    2087                 : 
    2088 UIC           0 :                 this_privileges &= (AclMode) ACL_SELECT;
    2089 EUB             :             }
    2090                 : 
    2091 GIC         469 :             expand_col_privileges(col_privs->cols, relOid,
    2092 ECB             :                                   this_privileges,
    2093                 :                                   col_privileges,
    2094                 :                                   num_col_privileges);
    2095 GIC         469 :             have_col_privileges = true;
    2096 ECB             :         }
    2097                 : 
    2098 GIC       25144 :         if (have_col_privileges)
    2099 ECB             :         {
    2100                 :             AttrNumber  i;
    2101                 : 
    2102 GIC       88733 :             for (i = 0; i < num_col_privileges; i++)
    2103 ECB             :             {
    2104 GIC       83817 :                 if (col_privileges[i] == ACL_NO_RIGHTS)
    2105 CBC       27923 :                     continue;
    2106           55894 :                 ExecGrant_Attribute(istmt,
    2107 ECB             :                                     relOid,
    2108 GIC       55894 :                                     NameStr(pg_class_tuple->relname),
    2109 CBC       55894 :                                     i + FirstLowInvalidHeapAttributeNumber,
    2110 ECB             :                                     ownerId,
    2111 GIC       55894 :                                     col_privileges[i],
    2112 ECB             :                                     attRelation,
    2113                 :                                     old_rel_acl);
    2114                 :             }
    2115                 :         }
    2116                 : 
    2117 GIC       25144 :         pfree(old_rel_acl);
    2118 CBC       25144 :         pfree(col_privileges);
    2119 ECB             : 
    2120 GIC       25144 :         ReleaseSysCache(tuple);
    2121 ECB             : 
    2122                 :         /* prevent error when processing duplicate objects */
    2123 GIC       25144 :         CommandCounterIncrement();
    2124 ECB             :     }
    2125                 : 
    2126 GIC       25111 :     table_close(attRelation, RowExclusiveLock);
    2127 CBC       25111 :     table_close(relation, RowExclusiveLock);
    2128           25111 : }
    2129 ECB             : 
    2130                 : static void
    2131 GNC       23681 : ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs,
    2132                 :                  void (*object_check) (InternalGrant *istmt, HeapTuple tuple))
    2133 ECB             : {
    2134                 :     int         cacheid;
    2135                 :     Relation    relation;
    2136                 :     ListCell   *cell;
    2137                 : 
    2138 GIC       23681 :     if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
    2139 GNC         231 :         istmt->privileges = default_privs;
    2140                 : 
    2141           23681 :     cacheid = get_object_catcache_oid(classid);
    2142                 : 
    2143           23681 :     relation = table_open(classid, RowExclusiveLock);
    2144 ECB             : 
    2145 GIC       47662 :     foreach(cell, istmt->objects)
    2146 ECB             :     {
    2147 GNC       24008 :         Oid         objectid = lfirst_oid(cell);
    2148                 :         Datum       aclDatum;
    2149                 :         Datum       nameDatum;
    2150 ECB             :         bool        isNull;
    2151                 :         AclMode     avail_goptions;
    2152                 :         AclMode     this_privileges;
    2153                 :         Acl        *old_acl;
    2154                 :         Acl        *new_acl;
    2155                 :         Oid         grantorId;
    2156                 :         Oid         ownerId;
    2157                 :         HeapTuple   tuple;
    2158                 :         HeapTuple   newtuple;
    2159 GNC       24008 :         Datum      *values = palloc0_array(Datum, RelationGetDescr(relation)->natts);
    2160           24008 :         bool       *nulls = palloc0_array(bool, RelationGetDescr(relation)->natts);
    2161           24008 :         bool       *replaces = palloc0_array(bool, RelationGetDescr(relation)->natts);
    2162                 :         int         noldmembers;
    2163                 :         int         nnewmembers;
    2164                 :         Oid        *oldmembers;
    2165 ECB             :         Oid        *newmembers;
    2166                 : 
    2167 GNC       24008 :         tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
    2168 GIC       24008 :         if (!HeapTupleIsValid(tuple))
    2169 UNC           0 :             elog(ERROR, "cache lookup failed for %s %u", get_object_class_descr(classid), objectid);
    2170                 : 
    2171                 :         /*
    2172                 :          * Additional object-type-specific checks
    2173                 :          */
    2174 GNC       24008 :         if (object_check)
    2175              74 :             object_check(istmt, tuple);
    2176 ECB             : 
    2177                 :         /*
    2178 EUB             :          * Get owner ID and working copy of existing ACL. If there's no ACL,
    2179                 :          * substitute the proper default.
    2180                 :          */
    2181 GNC       23999 :         ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
    2182                 :                                                           tuple,
    2183           23999 :                                                           get_object_attnum_owner(classid)));
    2184           23999 :         aclDatum = SysCacheGetAttr(cacheid,
    2185                 :                                    tuple,
    2186           23999 :                                    get_object_attnum_acl(classid),
    2187                 :                                    &isNull);
    2188 CBC       23999 :         if (isNull)
    2189                 :         {
    2190 GNC       20613 :             old_acl = acldefault(get_object_type(classid, objectid), ownerId);
    2191                 :             /* There are no old member roles according to the catalogs */
    2192 GIC       20613 :             noldmembers = 0;
    2193           20613 :             oldmembers = NULL;
    2194 ECB             :         }
    2195                 :         else
    2196                 :         {
    2197 CBC        3386 :             old_acl = DatumGetAclPCopy(aclDatum);
    2198                 :             /* Get the roles mentioned in the existing ACL */
    2199            3386 :             noldmembers = aclmembers(old_acl, &oldmembers);
    2200                 :         }
    2201 ECB             : 
    2202                 :         /* Determine ID to do the grant as, and available grant options */
    2203 CBC       23999 :         select_best_grantor(GetUserId(), istmt->privileges,
    2204                 :                             old_acl, ownerId,
    2205 ECB             :                             &grantorId, &avail_goptions);
    2206                 : 
    2207 GNC       23999 :         nameDatum = SysCacheGetAttrNotNull(cacheid, tuple,
    2208           23999 :                                            get_object_attnum_name(classid));
    2209                 : 
    2210                 :         /*
    2211                 :          * Restrict the privileges to what we can actually grant, and emit the
    2212                 :          * standards-mandated warning and error messages.
    2213 ECB             :          */
    2214                 :         this_privileges =
    2215 CBC       47998 :             restrict_and_check_grant(istmt->is_grant, avail_goptions,
    2216 GIC       23999 :                                      istmt->all_privs, istmt->privileges,
    2217                 :                                      objectid, grantorId, get_object_type(classid, objectid),
    2218 GNC       23999 :                                      NameStr(*DatumGetName(nameDatum)),
    2219 ECB             :                                      0, NULL);
    2220                 : 
    2221                 :         /*
    2222                 :          * Generate new ACL.
    2223                 :          */
    2224 CBC       23984 :         new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
    2225 GIC       23984 :                                        istmt->grant_option, istmt->behavior,
    2226                 :                                        istmt->grantees, this_privileges,
    2227                 :                                        grantorId, ownerId);
    2228                 : 
    2229                 :         /*
    2230                 :          * We need the members of both old and new ACLs so we can correct the
    2231 ECB             :          * shared dependency information.
    2232                 :          */
    2233 GIC       23981 :         nnewmembers = aclmembers(new_acl, &newmembers);
    2234 ECB             : 
    2235                 :         /* finished building new ACL value, now insert it */
    2236 GNC       23981 :         replaces[get_object_attnum_acl(classid) - 1] = true;
    2237           23981 :         values[get_object_attnum_acl(classid) - 1] = PointerGetDatum(new_acl);
    2238                 : 
    2239 GIC       23981 :         newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
    2240                 :                                      nulls, replaces);
    2241                 : 
    2242           23981 :         CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
    2243                 : 
    2244                 :         /* Update initial privileges for extensions */
    2245 GNC       23981 :         recordExtensionInitPriv(objectid, classid, 0, new_acl);
    2246                 : 
    2247                 :         /* Update the shared dependency ACL info */
    2248           23981 :         updateAclDependencies(classid,
    2249                 :                               objectid, 0,
    2250                 :                               ownerId,
    2251                 :                               noldmembers, oldmembers,
    2252 ECB             :                               nnewmembers, newmembers);
    2253                 : 
    2254 GIC       23981 :         ReleaseSysCache(tuple);
    2255 ECB             : 
    2256 GIC       23981 :         pfree(new_acl);
    2257                 : 
    2258 ECB             :         /* prevent error when processing duplicate objects */
    2259 GIC       23981 :         CommandCounterIncrement();
    2260                 :     }
    2261 ECB             : 
    2262 GIC       23654 :     table_close(relation, RowExclusiveLock);
    2263           23654 : }
    2264 ECB             : 
    2265                 : static void
    2266 GNC          21 : ExecGrant_Language_check(InternalGrant *istmt, HeapTuple tuple)
    2267                 : {
    2268                 :     Form_pg_language pg_language_tuple;
    2269 ECB             : 
    2270 GNC          21 :     pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
    2271                 : 
    2272              21 :     if (!pg_language_tuple->lanpltrusted)
    2273               3 :         ereport(ERROR,
    2274                 :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2275                 :                  errmsg("language \"%s\" is not trusted",
    2276                 :                         NameStr(pg_language_tuple->lanname)),
    2277                 :                  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
    2278                 :                            "because only superusers can use untrusted languages.")));
    2279 GBC          18 : }
    2280 EUB             : 
    2281                 : static void
    2282 GBC          37 : ExecGrant_Largeobject(InternalGrant *istmt)
    2283 EUB             : {
    2284                 :     Relation    relation;
    2285 ECB             :     ListCell   *cell;
    2286                 : 
    2287 CBC          37 :     if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
    2288 GBC          22 :         istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
    2289 EUB             : 
    2290 GBC          37 :     relation = table_open(LargeObjectMetadataRelationId,
    2291 EUB             :                           RowExclusiveLock);
    2292                 : 
    2293 GBC          77 :     foreach(cell, istmt->objects)
    2294 EUB             :     {
    2295 GBC          40 :         Oid         loid = lfirst_oid(cell);
    2296 EUB             :         Form_pg_largeobject_metadata form_lo_meta;
    2297 ECB             :         char        loname[NAMEDATALEN];
    2298                 :         Datum       aclDatum;
    2299                 :         bool        isNull;
    2300                 :         AclMode     avail_goptions;
    2301                 :         AclMode     this_privileges;
    2302                 :         Acl        *old_acl;
    2303 EUB             :         Acl        *new_acl;
    2304                 :         Oid         grantorId;
    2305                 :         Oid         ownerId;
    2306                 :         HeapTuple   newtuple;
    2307 GNC          40 :         Datum       values[Natts_pg_largeobject_metadata] = {0};
    2308              40 :         bool        nulls[Natts_pg_largeobject_metadata] = {0};
    2309              40 :         bool        replaces[Natts_pg_largeobject_metadata] = {0};
    2310 ECB             :         int         noldmembers;
    2311                 :         int         nnewmembers;
    2312                 :         Oid        *oldmembers;
    2313                 :         Oid        *newmembers;
    2314                 :         ScanKeyData entry[1];
    2315                 :         SysScanDesc scan;
    2316 EUB             :         HeapTuple   tuple;
    2317                 : 
    2318                 :         /* There's no syscache for pg_largeobject_metadata */
    2319 GIC          40 :         ScanKeyInit(&entry[0],
    2320                 :                     Anum_pg_largeobject_metadata_oid,
    2321                 :                     BTEqualStrategyNumber, F_OIDEQ,
    2322                 :                     ObjectIdGetDatum(loid));
    2323                 : 
    2324              40 :         scan = systable_beginscan(relation,
    2325                 :                                   LargeObjectMetadataOidIndexId, true,
    2326                 :                                   NULL, 1, entry);
    2327                 : 
    2328              40 :         tuple = systable_getnext(scan);
    2329              40 :         if (!HeapTupleIsValid(tuple))
    2330 UIC           0 :             elog(ERROR, "could not find tuple for large object %u", loid);
    2331                 : 
    2332 GIC          40 :         form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
    2333                 : 
    2334 EUB             :         /*
    2335                 :          * Get owner ID and working copy of existing ACL. If there's no ACL,
    2336                 :          * substitute the proper default.
    2337 ECB             :          */
    2338 GIC          40 :         ownerId = form_lo_meta->lomowner;
    2339              40 :         aclDatum = heap_getattr(tuple,
    2340                 :                                 Anum_pg_largeobject_metadata_lomacl,
    2341                 :                                 RelationGetDescr(relation), &isNull);
    2342 CBC          40 :         if (isNull)
    2343                 :         {
    2344              22 :             old_acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
    2345                 :             /* There are no old member roles according to the catalogs */
    2346 GIC          22 :             noldmembers = 0;
    2347              22 :             oldmembers = NULL;
    2348 ECB             :         }
    2349                 :         else
    2350                 :         {
    2351 GBC          18 :             old_acl = DatumGetAclPCopy(aclDatum);
    2352 EUB             :             /* Get the roles mentioned in the existing ACL */
    2353 GBC          18 :             noldmembers = aclmembers(old_acl, &oldmembers);
    2354 ECB             :         }
    2355                 : 
    2356                 :         /* Determine ID to do the grant as, and available grant options */
    2357 GBC          40 :         select_best_grantor(GetUserId(), istmt->privileges,
    2358 EUB             :                             old_acl, ownerId,
    2359                 :                             &grantorId, &avail_goptions);
    2360                 : 
    2361                 :         /*
    2362                 :          * Restrict the privileges to what we can actually grant, and emit the
    2363                 :          * standards-mandated warning and error messages.
    2364                 :          */
    2365 GBC          40 :         snprintf(loname, sizeof(loname), "large object %u", loid);
    2366 EUB             :         this_privileges =
    2367 GBC          40 :             restrict_and_check_grant(istmt->is_grant, avail_goptions,
    2368              40 :                                      istmt->all_privs, istmt->privileges,
    2369 ECB             :                                      loid, grantorId, OBJECT_LARGEOBJECT,
    2370                 :                                      loname, 0, NULL);
    2371                 : 
    2372                 :         /*
    2373                 :          * Generate new ACL.
    2374                 :          */
    2375 GBC          40 :         new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
    2376              40 :                                        istmt->grant_option, istmt->behavior,
    2377 EUB             :                                        istmt->grantees, this_privileges,
    2378 ECB             :                                        grantorId, ownerId);
    2379                 : 
    2380                 :         /*
    2381                 :          * We need the members of both old and new ACLs so we can correct the
    2382                 :          * shared dependency information.
    2383                 :          */
    2384 CBC          40 :         nnewmembers = aclmembers(new_acl, &newmembers);
    2385 ECB             : 
    2386                 :         /* finished building new ACL value, now insert it */
    2387 GBC          40 :         replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
    2388 EUB             :         values[Anum_pg_largeobject_metadata_lomacl - 1]
    2389 CBC          40 :             = PointerGetDatum(new_acl);
    2390 ECB             : 
    2391 CBC          40 :         newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
    2392 ECB             :                                      values, nulls, replaces);
    2393                 : 
    2394 CBC          40 :         CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
    2395 ECB             : 
    2396                 :         /* Update initial privileges for extensions */
    2397 CBC          40 :         recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
    2398 ECB             : 
    2399                 :         /* Update the shared dependency ACL info */
    2400 CBC          40 :         updateAclDependencies(LargeObjectRelationId,
    2401 ECB             :                               form_lo_meta->oid, 0,
    2402                 :                               ownerId,
    2403                 :                               noldmembers, oldmembers,
    2404 EUB             :                               nnewmembers, newmembers);
    2405                 : 
    2406 GBC          40 :         systable_endscan(scan);
    2407 ECB             : 
    2408 CBC          40 :         pfree(new_acl);
    2409 ECB             : 
    2410                 :         /* prevent error when processing duplicate objects */
    2411 CBC          40 :         CommandCounterIncrement();
    2412 ECB             :     }
    2413                 : 
    2414 CBC          37 :     table_close(relation, RowExclusiveLock);
    2415              37 : }
    2416 ECB             : 
    2417                 : static void
    2418 GNC          53 : ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple)
    2419 ECB             : {
    2420                 :     Form_pg_type pg_type_tuple;
    2421                 : 
    2422 GNC          53 :     pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
    2423 ECB             : 
    2424 GNC          53 :     if (IsTrueArrayType(pg_type_tuple))
    2425               3 :         ereport(ERROR,
    2426                 :                 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
    2427                 :                  errmsg("cannot set privileges of array types"),
    2428                 :                  errhint("Set the privileges of the element type instead.")));
    2429 ECB             : 
    2430                 :     /* Used GRANT DOMAIN on a non-domain? */
    2431 GNC          50 :     if (istmt->objtype == OBJECT_DOMAIN &&
    2432              10 :         pg_type_tuple->typtype != TYPTYPE_DOMAIN)
    2433               3 :         ereport(ERROR,
    2434                 :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2435                 :                  errmsg("\"%s\" is not a domain",
    2436                 :                         NameStr(pg_type_tuple->typname))));
    2437 GIC          47 : }
    2438                 : 
    2439                 : static void
    2440              49 : ExecGrant_Parameter(InternalGrant *istmt)
    2441                 : {
    2442                 :     Relation    relation;
    2443 ECB             :     ListCell   *cell;
    2444                 : 
    2445 GIC          49 :     if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
    2446              21 :         istmt->privileges = ACL_ALL_RIGHTS_PARAMETER_ACL;
    2447                 : 
    2448              49 :     relation = table_open(ParameterAclRelationId, RowExclusiveLock);
    2449                 : 
    2450             117 :     foreach(cell, istmt->objects)
    2451                 :     {
    2452              68 :         Oid         parameterId = lfirst_oid(cell);
    2453                 :         Datum       nameDatum;
    2454                 :         const char *parname;
    2455                 :         Datum       aclDatum;
    2456                 :         bool        isNull;
    2457 ECB             :         AclMode     avail_goptions;
    2458                 :         AclMode     this_privileges;
    2459                 :         Acl        *old_acl;
    2460 EUB             :         Acl        *new_acl;
    2461                 :         Oid         grantorId;
    2462                 :         Oid         ownerId;
    2463                 :         HeapTuple   tuple;
    2464                 :         int         noldmembers;
    2465                 :         int         nnewmembers;
    2466                 :         Oid        *oldmembers;
    2467                 :         Oid        *newmembers;
    2468                 : 
    2469 GIC          68 :         tuple = SearchSysCache1(PARAMETERACLOID, ObjectIdGetDatum(parameterId));
    2470              68 :         if (!HeapTupleIsValid(tuple))
    2471 UIC           0 :             elog(ERROR, "cache lookup failed for parameter ACL %u",
    2472                 :                  parameterId);
    2473 ECB             : 
    2474                 :         /* We'll need the GUC's name */
    2475 GNC          68 :         nameDatum = SysCacheGetAttrNotNull(PARAMETERACLOID, tuple,
    2476                 :                                            Anum_pg_parameter_acl_parname);
    2477 GIC          68 :         parname = TextDatumGetCString(nameDatum);
    2478                 : 
    2479                 :         /* Treat all parameters as belonging to the bootstrap superuser. */
    2480              68 :         ownerId = BOOTSTRAP_SUPERUSERID;
    2481 ECB             : 
    2482                 :         /*
    2483                 :          * Get working copy of existing ACL. If there's no ACL, substitute the
    2484                 :          * proper default.
    2485                 :          */
    2486 GIC          68 :         aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
    2487                 :                                    Anum_pg_parameter_acl_paracl,
    2488                 :                                    &isNull);
    2489                 : 
    2490 CBC          68 :         if (isNull)
    2491                 :         {
    2492              34 :             old_acl = acldefault(istmt->objtype, ownerId);
    2493 ECB             :             /* There are no old member roles according to the catalogs */
    2494 GIC          34 :             noldmembers = 0;
    2495              34 :             oldmembers = NULL;
    2496                 :         }
    2497                 :         else
    2498                 :         {
    2499 CBC          34 :             old_acl = DatumGetAclPCopy(aclDatum);
    2500                 :             /* Get the roles mentioned in the existing ACL */
    2501              34 :             noldmembers = aclmembers(old_acl, &oldmembers);
    2502                 :         }
    2503 ECB             : 
    2504                 :         /* Determine ID to do the grant as, and available grant options */
    2505 GIC          68 :         select_best_grantor(GetUserId(), istmt->privileges,
    2506 ECB             :                             old_acl, ownerId,
    2507                 :                             &grantorId, &avail_goptions);
    2508                 : 
    2509                 :         /*
    2510                 :          * Restrict the privileges to what we can actually grant, and emit the
    2511                 :          * standards-mandated warning and error messages.
    2512                 :          */
    2513                 :         this_privileges =
    2514 GIC          68 :             restrict_and_check_grant(istmt->is_grant, avail_goptions,
    2515 CBC          68 :                                      istmt->all_privs, istmt->privileges,
    2516                 :                                      parameterId, grantorId,
    2517                 :                                      OBJECT_PARAMETER_ACL,
    2518                 :                                      parname,
    2519                 :                                      0, NULL);
    2520 ECB             : 
    2521                 :         /*
    2522                 :          * Generate new ACL.
    2523                 :          */
    2524 GIC          68 :         new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
    2525              68 :                                        istmt->grant_option, istmt->behavior,
    2526 ECB             :                                        istmt->grantees, this_privileges,
    2527                 :                                        grantorId, ownerId);
    2528                 : 
    2529                 :         /*
    2530                 :          * We need the members of both old and new ACLs so we can correct the
    2531                 :          * shared dependency information.
    2532                 :          */
    2533 GIC          68 :         nnewmembers = aclmembers(new_acl, &newmembers);
    2534                 : 
    2535                 :         /*
    2536 ECB             :          * If the new ACL is equal to the default, we don't need the catalog
    2537                 :          * entry any longer.  Delete it rather than updating it, to avoid
    2538                 :          * leaving a degenerate entry.
    2539                 :          */
    2540 GIC          68 :         if (aclequal(new_acl, acldefault(istmt->objtype, ownerId)))
    2541                 :         {
    2542              29 :             CatalogTupleDelete(relation, &tuple->t_self);
    2543                 :         }
    2544                 :         else
    2545                 :         {
    2546                 :             /* finished building new ACL value, now insert it */
    2547 ECB             :             HeapTuple   newtuple;
    2548 GNC          39 :             Datum       values[Natts_pg_parameter_acl] = {0};
    2549              39 :             bool        nulls[Natts_pg_parameter_acl] = {0};
    2550              39 :             bool        replaces[Natts_pg_parameter_acl] = {0};
    2551                 : 
    2552 GIC          39 :             replaces[Anum_pg_parameter_acl_paracl - 1] = true;
    2553              39 :             values[Anum_pg_parameter_acl_paracl - 1] = PointerGetDatum(new_acl);
    2554 ECB             : 
    2555 CBC          39 :             newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
    2556 ECB             :                                          values, nulls, replaces);
    2557                 : 
    2558 GIC          39 :             CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
    2559 ECB             :         }
    2560                 : 
    2561                 :         /* Update initial privileges for extensions */
    2562 GIC          68 :         recordExtensionInitPriv(parameterId, ParameterAclRelationId, 0,
    2563                 :                                 new_acl);
    2564                 : 
    2565                 :         /* Update the shared dependency ACL info */
    2566              68 :         updateAclDependencies(ParameterAclRelationId, parameterId, 0,
    2567 ECB             :                               ownerId,
    2568                 :                               noldmembers, oldmembers,
    2569                 :                               nnewmembers, newmembers);
    2570                 : 
    2571 GIC          68 :         ReleaseSysCache(tuple);
    2572              68 :         pfree(new_acl);
    2573                 : 
    2574                 :         /* prevent error when processing duplicate objects */
    2575 CBC          68 :         CommandCounterIncrement();
    2576 ECB             :     }
    2577                 : 
    2578 GIC          49 :     table_close(relation, RowExclusiveLock);
    2579 CBC          49 : }
    2580 ECB             : 
    2581                 : 
    2582                 : static AclMode
    2583 CBC       45208 : string_to_privilege(const char *privname)
    2584                 : {
    2585           45208 :     if (strcmp(privname, "insert") == 0)
    2586 GIC         111 :         return ACL_INSERT;
    2587           45097 :     if (strcmp(privname, "select") == 0)
    2588 CBC       20424 :         return ACL_SELECT;
    2589 GIC       24673 :     if (strcmp(privname, "update") == 0)
    2590             426 :         return ACL_UPDATE;
    2591           24247 :     if (strcmp(privname, "delete") == 0)
    2592              57 :         return ACL_DELETE;
    2593           24190 :     if (strcmp(privname, "truncate") == 0)
    2594              17 :         return ACL_TRUNCATE;
    2595           24173 :     if (strcmp(privname, "references") == 0)
    2596 CBC           7 :         return ACL_REFERENCES;
    2597 GIC       24166 :     if (strcmp(privname, "trigger") == 0)
    2598               4 :         return ACL_TRIGGER;
    2599 CBC       24162 :     if (strcmp(privname, "execute") == 0)
    2600 GIC       22027 :         return ACL_EXECUTE;
    2601            2135 :     if (strcmp(privname, "usage") == 0)
    2602 GBC         821 :         return ACL_USAGE;
    2603            1314 :     if (strcmp(privname, "create") == 0)
    2604 GIC         651 :         return ACL_CREATE;
    2605             663 :     if (strcmp(privname, "temporary") == 0)
    2606             607 :         return ACL_CREATE_TEMP;
    2607              56 :     if (strcmp(privname, "temp") == 0)
    2608 LBC           0 :         return ACL_CREATE_TEMP;
    2609 GIC          56 :     if (strcmp(privname, "connect") == 0)
    2610               3 :         return ACL_CONNECT;
    2611 CBC          53 :     if (strcmp(privname, "set") == 0)
    2612 GIC          25 :         return ACL_SET;
    2613              28 :     if (strcmp(privname, "alter system") == 0)
    2614 CBC          12 :         return ACL_ALTER_SYSTEM;
    2615 GNC          16 :     if (strcmp(privname, "maintain") == 0)
    2616              16 :         return ACL_MAINTAIN;
    2617 LBC           0 :     if (strcmp(privname, "rule") == 0)
    2618 UIC           0 :         return 0;               /* ignore old RULE privileges */
    2619 LBC           0 :     ereport(ERROR,
    2620                 :             (errcode(ERRCODE_SYNTAX_ERROR),
    2621                 :              errmsg("unrecognized privilege type \"%s\"", privname)));
    2622 ECB             :     return 0;                   /* appease compiler */
    2623                 : }
    2624                 : 
    2625                 : static const char *
    2626 GIC          12 : privilege_to_string(AclMode privilege)
    2627                 : {
    2628              12 :     switch (privilege)
    2629                 :     {
    2630               3 :         case ACL_INSERT:
    2631               3 :             return "INSERT";
    2632 UIC           0 :         case ACL_SELECT:
    2633 UBC           0 :             return "SELECT";
    2634 UIC           0 :         case ACL_UPDATE:
    2635               0 :             return "UPDATE";
    2636               0 :         case ACL_DELETE:
    2637               0 :             return "DELETE";
    2638               0 :         case ACL_TRUNCATE:
    2639               0 :             return "TRUNCATE";
    2640               0 :         case ACL_REFERENCES:
    2641               0 :             return "REFERENCES";
    2642 UBC           0 :         case ACL_TRIGGER:
    2643               0 :             return "TRIGGER";
    2644 UIC           0 :         case ACL_EXECUTE:
    2645               0 :             return "EXECUTE";
    2646 GBC           9 :         case ACL_USAGE:
    2647               9 :             return "USAGE";
    2648 UBC           0 :         case ACL_CREATE:
    2649 UIC           0 :             return "CREATE";
    2650               0 :         case ACL_CREATE_TEMP:
    2651               0 :             return "TEMP";
    2652               0 :         case ACL_CONNECT:
    2653 UBC           0 :             return "CONNECT";
    2654 UIC           0 :         case ACL_SET:
    2655               0 :             return "SET";
    2656 UBC           0 :         case ACL_ALTER_SYSTEM:
    2657 UIC           0 :             return "ALTER SYSTEM";
    2658 UNC           0 :         case ACL_MAINTAIN:
    2659               0 :             return "MAINTAIN";
    2660 UIC           0 :         default:
    2661 UBC           0 :             elog(ERROR, "unrecognized privilege: %d", (int) privilege);
    2662 EUB             :     }
    2663                 :     return NULL;                /* appease compiler */
    2664                 : }
    2665                 : 
    2666                 : /*
    2667                 :  * Standardized reporting of aclcheck permissions failures.
    2668                 :  *
    2669                 :  * Note: we do not double-quote the %s's below, because many callers
    2670                 :  * supply strings that might be already quoted.
    2671                 :  */
    2672                 : void
    2673 GBC        1165 : aclcheck_error(AclResult aclerr, ObjectType objtype,
    2674 EUB             :                const char *objectname)
    2675                 : {
    2676 GBC        1165 :     switch (aclerr)
    2677                 :     {
    2678 UBC           0 :         case ACLCHECK_OK:
    2679                 :             /* no error, so return to caller */
    2680 UIC           0 :             break;
    2681 GIC         893 :         case ACLCHECK_NO_PRIV:
    2682                 :             {
    2683             893 :                 const char *msg = "???";
    2684                 : 
    2685                 :                 switch (objtype)
    2686                 :                 {
    2687               3 :                     case OBJECT_AGGREGATE:
    2688               3 :                         msg = gettext_noop("permission denied for aggregate %s");
    2689               3 :                         break;
    2690 UIC           0 :                     case OBJECT_COLLATION:
    2691               0 :                         msg = gettext_noop("permission denied for collation %s");
    2692               0 :                         break;
    2693               0 :                     case OBJECT_COLUMN:
    2694 LBC           0 :                         msg = gettext_noop("permission denied for column %s");
    2695 UIC           0 :                         break;
    2696               0 :                     case OBJECT_CONVERSION:
    2697               0 :                         msg = gettext_noop("permission denied for conversion %s");
    2698               0 :                         break;
    2699 GIC           9 :                     case OBJECT_DATABASE:
    2700               9 :                         msg = gettext_noop("permission denied for database %s");
    2701               9 :                         break;
    2702 UIC           0 :                     case OBJECT_DOMAIN:
    2703               0 :                         msg = gettext_noop("permission denied for domain %s");
    2704               0 :                         break;
    2705               0 :                     case OBJECT_EVENT_TRIGGER:
    2706               0 :                         msg = gettext_noop("permission denied for event trigger %s");
    2707               0 :                         break;
    2708               0 :                     case OBJECT_EXTENSION:
    2709 LBC           0 :                         msg = gettext_noop("permission denied for extension %s");
    2710               0 :                         break;
    2711 GIC          22 :                     case OBJECT_FDW:
    2712              22 :                         msg = gettext_noop("permission denied for foreign-data wrapper %s");
    2713              22 :                         break;
    2714              10 :                     case OBJECT_FOREIGN_SERVER:
    2715 CBC          10 :                         msg = gettext_noop("permission denied for foreign server %s");
    2716 GIC          10 :                         break;
    2717               1 :                     case OBJECT_FOREIGN_TABLE:
    2718 CBC           1 :                         msg = gettext_noop("permission denied for foreign table %s");
    2719 GIC           1 :                         break;
    2720              50 :                     case OBJECT_FUNCTION:
    2721              50 :                         msg = gettext_noop("permission denied for function %s");
    2722              50 :                         break;
    2723 LBC           0 :                     case OBJECT_INDEX:
    2724 UIC           0 :                         msg = gettext_noop("permission denied for index %s");
    2725               0 :                         break;
    2726 GIC           4 :                     case OBJECT_LANGUAGE:
    2727 CBC           4 :                         msg = gettext_noop("permission denied for language %s");
    2728               4 :                         break;
    2729 UBC           0 :                     case OBJECT_LARGEOBJECT:
    2730 UIC           0 :                         msg = gettext_noop("permission denied for large object %s");
    2731               0 :                         break;
    2732               0 :                     case OBJECT_MATVIEW:
    2733 LBC           0 :                         msg = gettext_noop("permission denied for materialized view %s");
    2734 UIC           0 :                         break;
    2735 LBC           0 :                     case OBJECT_OPCLASS:
    2736 UIC           0 :                         msg = gettext_noop("permission denied for operator class %s");
    2737               0 :                         break;
    2738 LBC           0 :                     case OBJECT_OPERATOR:
    2739 UIC           0 :                         msg = gettext_noop("permission denied for operator %s");
    2740               0 :                         break;
    2741 LBC           0 :                     case OBJECT_OPFAMILY:
    2742               0 :                         msg = gettext_noop("permission denied for operator family %s");
    2743 UIC           0 :                         break;
    2744               0 :                     case OBJECT_PARAMETER_ACL:
    2745               0 :                         msg = gettext_noop("permission denied for parameter %s");
    2746               0 :                         break;
    2747 LBC           0 :                     case OBJECT_POLICY:
    2748 UIC           0 :                         msg = gettext_noop("permission denied for policy %s");
    2749               0 :                         break;
    2750 CBC           6 :                     case OBJECT_PROCEDURE:
    2751 GIC           6 :                         msg = gettext_noop("permission denied for procedure %s");
    2752               6 :                         break;
    2753 LBC           0 :                     case OBJECT_PUBLICATION:
    2754               0 :                         msg = gettext_noop("permission denied for publication %s");
    2755 UIC           0 :                         break;
    2756 LBC           0 :                     case OBJECT_ROUTINE:
    2757 UIC           0 :                         msg = gettext_noop("permission denied for routine %s");
    2758 LBC           0 :                         break;
    2759 GIC           7 :                     case OBJECT_SCHEMA:
    2760 CBC           7 :                         msg = gettext_noop("permission denied for schema %s");
    2761 GIC           7 :                         break;
    2762 UIC           0 :                     case OBJECT_SEQUENCE:
    2763               0 :                         msg = gettext_noop("permission denied for sequence %s");
    2764               0 :                         break;
    2765               0 :                     case OBJECT_STATISTIC_EXT:
    2766               0 :                         msg = gettext_noop("permission denied for statistics object %s");
    2767 LBC           0 :                         break;
    2768 UIC           0 :                     case OBJECT_SUBSCRIPTION:
    2769               0 :                         msg = gettext_noop("permission denied for subscription %s");
    2770               0 :                         break;
    2771 GIC         582 :                     case OBJECT_TABLE:
    2772             582 :                         msg = gettext_noop("permission denied for table %s");
    2773             582 :                         break;
    2774               9 :                     case OBJECT_TABLESPACE:
    2775               9 :                         msg = gettext_noop("permission denied for tablespace %s");
    2776               9 :                         break;
    2777 UIC           0 :                     case OBJECT_TSCONFIGURATION:
    2778 LBC           0 :                         msg = gettext_noop("permission denied for text search configuration %s");
    2779               0 :                         break;
    2780 UIC           0 :                     case OBJECT_TSDICTIONARY:
    2781               0 :                         msg = gettext_noop("permission denied for text search dictionary %s");
    2782               0 :                         break;
    2783 GIC          57 :                     case OBJECT_TYPE:
    2784              57 :                         msg = gettext_noop("permission denied for type %s");
    2785              57 :                         break;
    2786             133 :                     case OBJECT_VIEW:
    2787             133 :                         msg = gettext_noop("permission denied for view %s");
    2788             133 :                         break;
    2789                 :                         /* these currently aren't used */
    2790 UIC           0 :                     case OBJECT_ACCESS_METHOD:
    2791                 :                     case OBJECT_AMOP:
    2792                 :                     case OBJECT_AMPROC:
    2793                 :                     case OBJECT_ATTRIBUTE:
    2794                 :                     case OBJECT_CAST:
    2795                 :                     case OBJECT_DEFAULT:
    2796                 :                     case OBJECT_DEFACL:
    2797                 :                     case OBJECT_DOMCONSTRAINT:
    2798                 :                     case OBJECT_PUBLICATION_NAMESPACE:
    2799                 :                     case OBJECT_PUBLICATION_REL:
    2800 ECB             :                     case OBJECT_ROLE:
    2801                 :                     case OBJECT_RULE:
    2802                 :                     case OBJECT_TABCONSTRAINT:
    2803                 :                     case OBJECT_TRANSFORM:
    2804                 :                     case OBJECT_TRIGGER:
    2805                 :                     case OBJECT_TSPARSER:
    2806 EUB             :                     case OBJECT_TSTEMPLATE:
    2807                 :                     case OBJECT_USER_MAPPING:
    2808 UNC           0 :                         elog(ERROR, "unsupported object type: %d", objtype);
    2809                 :                 }
    2810                 : 
    2811 GIC         893 :                 ereport(ERROR,
    2812 ECB             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2813                 :                          errmsg(msg, objectname)));
    2814 EUB             :                 break;
    2815                 :             }
    2816 GIC         272 :         case ACLCHECK_NOT_OWNER:
    2817                 :             {
    2818 CBC         272 :                 const char *msg = "???";
    2819                 : 
    2820 ECB             :                 switch (objtype)
    2821                 :                 {
    2822 CBC           3 :                     case OBJECT_AGGREGATE:
    2823 GIC           3 :                         msg = gettext_noop("must be owner of aggregate %s");
    2824               3 :                         break;
    2825 LBC           0 :                     case OBJECT_COLLATION:
    2826               0 :                         msg = gettext_noop("must be owner of collation %s");
    2827 UIC           0 :                         break;
    2828 GIC           9 :                     case OBJECT_CONVERSION:
    2829               9 :                         msg = gettext_noop("must be owner of conversion %s");
    2830               9 :                         break;
    2831 LBC           0 :                     case OBJECT_DATABASE:
    2832 UIC           0 :                         msg = gettext_noop("must be owner of database %s");
    2833               0 :                         break;
    2834 LBC           0 :                     case OBJECT_DOMAIN:
    2835 UIC           0 :                         msg = gettext_noop("must be owner of domain %s");
    2836               0 :                         break;
    2837 LBC           0 :                     case OBJECT_EVENT_TRIGGER:
    2838               0 :                         msg = gettext_noop("must be owner of event trigger %s");
    2839 UIC           0 :                         break;
    2840 LBC           0 :                     case OBJECT_EXTENSION:
    2841 UIC           0 :                         msg = gettext_noop("must be owner of extension %s");
    2842               0 :                         break;
    2843 GIC           9 :                     case OBJECT_FDW:
    2844               9 :                         msg = gettext_noop("must be owner of foreign-data wrapper %s");
    2845               9 :                         break;
    2846              57 :                     case OBJECT_FOREIGN_SERVER:
    2847              57 :                         msg = gettext_noop("must be owner of foreign server %s");
    2848 CBC          57 :                         break;
    2849 LBC           0 :                     case OBJECT_FOREIGN_TABLE:
    2850               0 :                         msg = gettext_noop("must be owner of foreign table %s");
    2851               0 :                         break;
    2852 CBC          21 :                     case OBJECT_FUNCTION:
    2853 GIC          21 :                         msg = gettext_noop("must be owner of function %s");
    2854              21 :                         break;
    2855              18 :                     case OBJECT_INDEX:
    2856              18 :                         msg = gettext_noop("must be owner of index %s");
    2857              18 :                         break;
    2858               6 :                     case OBJECT_LANGUAGE:
    2859 CBC           6 :                         msg = gettext_noop("must be owner of language %s");
    2860 GIC           6 :                         break;
    2861 UIC           0 :                     case OBJECT_LARGEOBJECT:
    2862               0 :                         msg = gettext_noop("must be owner of large object %s");
    2863               0 :                         break;
    2864               0 :                     case OBJECT_MATVIEW:
    2865               0 :                         msg = gettext_noop("must be owner of materialized view %s");
    2866               0 :                         break;
    2867 GIC           9 :                     case OBJECT_OPCLASS:
    2868               9 :                         msg = gettext_noop("must be owner of operator class %s");
    2869               9 :                         break;
    2870               9 :                     case OBJECT_OPERATOR:
    2871 CBC           9 :                         msg = gettext_noop("must be owner of operator %s");
    2872               9 :                         break;
    2873 GIC           9 :                     case OBJECT_OPFAMILY:
    2874               9 :                         msg = gettext_noop("must be owner of operator family %s");
    2875               9 :                         break;
    2876               3 :                     case OBJECT_PROCEDURE:
    2877 CBC           3 :                         msg = gettext_noop("must be owner of procedure %s");
    2878               3 :                         break;
    2879 GBC           3 :                     case OBJECT_PUBLICATION:
    2880 GIC           3 :                         msg = gettext_noop("must be owner of publication %s");
    2881               3 :                         break;
    2882 UIC           0 :                     case OBJECT_ROUTINE:
    2883 LBC           0 :                         msg = gettext_noop("must be owner of routine %s");
    2884 UIC           0 :                         break;
    2885 GIC           3 :                     case OBJECT_SEQUENCE:
    2886               3 :                         msg = gettext_noop("must be owner of sequence %s");
    2887               3 :                         break;
    2888               3 :                     case OBJECT_SUBSCRIPTION:
    2889 CBC           3 :                         msg = gettext_noop("must be owner of subscription %s");
    2890 GIC           3 :                         break;
    2891 CBC          44 :                     case OBJECT_TABLE:
    2892 GIC          44 :                         msg = gettext_noop("must be owner of table %s");
    2893 CBC          44 :                         break;
    2894 GIC           3 :                     case OBJECT_TYPE:
    2895 CBC           3 :                         msg = gettext_noop("must be owner of type %s");
    2896 GIC           3 :                         break;
    2897 CBC           9 :                     case OBJECT_VIEW:
    2898 GBC           9 :                         msg = gettext_noop("must be owner of view %s");
    2899 CBC           9 :                         break;
    2900 GIC           9 :                     case OBJECT_SCHEMA:
    2901               9 :                         msg = gettext_noop("must be owner of schema %s");
    2902               9 :                         break;
    2903              18 :                     case OBJECT_STATISTIC_EXT:
    2904              18 :                         msg = gettext_noop("must be owner of statistics object %s");
    2905 CBC          18 :                         break;
    2906 UIC           0 :                     case OBJECT_TABLESPACE:
    2907 LBC           0 :                         msg = gettext_noop("must be owner of tablespace %s");
    2908 UIC           0 :                         break;
    2909 CBC           9 :                     case OBJECT_TSCONFIGURATION:
    2910 GIC           9 :                         msg = gettext_noop("must be owner of text search configuration %s");
    2911               9 :                         break;
    2912 CBC           9 :                     case OBJECT_TSDICTIONARY:
    2913               9 :                         msg = gettext_noop("must be owner of text search dictionary %s");
    2914 GIC           9 :                         break;
    2915                 : 
    2916                 :                         /*
    2917                 :                          * Special cases: For these, the error message talks
    2918 ECB             :                          * about "relation", because that's where the
    2919                 :                          * ownership is attached.  See also
    2920                 :                          * check_object_ownership().
    2921                 :                          */
    2922 GIC           9 :                     case OBJECT_COLUMN:
    2923                 :                     case OBJECT_POLICY:
    2924 ECB             :                     case OBJECT_RULE:
    2925                 :                     case OBJECT_TABCONSTRAINT:
    2926                 :                     case OBJECT_TRIGGER:
    2927 CBC           9 :                         msg = gettext_noop("must be owner of relation %s");
    2928 GIC           9 :                         break;
    2929 ECB             :                         /* these currently aren't used */
    2930 UIC           0 :                     case OBJECT_ACCESS_METHOD:
    2931                 :                     case OBJECT_AMOP:
    2932                 :                     case OBJECT_AMPROC:
    2933                 :                     case OBJECT_ATTRIBUTE:
    2934                 :                     case OBJECT_CAST:
    2935                 :                     case OBJECT_DEFAULT:
    2936 ECB             :                     case OBJECT_DEFACL:
    2937                 :                     case OBJECT_DOMCONSTRAINT:
    2938                 :                     case OBJECT_PARAMETER_ACL:
    2939                 :                     case OBJECT_PUBLICATION_NAMESPACE:
    2940                 :                     case OBJECT_PUBLICATION_REL:
    2941                 :                     case OBJECT_ROLE:
    2942                 :                     case OBJECT_TRANSFORM:
    2943                 :                     case OBJECT_TSPARSER:
    2944                 :                     case OBJECT_TSTEMPLATE:
    2945                 :                     case OBJECT_USER_MAPPING:
    2946 UNC           0 :                         elog(ERROR, "unsupported object type: %d", objtype);
    2947                 :                 }
    2948                 : 
    2949 GIC         272 :                 ereport(ERROR,
    2950                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2951                 :                          errmsg(msg, objectname)));
    2952                 :                 break;
    2953                 :             }
    2954 UIC           0 :         default:
    2955 LBC           0 :             elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
    2956                 :             break;
    2957                 :     }
    2958               0 : }
    2959                 : 
    2960                 : 
    2961                 : void
    2962 UIC           0 : aclcheck_error_col(AclResult aclerr, ObjectType objtype,
    2963                 :                    const char *objectname, const char *colname)
    2964                 : {
    2965               0 :     switch (aclerr)
    2966                 :     {
    2967               0 :         case ACLCHECK_OK:
    2968                 :             /* no error, so return to caller */
    2969 LBC           0 :             break;
    2970 UIC           0 :         case ACLCHECK_NO_PRIV:
    2971               0 :             ereport(ERROR,
    2972 ECB             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    2973                 :                      errmsg("permission denied for column \"%s\" of relation \"%s\"",
    2974                 :                             colname, objectname)));
    2975                 :             break;
    2976 LBC           0 :         case ACLCHECK_NOT_OWNER:
    2977                 :             /* relation msg is OK since columns don't have separate owners */
    2978 UIC           0 :             aclcheck_error(aclerr, objtype, objectname);
    2979               0 :             break;
    2980               0 :         default:
    2981               0 :             elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
    2982                 :             break;
    2983                 :     }
    2984               0 : }
    2985                 : 
    2986                 : 
    2987                 : /*
    2988                 :  * Special common handling for types: use element type instead of array type,
    2989                 :  * and format nicely
    2990                 :  */
    2991                 : void
    2992 GIC          57 : aclcheck_error_type(AclResult aclerr, Oid typeOid)
    2993                 : {
    2994              57 :     Oid         element_type = get_element_type(typeOid);
    2995                 : 
    2996              57 :     aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
    2997 UIC           0 : }
    2998                 : 
    2999 ECB             : 
    3000                 : /*
    3001                 :  * Relay for the various pg_*_mask routines depending on object kind
    3002                 :  */
    3003                 : static AclMode
    3004 GNC          33 : pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid,
    3005                 :            AclMode mask, AclMaskHow how)
    3006                 : {
    3007 GIC          33 :     switch (objtype)
    3008                 :     {
    3009 UIC           0 :         case OBJECT_COLUMN:
    3010                 :             return
    3011 UNC           0 :                 pg_class_aclmask(object_oid, roleid, mask, how) |
    3012               0 :                 pg_attribute_aclmask(object_oid, attnum, roleid, mask, how);
    3013 CBC           6 :         case OBJECT_TABLE:
    3014 ECB             :         case OBJECT_SEQUENCE:
    3015 GNC           6 :             return pg_class_aclmask(object_oid, roleid, mask, how);
    3016 LBC           0 :         case OBJECT_DATABASE:
    3017 UNC           0 :             return object_aclmask(DatabaseRelationId, object_oid, roleid, mask, how);
    3018 LBC           0 :         case OBJECT_FUNCTION:
    3019 UNC           0 :             return object_aclmask(ProcedureRelationId, object_oid, roleid, mask, how);
    3020 CBC           3 :         case OBJECT_LANGUAGE:
    3021 GNC           3 :             return object_aclmask(LanguageRelationId, object_oid, roleid, mask, how);
    3022 UIC           0 :         case OBJECT_LARGEOBJECT:
    3023 UNC           0 :             return pg_largeobject_aclmask_snapshot(object_oid, roleid,
    3024                 :                                                    mask, how, NULL);
    3025 UIC           0 :         case OBJECT_PARAMETER_ACL:
    3026 UNC           0 :             return pg_parameter_acl_aclmask(object_oid, roleid, mask, how);
    3027 UIC           0 :         case OBJECT_SCHEMA:
    3028 UNC           0 :             return object_aclmask(NamespaceRelationId, object_oid, roleid, mask, how);
    3029 UIC           0 :         case OBJECT_STATISTIC_EXT:
    3030               0 :             elog(ERROR, "grantable rights not supported for statistics objects");
    3031                 :             /* not reached, but keep compiler quiet */
    3032                 :             return ACL_NO_RIGHTS;
    3033 LBC           0 :         case OBJECT_TABLESPACE:
    3034 UNC           0 :             return object_aclmask(TableSpaceRelationId, object_oid, roleid, mask, how);
    3035 GIC           9 :         case OBJECT_FDW:
    3036 GNC           9 :             return object_aclmask(ForeignDataWrapperRelationId, object_oid, roleid, mask, how);
    3037 GBC           9 :         case OBJECT_FOREIGN_SERVER:
    3038 GNC           9 :             return object_aclmask(ForeignServerRelationId, object_oid, roleid, mask, how);
    3039 UIC           0 :         case OBJECT_EVENT_TRIGGER:
    3040 LBC           0 :             elog(ERROR, "grantable rights not supported for event triggers");
    3041                 :             /* not reached, but keep compiler quiet */
    3042 ECB             :             return ACL_NO_RIGHTS;
    3043 CBC           6 :         case OBJECT_TYPE:
    3044 GNC           6 :             return object_aclmask(TypeRelationId, object_oid, roleid, mask, how);
    3045 UIC           0 :         default:
    3046 UNC           0 :             elog(ERROR, "unrecognized object type: %d",
    3047                 :                  (int) objtype);
    3048                 :             /* not reached, but keep compiler quiet */
    3049                 :             return ACL_NO_RIGHTS;
    3050                 :     }
    3051 ECB             : }
    3052                 : 
    3053                 : 
    3054                 : /* ****************************************************************
    3055                 :  * Exported routines for examining a user's privileges for various objects
    3056                 :  *
    3057                 :  * See aclmask() for a description of the common API for these functions.
    3058                 :  *
    3059                 :  * Note: we give lookup failure the full ereport treatment because the
    3060                 :  * has_xxx_privilege() family of functions allow users to pass any random
    3061                 :  * OID to these functions.
    3062                 :  * ****************************************************************
    3063                 :  */
    3064                 : 
    3065                 : /*
    3066                 :  * Generic routine for examining a user's privileges for an object
    3067                 :  */
    3068                 : static AclMode
    3069 GNC     1975448 : object_aclmask(Oid classid, Oid objectid, Oid roleid,
    3070                 :                AclMode mask, AclMaskHow how)
    3071                 : {
    3072                 :     int         cacheid;
    3073                 :     AclMode     result;
    3074                 :     HeapTuple   tuple;
    3075                 :     Datum       aclDatum;
    3076                 :     bool        isNull;
    3077                 :     Acl        *acl;
    3078                 :     Oid         ownerId;
    3079                 : 
    3080                 :     /* Special cases */
    3081         1975448 :     switch (classid)
    3082                 :     {
    3083          524988 :         case NamespaceRelationId:
    3084          524988 :             return pg_namespace_aclmask(objectid, roleid, mask, how);
    3085          620267 :         case TypeRelationId:
    3086          620267 :             return pg_type_aclmask(objectid, roleid, mask, how);
    3087                 :     }
    3088                 : 
    3089                 :     /* Even more special cases */
    3090          830193 :     Assert(classid != RelationRelationId);  /* should use pg_class_acl* */
    3091          830193 :     Assert(classid != LargeObjectMetadataRelationId);   /* should use
    3092                 :                                                          * pg_largeobject_acl* */
    3093                 : 
    3094                 :     /* Superusers bypass all permission checking. */
    3095          830193 :     if (superuser_arg(roleid))
    3096          812942 :         return mask;
    3097                 : 
    3098                 :     /*
    3099                 :      * Get the objects's ACL from its catalog
    3100                 :      */
    3101                 : 
    3102           17251 :     cacheid = get_object_catcache_oid(classid);
    3103                 : 
    3104           17251 :     tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
    3105           17251 :     if (!HeapTupleIsValid(tuple))
    3106 UNC           0 :         ereport(ERROR,
    3107                 :                 (errcode(ERRCODE_UNDEFINED_DATABASE),
    3108                 :                  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
    3109                 : 
    3110 GNC       17251 :     ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
    3111                 :                                                       tuple,
    3112           17251 :                                                       get_object_attnum_owner(classid)));
    3113                 : 
    3114           17251 :     aclDatum = SysCacheGetAttr(cacheid, tuple, get_object_attnum_acl(classid),
    3115                 :                                &isNull);
    3116           17251 :     if (isNull)
    3117                 :     {
    3118                 :         /* No ACL, so build default ACL */
    3119           16045 :         acl = acldefault(get_object_type(classid, objectid), ownerId);
    3120           16045 :         aclDatum = (Datum) 0;
    3121                 :     }
    3122                 :     else
    3123                 :     {
    3124                 :         /* detoast ACL if necessary */
    3125            1206 :         acl = DatumGetAclP(aclDatum);
    3126                 :     }
    3127                 : 
    3128           17251 :     result = aclmask(acl, roleid, ownerId, mask, how);
    3129                 : 
    3130                 :     /* if we have a detoasted copy, free it */
    3131           17251 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
    3132           17251 :         pfree(acl);
    3133                 : 
    3134           17251 :     ReleaseSysCache(tuple);
    3135                 : 
    3136           17251 :     return result;
    3137                 : }
    3138                 : 
    3139                 : /*
    3140                 :  * Routine for examining a user's privileges for a column
    3141 ECB             :  *
    3142                 :  * Note: this considers only privileges granted specifically on the column.
    3143                 :  * It is caller's responsibility to take relation-level privileges into account
    3144                 :  * as appropriate.  (For the same reason, we have no special case for
    3145                 :  * superuser-ness here.)
    3146                 :  */
    3147                 : static AclMode
    3148 GIC          90 : pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid,
    3149                 :                      AclMode mask, AclMaskHow how)
    3150                 : {
    3151              90 :     return pg_attribute_aclmask_ext(table_oid, attnum, roleid,
    3152                 :                                     mask, how, NULL);
    3153                 : }
    3154                 : 
    3155                 : /*
    3156                 :  * Routine for examining a user's privileges for a column
    3157                 :  *
    3158 ECB             :  * Does the bulk of the work for pg_attribute_aclmask(), and allows other
    3159                 :  * callers to avoid the missing attribute ERROR when is_missing is non-NULL.
    3160                 :  */
    3161                 : static AclMode
    3162 GIC        2730 : pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum, Oid roleid,
    3163                 :                          AclMode mask, AclMaskHow how, bool *is_missing)
    3164                 : {
    3165                 :     AclMode     result;
    3166                 :     HeapTuple   classTuple;
    3167                 :     HeapTuple   attTuple;
    3168                 :     Form_pg_class classForm;
    3169                 :     Form_pg_attribute attributeForm;
    3170 ECB             :     Datum       aclDatum;
    3171                 :     bool        isNull;
    3172                 :     Acl        *acl;
    3173                 :     Oid         ownerId;
    3174                 : 
    3175                 :     /*
    3176                 :      * First, get the column's ACL from its pg_attribute entry
    3177                 :      */
    3178 GIC        2730 :     attTuple = SearchSysCache2(ATTNUM,
    3179                 :                                ObjectIdGetDatum(table_oid),
    3180                 :                                Int16GetDatum(attnum));
    3181            2730 :     if (!HeapTupleIsValid(attTuple))
    3182                 :     {
    3183              15 :         if (is_missing != NULL)
    3184                 :         {
    3185 ECB             :             /* return "no privileges" instead of throwing an error */
    3186 GIC          15 :             *is_missing = true;
    3187 CBC          15 :             return 0;
    3188 ECB             :         }
    3189                 :         else
    3190 LBC           0 :             ereport(ERROR,
    3191                 :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    3192                 :                      errmsg("attribute %d of relation with OID %u does not exist",
    3193                 :                             attnum, table_oid)));
    3194                 :     }
    3195                 : 
    3196 GIC        2715 :     attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
    3197 ECB             : 
    3198                 :     /* Check dropped columns, too */
    3199 GIC        2715 :     if (attributeForm->attisdropped)
    3200 ECB             :     {
    3201 GIC           6 :         if (is_missing != NULL)
    3202 ECB             :         {
    3203                 :             /* return "no privileges" instead of throwing an error */
    3204 CBC           6 :             *is_missing = true;
    3205 GIC           6 :             ReleaseSysCache(attTuple);
    3206               6 :             return 0;
    3207                 :         }
    3208                 :         else
    3209 UIC           0 :             ereport(ERROR,
    3210                 :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    3211 ECB             :                      errmsg("attribute %d of relation with OID %u does not exist",
    3212                 :                             attnum, table_oid)));
    3213                 :     }
    3214                 : 
    3215 GIC        2709 :     aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
    3216                 :                                &isNull);
    3217 ECB             : 
    3218                 :     /*
    3219                 :      * Here we hard-wire knowledge that the default ACL for a column grants no
    3220                 :      * privileges, so that we can fall out quickly in the very common case
    3221                 :      * where attacl is null.
    3222                 :      */
    3223 GIC        2709 :     if (isNull)
    3224                 :     {
    3225 CBC        1481 :         ReleaseSysCache(attTuple);
    3226            1481 :         return 0;
    3227 EUB             :     }
    3228                 : 
    3229                 :     /*
    3230                 :      * Must get the relation's ownerId from pg_class.  Since we already found
    3231 ECB             :      * a pg_attribute entry, the only likely reason for this to fail is that a
    3232                 :      * concurrent DROP of the relation committed since then (which could only
    3233                 :      * happen if we don't have lock on the relation).  We prefer to report "no
    3234                 :      * privileges" rather than failing in such a case, so as to avoid unwanted
    3235                 :      * failures in has_column_privilege() tests.
    3236                 :      */
    3237 GIC        1228 :     classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
    3238            1228 :     if (!HeapTupleIsValid(classTuple))
    3239                 :     {
    3240 UIC           0 :         ReleaseSysCache(attTuple);
    3241               0 :         return 0;
    3242                 :     }
    3243 GIC        1228 :     classForm = (Form_pg_class) GETSTRUCT(classTuple);
    3244                 : 
    3245            1228 :     ownerId = classForm->relowner;
    3246 ECB             : 
    3247 GIC        1228 :     ReleaseSysCache(classTuple);
    3248 ECB             : 
    3249                 :     /* detoast column's ACL if necessary */
    3250 GIC        1228 :     acl = DatumGetAclP(aclDatum);
    3251                 : 
    3252            1228 :     result = aclmask(acl, roleid, ownerId, mask, how);
    3253 ECB             : 
    3254                 :     /* if we have a detoasted copy, free it */
    3255 GIC        1228 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
    3256            1228 :         pfree(acl);
    3257 ECB             : 
    3258 CBC        1228 :     ReleaseSysCache(attTuple);
    3259 EUB             : 
    3260 GIC        1228 :     return result;
    3261                 : }
    3262                 : 
    3263 ECB             : /*
    3264                 :  * Exported routine for examining a user's privileges for a table
    3265                 :  */
    3266                 : AclMode
    3267 CBC      237909 : pg_class_aclmask(Oid table_oid, Oid roleid,
    3268                 :                  AclMode mask, AclMaskHow how)
    3269 ECB             : {
    3270 CBC      237909 :     return pg_class_aclmask_ext(table_oid, roleid, mask, how, NULL);
    3271                 : }
    3272                 : 
    3273 ECB             : /*
    3274                 :  * Routine for examining a user's privileges for a table
    3275                 :  *
    3276                 :  * Does the bulk of the work for pg_class_aclmask(), and allows other
    3277                 :  * callers to avoid the missing relation ERROR when is_missing is non-NULL.
    3278                 :  */
    3279                 : static AclMode
    3280 GIC     1090166 : pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask,
    3281                 :                      AclMaskHow how, bool *is_missing)
    3282                 : {
    3283                 :     AclMode     result;
    3284                 :     HeapTuple   tuple;
    3285                 :     Form_pg_class classForm;
    3286                 :     Datum       aclDatum;
    3287                 :     bool        isNull;
    3288 ECB             :     Acl        *acl;
    3289                 :     Oid         ownerId;
    3290                 : 
    3291                 :     /*
    3292                 :      * Must get the relation's tuple from pg_class
    3293                 :      */
    3294 CBC     1090166 :     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
    3295         1090166 :     if (!HeapTupleIsValid(tuple))
    3296                 :     {
    3297 LBC           0 :         if (is_missing != NULL)
    3298 ECB             :         {
    3299                 :             /* return "no privileges" instead of throwing an error */
    3300 LBC           0 :             *is_missing = true;
    3301               0 :             return 0;
    3302                 :         }
    3303 ECB             :         else
    3304 UIC           0 :             ereport(ERROR,
    3305                 :                     (errcode(ERRCODE_UNDEFINED_TABLE),
    3306                 :                      errmsg("relation with OID %u does not exist",
    3307 ECB             :                             table_oid)));
    3308                 :     }
    3309                 : 
    3310 GIC     1090166 :     classForm = (Form_pg_class) GETSTRUCT(tuple);
    3311                 : 
    3312                 :     /*
    3313 ECB             :      * Deny anyone permission to update a system catalog unless
    3314                 :      * pg_authid.rolsuper is set.
    3315                 :      *
    3316                 :      * As of 7.4 we have some updatable system views; those shouldn't be
    3317                 :      * protected in this way.  Assume the view rules can take care of
    3318                 :      * themselves.  ACL_USAGE is if we ever have system sequences.
    3319                 :      */
    3320 CBC     1416751 :     if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
    3321 GIC      326585 :         IsSystemClass(table_oid, classForm) &&
    3322 CBC        5461 :         classForm->relkind != RELKIND_VIEW &&
    3323 GIC        5461 :         !superuser_arg(roleid))
    3324              35 :         mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE);
    3325                 : 
    3326                 :     /*
    3327                 :      * Otherwise, superusers bypass all permission-checking.
    3328                 :      */
    3329         1090166 :     if (superuser_arg(roleid))
    3330                 :     {
    3331 CBC     1075559 :         ReleaseSysCache(tuple);
    3332 GIC     1075559 :         return mask;
    3333 ECB             :     }
    3334                 : 
    3335                 :     /*
    3336                 :      * Normal case: get the relation's ACL from pg_class
    3337                 :      */
    3338 GIC       14607 :     ownerId = classForm->relowner;
    3339                 : 
    3340           14607 :     aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
    3341 ECB             :                                &isNull);
    3342 GIC       14607 :     if (isNull)
    3343                 :     {
    3344                 :         /* No ACL, so build default ACL */
    3345            2939 :         switch (classForm->relkind)
    3346 ECB             :         {
    3347 GIC          18 :             case RELKIND_SEQUENCE:
    3348              18 :                 acl = acldefault(OBJECT_SEQUENCE, ownerId);
    3349 CBC          18 :                 break;
    3350            2921 :             default:
    3351            2921 :                 acl = acldefault(OBJECT_TABLE, ownerId);
    3352 GIC        2921 :                 break;
    3353                 :         }
    3354 CBC        2939 :         aclDatum = (Datum) 0;
    3355                 :     }
    3356                 :     else
    3357                 :     {
    3358                 :         /* detoast rel's ACL if necessary */
    3359 GIC       11668 :         acl = DatumGetAclP(aclDatum);
    3360                 :     }
    3361                 : 
    3362           14607 :     result = aclmask(acl, roleid, ownerId, mask, how);
    3363                 : 
    3364                 :     /* if we have a detoasted copy, free it */
    3365           14607 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
    3366 CBC       14607 :         pfree(acl);
    3367                 : 
    3368 GIC       14607 :     ReleaseSysCache(tuple);
    3369                 : 
    3370                 :     /*
    3371                 :      * Check if ACL_SELECT is being checked and, if so, and not set already as
    3372                 :      * part of the result, then check if the user is a member of the
    3373                 :      * pg_read_all_data role, which allows read access to all relations.
    3374                 :      */
    3375           15555 :     if (mask & ACL_SELECT && !(result & ACL_SELECT) &&
    3376             948 :         has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA))
    3377               6 :         result |= ACL_SELECT;
    3378 ECB             : 
    3379 EUB             :     /*
    3380                 :      * Check if ACL_INSERT, ACL_UPDATE, or ACL_DELETE is being checked and, if
    3381                 :      * so, and not set already as part of the result, then check if the user
    3382 ECB             :      * is a member of the pg_write_all_data role, which allows
    3383                 :      * INSERT/UPDATE/DELETE access to all relations (except system catalogs,
    3384                 :      * which requires superuser, see above).
    3385                 :      */
    3386 CBC       14607 :     if (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE) &&
    3387 GIC        2991 :         !(result & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
    3388 CBC         621 :         has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA))
    3389               9 :         result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
    3390 ECB             : 
    3391                 :     /*
    3392                 :      * Check if ACL_MAINTAIN is being checked and, if so, and not already set as
    3393                 :      * part of the result, then check if the user is a member of the
    3394                 :      * pg_maintain role, which allows VACUUM, ANALYZE, CLUSTER, REFRESH
    3395                 :      * MATERIALIZED VIEW, and REINDEX on all relations.
    3396                 :      */
    3397 GNC       14607 :     if (mask & ACL_MAINTAIN &&
    3398            1250 :         !(result & ACL_MAINTAIN) &&
    3399             435 :         has_privs_of_role(roleid, ROLE_PG_MAINTAIN))
    3400              33 :         result |= ACL_MAINTAIN;
    3401                 : 
    3402 GIC       14607 :     return result;
    3403                 : }
    3404                 : 
    3405                 : /*
    3406                 :  * Routine for examining a user's privileges for a configuration
    3407 ECB             :  * parameter (GUC), identified by GUC name.
    3408                 :  */
    3409                 : static AclMode
    3410 CBC          85 : pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
    3411                 : {
    3412                 :     AclMode     result;
    3413 ECB             :     char       *parname;
    3414                 :     text       *partext;
    3415                 :     HeapTuple   tuple;
    3416                 : 
    3417                 :     /* Superusers bypass all permission checking. */
    3418 GIC          85 :     if (superuser_arg(roleid))
    3419               1 :         return mask;
    3420                 : 
    3421                 :     /* Convert name to the form it should have in pg_parameter_acl... */
    3422              84 :     parname = convert_GUC_name_for_parameter_acl(name);
    3423              84 :     partext = cstring_to_text(parname);
    3424                 : 
    3425                 :     /* ... and look it up */
    3426 CBC          84 :     tuple = SearchSysCache1(PARAMETERACLNAME, PointerGetDatum(partext));
    3427                 : 
    3428 GIC          84 :     if (!HeapTupleIsValid(tuple))
    3429                 :     {
    3430                 :         /* If no entry, GUC has no permissions for non-superusers */
    3431              39 :         result = ACL_NO_RIGHTS;
    3432                 :     }
    3433                 :     else
    3434                 :     {
    3435 ECB             :         Datum       aclDatum;
    3436                 :         bool        isNull;
    3437                 :         Acl        *acl;
    3438                 : 
    3439 GIC          45 :         aclDatum = SysCacheGetAttr(PARAMETERACLNAME, tuple,
    3440                 :                                    Anum_pg_parameter_acl_paracl,
    3441                 :                                    &isNull);
    3442 CBC          45 :         if (isNull)
    3443 ECB             :         {
    3444 EUB             :             /* No ACL, so build default ACL */
    3445 LBC           0 :             acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
    3446 UIC           0 :             aclDatum = (Datum) 0;
    3447                 :         }
    3448                 :         else
    3449                 :         {
    3450                 :             /* detoast ACL if necessary */
    3451 GIC          45 :             acl = DatumGetAclP(aclDatum);
    3452 ECB             :         }
    3453                 : 
    3454 CBC          45 :         result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
    3455                 : 
    3456 EUB             :         /* if we have a detoasted copy, free it */
    3457 GBC          45 :         if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
    3458 GIC          45 :             pfree(acl);
    3459                 : 
    3460              45 :         ReleaseSysCache(tuple);
    3461                 :     }
    3462                 : 
    3463              84 :     pfree(parname);
    3464 CBC          84 :     pfree(partext);
    3465                 : 
    3466 GIC          84 :     return result;
    3467 ECB             : }
    3468                 : 
    3469                 : /*
    3470                 :  * Routine for examining a user's privileges for a configuration
    3471                 :  * parameter (GUC), identified by the OID of its pg_parameter_acl entry.
    3472                 :  */
    3473                 : static AclMode
    3474 LBC           0 : pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
    3475                 : {
    3476                 :     AclMode     result;
    3477                 :     HeapTuple   tuple;
    3478 ECB             :     Datum       aclDatum;
    3479 EUB             :     bool        isNull;
    3480                 :     Acl        *acl;
    3481                 : 
    3482 ECB             :     /* Superusers bypass all permission checking. */
    3483 UIC           0 :     if (superuser_arg(roleid))
    3484 LBC           0 :         return mask;
    3485 ECB             : 
    3486                 :     /* Get the ACL from pg_parameter_acl */
    3487 UIC           0 :     tuple = SearchSysCache1(PARAMETERACLOID, ObjectIdGetDatum(acl_oid));
    3488 LBC           0 :     if (!HeapTupleIsValid(tuple))
    3489 UIC           0 :         ereport(ERROR,
    3490                 :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    3491                 :                  errmsg("parameter ACL with OID %u does not exist",
    3492                 :                         acl_oid)));
    3493 ECB             : 
    3494 UIC           0 :     aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
    3495 ECB             :                                Anum_pg_parameter_acl_paracl,
    3496                 :                                &isNull);
    3497 UIC           0 :     if (isNull)
    3498                 :     {
    3499 ECB             :         /* No ACL, so build default ACL */
    3500 LBC           0 :         acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
    3501 UIC           0 :         aclDatum = (Datum) 0;
    3502 ECB             :     }
    3503                 :     else
    3504                 :     {
    3505                 :         /* detoast ACL if necessary */
    3506 LBC           0 :         acl = DatumGetAclP(aclDatum);
    3507                 :     }
    3508                 : 
    3509 UIC           0 :     result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
    3510 ECB             : 
    3511                 :     /* if we have a detoasted copy, free it */
    3512 LBC           0 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
    3513 UIC           0 :         pfree(acl);
    3514 ECB             : 
    3515 UIC           0 :     ReleaseSysCache(tuple);
    3516                 : 
    3517 LBC           0 :     return result;
    3518                 : }
    3519                 : 
    3520                 : /*
    3521                 :  * Routine for examining a user's privileges for a largeobject
    3522                 :  *
    3523                 :  * When a large object is opened for reading, it is opened relative to the
    3524 ECB             :  * caller's snapshot, but when it is opened for writing, a current
    3525                 :  * MVCC snapshot will be used.  See doc/src/sgml/lobj.sgml.  This function
    3526                 :  * takes a snapshot argument so that the permissions check can be made
    3527                 :  * relative to the same snapshot that will be used to read the underlying
    3528                 :  * data.  The caller will actually pass NULL for an instantaneous MVCC
    3529 EUB             :  * snapshot, since all we do with the snapshot argument is pass it through
    3530                 :  * to systable_beginscan().
    3531                 :  */
    3532                 : static AclMode
    3533 CBC         292 : pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
    3534                 :                                 AclMode mask, AclMaskHow how,
    3535 ECB             :                                 Snapshot snapshot)
    3536                 : {
    3537                 :     AclMode     result;
    3538                 :     Relation    pg_lo_meta;
    3539                 :     ScanKeyData entry[1];
    3540                 :     SysScanDesc scan;
    3541                 :     HeapTuple   tuple;
    3542                 :     Datum       aclDatum;
    3543                 :     bool        isNull;
    3544                 :     Acl        *acl;
    3545                 :     Oid         ownerId;
    3546                 : 
    3547                 :     /* Superusers bypass all permission checking. */
    3548 GIC         292 :     if (superuser_arg(roleid))
    3549             217 :         return mask;
    3550                 : 
    3551                 :     /*
    3552                 :      * Get the largeobject's ACL from pg_largeobject_metadata
    3553                 :      */
    3554              75 :     pg_lo_meta = table_open(LargeObjectMetadataRelationId,
    3555                 :                             AccessShareLock);
    3556                 : 
    3557              75 :     ScanKeyInit(&entry[0],
    3558                 :                 Anum_pg_largeobject_metadata_oid,
    3559                 :                 BTEqualStrategyNumber, F_OIDEQ,
    3560                 :                 ObjectIdGetDatum(lobj_oid));
    3561                 : 
    3562              75 :     scan = systable_beginscan(pg_lo_meta,
    3563                 :                               LargeObjectMetadataOidIndexId, true,
    3564 ECB             :                               snapshot, 1, entry);
    3565                 : 
    3566 GIC          75 :     tuple = systable_getnext(scan);
    3567              75 :     if (!HeapTupleIsValid(tuple))
    3568 UIC           0 :         ereport(ERROR,
    3569                 :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    3570                 :                  errmsg("large object %u does not exist", lobj_oid)));
    3571                 : 
    3572 GIC          75 :     ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
    3573                 : 
    3574 CBC          75 :     aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
    3575 ECB             :                             RelationGetDescr(pg_lo_meta), &isNull);
    3576                 : 
    3577 CBC          75 :     if (isNull)
    3578                 :     {
    3579                 :         /* No ACL, so build default ACL */
    3580 GIC          18 :         acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
    3581              18 :         aclDatum = (Datum) 0;
    3582                 :     }
    3583                 :     else
    3584                 :     {
    3585                 :         /* detoast ACL if necessary */
    3586              57 :         acl = DatumGetAclP(aclDatum);
    3587                 :     }
    3588                 : 
    3589              75 :     result = aclmask(acl, roleid, ownerId, mask, how);
    3590                 : 
    3591                 :     /* if we have a detoasted copy, free it */
    3592              75 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
    3593 CBC          75 :         pfree(acl);
    3594                 : 
    3595 GIC          75 :     systable_endscan(scan);
    3596                 : 
    3597              75 :     table_close(pg_lo_meta, AccessShareLock);
    3598                 : 
    3599              75 :     return result;
    3600                 : }
    3601 ECB             : 
    3602                 : /*
    3603                 :  * Routine for examining a user's privileges for a namespace
    3604                 :  */
    3605                 : static AclMode
    3606 GIC      524988 : pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
    3607 ECB             :                      AclMode mask, AclMaskHow how)
    3608                 : {
    3609                 :     AclMode     result;
    3610                 :     HeapTuple   tuple;
    3611                 :     Datum       aclDatum;
    3612                 :     bool        isNull;
    3613                 :     Acl        *acl;
    3614                 :     Oid         ownerId;
    3615                 : 
    3616                 :     /* Superusers bypass all permission checking. */
    3617 GIC      524988 :     if (superuser_arg(roleid))
    3618          517205 :         return mask;
    3619                 : 
    3620 ECB             :     /*
    3621                 :      * If we have been assigned this namespace as a temp namespace, check to
    3622                 :      * make sure we have CREATE TEMP permission on the database, and if so act
    3623                 :      * as though we have all standard (but not GRANT OPTION) permissions on
    3624                 :      * the namespace.  If we don't have CREATE TEMP, act as though we have
    3625                 :      * only USAGE (and not CREATE) rights.
    3626                 :      *
    3627                 :      * This may seem redundant given the check in InitTempTableNamespace, but
    3628                 :      * it really isn't since current user ID may have changed since then. The
    3629                 :      * upshot of this behavior is that a SECURITY DEFINER function can create
    3630                 :      * temp tables that can then be accessed (if permission is granted) by
    3631                 :      * code in the same session that doesn't have permissions to create temp
    3632                 :      * tables.
    3633                 :      *
    3634                 :      * XXX Would it be safe to ereport a special error message as
    3635                 :      * InitTempTableNamespace does?  Returning zero here means we'll get a
    3636                 :      * generic "permission denied for schema pg_temp_N" message, which is not
    3637                 :      * remarkably user-friendly.
    3638                 :      */
    3639 GIC        7783 :     if (isTempNamespace(nsp_oid))
    3640                 :     {
    3641 GNC          96 :         if (object_aclcheck(DatabaseRelationId, MyDatabaseId, roleid,
    3642                 :                             ACL_CREATE_TEMP) == ACLCHECK_OK)
    3643 CBC          96 :             return mask & ACL_ALL_RIGHTS_SCHEMA;
    3644                 :         else
    3645 UIC           0 :             return mask & ACL_USAGE;
    3646                 :     }
    3647                 : 
    3648 ECB             :     /*
    3649                 :      * Get the schema's ACL from pg_namespace
    3650                 :      */
    3651 GIC        7687 :     tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
    3652            7687 :     if (!HeapTupleIsValid(tuple))
    3653 UIC           0 :         ereport(ERROR,
    3654                 :                 (errcode(ERRCODE_UNDEFINED_SCHEMA),
    3655                 :                  errmsg("schema with OID %u does not exist", nsp_oid)));
    3656                 : 
    3657 CBC        7687 :     ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
    3658                 : 
    3659 GIC        7687 :     aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
    3660 ECB             :                                &isNull);
    3661 CBC        7687 :     if (isNull)
    3662 ECB             :     {
    3663                 :         /* No ACL, so build default ACL */
    3664 GIC         126 :         acl = acldefault(OBJECT_SCHEMA, ownerId);
    3665 CBC         126 :         aclDatum = (Datum) 0;
    3666 ECB             :     }
    3667                 :     else
    3668                 :     {
    3669                 :         /* detoast ACL if necessary */
    3670 CBC        7561 :         acl = DatumGetAclP(aclDatum);
    3671                 :     }
    3672 ECB             : 
    3673 GIC        7687 :     result = aclmask(acl, roleid, ownerId, mask, how);
    3674                 : 
    3675                 :     /* if we have a detoasted copy, free it */
    3676 CBC        7687 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
    3677 GIC        7687 :         pfree(acl);
    3678                 : 
    3679 CBC        7687 :     ReleaseSysCache(tuple);
    3680                 : 
    3681 ECB             :     /*
    3682                 :      * Check if ACL_USAGE is being checked and, if so, and not set already as
    3683                 :      * part of the result, then check if the user is a member of the
    3684                 :      * pg_read_all_data or pg_write_all_data roles, which allow usage access
    3685                 :      * to all schemas.
    3686                 :      */
    3687 GIC        7706 :     if (mask & ACL_USAGE && !(result & ACL_USAGE) &&
    3688              35 :         (has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA) ||
    3689              16 :          has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA)))
    3690               6 :         result |= ACL_USAGE;
    3691            7687 :     return result;
    3692                 : }
    3693                 : 
    3694                 : /*
    3695                 :  * Routine for examining a user's privileges for a type.
    3696                 :  */
    3697                 : static AclMode
    3698          620267 : pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
    3699                 : {
    3700                 :     AclMode     result;
    3701                 :     HeapTuple   tuple;
    3702                 :     Datum       aclDatum;
    3703                 :     bool        isNull;
    3704                 :     Acl        *acl;
    3705                 :     Oid         ownerId;
    3706                 : 
    3707                 :     Form_pg_type typeForm;
    3708                 : 
    3709                 :     /* Bypass permission checks for superusers */
    3710          620267 :     if (superuser_arg(roleid))
    3711          618269 :         return mask;
    3712                 : 
    3713                 :     /*
    3714                 :      * Must get the type's tuple from pg_type
    3715                 :      */
    3716            1998 :     tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
    3717            1998 :     if (!HeapTupleIsValid(tuple))
    3718 UIC           0 :         ereport(ERROR,
    3719                 :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    3720                 :                  errmsg("type with OID %u does not exist",
    3721                 :                         type_oid)));
    3722 GIC        1998 :     typeForm = (Form_pg_type) GETSTRUCT(tuple);
    3723                 : 
    3724                 :     /*
    3725                 :      * "True" array types don't manage permissions of their own; consult the
    3726                 :      * element type instead.
    3727                 :      */
    3728            1998 :     if (IsTrueArrayType(typeForm))
    3729                 :     {
    3730              18 :         Oid         elttype_oid = typeForm->typelem;
    3731                 : 
    3732              18 :         ReleaseSysCache(tuple);
    3733                 : 
    3734              18 :         tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
    3735                 :         /* this case is not a user-facing error, so elog not ereport */
    3736              18 :         if (!HeapTupleIsValid(tuple))
    3737 UIC           0 :             elog(ERROR, "cache lookup failed for type %u", elttype_oid);
    3738 GIC          18 :         typeForm = (Form_pg_type) GETSTRUCT(tuple);
    3739                 :     }
    3740                 : 
    3741                 :     /*
    3742                 :      * Now get the type's owner and ACL from the tuple
    3743                 :      */
    3744            1998 :     ownerId = typeForm->typowner;
    3745                 : 
    3746            1998 :     aclDatum = SysCacheGetAttr(TYPEOID, tuple,
    3747                 :                                Anum_pg_type_typacl, &isNull);
    3748            1998 :     if (isNull)
    3749                 :     {
    3750                 :         /* No ACL, so build default ACL */
    3751            1887 :         acl = acldefault(OBJECT_TYPE, ownerId);
    3752            1887 :         aclDatum = (Datum) 0;
    3753                 :     }
    3754                 :     else
    3755                 :     {
    3756                 :         /* detoast rel's ACL if necessary */
    3757             111 :         acl = DatumGetAclP(aclDatum);
    3758                 :     }
    3759                 : 
    3760            1998 :     result = aclmask(acl, roleid, ownerId, mask, how);
    3761                 : 
    3762                 :     /* if we have a detoasted copy, free it */
    3763            1998 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
    3764            1998 :         pfree(acl);
    3765                 : 
    3766            1998 :     ReleaseSysCache(tuple);
    3767                 : 
    3768            1998 :     return result;
    3769                 : }
    3770                 : 
    3771                 : /*
    3772                 :  * Exported generic routine for checking a user's access privileges to an object
    3773                 :  */
    3774                 : AclResult
    3775 GNC     1975421 : object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
    3776                 : {
    3777         1975421 :     if (object_aclmask(classid, objectid, roleid, mode, ACLMASK_ANY) != 0)
    3778         1975150 :         return ACLCHECK_OK;
    3779                 :     else
    3780             271 :         return ACLCHECK_NO_PRIV;
    3781                 : }
    3782                 : 
    3783                 : /*
    3784                 :  * Exported routine for checking a user's access privileges to a column
    3785                 :  *
    3786                 :  * Returns ACLCHECK_OK if the user has any of the privileges identified by
    3787                 :  * 'mode'; otherwise returns a suitable error code (in practice, always
    3788                 :  * ACLCHECK_NO_PRIV).
    3789                 :  *
    3790                 :  * As with pg_attribute_aclmask, only privileges granted directly on the
    3791                 :  * column are considered here.
    3792                 :  */
    3793                 : AclResult
    3794 GIC        1576 : pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
    3795                 :                       Oid roleid, AclMode mode)
    3796                 : {
    3797            1576 :     return pg_attribute_aclcheck_ext(table_oid, attnum, roleid, mode, NULL);
    3798                 : }
    3799                 : 
    3800                 : 
    3801                 : /*
    3802                 :  * Exported routine for checking a user's access privileges to a column
    3803                 :  *
    3804                 :  * Does the bulk of the work for pg_attribute_aclcheck(), and allows other
    3805                 :  * callers to avoid the missing attribute ERROR when is_missing is non-NULL.
    3806                 :  */
    3807                 : AclResult
    3808            2640 : pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum,
    3809                 :                           Oid roleid, AclMode mode, bool *is_missing)
    3810                 : {
    3811            2640 :     if (pg_attribute_aclmask_ext(table_oid, attnum, roleid, mode,
    3812                 :                                  ACLMASK_ANY, is_missing) != 0)
    3813             904 :         return ACLCHECK_OK;
    3814                 :     else
    3815            1736 :         return ACLCHECK_NO_PRIV;
    3816                 : }
    3817                 : 
    3818                 : /*
    3819                 :  * Exported routine for checking a user's access privileges to any/all columns
    3820                 :  *
    3821                 :  * If 'how' is ACLMASK_ANY, then returns ACLCHECK_OK if user has any of the
    3822                 :  * privileges identified by 'mode' on any non-dropped column in the relation;
    3823                 :  * otherwise returns a suitable error code (in practice, always
    3824                 :  * ACLCHECK_NO_PRIV).
    3825                 :  *
    3826                 :  * If 'how' is ACLMASK_ALL, then returns ACLCHECK_OK if user has any of the
    3827                 :  * privileges identified by 'mode' on each non-dropped column in the relation
    3828                 :  * (and there must be at least one such column); otherwise returns a suitable
    3829                 :  * error code (in practice, always ACLCHECK_NO_PRIV).
    3830                 :  *
    3831                 :  * As with pg_attribute_aclmask, only privileges granted directly on the
    3832                 :  * column(s) are considered here.
    3833                 :  *
    3834                 :  * Note: system columns are not considered here; there are cases where that
    3835                 :  * might be appropriate but there are also cases where it wouldn't.
    3836                 :  */
    3837                 : AclResult
    3838              84 : pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode,
    3839                 :                           AclMaskHow how)
    3840                 : {
    3841                 :     AclResult   result;
    3842                 :     HeapTuple   classTuple;
    3843                 :     Form_pg_class classForm;
    3844                 :     AttrNumber  nattrs;
    3845                 :     AttrNumber  curr_att;
    3846                 : 
    3847                 :     /*
    3848                 :      * Must fetch pg_class row to check number of attributes.  As in
    3849                 :      * pg_attribute_aclmask, we prefer to return "no privileges" instead of
    3850                 :      * throwing an error if we get any unexpected lookup errors.
    3851                 :      */
    3852              84 :     classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
    3853              84 :     if (!HeapTupleIsValid(classTuple))
    3854 UIC           0 :         return ACLCHECK_NO_PRIV;
    3855 GIC          84 :     classForm = (Form_pg_class) GETSTRUCT(classTuple);
    3856                 : 
    3857              84 :     nattrs = classForm->relnatts;
    3858                 : 
    3859              84 :     ReleaseSysCache(classTuple);
    3860                 : 
    3861                 :     /*
    3862                 :      * Initialize result in case there are no non-dropped columns.  We want to
    3863                 :      * report failure in such cases for either value of 'how'.
    3864                 :      */
    3865              84 :     result = ACLCHECK_NO_PRIV;
    3866                 : 
    3867             216 :     for (curr_att = 1; curr_att <= nattrs; curr_att++)
    3868                 :     {
    3869                 :         HeapTuple   attTuple;
    3870                 :         AclMode     attmask;
    3871                 : 
    3872             171 :         attTuple = SearchSysCache2(ATTNUM,
    3873                 :                                    ObjectIdGetDatum(table_oid),
    3874                 :                                    Int16GetDatum(curr_att));
    3875             171 :         if (!HeapTupleIsValid(attTuple))
    3876 UIC           0 :             continue;
    3877                 : 
    3878                 :         /* ignore dropped columns */
    3879 GIC         171 :         if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
    3880                 :         {
    3881               9 :             ReleaseSysCache(attTuple);
    3882               9 :             continue;
    3883                 :         }
    3884                 : 
    3885                 :         /*
    3886                 :          * Here we hard-wire knowledge that the default ACL for a column
    3887                 :          * grants no privileges, so that we can fall out quickly in the very
    3888                 :          * common case where attacl is null.
    3889                 :          */
    3890             162 :         if (heap_attisnull(attTuple, Anum_pg_attribute_attacl, NULL))
    3891              72 :             attmask = 0;
    3892                 :         else
    3893              90 :             attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
    3894                 :                                            mode, ACLMASK_ANY);
    3895                 : 
    3896             162 :         ReleaseSysCache(attTuple);
    3897                 : 
    3898             162 :         if (attmask != 0)
    3899                 :         {
    3900              81 :             result = ACLCHECK_OK;
    3901              81 :             if (how == ACLMASK_ANY)
    3902              21 :                 break;          /* succeed on any success */
    3903                 :         }
    3904                 :         else
    3905                 :         {
    3906              81 :             result = ACLCHECK_NO_PRIV;
    3907              81 :             if (how == ACLMASK_ALL)
    3908              18 :                 break;          /* fail on any failure */
    3909                 :         }
    3910                 :     }
    3911                 : 
    3912              84 :     return result;
    3913                 : }
    3914                 : 
    3915                 : /*
    3916                 :  * Exported routine for checking a user's access privileges to a table
    3917                 :  *
    3918                 :  * Returns ACLCHECK_OK if the user has any of the privileges identified by
    3919                 :  * 'mode'; otherwise returns a suitable error code (in practice, always
    3920                 :  * ACLCHECK_NO_PRIV).
    3921                 :  */
    3922                 : AclResult
    3923          851220 : pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
    3924                 : {
    3925          851220 :     return pg_class_aclcheck_ext(table_oid, roleid, mode, NULL);
    3926                 : }
    3927                 : 
    3928                 : /*
    3929                 :  * Exported routine for checking a user's access privileges to a table
    3930                 :  *
    3931                 :  * Does the bulk of the work for pg_class_aclcheck(), and allows other
    3932                 :  * callers to avoid the missing relation ERROR when is_missing is non-NULL.
    3933                 :  */
    3934                 : AclResult
    3935          852257 : pg_class_aclcheck_ext(Oid table_oid, Oid roleid,
    3936                 :                       AclMode mode, bool *is_missing)
    3937                 : {
    3938          852257 :     if (pg_class_aclmask_ext(table_oid, roleid, mode,
    3939                 :                              ACLMASK_ANY, is_missing) != 0)
    3940          851590 :         return ACLCHECK_OK;
    3941                 :     else
    3942             667 :         return ACLCHECK_NO_PRIV;
    3943                 : }
    3944                 : 
    3945                 : /*
    3946                 :  * Exported routine for checking a user's access privileges to a configuration
    3947                 :  * parameter (GUC), identified by GUC name.
    3948                 :  */
    3949                 : AclResult
    3950              85 : pg_parameter_aclcheck(const char *name, Oid roleid, AclMode mode)
    3951                 : {
    3952              85 :     if (pg_parameter_aclmask(name, roleid, mode, ACLMASK_ANY) != 0)
    3953              35 :         return ACLCHECK_OK;
    3954                 :     else
    3955              50 :         return ACLCHECK_NO_PRIV;
    3956                 : }
    3957                 : 
    3958                 : /*
    3959                 :  * Exported routine for checking a user's access privileges to a largeobject
    3960                 :  */
    3961                 : AclResult
    3962             292 : pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid, AclMode mode,
    3963                 :                                  Snapshot snapshot)
    3964                 : {
    3965             292 :     if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
    3966                 :                                         ACLMASK_ANY, snapshot) != 0)
    3967             265 :         return ACLCHECK_OK;
    3968                 :     else
    3969              27 :         return ACLCHECK_NO_PRIV;
    3970                 : }
    3971                 : 
    3972                 : /*
    3973                 :  * Generic ownership check for an object
    3974                 :  */
    3975                 : bool
    3976 GNC      331205 : object_ownercheck(Oid classid, Oid objectid, Oid roleid)
    3977                 : {
    3978                 :     int         cacheid;
    3979                 :     Oid         ownerId;
    3980                 : 
    3981                 :     /* Superusers bypass all permission checking. */
    3982          331205 :     if (superuser_arg(roleid))
    3983          327414 :         return true;
    3984                 : 
    3985            3791 :     cacheid = get_object_catcache_oid(classid);
    3986            3791 :     if (cacheid != -1)
    3987                 :     {
    3988                 :         HeapTuple   tuple;
    3989                 : 
    3990            3781 :         tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
    3991            3781 :         if (!HeapTupleIsValid(tuple))
    3992 UNC           0 :             ereport(ERROR,
    3993                 :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    3994                 :                      errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
    3995                 : 
    3996 GNC        3781 :         ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
    3997                 :                                                           tuple,
    3998            3781 :                                                           get_object_attnum_owner(classid)));
    3999            3781 :         ReleaseSysCache(tuple);
    4000                 :     }
    4001                 :     else
    4002                 :     {
    4003                 :         /* for catalogs without an appropriate syscache */
    4004                 : 
    4005                 :         Relation    rel;
    4006                 :         ScanKeyData entry[1];
    4007                 :         SysScanDesc scan;
    4008                 :         HeapTuple   tuple;
    4009                 :         bool        isnull;
    4010                 : 
    4011              10 :         rel = table_open(classid, AccessShareLock);
    4012                 : 
    4013              20 :         ScanKeyInit(&entry[0],
    4014              10 :                     get_object_attnum_oid(classid),
    4015                 :                     BTEqualStrategyNumber, F_OIDEQ,
    4016                 :                     ObjectIdGetDatum(objectid));
    4017                 : 
    4018              10 :         scan = systable_beginscan(rel,
    4019                 :                                   get_object_oid_index(classid), true,
    4020                 :                                   NULL, 1, entry);
    4021                 : 
    4022              10 :         tuple = systable_getnext(scan);
    4023              10 :         if (!HeapTupleIsValid(tuple))
    4024 UNC           0 :             ereport(ERROR,
    4025                 :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    4026                 :                      errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
    4027                 : 
    4028 GNC          10 :         ownerId = DatumGetObjectId(heap_getattr(tuple,
    4029              10 :                                                 get_object_attnum_owner(classid),
    4030                 :                                                 RelationGetDescr(rel),
    4031                 :                                                 &isnull));
    4032              10 :         Assert(!isnull);
    4033                 : 
    4034              10 :         systable_endscan(scan);
    4035              10 :         table_close(rel, AccessShareLock);
    4036                 :     }
    4037                 : 
    4038 GIC        3791 :     return has_privs_of_role(roleid, ownerId);
    4039                 : }
    4040                 : 
    4041                 : /*
    4042                 :  * Check whether specified role has CREATEROLE privilege (or is a superuser)
    4043                 :  *
    4044                 :  * Note: roles do not have owners per se; instead we use this test in
    4045                 :  * places where an ownership-like permissions test is needed for a role.
    4046                 :  * Be sure to apply it to the role trying to do the operation, not the
    4047                 :  * role being operated on!  Also note that this generally should not be
    4048                 :  * considered enough privilege if the target role is a superuser.
    4049                 :  * (We don't handle that consideration here because we want to give a
    4050                 :  * separate error message for such cases, so the caller has to deal with it.)
    4051                 :  */
    4052                 : bool
    4053            1136 : has_createrole_privilege(Oid roleid)
    4054                 : {
    4055            1136 :     bool        result = false;
    4056                 :     HeapTuple   utup;
    4057                 : 
    4058                 :     /* Superusers bypass all permission checking. */
    4059            1136 :     if (superuser_arg(roleid))
    4060             871 :         return true;
    4061                 : 
    4062             265 :     utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
    4063             265 :     if (HeapTupleIsValid(utup))
    4064                 :     {
    4065             265 :         result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
    4066             265 :         ReleaseSysCache(utup);
    4067                 :     }
    4068             265 :     return result;
    4069                 : }
    4070                 : 
    4071                 : bool
    4072            2110 : has_bypassrls_privilege(Oid roleid)
    4073                 : {
    4074            2110 :     bool        result = false;
    4075                 :     HeapTuple   utup;
    4076                 : 
    4077                 :     /* Superusers bypass all permission checking. */
    4078            2110 :     if (superuser_arg(roleid))
    4079             673 :         return true;
    4080                 : 
    4081            1437 :     utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
    4082            1437 :     if (HeapTupleIsValid(utup))
    4083                 :     {
    4084            1437 :         result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
    4085            1437 :         ReleaseSysCache(utup);
    4086                 :     }
    4087            1437 :     return result;
    4088                 : }
    4089                 : 
    4090                 : /*
    4091                 :  * Fetch pg_default_acl entry for given role, namespace and object type
    4092                 :  * (object type must be given in pg_default_acl's encoding).
    4093                 :  * Returns NULL if no such entry.
    4094                 :  */
    4095                 : static Acl *
    4096          153856 : get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
    4097                 : {
    4098          153856 :     Acl        *result = NULL;
    4099                 :     HeapTuple   tuple;
    4100                 : 
    4101          153856 :     tuple = SearchSysCache3(DEFACLROLENSPOBJ,
    4102                 :                             ObjectIdGetDatum(roleId),
    4103                 :                             ObjectIdGetDatum(nsp_oid),
    4104                 :                             CharGetDatum(objtype));
    4105                 : 
    4106          153856 :     if (HeapTupleIsValid(tuple))
    4107                 :     {
    4108                 :         Datum       aclDatum;
    4109                 :         bool        isNull;
    4110                 : 
    4111             114 :         aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
    4112                 :                                    Anum_pg_default_acl_defaclacl,
    4113                 :                                    &isNull);
    4114             114 :         if (!isNull)
    4115             114 :             result = DatumGetAclPCopy(aclDatum);
    4116             114 :         ReleaseSysCache(tuple);
    4117                 :     }
    4118                 : 
    4119          153856 :     return result;
    4120                 : }
    4121                 : 
    4122                 : /*
    4123                 :  * Get default permissions for newly created object within given schema
    4124                 :  *
    4125                 :  * Returns NULL if built-in system defaults should be used.
    4126                 :  *
    4127                 :  * If the result is not NULL, caller must call recordDependencyOnNewAcl
    4128                 :  * once the OID of the new object is known.
    4129                 :  */
    4130                 : Acl *
    4131           76928 : get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
    4132                 : {
    4133                 :     Acl        *result;
    4134                 :     Acl        *glob_acl;
    4135                 :     Acl        *schema_acl;
    4136                 :     Acl        *def_acl;
    4137                 :     char        defaclobjtype;
    4138                 : 
    4139                 :     /*
    4140                 :      * Use NULL during bootstrap, since pg_default_acl probably isn't there
    4141                 :      * yet.
    4142                 :      */
    4143           76928 :     if (IsBootstrapProcessingMode())
    4144 UIC           0 :         return NULL;
    4145                 : 
    4146                 :     /* Check if object type is supported in pg_default_acl */
    4147 GIC       76928 :     switch (objtype)
    4148                 :     {
    4149           61675 :         case OBJECT_TABLE:
    4150           61675 :             defaclobjtype = DEFACLOBJ_RELATION;
    4151           61675 :             break;
    4152                 : 
    4153             744 :         case OBJECT_SEQUENCE:
    4154             744 :             defaclobjtype = DEFACLOBJ_SEQUENCE;
    4155             744 :             break;
    4156                 : 
    4157           11262 :         case OBJECT_FUNCTION:
    4158           11262 :             defaclobjtype = DEFACLOBJ_FUNCTION;
    4159           11262 :             break;
    4160                 : 
    4161            2598 :         case OBJECT_TYPE:
    4162            2598 :             defaclobjtype = DEFACLOBJ_TYPE;
    4163            2598 :             break;
    4164                 : 
    4165             649 :         case OBJECT_SCHEMA:
    4166             649 :             defaclobjtype = DEFACLOBJ_NAMESPACE;
    4167             649 :             break;
    4168                 : 
    4169 UIC           0 :         default:
    4170               0 :             return NULL;
    4171                 :     }
    4172                 : 
    4173                 :     /* Look up the relevant pg_default_acl entries */
    4174 GIC       76928 :     glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
    4175           76928 :     schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
    4176                 : 
    4177                 :     /* Quick out if neither entry exists */
    4178           76928 :     if (glob_acl == NULL && schema_acl == NULL)
    4179           76832 :         return NULL;
    4180                 : 
    4181                 :     /* We need to know the hard-wired default value, too */
    4182              96 :     def_acl = acldefault(objtype, ownerId);
    4183                 : 
    4184                 :     /* If there's no global entry, substitute the hard-wired default */
    4185              96 :     if (glob_acl == NULL)
    4186               9 :         glob_acl = def_acl;
    4187                 : 
    4188                 :     /* Merge in any per-schema privileges */
    4189              96 :     result = aclmerge(glob_acl, schema_acl, ownerId);
    4190                 : 
    4191                 :     /*
    4192                 :      * For efficiency, we want to return NULL if the result equals default.
    4193                 :      * This requires sorting both arrays to get an accurate comparison.
    4194                 :      */
    4195              96 :     aclitemsort(result);
    4196              96 :     aclitemsort(def_acl);
    4197              96 :     if (aclequal(result, def_acl))
    4198              12 :         result = NULL;
    4199                 : 
    4200              96 :     return result;
    4201                 : }
    4202                 : 
    4203                 : /*
    4204                 :  * Record dependencies on roles mentioned in a new object's ACL.
    4205                 :  */
    4206                 : void
    4207           77982 : recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId,
    4208                 :                          Oid ownerId, Acl *acl)
    4209                 : {
    4210                 :     int         nmembers;
    4211                 :     Oid        *members;
    4212                 : 
    4213                 :     /* Nothing to do if ACL is defaulted */
    4214           77982 :     if (acl == NULL)
    4215           77898 :         return;
    4216                 : 
    4217                 :     /* Extract roles mentioned in ACL */
    4218              84 :     nmembers = aclmembers(acl, &members);
    4219                 : 
    4220                 :     /* Update the shared dependency ACL info */
    4221              84 :     updateAclDependencies(classId, objectId, objsubId,
    4222                 :                           ownerId,
    4223                 :                           0, NULL,
    4224                 :                           nmembers, members);
    4225                 : }
    4226                 : 
    4227                 : /*
    4228                 :  * Record initial privileges for the top-level object passed in.
    4229                 :  *
    4230                 :  * For the object passed in, this will record its ACL (if any) and the ACLs of
    4231                 :  * any sub-objects (eg: columns) into pg_init_privs.
    4232                 :  */
    4233                 : void
    4234              28 : recordExtObjInitPriv(Oid objoid, Oid classoid)
    4235                 : {
    4236                 :     /*
    4237                 :      * pg_class / pg_attribute
    4238                 :      *
    4239                 :      * If this is a relation then we need to see if there are any sub-objects
    4240                 :      * (eg: columns) for it and, if so, be sure to call
    4241                 :      * recordExtensionInitPrivWorker() for each one.
    4242                 :      */
    4243              28 :     if (classoid == RelationRelationId)
    4244                 :     {
    4245                 :         Form_pg_class pg_class_tuple;
    4246                 :         Datum       aclDatum;
    4247                 :         bool        isNull;
    4248                 :         HeapTuple   tuple;
    4249                 : 
    4250               7 :         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
    4251               7 :         if (!HeapTupleIsValid(tuple))
    4252 UIC           0 :             elog(ERROR, "cache lookup failed for relation %u", objoid);
    4253 GIC           7 :         pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
    4254                 : 
    4255                 :         /*
    4256                 :          * Indexes don't have permissions, neither do the pg_class rows for
    4257                 :          * composite types.  (These cases are unreachable given the
    4258                 :          * restrictions in ALTER EXTENSION ADD, but let's check anyway.)
    4259                 :          */
    4260               7 :         if (pg_class_tuple->relkind == RELKIND_INDEX ||
    4261               7 :             pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
    4262               7 :             pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
    4263                 :         {
    4264 UIC           0 :             ReleaseSysCache(tuple);
    4265               0 :             return;
    4266                 :         }
    4267                 : 
    4268                 :         /*
    4269                 :          * If this isn't a sequence then it's possibly going to have
    4270                 :          * column-level ACLs associated with it.
    4271                 :          */
    4272 GIC           7 :         if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
    4273                 :         {
    4274                 :             AttrNumber  curr_att;
    4275               6 :             AttrNumber  nattrs = pg_class_tuple->relnatts;
    4276                 : 
    4277              16 :             for (curr_att = 1; curr_att <= nattrs; curr_att++)
    4278                 :             {
    4279                 :                 HeapTuple   attTuple;
    4280                 :                 Datum       attaclDatum;
    4281                 : 
    4282              10 :                 attTuple = SearchSysCache2(ATTNUM,
    4283                 :                                            ObjectIdGetDatum(objoid),
    4284                 :                                            Int16GetDatum(curr_att));
    4285                 : 
    4286              10 :                 if (!HeapTupleIsValid(attTuple))
    4287 UIC           0 :                     continue;
    4288                 : 
    4289                 :                 /* ignore dropped columns */
    4290 GIC          10 :                 if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
    4291                 :                 {
    4292               1 :                     ReleaseSysCache(attTuple);
    4293               1 :                     continue;
    4294                 :                 }
    4295                 : 
    4296               9 :                 attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
    4297                 :                                               Anum_pg_attribute_attacl,
    4298                 :                                               &isNull);
    4299                 : 
    4300                 :                 /* no need to do anything for a NULL ACL */
    4301               9 :                 if (isNull)
    4302                 :                 {
    4303               7 :                     ReleaseSysCache(attTuple);
    4304               7 :                     continue;
    4305                 :                 }
    4306                 : 
    4307               2 :                 recordExtensionInitPrivWorker(objoid, classoid, curr_att,
    4308               2 :                                               DatumGetAclP(attaclDatum));
    4309                 : 
    4310               2 :                 ReleaseSysCache(attTuple);
    4311                 :             }
    4312                 :         }
    4313                 : 
    4314               7 :         aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
    4315                 :                                    &isNull);
    4316                 : 
    4317                 :         /* Add the record, if any, for the top-level object */
    4318               7 :         if (!isNull)
    4319               4 :             recordExtensionInitPrivWorker(objoid, classoid, 0,
    4320               4 :                                           DatumGetAclP(aclDatum));
    4321                 : 
    4322               7 :         ReleaseSysCache(tuple);
    4323                 :     }
    4324                 :     /* pg_largeobject_metadata */
    4325              21 :     else if (classoid == LargeObjectMetadataRelationId)
    4326                 :     {
    4327                 :         Datum       aclDatum;
    4328                 :         bool        isNull;
    4329                 :         HeapTuple   tuple;
    4330                 :         ScanKeyData entry[1];
    4331                 :         SysScanDesc scan;
    4332                 :         Relation    relation;
    4333                 : 
    4334                 :         /*
    4335                 :          * Note: this is dead code, given that we don't allow large objects to
    4336                 :          * be made extension members.  But it seems worth carrying in case
    4337                 :          * some future caller of this function has need for it.
    4338                 :          */
    4339 UIC           0 :         relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
    4340                 : 
    4341                 :         /* There's no syscache for pg_largeobject_metadata */
    4342               0 :         ScanKeyInit(&entry[0],
    4343                 :                     Anum_pg_largeobject_metadata_oid,
    4344                 :                     BTEqualStrategyNumber, F_OIDEQ,
    4345                 :                     ObjectIdGetDatum(objoid));
    4346                 : 
    4347               0 :         scan = systable_beginscan(relation,
    4348                 :                                   LargeObjectMetadataOidIndexId, true,
    4349                 :                                   NULL, 1, entry);
    4350                 : 
    4351               0 :         tuple = systable_getnext(scan);
    4352               0 :         if (!HeapTupleIsValid(tuple))
    4353               0 :             elog(ERROR, "could not find tuple for large object %u", objoid);
    4354                 : 
    4355               0 :         aclDatum = heap_getattr(tuple,
    4356                 :                                 Anum_pg_largeobject_metadata_lomacl,
    4357                 :                                 RelationGetDescr(relation), &isNull);
    4358                 : 
    4359                 :         /* Add the record, if any, for the top-level object */
    4360               0 :         if (!isNull)
    4361               0 :             recordExtensionInitPrivWorker(objoid, classoid, 0,
    4362               0 :                                           DatumGetAclP(aclDatum));
    4363                 : 
    4364               0 :         systable_endscan(scan);
    4365                 :     }
    4366                 :     /* This will error on unsupported classoid. */
    4367 GNC          21 :     else if (get_object_attnum_acl(classoid) != InvalidAttrNumber)
    4368                 :     {
    4369                 :         Datum       aclDatum;
    4370                 :         bool        isNull;
    4371                 :         HeapTuple   tuple;
    4372                 : 
    4373              10 :         tuple = SearchSysCache1(get_object_catcache_oid(classoid),
    4374                 :                                 ObjectIdGetDatum(objoid));
    4375 GIC          10 :         if (!HeapTupleIsValid(tuple))
    4376 UNC           0 :             elog(ERROR, "cache lookup failed for %s %u",
    4377                 :                  get_object_class_descr(classoid), objoid);
    4378                 : 
    4379 GNC          10 :         aclDatum = SysCacheGetAttr(get_object_catcache_oid(classoid), tuple,
    4380              10 :                                    get_object_attnum_acl(classoid),
    4381                 :                                    &isNull);
    4382                 : 
    4383                 :         /* Add the record, if any, for the top-level object */
    4384 GIC          10 :         if (!isNull)
    4385               5 :             recordExtensionInitPrivWorker(objoid, classoid, 0,
    4386               5 :                                           DatumGetAclP(aclDatum));
    4387                 : 
    4388              10 :         ReleaseSysCache(tuple);
    4389                 :     }
    4390                 : }
    4391                 : 
    4392                 : /*
    4393                 :  * For the object passed in, remove its ACL and the ACLs of any object subIds
    4394                 :  * from pg_init_privs (via recordExtensionInitPrivWorker()).
    4395                 :  */
    4396                 : void
    4397              58 : removeExtObjInitPriv(Oid objoid, Oid classoid)
    4398                 : {
    4399                 :     /*
    4400                 :      * If this is a relation then we need to see if there are any sub-objects
    4401                 :      * (eg: columns) for it and, if so, be sure to call
    4402                 :      * recordExtensionInitPrivWorker() for each one.
    4403                 :      */
    4404              58 :     if (classoid == RelationRelationId)
    4405                 :     {
    4406                 :         Form_pg_class pg_class_tuple;
    4407                 :         HeapTuple   tuple;
    4408                 : 
    4409              16 :         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
    4410              16 :         if (!HeapTupleIsValid(tuple))
    4411 UIC           0 :             elog(ERROR, "cache lookup failed for relation %u", objoid);
    4412 GIC          16 :         pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
    4413                 : 
    4414                 :         /*
    4415                 :          * Indexes don't have permissions, neither do the pg_class rows for
    4416                 :          * composite types.  (These cases are unreachable given the
    4417                 :          * restrictions in ALTER EXTENSION DROP, but let's check anyway.)
    4418                 :          */
    4419              16 :         if (pg_class_tuple->relkind == RELKIND_INDEX ||
    4420              16 :             pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
    4421              16 :             pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
    4422                 :         {
    4423 UIC           0 :             ReleaseSysCache(tuple);
    4424               0 :             return;
    4425                 :         }
    4426                 : 
    4427                 :         /*
    4428                 :          * If this isn't a sequence then it's possibly going to have
    4429                 :          * column-level ACLs associated with it.
    4430                 :          */
    4431 GIC          16 :         if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
    4432                 :         {
    4433                 :             AttrNumber  curr_att;
    4434              16 :             AttrNumber  nattrs = pg_class_tuple->relnatts;
    4435                 : 
    4436             375 :             for (curr_att = 1; curr_att <= nattrs; curr_att++)
    4437                 :             {
    4438                 :                 HeapTuple   attTuple;
    4439                 : 
    4440             359 :                 attTuple = SearchSysCache2(ATTNUM,
    4441                 :                                            ObjectIdGetDatum(objoid),
    4442                 :                                            Int16GetDatum(curr_att));
    4443                 : 
    4444             359 :                 if (!HeapTupleIsValid(attTuple))
    4445 UIC           0 :                     continue;
    4446                 : 
    4447                 :                 /* when removing, remove all entries, even dropped columns */
    4448                 : 
    4449 GIC         359 :                 recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
    4450                 : 
    4451             359 :                 ReleaseSysCache(attTuple);
    4452                 :             }
    4453                 :         }
    4454                 : 
    4455              16 :         ReleaseSysCache(tuple);
    4456                 :     }
    4457                 : 
    4458                 :     /* Remove the record, if any, for the top-level object */
    4459              58 :     recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
    4460                 : }
    4461                 : 
    4462                 : /*
    4463                 :  * Record initial ACL for an extension object
    4464                 :  *
    4465                 :  * Can be called at any time, we check if 'creating_extension' is set and, if
    4466                 :  * not, exit immediately.
    4467                 :  *
    4468                 :  * Pass in the object OID, the OID of the class (the OID of the table which
    4469                 :  * the object is defined in) and the 'sub' id of the object (objsubid), if
    4470                 :  * any.  If there is no 'sub' id (they are currently only used for columns of
    4471                 :  * tables) then pass in '0'.  Finally, pass in the complete ACL to store.
    4472                 :  *
    4473                 :  * If an ACL already exists for this object/sub-object then we will replace
    4474                 :  * it with what is passed in.
    4475                 :  *
    4476                 :  * Passing in NULL for 'new_acl' will result in the entry for the object being
    4477                 :  * removed, if one is found.
    4478                 :  */
    4479                 : static void
    4480           53978 : recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
    4481                 : {
    4482                 :     /*
    4483                 :      * Generally, we only record the initial privileges when an extension is
    4484                 :      * being created, but because we don't actually use CREATE EXTENSION
    4485                 :      * during binary upgrades with pg_upgrade, there is a variable to let us
    4486                 :      * know that the GRANT and REVOKE statements being issued, while this
    4487                 :      * variable is true, are for the initial privileges of the extension
    4488                 :      * object and therefore we need to record them.
    4489                 :      */
    4490           53978 :     if (!creating_extension && !binary_upgrade_record_init_privs)
    4491           53751 :         return;
    4492                 : 
    4493             227 :     recordExtensionInitPrivWorker(objoid, classoid, objsubid, new_acl);
    4494                 : }
    4495                 : 
    4496                 : /*
    4497                 :  * Record initial ACL for an extension object, worker.
    4498                 :  *
    4499                 :  * This will perform a wholesale replacement of the entire ACL for the object
    4500                 :  * passed in, therefore be sure to pass in the complete new ACL to use.
    4501                 :  *
    4502                 :  * Generally speaking, do *not* use this function directly but instead use
    4503                 :  * recordExtensionInitPriv(), which checks if 'creating_extension' is set.
    4504                 :  * This function does *not* check if 'creating_extension' is set as it is also
    4505                 :  * used when an object is added to or removed from an extension via ALTER
    4506                 :  * EXTENSION ... ADD/DROP.
    4507                 :  */
    4508                 : static void
    4509             655 : recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
    4510                 : {
    4511                 :     Relation    relation;
    4512                 :     ScanKeyData key[3];
    4513                 :     SysScanDesc scan;
    4514                 :     HeapTuple   tuple;
    4515                 :     HeapTuple   oldtuple;
    4516                 : 
    4517             655 :     relation = table_open(InitPrivsRelationId, RowExclusiveLock);
    4518                 : 
    4519             655 :     ScanKeyInit(&key[0],
    4520                 :                 Anum_pg_init_privs_objoid,
    4521                 :                 BTEqualStrategyNumber, F_OIDEQ,
    4522                 :                 ObjectIdGetDatum(objoid));
    4523             655 :     ScanKeyInit(&key[1],
    4524                 :                 Anum_pg_init_privs_classoid,
    4525                 :                 BTEqualStrategyNumber, F_OIDEQ,
    4526                 :                 ObjectIdGetDatum(classoid));
    4527             655 :     ScanKeyInit(&key[2],
    4528                 :                 Anum_pg_init_privs_objsubid,
    4529                 :                 BTEqualStrategyNumber, F_INT4EQ,
    4530                 :                 Int32GetDatum(objsubid));
    4531                 : 
    4532             655 :     scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
    4533                 :                               NULL, 3, key);
    4534                 : 
    4535                 :     /* There should exist only one entry or none. */
    4536             655 :     oldtuple = systable_getnext(scan);
    4537                 : 
    4538                 :     /* If we find an entry, update it with the latest ACL. */
    4539             655 :     if (HeapTupleIsValid(oldtuple))
    4540                 :     {
    4541 GNC          85 :         Datum       values[Natts_pg_init_privs] = {0};
    4542              85 :         bool        nulls[Natts_pg_init_privs] = {0};
    4543              85 :         bool        replace[Natts_pg_init_privs] = {0};
    4544                 : 
    4545                 :         /* If we have a new ACL to set, then update the row with it. */
    4546 GIC          85 :         if (new_acl)
    4547                 :         {
    4548              57 :             values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
    4549              57 :             replace[Anum_pg_init_privs_initprivs - 1] = true;
    4550                 : 
    4551              57 :             oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
    4552                 :                                          values, nulls, replace);
    4553                 : 
    4554              57 :             CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
    4555                 :         }
    4556                 :         else
    4557                 :         {
    4558                 :             /* new_acl is NULL, so delete the entry we found. */
    4559              28 :             CatalogTupleDelete(relation, &oldtuple->t_self);
    4560                 :         }
    4561                 :     }
    4562                 :     else
    4563                 :     {
    4564 GNC         570 :         Datum       values[Natts_pg_init_privs] = {0};
    4565             570 :         bool        nulls[Natts_pg_init_privs] = {0};
    4566                 : 
    4567                 :         /*
    4568                 :          * Only add a new entry if the new ACL is non-NULL.
    4569                 :          *
    4570                 :          * If we are passed in a NULL ACL and no entry exists, we can just
    4571                 :          * fall through and do nothing.
    4572                 :          */
    4573 GIC         570 :         if (new_acl)
    4574                 :         {
    4575                 :             /* No entry found, so add it. */
    4576             179 :             values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
    4577             179 :             values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
    4578             179 :             values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
    4579                 : 
    4580                 :             /* This function only handles initial privileges of extensions */
    4581             179 :             values[Anum_pg_init_privs_privtype - 1] =
    4582             179 :                 CharGetDatum(INITPRIVS_EXTENSION);
    4583                 : 
    4584             179 :             values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
    4585                 : 
    4586             179 :             tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
    4587                 : 
    4588             179 :             CatalogTupleInsert(relation, tuple);
    4589                 :         }
    4590                 :     }
    4591                 : 
    4592             655 :     systable_endscan(scan);
    4593                 : 
    4594                 :     /* prevent error when processing objects multiple times */
    4595             655 :     CommandCounterIncrement();
    4596                 : 
    4597             655 :     table_close(relation, RowExclusiveLock);
    4598             655 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a