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 17:13:01 Functions: 96.3 % 54 52 2 45 7 1 35 1 17
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 9 9 9
Legend: Lines: hit not hit (60,120] days: 91.9 % 74 68 5 1 7 6 50 5 4 9
(120,180] days: 77.3 % 66 51 15 51 1
(180,240] days: 50.0 % 2 1 1 1
(240..) days: 80.9 % 1621 1312 99 192 18 62 849 19 382 91 623
Function coverage date bins:
(60,120] days: 100.0 % 4 4 1 3
(120,180] days: 100.0 % 4 4 4
(240..) days: 53.7 % 82 44 2 44 1 35

 Age         Owner                  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 *
 7658 tgl                       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                 : 
 7720 peter_e                   183          104765 :     new_acl = old_acl;
                                184                 : 
                                185          209569 :     foreach(j, grantees)
                                186                 :     {
                                187                 :         AclItem     aclitem;
 7157 tgl                       188 ECB             :         Acl        *newer_acl;
                                189                 : 
 3955 bruce                     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.
 7381 peter_e                   197 ECB             :          */
 6494 tgl                       198 GIC      104810 :         if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
 7202 tgl                       199 LBC           0 :             ereport(ERROR,
                                200                 :                     (errcode(ERRCODE_INVALID_GRANT_OPERATION),
 6494 tgl                       201 ECB             :                      errmsg("grant options can only be granted to roles")));
                                202                 : 
 3955 bruce                     203 GIC      104810 :         aclitem.ai_grantor = grantorId;
                                204                 : 
                                205                 :         /*
 6886 tgl                       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                 :          */
 6494 tgl                       212 GIC      104810 :         ACLITEM_SET_PRIVS_GOPTIONS(aclitem,
                                213                 :                                    (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
 2118 tgl                       214 ECB             :                                    (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
 7720 peter_e                   215 EUB             : 
 6494 tgl                       216 GIC      104810 :         newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
                                217                 : 
                                218                 :         /* avoid memory leak when there are many grantees */
 7157 tgl                       219 CBC      104804 :         pfree(new_acl);
 7157 tgl                       220 GIC      104804 :         new_acl = newer_acl;
                                221                 :     }
                                222                 : 
 7720 peter_e                   223          104759 :     return new_acl;
                                224                 : }
                                225                 : 
                                226                 : /*
                                227                 :  * Restrict the privileges to what we can actually grant, and emit
 6338 alvherre                  228 ECB             :  * the standards-mandated warning and error messages.
                                229                 :  */
                                230                 : static AclMode
 6338 alvherre                  231 GIC      104685 : restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
 6338 alvherre                  232 ECB             :                          AclMode privileges, Oid objectId, Oid grantorId,
                                233                 :                          ObjectType objtype, const char *objname,
                                234                 :                          AttrNumber att_number, const char *colname)
                                235                 : {
 6031 bruce                     236                 :     AclMode     this_privileges;
                                237                 :     AclMode     whole_mask;
                                238                 : 
 1954 peter_e                   239 CBC      104685 :     switch (objtype)
                                240                 :     {
 1954 peter_e                   241 GIC       55894 :         case OBJECT_COLUMN:
 5190 tgl                       242           55894 :             whole_mask = ACL_ALL_RIGHTS_COLUMN;
                                243           55894 :             break;
 1954 peter_e                   244           24608 :         case OBJECT_TABLE:
 6338 alvherre                  245           24608 :             whole_mask = ACL_ALL_RIGHTS_RELATION;
                                246           24608 :             break;
 1954 peter_e                   247 CBC          76 :         case OBJECT_SEQUENCE:
 6287 bruce                     248 GIC          76 :             whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
                                249              76 :             break;
 1954 peter_e                   250             659 :         case OBJECT_DATABASE:
 6338 alvherre                  251             659 :             whole_mask = ACL_ALL_RIGHTS_DATABASE;
                                252             659 :             break;
 1954 peter_e                   253           22206 :         case OBJECT_FUNCTION:
 6338 alvherre                  254           22206 :             whole_mask = ACL_ALL_RIGHTS_FUNCTION;
 6338 alvherre                  255 CBC       22206 :             break;
 1954 peter_e                   256 GIC          18 :         case OBJECT_LANGUAGE:
 6338 alvherre                  257 CBC          18 :             whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
                                258              18 :             break;
 1954 peter_e                   259              40 :         case OBJECT_LARGEOBJECT:
 4867 itagaki.takahiro          260              40 :             whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
                                261              40 :             break;
 1954 peter_e                   262             978 :         case OBJECT_SCHEMA:
 2006                           263             978 :             whole_mask = ACL_ALL_RIGHTS_SCHEMA;
 6338 alvherre                  264             978 :             break;
 1954 peter_e                   265 LBC           0 :         case OBJECT_TABLESPACE:
 6338 alvherre                  266               0 :             whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
                                267               0 :             break;
 1954 peter_e                   268 CBC          47 :         case OBJECT_FDW:
 5224                           269              47 :             whole_mask = ACL_ALL_RIGHTS_FDW;
                                270              47 :             break;
 1954                           271              44 :         case OBJECT_FOREIGN_SERVER:
 5224                           272              44 :             whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
                                273              44 :             break;
 1954 peter_e                   274 LBC           0 :         case OBJECT_EVENT_TRIGGER:
 3917 rhaas                     275               0 :             elog(ERROR, "grantable rights not supported for event triggers");
 3917 rhaas                     276 ECB             :             /* not reached, but keep compiler quiet */
                                277                 :             return ACL_NO_RIGHTS;
 1954 peter_e                   278 CBC          47 :         case OBJECT_TYPE:
 4128                           279              47 :             whole_mask = ACL_ALL_RIGHTS_TYPE;
                                280              47 :             break;
  368 tgl                       281 GBC          68 :         case OBJECT_PARAMETER_ACL:
                                282              68 :             whole_mask = ACL_ALL_RIGHTS_PARAMETER_ACL;
                                283              68 :             break;
 6338 alvherre                  284 LBC           0 :         default:
 1954 peter_e                   285               0 :             elog(ERROR, "unrecognized object type: %d", objtype);
 6338 alvherre                  286 ECB             :             /* not reached, but keep compiler quiet */
                                287                 :             return ACL_NO_RIGHTS;
                                288                 :     }
                                289                 : 
 6338 alvherre                  290 EUB             :     /*
 6031 bruce                     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.
 6338 alvherre                  294 ECB             :      */
 6338 alvherre                  295 CBC      104685 :     if (avail_goptions == ACL_NO_RIGHTS)
 6338 alvherre                  296 ECB             :     {
 1954 peter_e                   297 CBC          33 :         if (pg_aclmask(objtype, objectId, att_number, grantorId,
 6338 alvherre                  298              33 :                        whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
 6338 alvherre                  299 ECB             :                        ACLMASK_ANY) == ACL_NO_RIGHTS)
 5190 tgl                       300 EUB             :         {
 1954 peter_e                   301 GBC          15 :             if (objtype == OBJECT_COLUMN && colname)
 1954 peter_e                   302 UIC           0 :                 aclcheck_error_col(ACLCHECK_NO_PRIV, objtype, objname, colname);
                                303                 :             else
 1954 peter_e                   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
 6031 bruce                     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.)
 6338 alvherre                  314                 :      */
 6338 alvherre                  315 GIC      104670 :     this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
                                316          104670 :     if (is_grant)
 6338 alvherre                  317 ECB             :     {
 6338 alvherre                  318 GBC       29688 :         if (this_privileges == 0)
                                319                 :         {
 1954 peter_e                   320 CBC          15 :             if (objtype == OBJECT_COLUMN && colname)
 4782 tgl                       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
 4782 tgl                       326 GIC          15 :                 ereport(WARNING,
                                327                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
                                328                 :                          errmsg("no privileges were granted for \"%s\"",
                                329                 :                                 objname)));
                                330                 :         }
 6338 alvherre                  331 CBC       29673 :         else if (!all_privs && this_privileges != privileges)
 4782 tgl                       332 ECB             :         {
 1954 peter_e                   333 UIC           0 :             if (objtype == OBJECT_COLUMN && colname)
 4782 tgl                       334 LBC           0 :                 ereport(WARNING,
                                335                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
 4782 tgl                       336 ECB             :                          errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
 4782 tgl                       337 EUB             :                                 colname, objname)));
                                338                 :             else
 4782 tgl                       339 UIC           0 :                 ereport(WARNING,
                                340                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
                                341                 :                          errmsg("not all privileges were granted for \"%s\"",
 4782 tgl                       342 ECB             :                                 objname)));
                                343                 :         }
                                344                 :     }
                                345                 :     else
                                346                 :     {
 6338 alvherre                  347 CBC       74982 :         if (this_privileges == 0)
                                348                 :         {
 1954 peter_e                   349 GBC           3 :             if (objtype == OBJECT_COLUMN && colname)
 4782 tgl                       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
 4782 tgl                       355 GBC           3 :                 ereport(WARNING,
                                356                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
                                357                 :                          errmsg("no privileges could be revoked for \"%s\"",
                                358                 :                                 objname)));
                                359                 :         }
 6338 alvherre                  360 GIC       74979 :         else if (!all_privs && this_privileges != privileges)
                                361                 :         {
 1954 peter_e                   362 UIC           0 :             if (objtype == OBJECT_COLUMN && colname)
 4782 tgl                       363 LBC           0 :                 ereport(WARNING,
                                364                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
 4782 tgl                       365 ECB             :                          errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
 4782 tgl                       366 EUB             :                                 colname, objname)));
                                367                 :             else
 4782 tgl                       368 UIC           0 :                 ereport(WARNING,
                                369                 :                         (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
                                370                 :                          errmsg("not all privileges could be revoked for \"%s\"",
 2118 tgl                       371 ECB             :                                 objname)));
                                372                 :         }
                                373                 :     }
                                374                 : 
 6338 alvherre                  375 GIC      104670 :     return this_privileges;
 6338 alvherre                  376 ECB             : }
                                377                 : 
 9770 scrappy                   378 EUB             : /*
 7974 peter_e                   379                 :  * Called to execute the utility commands GRANT and REVOKE
                                380                 :  */
                                381                 : void
 7974 peter_e                   382 GIC       48822 : ExecuteGrantStmt(GrantStmt *stmt)
                                383                 : {
 6338 alvherre                  384 EUB             :     InternalGrant istmt;
                                385                 :     ListCell   *cell;
                                386                 :     const char *errormsg;
                                387                 :     AclMode     all_privileges;
                                388                 : 
  799 peter                     389 GIC       48822 :     if (stmt->grantor)
                                390                 :     {
  799 peter                     391 ECB             :         Oid         grantor;
                                392                 : 
  799 peter                     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.
  799 peter                     398 ECB             :          */
  799 peter                     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                 : 
 6338 alvherre                  405 ECB             :     /*
                                406                 :      * Turn the regular GrantStmt into the InternalGrant form.
                                407                 :      */
 6338 alvherre                  408 GIC       48819 :     istmt.is_grant = stmt->is_grant;
 6338 alvherre                  409 CBC       48819 :     istmt.objtype = stmt->objtype;
                                410                 : 
                                411                 :     /* Collect the OIDs of the target objects */
 4927 tgl                       412 GIC       48819 :     switch (stmt->targtype)
                                413                 :     {
                                414           48804 :         case ACL_TARGET_OBJECT:
  368 tgl                       415 CBC       97595 :             istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects,
                                416           48804 :                                               stmt->is_grant);
 4927 tgl                       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 */
 4927 tgl                       422 UIC           0 :         default:
                                423               0 :             elog(ERROR, "unrecognized GrantStmt.targtype: %d",
 4927 tgl                       424 ECB             :                  (int) stmt->targtype);
                                425                 :     }
                                426                 : 
                                427                 :     /* all_privs to be filled below */
 6338 alvherre                  428                 :     /* privileges to be filled below */
 5190 tgl                       429 GIC       48806 :     istmt.col_privs = NIL;      /* may get filled below */
 5190 tgl                       430 CBC       48806 :     istmt.grantees = NIL;       /* filled below */
 6338 alvherre                  431           48806 :     istmt.grant_option = stmt->grant_option;
                                432           48806 :     istmt.behavior = stmt->behavior;
 6338 alvherre                  433 ECB             : 
 6348                           434                 :     /*
 2878 bruce                     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.
 6348 alvherre                  438 EUB             :      */
 6348 alvherre                  439 GBC       97639 :     foreach(cell, stmt->grantees)
                                440                 :     {
 2878 bruce                     441 GIC       48836 :         RoleSpec   *grantee = (RoleSpec *) lfirst(cell);
                                442                 :         Oid         grantee_uid;
                                443                 : 
 2953 alvherre                  444           48836 :         switch (grantee->roletype)
 2953 alvherre                  445 ECB             :         {
 2953 alvherre                  446 CBC       44015 :             case ROLESPEC_PUBLIC:
                                447           44015 :                 grantee_uid = ACL_ID_PUBLIC;
                                448           44015 :                 break;
 2953 alvherre                  449 GIC        4821 :             default:
 2293 peter_e                   450            4821 :                 grantee_uid = get_rolespec_oid(grantee, false);
 2953 alvherre                  451            4818 :                 break;
                                452                 :         }
                                453           48833 :         istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
                                454                 :     }
 6348 alvherre                  455 ECB             : 
                                456                 :     /*
 5050 bruce                     457                 :      * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
                                458                 :      * bitmask.  Note: objtype can't be OBJECT_COLUMN.
                                459                 :      */
 7658 tgl                       460 CBC       48803 :     switch (stmt->objtype)
                                461                 :     {
 2006 peter_e                   462           25070 :         case OBJECT_TABLE:
 1809 tgl                       463 ECB             : 
 6031 bruce                     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                 :              */
 6287 bruce                     469 CBC       25070 :             all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE;
 5494 tgl                       470 GIC       25070 :             errormsg = gettext_noop("invalid privilege type %s for relation");
 6287 bruce                     471           25070 :             break;
 2006 peter_e                   472               6 :         case OBJECT_SEQUENCE:
 6287 bruce                     473               6 :             all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
 5494 tgl                       474               6 :             errormsg = gettext_noop("invalid privilege type %s for sequence");
 7658                           475               6 :             break;
 2006 peter_e                   476 CBC         655 :         case OBJECT_DATABASE:
 6348 alvherre                  477 GIC         655 :             all_privileges = ACL_ALL_RIGHTS_DATABASE;
 5494 tgl                       478 CBC         655 :             errormsg = gettext_noop("invalid privilege type %s for database");
 7720 peter_e                   479 GIC         655 :             break;
 2006                           480              10 :         case OBJECT_DOMAIN:
 4128                           481              10 :             all_privileges = ACL_ALL_RIGHTS_TYPE;
                                482              10 :             errormsg = gettext_noop("invalid privilege type %s for domain");
                                483              10 :             break;
 2006                           484           22156 :         case OBJECT_FUNCTION:
 6348 alvherre                  485 CBC       22156 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
 5494 tgl                       486           22156 :             errormsg = gettext_noop("invalid privilege type %s for function");
 7720 peter_e                   487           22156 :             break;
 2006                           488              21 :         case OBJECT_LANGUAGE:
 6348 alvherre                  489              21 :             all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
 5494 tgl                       490              21 :             errormsg = gettext_noop("invalid privilege type %s for language");
 7658                           491              21 :             break;
 2006 peter_e                   492              31 :         case OBJECT_LARGEOBJECT:
 4867 itagaki.takahiro          493              31 :             all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
                                494              31 :             errormsg = gettext_noop("invalid privilege type %s for large object");
                                495              31 :             break;
 2006 peter_e                   496             666 :         case OBJECT_SCHEMA:
                                497             666 :             all_privileges = ACL_ALL_RIGHTS_SCHEMA;
 5494 tgl                       498             666 :             errormsg = gettext_noop("invalid privilege type %s for schema");
 7720 peter_e                   499             666 :             break;
 2006                           500              21 :         case OBJECT_PROCEDURE:
 1956                           501              21 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
                                502              21 :             errormsg = gettext_noop("invalid privilege type %s for procedure");
                                503              21 :             break;
 2006                           504               3 :         case OBJECT_ROUTINE:
 1956                           505               3 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
                                506               3 :             errormsg = gettext_noop("invalid privilege type %s for routine");
                                507               3 :             break;
 2006 peter_e                   508 LBC           0 :         case OBJECT_TABLESPACE:
 6348 alvherre                  509               0 :             all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
 5494 tgl                       510               0 :             errormsg = gettext_noop("invalid privilege type %s for tablespace");
 6869                           511               0 :             break;
 2006 peter_e                   512 CBC          43 :         case OBJECT_TYPE:
 4128                           513              43 :             all_privileges = ACL_ALL_RIGHTS_TYPE;
                                514              43 :             errormsg = gettext_noop("invalid privilege type %s for type");
                                515              43 :             break;
 2006                           516              46 :         case OBJECT_FDW:
 5224                           517              46 :             all_privileges = ACL_ALL_RIGHTS_FDW;
                                518              46 :             errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
                                519              46 :             break;
 2006                           520              38 :         case OBJECT_FOREIGN_SERVER:
 5224                           521              38 :             all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
                                522              38 :             errormsg = gettext_noop("invalid privilege type %s for foreign server");
                                523              38 :             break;
  368 tgl                       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;
 7720 peter_e                   528 LBC           0 :         default:
 4934 tgl                       529               0 :             elog(ERROR, "unrecognized GrantStmt.objtype: %d",
 4934 tgl                       530 ECB             :                  (int) stmt->objtype);
 6338 alvherre                  531                 :             /* keep compiler quiet */
                                532                 :             all_privileges = ACL_NO_RIGHTS;
                                533                 :             errormsg = NULL;
 7720 peter_e                   534                 :     }
                                535                 : 
 6494 tgl                       536 CBC       48803 :     if (stmt->privileges == NIL)
 6886 tgl                       537 ECB             :     {
 6338 alvherre                  538 CBC        4646 :         istmt.all_privs = true;
 6031 bruce                     539 ECB             : 
 6338 alvherre                  540                 :         /*
                                541                 :          * will be turned into ACL_ALL_RIGHTS_* by the internal routines
                                542                 :          * depending on the object type
                                543                 :          */
 6338 alvherre                  544 GBC        4646 :         istmt.privileges = ACL_NO_RIGHTS;
 6886 tgl                       545 EUB             :     }
                                546                 :     else
                                547                 :     {
 6338 alvherre                  548 GIC       44157 :         istmt.all_privs = false;
                                549           44157 :         istmt.privileges = ACL_NO_RIGHTS;
                                550                 : 
 6348                           551           89310 :         foreach(cell, stmt->privileges)
 7720 peter_e                   552 ECB             :         {
 5190 tgl                       553 GIC       45165 :             AccessPriv *privnode = (AccessPriv *) lfirst(cell);
 5190 tgl                       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                 :              */
 5190 tgl                       560 CBC       45165 :             if (privnode->cols)
                                561                 :             {
 2006 peter_e                   562 GIC         469 :                 if (stmt->objtype != OBJECT_TABLE)
 5190 tgl                       563 UIC           0 :                     ereport(ERROR,
 5190 tgl                       564 ECB             :                             (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                                565                 :                              errmsg("column privileges are only valid for relations")));
 5190 tgl                       566 GIC         469 :                 istmt.col_privs = lappend(istmt.col_privs, privnode);
 5190 tgl                       567 CBC         469 :                 continue;
                                568                 :             }
 5190 tgl                       569 ECB             : 
 5050 bruce                     570 GIC       44696 :             if (privnode->priv_name == NULL) /* parser mistake? */
 5190 tgl                       571 UIC           0 :                 elog(ERROR, "AccessPriv node must specify privilege or columns");
 5190 tgl                       572 GIC       44696 :             priv = string_to_privilege(privnode->priv_name);
                                573                 : 
 6348 alvherre                  574           44696 :             if (priv & ~((AclMode) all_privileges))
 7202 tgl                       575              12 :                 ereport(ERROR,
 7202 tgl                       576 ECB             :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                                577                 :                          errmsg(errormsg, privilege_to_string(priv))));
 6348 alvherre                  578                 : 
 6338 alvherre                  579 GBC       44684 :             istmt.privileges |= priv;
                                580                 :         }
                                581                 :     }
 7720 peter_e                   582 ECB             : 
 6338 alvherre                  583 CBC       48791 :     ExecGrantStmt_oids(&istmt);
 6348 alvherre                  584 GIC       48761 : }
                                585                 : 
 6348 alvherre                  586 ECB             : /*
 6348 alvherre                  587 EUB             :  * ExecGrantStmt_oids
 6348 alvherre                  588 ECB             :  *
                                589                 :  * Internal entry point for granting and revoking privileges.
                                590                 :  */
 4934 tgl                       591                 : static void
 6338 alvherre                  592 GIC       48881 : ExecGrantStmt_oids(InternalGrant *istmt)
                                593                 : {
                                594           48881 :     switch (istmt->objtype)
 8287 tgl                       595 ECB             :     {
 2006 peter_e                   596 GIC       25114 :         case OBJECT_TABLE:
                                597                 :         case OBJECT_SEQUENCE:
 6338 alvherre                  598           25114 :             ExecGrant_Relation(istmt);
 6348 alvherre                  599 CBC       25111 :             break;
 2006 peter_e                   600             659 :         case OBJECT_DATABASE:
  117 peter                     601 GNC         659 :             ExecGrant_common(istmt, DatabaseRelationId, ACL_ALL_RIGHTS_DATABASE, NULL);
 6348 alvherre                  602 GIC         659 :             break;
 2006 peter_e                   603              53 :         case OBJECT_DOMAIN:
                                604                 :         case OBJECT_TYPE:
  117 peter                     605 GNC          53 :             ExecGrant_common(istmt, TypeRelationId, ACL_ALL_RIGHTS_TYPE, ExecGrant_Type_check);
 4128 peter_e                   606 GIC          44 :             break;
 2006                           607              47 :         case OBJECT_FDW:
  117 peter                     608 GNC          47 :             ExecGrant_common(istmt, ForeignDataWrapperRelationId, ACL_ALL_RIGHTS_FDW, NULL);
 5224 peter_e                   609 GIC          38 :             break;
 2006 peter_e                   610 CBC          44 :         case OBJECT_FOREIGN_SERVER:
  117 peter                     611 GNC          44 :             ExecGrant_common(istmt, ForeignServerRelationId, ACL_ALL_RIGHTS_FOREIGN_SERVER, NULL);
 5224 peter_e                   612 CBC          38 :             break;
 2006 peter_e                   613 GIC       22185 :         case OBJECT_FUNCTION:
 2006 peter_e                   614 ECB             :         case OBJECT_PROCEDURE:
                                615                 :         case OBJECT_ROUTINE:
  117 peter                     616 GNC       22185 :             ExecGrant_common(istmt, ProcedureRelationId, ACL_ALL_RIGHTS_FUNCTION, NULL);
 6348 alvherre                  617 CBC       22185 :             break;
 2006 peter_e                   618              21 :         case OBJECT_LANGUAGE:
  117 peter                     619 GNC          21 :             ExecGrant_common(istmt, LanguageRelationId, ACL_ALL_RIGHTS_LANGUAGE, ExecGrant_Language_check);
 6348 alvherre                  620 GIC          18 :             break;
 2006 peter_e                   621 CBC          37 :         case OBJECT_LARGEOBJECT:
 4867 itagaki.takahiro          622              37 :             ExecGrant_Largeobject(istmt);
                                623              37 :             break;
 2006 peter_e                   624             672 :         case OBJECT_SCHEMA:
  117 peter                     625 GNC         672 :             ExecGrant_common(istmt, NamespaceRelationId, ACL_ALL_RIGHTS_SCHEMA, NULL);
 6348 alvherre                  626 CBC         672 :             break;
 2006 peter_e                   627 LBC           0 :         case OBJECT_TABLESPACE:
  117 peter                     628 UNC           0 :             ExecGrant_common(istmt, TableSpaceRelationId, ACL_ALL_RIGHTS_TABLESPACE, NULL);
 6348 alvherre                  629 LBC           0 :             break;
  368 tgl                       630 GIC          49 :         case OBJECT_PARAMETER_ACL:
                                631              49 :             ExecGrant_Parameter(istmt);
  368 tgl                       632 CBC          49 :             break;
 6348 alvherre                  633 LBC           0 :         default:
                                634               0 :             elog(ERROR, "unrecognized GrantStmt.objtype: %d",
 6338 alvherre                  635 ECB             :                  (int) istmt->objtype);
 6348                           636                 :     }
 2890                           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.
 2890 alvherre                  643 EUB             :      */
 2006 peter_e                   644 GBC       48851 :     if (EventTriggerSupportsObjectType(istmt->objtype))
 2890 alvherre                  645           48143 :         EventTriggerCollectGrant(istmt);
 6348 alvherre                  646 CBC       48851 : }
 6348 alvherre                  647 ECB             : 
                                648                 : /*
 6348 alvherre                  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 *
  368 tgl                       659 GIC       48804 : objectNamesToOids(ObjectType objtype, List *objnames, bool is_grant)
 6348 alvherre                  660 ECB             : {
 6347 bruce                     661 CBC       48804 :     List       *objects = NIL;
 6347 bruce                     662 ECB             :     ListCell   *cell;
                                663                 : 
 6348 alvherre                  664 GIC       48804 :     Assert(objnames != NIL);
                                665                 : 
                                666           48804 :     switch (objtype)
                                667                 :     {
 2006 peter_e                   668           25070 :         case OBJECT_TABLE:
                                669                 :         case OBJECT_SEQUENCE:
 6348 alvherre                  670           50167 :             foreach(cell, objnames)
                                671                 :             {
                                672           25097 :                 RangeVar   *relvar = (RangeVar *) lfirst(cell);
                                673                 :                 Oid         relOid;
                                674                 : 
 4148 rhaas                     675 CBC       25097 :                 relOid = RangeVarGetRelid(relvar, NoLock, false);
 6348 alvherre                  676 GIC       25097 :                 objects = lappend_oid(objects, relOid);
 6348 alvherre                  677 ECB             :             }
 6348 alvherre                  678 GIC       25070 :             break;
 2006 peter_e                   679             655 :         case OBJECT_DATABASE:
 6348 alvherre                  680 CBC        1310 :             foreach(cell, objnames)
                                681                 :             {
                                682             655 :                 char       *dbname = strVal(lfirst(cell));
                                683                 :                 Oid         dbid;
 6348 alvherre                  684 ECB             : 
 4630 rhaas                     685 GIC         655 :                 dbid = get_database_oid(dbname, false);
 6185 tgl                       686 CBC         655 :                 objects = lappend_oid(objects, dbid);
                                687                 :             }
 6348 alvherre                  688             655 :             break;
 2006 peter_e                   689 GIC          53 :         case OBJECT_DOMAIN:
                                690                 :         case OBJECT_TYPE:
 4128 peter_e                   691 CBC         106 :             foreach(cell, objnames)
 4128 peter_e                   692 ECB             :             {
 4128 peter_e                   693 GIC          53 :                 List       *typname = (List *) lfirst(cell);
 4128 peter_e                   694 ECB             :                 Oid         oid;
                                695                 : 
 4128 peter_e                   696 CBC          53 :                 oid = typenameTypeId(NULL, makeTypeNameFromNameList(typname));
 4128 peter_e                   697 GIC          53 :                 objects = lappend_oid(objects, oid);
 4128 peter_e                   698 ECB             :             }
 4128 peter_e                   699 GIC          53 :             break;
 2006                           700           22159 :         case OBJECT_FUNCTION:
 6348 alvherre                  701 CBC       44324 :             foreach(cell, objnames)
 6348 alvherre                  702 ECB             :             {
 2293 peter_e                   703 GIC       22171 :                 ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
 6348 alvherre                  704 ECB             :                 Oid         funcid;
                                705                 : 
 1956 peter_e                   706 GIC       22171 :                 funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false);
 6348 alvherre                  707 CBC       22165 :                 objects = lappend_oid(objects, funcid);
                                708                 :             }
                                709           22153 :             break;
 2006 peter_e                   710 GIC          21 :         case OBJECT_LANGUAGE:
 6348 alvherre                  711              42 :             foreach(cell, objnames)
 6348 alvherre                  712 ECB             :             {
 6347 bruce                     713 CBC          21 :                 char       *langname = strVal(lfirst(cell));
                                714                 :                 Oid         oid;
 6348 alvherre                  715 ECB             : 
 4630 rhaas                     716 CBC          21 :                 oid = get_language_oid(langname, false);
                                717              21 :                 objects = lappend_oid(objects, oid);
                                718                 :             }
 6348 alvherre                  719              21 :             break;
 2006 peter_e                   720 GIC          40 :         case OBJECT_LARGEOBJECT:
 4867 itagaki.takahiro          721              77 :             foreach(cell, objnames)
 4867 itagaki.takahiro          722 ECB             :             {
 4683 rhaas                     723 CBC          43 :                 Oid         lobjOid = oidparse(lfirst(cell));
                                724                 : 
 4867 itagaki.takahiro          725              43 :                 if (!LargeObjectExists(lobjOid))
                                726               6 :                     ereport(ERROR,
 4867 itagaki.takahiro          727 ECB             :                             (errcode(ERRCODE_UNDEFINED_OBJECT),
                                728                 :                              errmsg("large object %u does not exist",
                                729                 :                                     lobjOid)));
                                730                 : 
 4867 itagaki.takahiro          731 GIC          37 :                 objects = lappend_oid(objects, lobjOid);
 4867 itagaki.takahiro          732 ECB             :             }
 4867 itagaki.takahiro          733 CBC          34 :             break;
 2006 peter_e                   734 GIC         666 :         case OBJECT_SCHEMA:
 6347 bruce                     735 CBC        1638 :             foreach(cell, objnames)
 6348 alvherre                  736 ECB             :             {
 6348 alvherre                  737 CBC         972 :                 char       *nspname = strVal(lfirst(cell));
                                738                 :                 Oid         oid;
 6348 alvherre                  739 ECB             : 
 4630 rhaas                     740 GIC         972 :                 oid = get_namespace_oid(nspname, false);
 4630 rhaas                     741 CBC         972 :                 objects = lappend_oid(objects, oid);
 6348 alvherre                  742 ECB             :             }
 6348 alvherre                  743 GIC         666 :             break;
 2006 peter_e                   744              18 :         case OBJECT_PROCEDURE:
 1956                           745              36 :             foreach(cell, objnames)
                                746                 :             {
 1956 peter_e                   747 CBC          18 :                 ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
                                748                 :                 Oid         procid;
 1956 peter_e                   749 ECB             : 
 1956 peter_e                   750 CBC          18 :                 procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false);
                                751              18 :                 objects = lappend_oid(objects, procid);
                                752                 :             }
                                753              18 :             break;
 2006 peter_e                   754 UIC           0 :         case OBJECT_ROUTINE:
 1956                           755               0 :             foreach(cell, objnames)
 1956 peter_e                   756 ECB             :             {
 1956 peter_e                   757 LBC           0 :                 ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
                                758                 :                 Oid         routid;
 1956 peter_e                   759 ECB             : 
 1956 peter_e                   760 LBC           0 :                 routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false);
                                761               0 :                 objects = lappend_oid(objects, routid);
                                762                 :             }
                                763               0 :             break;
 2006 peter_e                   764 UIC           0 :         case OBJECT_TABLESPACE:
 6347 bruce                     765               0 :             foreach(cell, objnames)
 6348 alvherre                  766 ECB             :             {
 6347 bruce                     767 LBC           0 :                 char       *spcname = strVal(lfirst(cell));
                                768                 :                 Oid         spcoid;
 6348 alvherre                  769 ECB             : 
 4630 rhaas                     770 UBC           0 :                 spcoid = get_tablespace_oid(spcname, false);
                                771               0 :                 objects = lappend_oid(objects, spcoid);
                                772                 :             }
 6348 alvherre                  773               0 :             break;
 2006 peter_e                   774 GIC          46 :         case OBJECT_FDW:
 5224                           775              92 :             foreach(cell, objnames)
 5224 peter_e                   776 EUB             :             {
 5050 bruce                     777 GBC          46 :                 char       *fdwname = strVal(lfirst(cell));
 4391 rhaas                     778 GIC          46 :                 Oid         fdwid = get_foreign_data_wrapper_oid(fdwname, false);
 5224 peter_e                   779 EUB             : 
 5224 peter_e                   780 GBC          46 :                 objects = lappend_oid(objects, fdwid);
 5224 peter_e                   781 EUB             :             }
 5224 peter_e                   782 GIC          46 :             break;
 2006 peter_e                   783 GBC          38 :         case OBJECT_FOREIGN_SERVER:
 5224 peter_e                   784 GIC          76 :             foreach(cell, objnames)
                                785                 :             {
 5050 bruce                     786 GBC          38 :                 char       *srvname = strVal(lfirst(cell));
 4391 rhaas                     787              38 :                 Oid         srvid = get_foreign_server_oid(srvname, false);
                                788                 : 
 5224 peter_e                   789              38 :                 objects = lappend_oid(objects, srvid);
 5224 peter_e                   790 ECB             :             }
 5224 peter_e                   791 CBC          38 :             break;
  368 tgl                       792 GIC          38 :         case OBJECT_PARAMETER_ACL:
  368 tgl                       793 CBC         100 :             foreach(cell, objnames)
  368 tgl                       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                 :                  */
  368 tgl                       805 CBC          63 :                 char       *parameter = strVal(lfirst(cell));
  368 tgl                       806 GIC          63 :                 Oid         parameterId = ParameterAclLookup(parameter, true);
  368 tgl                       807 ECB             : 
  368 tgl                       808 CBC          63 :                 if (!OidIsValid(parameterId) && is_grant)
  368 tgl                       809 ECB             :                 {
  368 tgl                       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);
  368 tgl                       821 ECB             :             }
  368 tgl                       822 CBC          37 :             break;
 6348 alvherre                  823 UIC           0 :         default:
 6348 alvherre                  824 LBC           0 :             elog(ERROR, "unrecognized GrantStmt.objtype: %d",
                                825                 :                  (int) objtype);
 6348 alvherre                  826 ECB             :     }
                                827                 : 
 6348 alvherre                  828 GIC       48791 :     return objects;
                                829                 : }
                                830                 : 
                                831                 : /*
                                832                 :  * objectsInSchemaToOids
 4927 tgl                       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 *
 2006 peter_e                   839 GBC          15 : objectsInSchemaToOids(ObjectType objtype, List *nspnames)
 4927 tgl                       840 EUB             : {
 4927 tgl                       841 GIC          15 :     List       *objects = NIL;
                                842                 :     ListCell   *cell;
                                843                 : 
 4927 tgl                       844 CBC          30 :     foreach(cell, nspnames)
                                845                 :     {
 4927 tgl                       846 GIC          15 :         char       *nspname = strVal(lfirst(cell));
                                847                 :         Oid         namespaceId;
                                848                 :         List       *objs;
                                849                 : 
 3725 bruce                     850              15 :         namespaceId = LookupExplicitNamespace(nspname, false);
                                851                 : 
 4927 tgl                       852              15 :         switch (objtype)
                                853                 :         {
 2006 peter_e                   854               6 :             case OBJECT_TABLE:
 4927 tgl                       855 CBC           6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
 4927 tgl                       856 GIC           6 :                 objects = list_concat(objects, objs);
 4927 tgl                       857 CBC           6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
 4927 tgl                       858 GIC           6 :                 objects = list_concat(objects, objs);
 3689 kgrittn                   859               6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
 3689 kgrittn                   860 CBC           6 :                 objects = list_concat(objects, objs);
 4481 rhaas                     861 GIC           6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
 4481 rhaas                     862 CBC           6 :                 objects = list_concat(objects, objs);
 2314 rhaas                     863 GIC           6 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE);
                                864               6 :                 objects = list_concat(objects, objs);
 4927 tgl                       865               6 :                 break;
 2006 peter_e                   866 LBC           0 :             case OBJECT_SEQUENCE:
 4927 tgl                       867 UIC           0 :                 objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
 4927 tgl                       868 LBC           0 :                 objects = list_concat(objects, objs);
 4927 tgl                       869 UIC           0 :                 break;
 2006 peter_e                   870 CBC           9 :             case OBJECT_FUNCTION:
 2006 peter_e                   871 ECB             :             case OBJECT_PROCEDURE:
                                872                 :             case OBJECT_ROUTINE:
 4927 tgl                       873                 :                 {
 1956 peter_e                   874                 :                     ScanKeyData key[2];
                                875                 :                     int         keycount;
 4927 tgl                       876                 :                     Relation    rel;
 1490 andres                    877                 :                     TableScanDesc scan;
 4927 tgl                       878                 :                     HeapTuple   tuple;
                                879                 : 
 1956 peter_e                   880 CBC           9 :                     keycount = 0;
                                881               9 :                     ScanKeyInit(&key[keycount++],
 4927 tgl                       882 EUB             :                                 Anum_pg_proc_pronamespace,
                                883                 :                                 BTEqualStrategyNumber, F_OIDEQ,
                                884                 :                                 ObjectIdGetDatum(namespaceId));
                                885                 : 
 2006 peter_e                   886 CBC           9 :                     if (objtype == OBJECT_FUNCTION)
                                887                 :                         /* includes aggregates and window functions */
 1956 peter_e                   888 GIC           3 :                         ScanKeyInit(&key[keycount++],
                                889                 :                                     Anum_pg_proc_prokind,
                                890                 :                                     BTEqualStrategyNumber, F_CHARNE,
                                891                 :                                     CharGetDatum(PROKIND_PROCEDURE));
 2006                           892               6 :                     else if (objtype == OBJECT_PROCEDURE)
 1956                           893               3 :                         ScanKeyInit(&key[keycount++],
                                894                 :                                     Anum_pg_proc_prokind,
                                895                 :                                     BTEqualStrategyNumber, F_CHAREQ,
 1864 peter_e                   896 ECB             :                                     CharGetDatum(PROKIND_PROCEDURE));
 1956                           897                 : 
 1539 andres                    898 GIC           9 :                     rel = table_open(ProcedureRelationId, AccessShareLock);
 1490                           899               9 :                     scan = table_beginscan_catalog(rel, keycount, key);
                                900                 : 
 4927 tgl                       901              27 :                     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 4927 tgl                       902 ECB             :                     {
 1418 tgl                       903 GIC          18 :                         Oid         oid = ((Form_pg_proc) GETSTRUCT(tuple))->oid;
 1601 andres                    904 ECB             : 
 1601 andres                    905 GIC          18 :                         objects = lappend_oid(objects, oid);
                                906                 :                     }
                                907                 : 
 1490 andres                    908 CBC           9 :                     table_endscan(scan);
 1539                           909               9 :                     table_close(rel, AccessShareLock);
                                910                 :                 }
 4927 tgl                       911 GIC           9 :                 break;
 4927 tgl                       912 UIC           0 :             default:
                                913                 :                 /* should not happen */
 4927 tgl                       914 LBC           0 :                 elog(ERROR, "unrecognized GrantStmt.objtype: %d",
 4927 tgl                       915 ECB             :                      (int) objtype);
                                916                 :         }
                                917                 :     }
                                918                 : 
 4927 tgl                       919 CBC          15 :     return objects;
                                920                 : }
 4927 tgl                       921 ECB             : 
                                922                 : /*
                                923                 :  * getRelationsInNamespace
                                924                 :  *
                                925                 :  * Return Oid list of relations in given namespace filtered by relation kind
                                926                 :  */
                                927                 : static List *
 4927 tgl                       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;
 4927 tgl                       935 ECB             : 
 4927 tgl                       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));
 4927 tgl                       944 ECB             : 
 1539 andres                    945 GIC          30 :     rel = table_open(RelationRelationId, AccessShareLock);
 1490 andres                    946 CBC          30 :     scan = table_beginscan_catalog(rel, 2, key);
                                947                 : 
 4927 tgl                       948 GIC          42 :     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
                                949                 :     {
 1418                           950              12 :         Oid         oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
                                951                 : 
 1601 andres                    952 CBC          12 :         relations = lappend_oid(relations, oid);
                                953                 :     }
                                954                 : 
 1490 andres                    955 GIC          30 :     table_endscan(scan);
 1539 andres                    956 CBC          30 :     table_close(rel, AccessShareLock);
                                957                 : 
 4927 tgl                       958 GIC          30 :     return relations;
                                959                 : }
                                960                 : 
 4927 tgl                       961 ECB             : 
 4934                           962                 : /*
                                963                 :  * ALTER DEFAULT PRIVILEGES statement
                                964                 :  */
                                965                 : void
 2406 peter_e                   966 CBC          80 : ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
                                967                 : {
 4934 tgl                       968              80 :     GrantStmt  *action = stmt->action;
                                969                 :     InternalDefaultACL iacls;
                                970                 :     ListCell   *cell;
 2953 alvherre                  971              80 :     List       *rolespecs = NIL;
 4934 tgl                       972              80 :     List       *nspnames = NIL;
 2953 alvherre                  973 GIC          80 :     DefElem    *drolespecs = NULL;
 4934 tgl                       974 CBC          80 :     DefElem    *dnspnames = NULL;
                                975                 :     AclMode     all_privileges;
                                976                 :     const char *errormsg;
                                977                 : 
                                978                 :     /* Deconstruct the "options" part of the statement */
 4934 tgl                       979 GIC         141 :     foreach(cell, stmt->options)
                                980                 :     {
                                981              61 :         DefElem    *defel = (DefElem *) lfirst(cell);
 4934 tgl                       982 ECB             : 
 4934 tgl                       983 GIC          61 :         if (strcmp(defel->defname, "schemas") == 0)
 4934 tgl                       984 ECB             :         {
 4934 tgl                       985 GIC          27 :             if (dnspnames)
  633 dean.a.rasheed            986 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 4934 tgl                       987 CBC          27 :             dnspnames = defel;
 4934 tgl                       988 ECB             :         }
 4934 tgl                       989 CBC          34 :         else if (strcmp(defel->defname, "roles") == 0)
 4934 tgl                       990 ECB             :         {
 2953 alvherre                  991 GIC          34 :             if (drolespecs)
  633 dean.a.rasheed            992 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 2953 alvherre                  993 GIC          34 :             drolespecs = defel;
                                994                 :         }
 4934 tgl                       995 ECB             :         else
 4934 tgl                       996 UIC           0 :             elog(ERROR, "option \"%s\" not recognized", defel->defname);
 4934 tgl                       997 ECB             :     }
                                998                 : 
 4934 tgl                       999 CBC          80 :     if (dnspnames)
 4934 tgl                      1000 GIC          27 :         nspnames = (List *) dnspnames->arg;
 2953 alvherre                 1001 CBC          80 :     if (drolespecs)
 2953 alvherre                 1002 GBC          34 :         rolespecs = (List *) drolespecs->arg;
 4934 tgl                      1003 ECB             : 
                               1004                 :     /* Prepare the InternalDefaultACL representation of the statement */
                               1005                 :     /* roleid to be filled below */
                               1006                 :     /* nspid to be filled in SetDefaultACLsInSchemas */
 4934 tgl                      1007 CBC          80 :     iacls.is_grant = action->is_grant;
 4934 tgl                      1008 GBC          80 :     iacls.objtype = action->objtype;
 4934 tgl                      1009 ECB             :     /* all_privs to be filled below */
                               1010                 :     /* privileges to be filled below */
 4934 tgl                      1011 GIC          80 :     iacls.grantees = NIL;       /* filled below */
 4934 tgl                      1012 GBC          80 :     iacls.grant_option = action->grant_option;
 4934 tgl                      1013 GIC          80 :     iacls.behavior = action->behavior;
                               1014                 : 
 4934 tgl                      1015 ECB             :     /*
 2878 bruce                    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
 2953 alvherre                 1018                 :      * there shouldn't be any additional work needed to support this case.
                               1019                 :      */
 4934 tgl                      1020 GIC         163 :     foreach(cell, action->grantees)
                               1021                 :     {
 2878 bruce                    1022              83 :         RoleSpec   *grantee = (RoleSpec *) lfirst(cell);
 2878 bruce                    1023 ECB             :         Oid         grantee_uid;
 4934 tgl                      1024                 : 
 2953 alvherre                 1025 GIC          83 :         switch (grantee->roletype)
                               1026                 :         {
 2953 alvherre                 1027 CBC          20 :             case ROLESPEC_PUBLIC:
                               1028              20 :                 grantee_uid = ACL_ID_PUBLIC;
                               1029              20 :                 break;
 2953 alvherre                 1030 GIC          63 :             default:
 2293 peter_e                  1031              63 :                 grantee_uid = get_rolespec_oid(grantee, false);
 2953 alvherre                 1032              63 :                 break;
                               1033                 :         }
                               1034              83 :         iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
                               1035                 :     }
 4934 tgl                      1036 ECB             : 
                               1037                 :     /*
 4790 bruce                    1038                 :      * Convert action->privileges, a list of privilege strings, into an
                               1039                 :      * AclMode bitmask.
                               1040                 :      */
 4934 tgl                      1041 CBC          80 :     switch (action->objtype)
                               1042                 :     {
 2006 peter_e                  1043              39 :         case OBJECT_TABLE:
 4934 tgl                      1044              39 :             all_privileges = ACL_ALL_RIGHTS_RELATION;
                               1045              39 :             errormsg = gettext_noop("invalid privilege type %s for relation");
                               1046              39 :             break;
 2006 peter_e                  1047               3 :         case OBJECT_SEQUENCE:
 4934 tgl                      1048               3 :             all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
 4934 tgl                      1049 GIC           3 :             errormsg = gettext_noop("invalid privilege type %s for sequence");
 4934 tgl                      1050 CBC           3 :             break;
 2006 peter_e                  1051 GIC          11 :         case OBJECT_FUNCTION:
 4934 tgl                      1052              11 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
                               1053              11 :             errormsg = gettext_noop("invalid privilege type %s for function");
                               1054              11 :             break;
 2006 peter_e                  1055 UIC           0 :         case OBJECT_PROCEDURE:
 1956                          1056               0 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
 1956 peter_e                  1057 LBC           0 :             errormsg = gettext_noop("invalid privilege type %s for procedure");
 1956 peter_e                  1058 UIC           0 :             break;
 2006 peter_e                  1059 LBC           0 :         case OBJECT_ROUTINE:
 1956                          1060               0 :             all_privileges = ACL_ALL_RIGHTS_FUNCTION;
                               1061               0 :             errormsg = gettext_noop("invalid privilege type %s for routine");
                               1062               0 :             break;
 2006 peter_e                  1063 CBC           9 :         case OBJECT_TYPE:
 4128                          1064               9 :             all_privileges = ACL_ALL_RIGHTS_TYPE;
                               1065               9 :             errormsg = gettext_noop("invalid privilege type %s for type");
                               1066               9 :             break;
 2006                          1067              18 :         case OBJECT_SCHEMA:
                               1068              18 :             all_privileges = ACL_ALL_RIGHTS_SCHEMA;
 2203 teodor                   1069              18 :             errormsg = gettext_noop("invalid privilege type %s for schema");
                               1070              18 :             break;
 4934 tgl                      1071 UBC           0 :         default:
                               1072               0 :             elog(ERROR, "unrecognized GrantStmt.objtype: %d",
 4934 tgl                      1073 EUB             :                  (int) action->objtype);
                               1074                 :             /* keep compiler quiet */
                               1075                 :             all_privileges = ACL_NO_RIGHTS;
                               1076                 :             errormsg = NULL;
                               1077                 :     }
                               1078                 : 
 4934 tgl                      1079 CBC          80 :     if (action->privileges == NIL)
 4934 tgl                      1080 ECB             :     {
 4934 tgl                      1081 CBC          28 :         iacls.all_privs = true;
 4934 tgl                      1082 ECB             : 
                               1083                 :         /*
                               1084                 :          * will be turned into ACL_ALL_RIGHTS_* by the internal routines
                               1085                 :          * depending on the object type
                               1086                 :          */
 4934 tgl                      1087 GBC          28 :         iacls.privileges = ACL_NO_RIGHTS;
 4934 tgl                      1088 EUB             :     }
                               1089                 :     else
                               1090                 :     {
 4934 tgl                      1091 GIC          52 :         iacls.all_privs = false;
                               1092              52 :         iacls.privileges = ACL_NO_RIGHTS;
                               1093                 : 
                               1094             104 :         foreach(cell, action->privileges)
 4934 tgl                      1095 ECB             :         {
 4934 tgl                      1096 GIC          52 :             AccessPriv *privnode = (AccessPriv *) lfirst(cell);
 4934 tgl                      1097 ECB             :             AclMode     priv;
                               1098                 : 
 4934 tgl                      1099 GIC          52 :             if (privnode->cols)
 4934 tgl                      1100 UIC           0 :                 ereport(ERROR,
                               1101                 :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                               1102                 :                          errmsg("default privileges cannot be set for columns")));
 4934 tgl                      1103 ECB             : 
 4934 tgl                      1104 GIC          52 :             if (privnode->priv_name == NULL) /* parser mistake? */
 4934 tgl                      1105 UIC           0 :                 elog(ERROR, "AccessPriv node must specify privilege");
 4934 tgl                      1106 GIC          52 :             priv = string_to_privilege(privnode->priv_name);
 4934 tgl                      1107 ECB             : 
 4934 tgl                      1108 CBC          52 :             if (priv & ~((AclMode) all_privileges))
 4934 tgl                      1109 UIC           0 :                 ereport(ERROR,
 4934 tgl                      1110 ECB             :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                               1111                 :                          errmsg(errormsg, privilege_to_string(priv))));
                               1112                 : 
 4934 tgl                      1113 GIC          52 :             iacls.privileges |= priv;
                               1114                 :         }
 4934 tgl                      1115 ECB             :     }
 4934 tgl                      1116 EUB             : 
 2953 alvherre                 1117 GIC          80 :     if (rolespecs == NIL)
                               1118                 :     {
                               1119                 :         /* Set permissions for myself */
 4934 tgl                      1120 CBC          46 :         iacls.roleid = GetUserId();
 4934 tgl                      1121 EUB             : 
 4934 tgl                      1122 CBC          46 :         SetDefaultACLsInSchemas(&iacls, nspnames);
                               1123                 :     }
 4934 tgl                      1124 ECB             :     else
 4934 tgl                      1125 EUB             :     {
                               1126                 :         /* Look up the role OIDs and do permissions checks */
                               1127                 :         ListCell   *rolecell;
                               1128                 : 
 2953 alvherre                 1129 CBC          68 :         foreach(rolecell, rolespecs)
                               1130                 :         {
 2953 alvherre                 1131 GIC          34 :             RoleSpec   *rolespec = lfirst(rolecell);
                               1132                 : 
 2293 peter_e                  1133 CBC          34 :             iacls.roleid = get_rolespec_oid(rolespec, false);
                               1134                 : 
  202 rhaas                    1135 GNC          34 :             if (!has_privs_of_role(GetUserId(), iacls.roleid))
  202 rhaas                    1136 UNC           0 :                 ereport(ERROR,
                               1137                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1138                 :                          errmsg("permission denied to change default privileges")));
                               1139                 : 
 4934 tgl                      1140 GIC          34 :             SetDefaultACLsInSchemas(&iacls, nspnames);
                               1141                 :         }
 4934 tgl                      1142 ECB             :     }
 4934 tgl                      1143 GIC          77 : }
 4934 tgl                      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
 4934 tgl                      1149 EUB             :  */
                               1150                 : static void
 4934 tgl                      1151 GIC          80 : SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
                               1152                 : {
 4934 tgl                      1153 CBC          80 :     if (nspnames == NIL)
                               1154                 :     {
                               1155                 :         /* Set database-wide permissions if no schema was specified */
                               1156              53 :         iacls->nspid = InvalidOid;
                               1157                 : 
 4934 tgl                      1158 GIC          53 :         SetDefaultACL(iacls);
                               1159                 :     }
                               1160                 :     else
                               1161                 :     {
                               1162                 :         /* Look up the schema OIDs and set permissions for each one */
                               1163                 :         ListCell   *nspcell;
 4934 tgl                      1164 ECB             : 
 4934 tgl                      1165 GIC          54 :         foreach(nspcell, nspnames)
 4934 tgl                      1166 ECB             :         {
 4934 tgl                      1167 GIC          30 :             char       *nspname = strVal(lfirst(nspcell));
                               1168                 : 
 4630 rhaas                    1169 CBC          30 :             iacls->nspid = get_namespace_oid(nspname, false);
                               1170                 : 
 3591 tgl                      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                 :              */
 4934                          1182                 : 
 4934 tgl                      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;
 4934 tgl                      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                 : 
 1539 andres                   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                 :      */
 4752 tgl                      1217              98 :     if (!OidIsValid(iacls->nspid))
                               1218              68 :         def_acl = acldefault(iacls->objtype, iacls->roleid);
 4752 tgl                      1219 ECB             :     else
 4752 tgl                      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                 :      */
 4934                          1226              98 :     switch (iacls->objtype)
 4934 tgl                      1227 ECB             :     {
 2006 peter_e                  1228 CBC          45 :         case OBJECT_TABLE:
 4934 tgl                      1229 GIC          45 :             objtype = DEFACLOBJ_RELATION;
 4934 tgl                      1230 CBC          45 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
 4934 tgl                      1231 GIC          13 :                 this_privileges = ACL_ALL_RIGHTS_RELATION;
                               1232              45 :             break;
                               1233                 : 
 2006 peter_e                  1234               6 :         case OBJECT_SEQUENCE:
 4934 tgl                      1235               6 :             objtype = DEFACLOBJ_SEQUENCE;
 4934 tgl                      1236 CBC           6 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
 4934 tgl                      1237 GIC           6 :                 this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
 4934 tgl                      1238 CBC           6 :             break;
 4934 tgl                      1239 ECB             : 
 2006 peter_e                  1240 CBC          14 :         case OBJECT_FUNCTION:
 4934 tgl                      1241              14 :             objtype = DEFACLOBJ_FUNCTION;
                               1242              14 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
 4934 tgl                      1243 GIC           6 :                 this_privileges = ACL_ALL_RIGHTS_FUNCTION;
 4934 tgl                      1244 CBC          14 :             break;
 4934 tgl                      1245 ECB             : 
 2006 peter_e                  1246 CBC          12 :         case OBJECT_TYPE:
 4128                          1247              12 :             objtype = DEFACLOBJ_TYPE;
                               1248              12 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
 4128 peter_e                  1249 GIC           6 :                 this_privileges = ACL_ALL_RIGHTS_TYPE;
 4128 peter_e                  1250 CBC          12 :             break;
 4128 peter_e                  1251 ECB             : 
 2006 peter_e                  1252 CBC          21 :         case OBJECT_SCHEMA:
 2203 teodor                   1253              21 :             if (OidIsValid(iacls->nspid))
                               1254               3 :                 ereport(ERROR,
                               1255                 :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
 2203 teodor                   1256 ECB             :                          errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS")));
 2203 teodor                   1257 CBC          18 :             objtype = DEFACLOBJ_NAMESPACE;
                               1258              18 :             if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
 2006 peter_e                  1259              12 :                 this_privileges = ACL_ALL_RIGHTS_SCHEMA;
 2203 teodor                   1260              18 :             break;
                               1261                 : 
 4934 tgl                      1262 LBC           0 :         default:
  152 peter                    1263 UNC           0 :             elog(ERROR, "unrecognized object type: %d",
 4934 tgl                      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 */
 4802 rhaas                    1270 CBC          95 :     tuple = SearchSysCache3(DEFACLROLENSPOBJ,
                               1271                 :                             ObjectIdGetDatum(iacls->roleid),
 4802 rhaas                    1272 EUB             :                             ObjectIdGetDatum(iacls->nspid),
 4790 bruce                    1273                 :                             CharGetDatum(objtype));
                               1274                 : 
 4934 tgl                      1275 GIC          95 :     if (HeapTupleIsValid(tuple))
                               1276                 :     {
                               1277                 :         Datum       aclDatum;
                               1278                 :         bool        isNull;
                               1279                 : 
 4934 tgl                      1280 CBC          36 :         aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
                               1281                 :                                    Anum_pg_default_acl_defaclacl,
                               1282                 :                                    &isNull);
 4934 tgl                      1283 GIC          36 :         if (!isNull)
                               1284              36 :             old_acl = DatumGetAclPCopy(aclDatum);
 4934 tgl                      1285 ECB             :         else
 4752 tgl                      1286 UIC           0 :             old_acl = NULL;     /* this case shouldn't happen, probably */
 4934 tgl                      1287 GIC          36 :         isNew = false;
                               1288                 :     }
                               1289                 :     else
 4934 tgl                      1290 ECB             :     {
 4934 tgl                      1291 GIC          59 :         old_acl = NULL;
                               1292              59 :         isNew = true;
 4934 tgl                      1293 ECB             :     }
                               1294                 : 
 4752 tgl                      1295 GIC          95 :     if (old_acl != NULL)
 4752 tgl                      1296 EUB             :     {
 4752 tgl                      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                 :          */
 4752 tgl                      1302 CBC          36 :         noldmembers = aclmembers(old_acl, &oldmembers);
                               1303                 :     }
                               1304                 :     else
 4934 tgl                      1305 ECB             :     {
                               1306                 :         /* If no or null entry, start with the default ACL value */
 4752 tgl                      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                 :     }
 4934 tgl                      1312 ECB             : 
                               1313                 :     /*
                               1314                 :      * Generate new ACL.  Grantor of rights is always the same as the target
                               1315                 :      * role.
                               1316                 :      */
 4934 tgl                      1317 CBC          95 :     new_acl = merge_acl_with_grant(old_acl,
 4934 tgl                      1318 GIC          95 :                                    iacls->is_grant,
 4934 tgl                      1319 CBC          95 :                                    iacls->grant_option,
 4934 tgl                      1320 ECB             :                                    iacls->behavior,
                               1321                 :                                    iacls->grantees,
                               1322                 :                                    this_privileges,
                               1323                 :                                    iacls->roleid,
                               1324                 :                                    iacls->roleid);
                               1325                 : 
                               1326                 :     /*
 4752                          1327                 :      * If the result is the same as the default value, we do not need an
 4660 bruce                    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                 :      */
 4752 tgl                      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                 :             /*
 4752 tgl                      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                 :              */
 4752 tgl                      1345 GIC          27 :             myself.classId = DefaultAclRelationId;
 1601 andres                   1346 CBC          27 :             myself.objectId = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
 4752 tgl                      1347 GIC          27 :             myself.objectSubId = 0;
                               1348                 : 
 4091 rhaas                    1349              27 :             performDeletion(&myself, DROP_RESTRICT, 0);
                               1350                 :         }
                               1351                 :     }
                               1352                 :     else
                               1353                 :     {
  267 peter                    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;
 1601 andres                   1358 ECB             : 
 4752 tgl                      1359 GIC          67 :         if (isNew)
                               1360                 :         {
                               1361                 :             /* insert new entry */
 1601 andres                   1362 CBC          58 :             defAclOid = GetNewOidWithIndex(rel, DefaultAclOidIndexId,
 1601 andres                   1363 ECB             :                                            Anum_pg_default_acl_oid);
 1601 andres                   1364 CBC          58 :             values[Anum_pg_default_acl_oid - 1] = ObjectIdGetDatum(defAclOid);
 4752 tgl                      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);
 4752 tgl                      1367 CBC          58 :             values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
 4752 tgl                      1368 GIC          58 :             values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
                               1369                 : 
 4752 tgl                      1370 CBC          58 :             newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
 2259 alvherre                 1371 GIC          58 :             CatalogTupleInsert(rel, newtuple);
 4752 tgl                      1372 ECB             :         }
                               1373                 :         else
                               1374                 :         {
 1601 andres                   1375 CBC           9 :             defAclOid = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
 1601 andres                   1376 ECB             : 
                               1377                 :             /* update existing entry */
 4752 tgl                      1378 CBC           9 :             values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
                               1379               9 :             replaces[Anum_pg_default_acl_defaclacl - 1] = true;
                               1380                 : 
 4752 tgl                      1381 GIC           9 :             newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
                               1382                 :                                          values, nulls, replaces);
 2259 alvherre                 1383 CBC           9 :             CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
                               1384                 :         }
                               1385                 : 
 4752 tgl                      1386 ECB             :         /* these dependencies don't change in an update */
 4752 tgl                      1387 CBC          67 :         if (isNew)
                               1388                 :         {
 4752 tgl                      1389 ECB             :             /* dependency on role */
 1601 andres                   1390 GIC          58 :             recordDependencyOnOwner(DefaultAclRelationId, defAclOid,
 4752 tgl                      1391 ECB             :                                     iacls->roleid);
                               1392                 : 
                               1393                 :             /* dependency on namespace */
 4752 tgl                      1394 GIC          58 :             if (OidIsValid(iacls->nspid))
 4752 tgl                      1395 ECB             :             {
                               1396                 :                 ObjectAddress myself,
                               1397                 :                             referenced;
 4934                          1398                 : 
 4752 tgl                      1399 GIC          17 :                 myself.classId = DefaultAclRelationId;
 1601 andres                   1400              17 :                 myself.objectId = defAclOid;
 4752 tgl                      1401              17 :                 myself.objectSubId = 0;
 4934 tgl                      1402 ECB             : 
 4752 tgl                      1403 GIC          17 :                 referenced.classId = NamespaceRelationId;
                               1404              17 :                 referenced.objectId = iacls->nspid;
                               1405              17 :                 referenced.objectSubId = 0;
                               1406                 : 
 4752 tgl                      1407 CBC          17 :                 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
 4752 tgl                      1408 ECB             :             }
                               1409                 :         }
                               1410                 : 
                               1411                 :         /*
                               1412                 :          * Update the shared dependency ACL info
                               1413                 :          */
 4752 tgl                      1414 GIC          67 :         nnewmembers = aclmembers(new_acl, &newmembers);
 4934 tgl                      1415 ECB             : 
 4752 tgl                      1416 GIC          67 :         updateAclDependencies(DefaultAclRelationId,
                               1417                 :                               defAclOid, 0,
                               1418                 :                               iacls->roleid,
                               1419                 :                               noldmembers, oldmembers,
                               1420                 :                               nnewmembers, newmembers);
                               1421                 : 
 3675 rhaas                    1422 CBC          67 :         if (isNew)
 1601 andres                   1423 GIC          58 :             InvokeObjectPostCreateHook(DefaultAclRelationId, defAclOid, 0);
 3675 rhaas                    1424 ECB             :         else
 1418 tgl                      1425 GIC           9 :             InvokeObjectPostAlterHook(DefaultAclRelationId, defAclOid, 0);
                               1426                 :     }
                               1427                 : 
 4934                          1428              95 :     if (HeapTupleIsValid(tuple))
                               1429              36 :         ReleaseSysCache(tuple);
 4934 tgl                      1430 ECB             : 
 1539 andres                   1431 CBC          95 :     table_close(rel, RowExclusiveLock);
                               1432                 : 
  809 michael                  1433 ECB             :     /* prevent error when processing duplicate objects */
  809 michael                  1434 GIC          95 :     CommandCounterIncrement();
 4934 tgl                      1435              95 : }
 4934 tgl                      1436 ECB             : 
                               1437                 : 
                               1438                 : /*
                               1439                 :  * RemoveRoleFromObjectACL
                               1440                 :  *
                               1441                 :  * Used by shdepDropOwned to remove mentions of a role in ACLs
                               1442                 :  */
                               1443                 : void
 4934 tgl                      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];
 4934 tgl                      1452 ECB             :         SysScanDesc scan;
                               1453                 :         HeapTuple   tuple;
                               1454                 : 
                               1455                 :         /* first fetch info needed by SetDefaultACL */
 1539 andres                   1456 GIC          15 :         rel = table_open(DefaultAclRelationId, AccessShareLock);
                               1457                 : 
 4934 tgl                      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,
 3568 rhaas                    1464 ECB             :                                   NULL, 1, skey);
                               1465                 : 
 4934 tgl                      1466 CBC          15 :         tuple = systable_getnext(scan);
                               1467                 : 
 4934 tgl                      1468 GIC          15 :         if (!HeapTupleIsValid(tuple))
 4934 tgl                      1469 UIC           0 :             elog(ERROR, "could not find tuple for default ACL %u", objid);
                               1470                 : 
 4934 tgl                      1471 CBC          15 :         pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
                               1472                 : 
 4934 tgl                      1473 GIC          15 :         iacls.roleid = pg_default_acl_tuple->defaclrole;
 4934 tgl                      1474 CBC          15 :         iacls.nspid = pg_default_acl_tuple->defaclnamespace;
                               1475                 : 
                               1476              15 :         switch (pg_default_acl_tuple->defaclobjtype)
 4934 tgl                      1477 EUB             :         {
 4934 tgl                      1478 GIC           3 :             case DEFACLOBJ_RELATION:
 2006 peter_e                  1479 CBC           3 :                 iacls.objtype = OBJECT_TABLE;
 4934 tgl                      1480 GIC           3 :                 break;
 4372 rhaas                    1481 CBC           3 :             case DEFACLOBJ_SEQUENCE:
 2006 peter_e                  1482               3 :                 iacls.objtype = OBJECT_SEQUENCE;
 4934 tgl                      1483 GIC           3 :                 break;
 4934 tgl                      1484 CBC           3 :             case DEFACLOBJ_FUNCTION:
 2006 peter_e                  1485 GIC           3 :                 iacls.objtype = OBJECT_FUNCTION;
 4934 tgl                      1486 CBC           3 :                 break;
 3773                          1487               3 :             case DEFACLOBJ_TYPE:
 2006 peter_e                  1488               3 :                 iacls.objtype = OBJECT_TYPE;
 3773 tgl                      1489               3 :                 break;
 2203 teodor                   1490               3 :             case DEFACLOBJ_NAMESPACE:
 2006 peter_e                  1491               3 :                 iacls.objtype = OBJECT_SCHEMA;
 2203 teodor                   1492               3 :                 break;
 4934 tgl                      1493 LBC           0 :             default:
 4934 tgl                      1494 ECB             :                 /* Shouldn't get here */
 3773 tgl                      1495 LBC           0 :                 elog(ERROR, "unexpected default ACL type: %d",
 3773 tgl                      1496 ECB             :                      (int) pg_default_acl_tuple->defaclobjtype);
 4934                          1497                 :                 break;
                               1498                 :         }
                               1499                 : 
 4934 tgl                      1500 CBC          15 :         systable_endscan(scan);
 1539 andres                   1501 GBC          15 :         table_close(rel, AccessShareLock);
                               1502                 : 
 4934 tgl                      1503              15 :         iacls.is_grant = false;
 4934 tgl                      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;
 4934 tgl                      1508 CBC          15 :         iacls.behavior = DROP_CASCADE;
 4934 tgl                      1509 ECB             : 
                               1510                 :         /* Do it */
 4934 tgl                      1511 CBC          15 :         SetDefaultACL(&iacls);
 4934 tgl                      1512 ECB             :     }
                               1513                 :     else
                               1514                 :     {
                               1515                 :         InternalGrant istmt;
                               1516                 : 
 4934 tgl                      1517 GIC          90 :         switch (classid)
                               1518                 :         {
 4934 tgl                      1519 CBC          38 :             case RelationRelationId:
                               1520                 :                 /* it's OK to use TABLE for a sequence */
 2006 peter_e                  1521 GIC          38 :                 istmt.objtype = OBJECT_TABLE;
 4934 tgl                      1522              38 :                 break;
                               1523               4 :             case DatabaseRelationId:
 2006 peter_e                  1524               4 :                 istmt.objtype = OBJECT_DATABASE;
 4934 tgl                      1525 CBC           4 :                 break;
 4128 peter_e                  1526 UIC           0 :             case TypeRelationId:
 2006 peter_e                  1527 LBC           0 :                 istmt.objtype = OBJECT_TYPE;
 4128 peter_e                  1528 UIC           0 :                 break;
 4934 tgl                      1529 CBC          14 :             case ProcedureRelationId:
 2006 peter_e                  1530              14 :                 istmt.objtype = OBJECT_ROUTINE;
 4934 tgl                      1531              14 :                 break;
 4934 tgl                      1532 LBC           0 :             case LanguageRelationId:
 2006 peter_e                  1533               0 :                 istmt.objtype = OBJECT_LANGUAGE;
 4934 tgl                      1534 UBC           0 :                 break;
 4867 itagaki.takahiro         1535 GBC           9 :             case LargeObjectRelationId:
 2006 peter_e                  1536               9 :                 istmt.objtype = OBJECT_LARGEOBJECT;
 4867 itagaki.takahiro         1537 CBC           9 :                 break;
 4934 tgl                      1538               6 :             case NamespaceRelationId:
 2006 peter_e                  1539               6 :                 istmt.objtype = OBJECT_SCHEMA;
 4934 tgl                      1540 GBC           6 :                 break;
 4934 tgl                      1541 UBC           0 :             case TableSpaceRelationId:
 2006 peter_e                  1542               0 :                 istmt.objtype = OBJECT_TABLESPACE;
 4934 tgl                      1543 LBC           0 :                 break;
 4531 heikki.linnakangas       1544 CBC           6 :             case ForeignServerRelationId:
 2006 peter_e                  1545               6 :                 istmt.objtype = OBJECT_FOREIGN_SERVER;
 4531 heikki.linnakangas       1546               6 :                 break;
                               1547               1 :             case ForeignDataWrapperRelationId:
 2006 peter_e                  1548               1 :                 istmt.objtype = OBJECT_FDW;
 4531 heikki.linnakangas       1549 GBC           1 :                 break;
  368 tgl                      1550              12 :             case ParameterAclRelationId:
                               1551              12 :                 istmt.objtype = OBJECT_PARAMETER_ACL;
  368 tgl                      1552 CBC          12 :                 break;
 4934 tgl                      1553 LBC           0 :             default:
                               1554               0 :                 elog(ERROR, "unexpected object class %u", classid);
 4934 tgl                      1555 ECB             :                 break;
                               1556                 :         }
 4934 tgl                      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;
 4934 tgl                      1561 GBC          90 :         istmt.col_privs = NIL;
                               1562              90 :         istmt.grantees = list_make1_oid(roleid);
 4934 tgl                      1563 GIC          90 :         istmt.grant_option = false;
                               1564              90 :         istmt.behavior = DROP_CASCADE;
 4934 tgl                      1565 ECB             : 
 4934 tgl                      1566 CBC          90 :         ExecGrantStmt_oids(&istmt);
 4934 tgl                      1567 ECB             :     }
 4934 tgl                      1568 CBC         105 : }
 4934 tgl                      1569 ECB             : 
                               1570                 : 
 5190                          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
 5190 tgl                      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)
 5190 tgl                      1587 ECB             :     {
 5190 tgl                      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)
 5190 tgl                      1593 UIC           0 :             ereport(ERROR,
 5190 tgl                      1594 ECB             :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
                               1595                 :                      errmsg("column \"%s\" of relation \"%s\" does not exist",
                               1596                 :                             colname, get_rel_name(table_oid))));
 5190 tgl                      1597 GIC        5151 :         attnum -= FirstLowInvalidHeapAttributeNumber;
                               1598            5151 :         if (attnum <= 0 || attnum >= num_col_privileges)
 5050 bruce                    1599 LBC           0 :             elog(ERROR, "column number out of range");    /* safety check */
 5190 tgl                      1600 CBC        5151 :         col_privileges[attnum] |= this_privileges;
 5190 tgl                      1601 EUB             :     }
 5190 tgl                      1602 GIC         469 : }
                               1603                 : 
                               1604                 : /*
 5190 tgl                      1605 ECB             :  * expand_all_col_privileges
                               1606                 :  *
 5190 tgl                      1607 EUB             :  * OR the specified privilege(s) into per-column array entries for each valid
 5190 tgl                      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
 5190 tgl                      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);
 5190 tgl                      1620 CBC        4456 :     for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
 5190 tgl                      1621 GIC       74307 :          curr_att <= classForm->relnatts;
                               1622           69851 :          curr_att++)
                               1623                 :     {
                               1624                 :         HeapTuple   attTuple;
                               1625                 :         bool        isdropped;
                               1626                 : 
 5190 tgl                      1627 CBC       69851 :         if (curr_att == InvalidAttrNumber)
                               1628            4456 :             continue;
 5190 tgl                      1629 ECB             : 
                               1630                 :         /* Views don't have any system columns at all */
 5190 tgl                      1631 GIC       65395 :         if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
                               1632           14628 :             continue;
                               1633                 : 
 4802 rhaas                    1634           50767 :         attTuple = SearchSysCache2(ATTNUM,
 4802 rhaas                    1635 ECB             :                                    ObjectIdGetDatum(table_oid),
                               1636                 :                                    Int16GetDatum(curr_att));
 5190 tgl                      1637 GIC       50767 :         if (!HeapTupleIsValid(attTuple))
 5190 tgl                      1638 UIC           0 :             elog(ERROR, "cache lookup failed for attribute %d of relation %u",
 5190 tgl                      1639 ECB             :                  curr_att, table_oid);
                               1640                 : 
 5190 tgl                      1641 GIC       50767 :         isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
 5190 tgl                      1642 ECB             : 
 5190 tgl                      1643 GIC       50767 :         ReleaseSysCache(attTuple);
                               1644                 : 
 5190 tgl                      1645 ECB             :         /* ignore dropped columns */
 5190 tgl                      1646 GBC       50767 :         if (isdropped)
 5190 tgl                      1647 GIC           3 :             continue;
                               1648                 : 
 5190 tgl                      1649 CBC       50764 :         col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
                               1650                 :     }
                               1651            4456 : }
                               1652                 : 
                               1653                 : /*
 5190 tgl                      1654 ECB             :  *  This processes attributes, but expects to be called from
 1371 michael                  1655                 :  *  ExecGrant_Relation, not directly from ExecuteGrantStmt.
                               1656                 :  */
 5190 tgl                      1657                 : static void
 5190 tgl                      1658 GIC       55894 : ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
 5190 tgl                      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;
 5050 bruce                    1666                 :     Acl        *merged_acl;
                               1667                 :     Datum       aclDatum;
                               1668                 :     bool        isNull;
                               1669                 :     Oid         grantorId;
                               1670                 :     AclMode     avail_goptions;
                               1671                 :     bool        need_update;
                               1672                 :     HeapTuple   newtuple;
  267 peter                    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                 : 
 4802 rhaas                    1681 CBC       55894 :     attr_tuple = SearchSysCache2(ATTNUM,
 4802 rhaas                    1682 ECB             :                                  ObjectIdGetDatum(relOid),
                               1683                 :                                  Int16GetDatum(attnum));
 5190 tgl                      1684 GIC       55894 :     if (!HeapTupleIsValid(attr_tuple))
 5190 tgl                      1685 UIC           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
                               1686                 :              attnum, relOid);
 5190 tgl                      1687 GIC       55894 :     pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
                               1688                 : 
 5190 tgl                      1689 ECB             :     /*
                               1690                 :      * Get working copy of existing ACL. If there's no ACL, substitute the
                               1691                 :      * proper default.
                               1692                 :      */
 5190 tgl                      1693 GBC       55894 :     aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
                               1694                 :                                &isNull);
 5190 tgl                      1695 CBC       55894 :     if (isNull)
                               1696                 :     {
 2006 peter_e                  1697 GIC       55743 :         old_acl = acldefault(OBJECT_COLUMN, ownerId);
                               1698                 :         /* There are no old member roles according to the catalogs */
 4752 tgl                      1699           55743 :         noldmembers = 0;
                               1700           55743 :         oldmembers = NULL;
 4752 tgl                      1701 ECB             :     }
                               1702                 :     else
                               1703                 :     {
 5190 tgl                      1704 GIC         151 :         old_acl = DatumGetAclPCopy(aclDatum);
 4752 tgl                      1705 ECB             :         /* Get the roles mentioned in the existing ACL */
 4752 tgl                      1706 GIC         151 :         noldmembers = aclmembers(old_acl, &oldmembers);
 4752 tgl                      1707 ECB             :     }
 5190                          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
 5050 bruce                    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.)
 5190 tgl                      1714                 :      */
 5190 tgl                      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);
 5190 tgl                      1723 ECB             : 
                               1724                 :     /*
                               1725                 :      * Restrict the privileges to what we can actually grant, and emit the
 5050 bruce                    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 =
 5190 tgl                      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                 :     /*
 5190 tgl                      1741 ECB             :      * Generate new ACL.
                               1742                 :      */
 5190 tgl                      1743 GIC       55894 :     new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
                               1744           55894 :                                    istmt->grant_option,
                               1745                 :                                    istmt->behavior, istmt->grantees,
 5190 tgl                      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
 4752                          1751                 :      * shared dependency information.
                               1752                 :      */
 5190 tgl                      1753 GIC       55894 :     nnewmembers = aclmembers(new_acl, &newmembers);
                               1754                 : 
                               1755                 :     /* finished building new ACL value, now insert it */
                               1756                 : 
                               1757                 :     /*
 5050 bruce                    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                 :      */
 5190 tgl                      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                 :     }
 5190 tgl                      1769 ECB             :     else
                               1770                 :     {
 5190 tgl                      1771 CBC       50732 :         nulls[Anum_pg_attribute_attacl - 1] = true;
                               1772           50732 :         need_update = !isNull;
                               1773                 :     }
 5190 tgl                      1774 GIC       55894 :     replaces[Anum_pg_attribute_attacl - 1] = true;
                               1775                 : 
 5190 tgl                      1776 CBC       55894 :     if (need_update)
 5190 tgl                      1777 ECB             :     {
 5190 tgl                      1778 GIC        5208 :         newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
 5190 tgl                      1779 ECB             :                                      values, nulls, replaces);
                               1780                 : 
 2259 alvherre                 1781 CBC        5208 :         CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
                               1782                 : 
 2559 sfrost                   1783 ECB             :         /* Update initial privileges for extensions */
 2559 sfrost                   1784 GIC        5208 :         recordExtensionInitPriv(relOid, RelationRelationId, attnum,
                               1785            5208 :                                 ACL_NUM(new_acl) > 0 ? new_acl : NULL);
 2559 sfrost                   1786 ECB             : 
                               1787                 :         /* Update the shared dependency ACL info */
 5190 tgl                      1788 GIC        5208 :         updateAclDependencies(RelationRelationId, relOid, attnum,
 4752 tgl                      1789 ECB             :                               ownerId,
 5190                          1790                 :                               noldmembers, oldmembers,
                               1791                 :                               nnewmembers, newmembers);
                               1792                 :     }
                               1793                 : 
 5190 tgl                      1794 GIC       55894 :     pfree(new_acl);
                               1795                 : 
                               1796           55894 :     ReleaseSysCache(attr_tuple);
                               1797           55894 : }
                               1798                 : 
 6287 bruce                    1799 ECB             : /*
                               1800                 :  *  This processes both sequences and non-sequences.
                               1801                 :  */
 6348 alvherre                 1802                 : static void
 6338 alvherre                 1803 GIC       25114 : ExecGrant_Relation(InternalGrant *istmt)
                               1804                 : {
                               1805                 :     Relation    relation;
                               1806                 :     Relation    attRelation;
                               1807                 :     ListCell   *cell;
 6348 alvherre                 1808 ECB             : 
 1539 andres                   1809 GIC       25114 :     relation = table_open(RelationRelationId, RowExclusiveLock);
                               1810           25114 :     attRelation = table_open(AttributeRelationId, RowExclusiveLock);
                               1811                 : 
 6338 alvherre                 1812           50258 :     foreach(cell, istmt->objects)
                               1813                 :     {
 6348 alvherre                 1814 CBC       25147 :         Oid         relOid = lfirst_oid(cell);
 7974 peter_e                  1815 ECB             :         Datum       aclDatum;
                               1816                 :         Form_pg_class pg_class_tuple;
                               1817                 :         bool        isNull;
                               1818                 :         AclMode     this_privileges;
 5050 bruce                    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                 : 
 4802 rhaas                    1830 GIC       25147 :         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
 7974 peter_e                  1831           25147 :         if (!HeapTupleIsValid(tuple))
 7202 tgl                      1832 UIC           0 :             elog(ERROR, "cache lookup failed for relation %u", relOid);
 7974 peter_e                  1833 GIC       25147 :         pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
                               1834                 : 
 7202 tgl                      1835 ECB             :         /* Not sensible to grant on an index */
 1906 alvherre                 1836 CBC       25147 :         if (pg_class_tuple->relkind == RELKIND_INDEX ||
 1906 alvherre                 1837 GBC       25147 :             pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX)
 7202 tgl                      1838 LBC           0 :             ereport(ERROR,
                               1839                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                               1840                 :                      errmsg("\"%s\" is an index",
 6348 alvherre                 1841 ECB             :                             NameStr(pg_class_tuple->relname))));
 7974 peter_e                  1842                 : 
 6886 tgl                      1843 EUB             :         /* Composite types aren't tables either */
 6886 tgl                      1844 GIC       25147 :         if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
 6886 tgl                      1845 UIC           0 :             ereport(ERROR,
                               1846                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                               1847                 :                      errmsg("\"%s\" is a composite type",
                               1848                 :                             NameStr(pg_class_tuple->relname))));
 6347 bruce                    1849 ECB             : 
 6287 bruce                    1850 EUB             :         /* Used GRANT SEQUENCE on a non-sequence? */
 2006 peter_e                  1851 GIC       25147 :         if (istmt->objtype == OBJECT_SEQUENCE &&
 6287 bruce                    1852               6 :             pg_class_tuple->relkind != RELKIND_SEQUENCE)
 6287 bruce                    1853 UIC           0 :             ereport(ERROR,
                               1854                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                               1855                 :                      errmsg("\"%s\" is not a sequence",
 6287 bruce                    1856 ECB             :                             NameStr(pg_class_tuple->relname))));
                               1857                 : 
 4481 rhaas                    1858 EUB             :         /* Adjust the default permissions based on object type */
 6287 bruce                    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
 6287 bruce                    1864 CBC        4448 :                 this_privileges = ACL_ALL_RIGHTS_RELATION;
                               1865                 :         }
 6287 bruce                    1866 ECB             :         else
 6287 bruce                    1867 CBC       20664 :             this_privileges = istmt->privileges;
                               1868                 : 
 6287 bruce                    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
 6031                          1872                 :          * permissions.  The OR of table and sequence permissions were already
                               1873                 :          * checked.
                               1874                 :          */
 2006 peter_e                  1875 GIC       25147 :         if (istmt->objtype == OBJECT_TABLE)
                               1876                 :         {
 6287 bruce                    1877           25141 :             if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
                               1878                 :             {
                               1879                 :                 /*
 5190 tgl                      1880 ECB             :                  * For backward compatibility, just throw a warning for
                               1881                 :                  * invalid sequence permissions when using the non-sequence
                               1882                 :                  * GRANT syntax.
                               1883                 :                  */
 6287 bruce                    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
 6031 bruce                    1889 ECB             :                      * WARNING allows the command to continue.
                               1890                 :                      */
 6287 bruce                    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;
 6287 bruce                    1896 EUB             :                 }
                               1897                 :             }
                               1898                 :             else
                               1899                 :             {
 6287 bruce                    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
 6031 bruce                    1905 ECB             :                      * because we didn't in the combined TABLE | SEQUENCE
                               1906                 :                      * check.
                               1907                 :                      */
 6287 bruce                    1908 UIC           0 :                     ereport(ERROR,
                               1909                 :                             (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                               1910                 :                              errmsg("invalid privilege type %s for table",
                               1911                 :                                     "USAGE")));
                               1912                 :                 }
 6287 bruce                    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                 :          */
 5190 tgl                      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                 :         /*
 5190 tgl                      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                 :          */
 5190 tgl                      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,
 5190 tgl                      1937 ECB             :                                       col_privileges,
                               1938                 :                                       num_col_privileges);
 5190 tgl                      1939 GIC        4456 :             have_col_privileges = true;
 5190 tgl                      1940 ECB             :         }
                               1941                 : 
                               1942                 :         /*
                               1943                 :          * Get owner ID and working copy of existing ACL. If there's no ACL,
 6385 bruce                    1944                 :          * substitute the proper default.
                               1945                 :          */
 6886 tgl                      1946 GIC       25147 :         ownerId = pg_class_tuple->relowner;
 6390                          1947           25147 :         aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
                               1948                 :                                    &isNull);
                               1949           25147 :         if (isNull)
                               1950                 :         {
 4481 rhaas                    1951 CBC       23554 :             switch (pg_class_tuple->relkind)
 4481 rhaas                    1952 ECB             :             {
 4481 rhaas                    1953 GIC          40 :                 case RELKIND_SEQUENCE:
 2006 peter_e                  1954 CBC          40 :                     old_acl = acldefault(OBJECT_SEQUENCE, ownerId);
 4481 rhaas                    1955 GIC          40 :                     break;
 4481 rhaas                    1956 CBC       23514 :                 default:
 2006 peter_e                  1957 GIC       23514 :                     old_acl = acldefault(OBJECT_TABLE, ownerId);
 4481 rhaas                    1958 CBC       23514 :                     break;
 4481 rhaas                    1959 ECB             :             }
 4752 tgl                      1960                 :             /* There are no old member roles according to the catalogs */
 4752 tgl                      1961 CBC       23554 :             noldmembers = 0;
                               1962           23554 :             oldmembers = NULL;
 4752 tgl                      1963 ECB             :         }
                               1964                 :         else
                               1965                 :         {
 6390 tgl                      1966 CBC        1593 :             old_acl = DatumGetAclPCopy(aclDatum);
 4752 tgl                      1967 ECB             :             /* Get the roles mentioned in the existing ACL */
 4752 tgl                      1968 GIC        1593 :             noldmembers = aclmembers(old_acl, &oldmembers);
                               1969                 :         }
                               1970                 : 
 5190 tgl                      1971 ECB             :         /* Need an extra copy of original rel ACL for column handling */
 5190 tgl                      1972 GIC       25147 :         old_rel_acl = aclcopy(old_acl);
 6886 tgl                      1973 ECB             : 
                               1974                 :         /*
                               1975                 :          * Handle relation-level privileges, if any were specified
                               1976                 :          */
 5190 tgl                      1977 CBC       25147 :         if (this_privileges != ACL_NO_RIGHTS)
                               1978                 :         {
                               1979                 :             AclMode     avail_goptions;
                               1980                 :             Acl        *new_acl;
                               1981                 :             Oid         grantorId;
 5190 tgl                      1982 ECB             :             HeapTuple   newtuple;
  267 peter                    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;
 1954 peter_e                  1988 ECB             :             ObjectType  objtype;
 5190 tgl                      1989                 : 
                               1990                 :             /* Determine ID to do the grant as, and available grant options */
 5190 tgl                      1991 GIC       24684 :             select_best_grantor(GetUserId(), this_privileges,
                               1992                 :                                 old_acl, ownerId,
                               1993                 :                                 &grantorId, &avail_goptions);
                               1994                 : 
 4481 rhaas                    1995           24684 :             switch (pg_class_tuple->relkind)
 4481 rhaas                    1996 ECB             :             {
 4481 rhaas                    1997 GIC          76 :                 case RELKIND_SEQUENCE:
 1954 peter_e                  1998              76 :                     objtype = OBJECT_SEQUENCE;
 4481 rhaas                    1999              76 :                     break;
 4481 rhaas                    2000 CBC       24608 :                 default:
 1954 peter_e                  2001 GIC       24608 :                     objtype = OBJECT_TABLE;
 4481 rhaas                    2002 CBC       24608 :                     break;
 4481 rhaas                    2003 ECB             :             }
                               2004                 : 
 5190 tgl                      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 =
 5190 tgl                      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);
 5190 tgl                      2015 ECB             : 
                               2016                 :             /*
                               2017                 :              * Generate new ACL.
                               2018                 :              */
 5190 tgl                      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,
 5190 tgl                      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                 :              */
 5190 tgl                      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;
 5190 tgl                      2036 CBC       24681 :             values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
 5190 tgl                      2037 ECB             : 
 5190 tgl                      2038 GIC       24681 :             newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
 5190 tgl                      2039 ECB             :                                          values, nulls, replaces);
                               2040                 : 
 2259 alvherre                 2041 GIC       24681 :             CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
 5190 tgl                      2042 ECB             : 
                               2043                 :             /* Update initial privileges for extensions */
 2559 sfrost                   2044 GIC       24681 :             recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
 2559 sfrost                   2045 ECB             : 
                               2046                 :             /* Update the shared dependency ACL info */
 5190 tgl                      2047 GIC       24681 :             updateAclDependencies(RelationRelationId, relOid, 0,
 4752 tgl                      2048 ECB             :                                   ownerId,
                               2049                 :                                   noldmembers, oldmembers,
                               2050                 :                                   nnewmembers, newmembers);
                               2051                 : 
 5190 tgl                      2052 GIC       24681 :             pfree(new_acl);
 5190 tgl                      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                 :          */
 5190 tgl                      2060 GIC       25613 :         foreach(cell_colprivs, istmt->col_privs)
 5190 tgl                      2061 ECB             :         {
 5050 bruce                    2062 GIC         469 :             AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
 6485 tgl                      2063 ECB             : 
 5190 tgl                      2064 GIC         469 :             if (col_privs->priv_name == NULL)
 5190 tgl                      2065 CBC           9 :                 this_privileges = ACL_ALL_RIGHTS_COLUMN;
 5190 tgl                      2066 ECB             :             else
 5190 tgl                      2067 GIC         460 :                 this_privileges = string_to_privilege(col_privs->priv_name);
 7974 peter_e                  2068 ECB             : 
 5190 tgl                      2069 GIC         469 :             if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
 5190 tgl                      2070 LBC           0 :                 ereport(ERROR,
 5190 tgl                      2071 EUB             :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                               2072                 :                          errmsg("invalid privilege type %s for column",
                               2073                 :                                 privilege_to_string(this_privileges))));
                               2074                 : 
 5190 tgl                      2075 GIC         469 :             if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
 5190 tgl                      2076 LBC           0 :                 this_privileges & ~((AclMode) ACL_SELECT))
 5190 tgl                      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                 :                  */
 5190 tgl                      2083 UIC           0 :                 ereport(WARNING,
 5190 tgl                      2084 EUB             :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                               2085                 :                          errmsg("sequence \"%s\" only supports SELECT column privileges",
                               2086                 :                                 NameStr(pg_class_tuple->relname))));
                               2087                 : 
 5190 tgl                      2088 UIC           0 :                 this_privileges &= (AclMode) ACL_SELECT;
 5190 tgl                      2089 EUB             :             }
                               2090                 : 
 5190 tgl                      2091 GIC         469 :             expand_col_privileges(col_privs->cols, relOid,
 5190 tgl                      2092 ECB             :                                   this_privileges,
                               2093                 :                                   col_privileges,
                               2094                 :                                   num_col_privileges);
 5190 tgl                      2095 GIC         469 :             have_col_privileges = true;
 5190 tgl                      2096 ECB             :         }
                               2097                 : 
 5190 tgl                      2098 GIC       25144 :         if (have_col_privileges)
 5190 tgl                      2099 ECB             :         {
                               2100                 :             AttrNumber  i;
                               2101                 : 
 5190 tgl                      2102 GIC       88733 :             for (i = 0; i < num_col_privileges; i++)
 5190 tgl                      2103 ECB             :             {
 5190 tgl                      2104 GIC       83817 :                 if (col_privileges[i] == ACL_NO_RIGHTS)
 5190 tgl                      2105 CBC       27923 :                     continue;
                               2106           55894 :                 ExecGrant_Attribute(istmt,
 5190 tgl                      2107 ECB             :                                     relOid,
 5190 tgl                      2108 GIC       55894 :                                     NameStr(pg_class_tuple->relname),
 5190 tgl                      2109 CBC       55894 :                                     i + FirstLowInvalidHeapAttributeNumber,
 5190 tgl                      2110 ECB             :                                     ownerId,
 5190 tgl                      2111 GIC       55894 :                                     col_privileges[i],
 5190 tgl                      2112 ECB             :                                     attRelation,
                               2113                 :                                     old_rel_acl);
                               2114                 :             }
                               2115                 :         }
                               2116                 : 
 5190 tgl                      2117 GIC       25144 :         pfree(old_rel_acl);
 5190 tgl                      2118 CBC       25144 :         pfree(col_privileges);
 6485 tgl                      2119 ECB             : 
 6485 tgl                      2120 GIC       25144 :         ReleaseSysCache(tuple);
 6485 tgl                      2121 ECB             : 
                               2122                 :         /* prevent error when processing duplicate objects */
 6449 bruce                    2123 GIC       25144 :         CommandCounterIncrement();
 7974 peter_e                  2124 ECB             :     }
                               2125                 : 
 1539 andres                   2126 GIC       25111 :     table_close(attRelation, RowExclusiveLock);
 1539 andres                   2127 CBC       25111 :     table_close(relation, RowExclusiveLock);
 9770 scrappy                  2128           25111 : }
 9770 scrappy                  2129 ECB             : 
                               2130                 : static void
  117 peter                    2131 GNC       23681 : ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs,
                               2132                 :                  void (*object_check) (InternalGrant *istmt, HeapTuple tuple))
 7658 tgl                      2133 ECB             : {
                               2134                 :     int         cacheid;
                               2135                 :     Relation    relation;
                               2136                 :     ListCell   *cell;
                               2137                 : 
 6338 alvherre                 2138 GIC       23681 :     if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
  117 peter                    2139 GNC         231 :         istmt->privileges = default_privs;
                               2140                 : 
                               2141           23681 :     cacheid = get_object_catcache_oid(classid);
                               2142                 : 
                               2143           23681 :     relation = table_open(classid, RowExclusiveLock);
 5224 peter_e                  2144 ECB             : 
 5224 peter_e                  2145 GIC       47662 :     foreach(cell, istmt->objects)
 5224 peter_e                  2146 ECB             :     {
  117 peter                    2147 GNC       24008 :         Oid         objectid = lfirst_oid(cell);
                               2148                 :         Datum       aclDatum;
                               2149                 :         Datum       nameDatum;
 5224 peter_e                  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;
  117 peter                    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;
 5224 peter_e                  2165 ECB             :         Oid        *newmembers;
                               2166                 : 
  117 peter                    2167 GNC       24008 :         tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
 5224 peter_e                  2168 GIC       24008 :         if (!HeapTupleIsValid(tuple))
  117 peter                    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                 :          */
  117 peter                    2174 GNC       24008 :         if (object_check)
                               2175              74 :             object_check(istmt, tuple);
 5224 peter_e                  2176 ECB             : 
                               2177                 :         /*
 5224 peter_e                  2178 EUB             :          * Get owner ID and working copy of existing ACL. If there's no ACL,
                               2179                 :          * substitute the proper default.
                               2180                 :          */
   15 dgustafsson              2181 GNC       23999 :         ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
                               2182                 :                                                           tuple,
                               2183           23999 :                                                           get_object_attnum_owner(classid)));
  117 peter                    2184           23999 :         aclDatum = SysCacheGetAttr(cacheid,
                               2185                 :                                    tuple,
                               2186           23999 :                                    get_object_attnum_acl(classid),
                               2187                 :                                    &isNull);
 5224 peter_e                  2188 CBC       23999 :         if (isNull)
                               2189                 :         {
  117 peter                    2190 GNC       20613 :             old_acl = acldefault(get_object_type(classid, objectid), ownerId);
                               2191                 :             /* There are no old member roles according to the catalogs */
 4752 tgl                      2192 GIC       20613 :             noldmembers = 0;
                               2193           20613 :             oldmembers = NULL;
 4752 tgl                      2194 ECB             :         }
                               2195                 :         else
                               2196                 :         {
 5224 peter_e                  2197 CBC        3386 :             old_acl = DatumGetAclPCopy(aclDatum);
                               2198                 :             /* Get the roles mentioned in the existing ACL */
 4752 tgl                      2199            3386 :             noldmembers = aclmembers(old_acl, &oldmembers);
                               2200                 :         }
 5224 peter_e                  2201 ECB             : 
                               2202                 :         /* Determine ID to do the grant as, and available grant options */
 5224 peter_e                  2203 CBC       23999 :         select_best_grantor(GetUserId(), istmt->privileges,
                               2204                 :                             old_acl, ownerId,
 5224 peter_e                  2205 ECB             :                             &grantorId, &avail_goptions);
                               2206                 : 
   15 dgustafsson              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.
 5224 peter_e                  2213 ECB             :          */
                               2214                 :         this_privileges =
 5224 peter_e                  2215 CBC       47998 :             restrict_and_check_grant(istmt->is_grant, avail_goptions,
 5224 peter_e                  2216 GIC       23999 :                                      istmt->all_privs, istmt->privileges,
                               2217                 :                                      objectid, grantorId, get_object_type(classid, objectid),
  117 peter                    2218 GNC       23999 :                                      NameStr(*DatumGetName(nameDatum)),
 5190 tgl                      2219 ECB             :                                      0, NULL);
                               2220                 : 
                               2221                 :         /*
                               2222                 :          * Generate new ACL.
 5224 peter_e                  2223                 :          */
 5224 peter_e                  2224 CBC       23984 :         new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
 5224 peter_e                  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
 4752 tgl                      2231 ECB             :          * shared dependency information.
                               2232                 :          */
 5224 peter_e                  2233 GIC       23981 :         nnewmembers = aclmembers(new_acl, &newmembers);
 5224 peter_e                  2234 ECB             : 
                               2235                 :         /* finished building new ACL value, now insert it */
  117 peter                    2236 GNC       23981 :         replaces[get_object_attnum_acl(classid) - 1] = true;
                               2237           23981 :         values[get_object_attnum_acl(classid) - 1] = PointerGetDatum(new_acl);
                               2238                 : 
 5224 peter_e                  2239 GIC       23981 :         newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
                               2240                 :                                      nulls, replaces);
                               2241                 : 
 2259 alvherre                 2242           23981 :         CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
                               2243                 : 
                               2244                 :         /* Update initial privileges for extensions */
  117 peter                    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,
 5224 peter_e                  2252 ECB             :                               nnewmembers, newmembers);
                               2253                 : 
 5224 peter_e                  2254 GIC       23981 :         ReleaseSysCache(tuple);
 5224 peter_e                  2255 ECB             : 
 5224 peter_e                  2256 GIC       23981 :         pfree(new_acl);
                               2257                 : 
 5224 peter_e                  2258 ECB             :         /* prevent error when processing duplicate objects */
 5224 peter_e                  2259 GIC       23981 :         CommandCounterIncrement();
                               2260                 :     }
 5224 peter_e                  2261 ECB             : 
 1539 andres                   2262 GIC       23654 :     table_close(relation, RowExclusiveLock);
 5224 peter_e                  2263           23654 : }
 5224 peter_e                  2264 ECB             : 
                               2265                 : static void
  117 peter                    2266 GNC          21 : ExecGrant_Language_check(InternalGrant *istmt, HeapTuple tuple)
                               2267                 : {
                               2268                 :     Form_pg_language pg_language_tuple;
 5224 peter_e                  2269 ECB             : 
  117 peter                    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.")));
 5224 peter_e                  2279 GBC          18 : }
 5224 peter_e                  2280 EUB             : 
 7720                          2281                 : static void
  117 peter                    2282 GBC          37 : ExecGrant_Largeobject(InternalGrant *istmt)
 7720 peter_e                  2283 EUB             : {
 6348 alvherre                 2284                 :     Relation    relation;
 6348 alvherre                 2285 ECB             :     ListCell   *cell;
 7720 peter_e                  2286                 : 
 6338 alvherre                 2287 CBC          37 :     if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
  117 peter                    2288 GBC          22 :         istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
 7658 tgl                      2289 EUB             : 
  117 peter                    2290 GBC          37 :     relation = table_open(LargeObjectMetadataRelationId,
  117 peter                    2291 EUB             :                           RowExclusiveLock);
 7720 peter_e                  2292                 : 
 6338 alvherre                 2293 GBC          77 :     foreach(cell, istmt->objects)
 7720 peter_e                  2294 EUB             :     {
  117 peter                    2295 GBC          40 :         Oid         loid = lfirst_oid(cell);
  117 peter                    2296 EUB             :         Form_pg_largeobject_metadata form_lo_meta;
  117 peter                    2297 ECB             :         char        loname[NAMEDATALEN];
 7720 peter_e                  2298                 :         Datum       aclDatum;
                               2299                 :         bool        isNull;
 6390 tgl                      2300                 :         AclMode     avail_goptions;
 6886                          2301                 :         AclMode     this_privileges;
 7720 peter_e                  2302                 :         Acl        *old_acl;
 7720 peter_e                  2303 EUB             :         Acl        *new_acl;
 6385 bruce                    2304                 :         Oid         grantorId;
                               2305                 :         Oid         ownerId;
 7720 peter_e                  2306                 :         HeapTuple   newtuple;
  117 peter                    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};
 6485 tgl                      2310 ECB             :         int         noldmembers;
                               2311                 :         int         nnewmembers;
                               2312                 :         Oid        *oldmembers;
                               2313                 :         Oid        *newmembers;
  117 peter                    2314                 :         ScanKeyData entry[1];
                               2315                 :         SysScanDesc scan;
  117 peter                    2316 EUB             :         HeapTuple   tuple;
                               2317                 : 
                               2318                 :         /* There's no syscache for pg_largeobject_metadata */
  117 peter                    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);
 7720 peter_e                  2329              40 :         if (!HeapTupleIsValid(tuple))
  117 peter                    2330 UIC           0 :             elog(ERROR, "could not find tuple for large object %u", loid);
                               2331                 : 
  117 peter                    2332 GIC          40 :         form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
                               2333                 : 
 6390 tgl                      2334 EUB             :         /*
                               2335                 :          * Get owner ID and working copy of existing ACL. If there's no ACL,
                               2336                 :          * substitute the proper default.
 6390 tgl                      2337 ECB             :          */
  117 peter                    2338 GIC          40 :         ownerId = form_lo_meta->lomowner;
                               2339              40 :         aclDatum = heap_getattr(tuple,
                               2340                 :                                 Anum_pg_largeobject_metadata_lomacl,
                               2341                 :                                 RelationGetDescr(relation), &isNull);
 6390 tgl                      2342 CBC          40 :         if (isNull)
                               2343                 :         {
  117 peter                    2344              22 :             old_acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
                               2345                 :             /* There are no old member roles according to the catalogs */
 4752 tgl                      2346 GIC          22 :             noldmembers = 0;
                               2347              22 :             oldmembers = NULL;
 4752 tgl                      2348 ECB             :         }
 6390                          2349                 :         else
 4752                          2350                 :         {
 6390 tgl                      2351 GBC          18 :             old_acl = DatumGetAclPCopy(aclDatum);
 4752 tgl                      2352 EUB             :             /* Get the roles mentioned in the existing ACL */
 4752 tgl                      2353 GBC          18 :             noldmembers = aclmembers(old_acl, &oldmembers);
 4752 tgl                      2354 ECB             :         }
 6390                          2355                 : 
                               2356                 :         /* Determine ID to do the grant as, and available grant options */
 6338 alvherre                 2357 GBC          40 :         select_best_grantor(GetUserId(), istmt->privileges,
 6390 tgl                      2358 EUB             :                             old_acl, ownerId,
                               2359                 :                             &grantorId, &avail_goptions);
 7100                          2360                 : 
 6886                          2361                 :         /*
 6031 bruce                    2362                 :          * Restrict the privileges to what we can actually grant, and emit the
                               2363                 :          * standards-mandated warning and error messages.
 6886 tgl                      2364                 :          */
  117 peter                    2365 GBC          40 :         snprintf(loname, sizeof(loname), "large object %u", loid);
 6338 alvherre                 2366 EUB             :         this_privileges =
 6338 alvherre                 2367 GBC          40 :             restrict_and_check_grant(istmt->is_grant, avail_goptions,
                               2368              40 :                                      istmt->all_privs, istmt->privileges,
  117 peter                    2369 ECB             :                                      loid, grantorId, OBJECT_LARGEOBJECT,
                               2370                 :                                      loname, 0, NULL);
 7720 peter_e                  2371                 : 
                               2372                 :         /*
 6390 tgl                      2373                 :          * Generate new ACL.
 6485                          2374                 :          */
 6338 alvherre                 2375 GBC          40 :         new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
                               2376              40 :                                        istmt->grant_option, istmt->behavior,
 6338 alvherre                 2377 EUB             :                                        istmt->grantees, this_privileges,
 7100 tgl                      2378 ECB             :                                        grantorId, ownerId);
 7720 peter_e                  2379                 : 
 4752 tgl                      2380                 :         /*
                               2381                 :          * We need the members of both old and new ACLs so we can correct the
                               2382                 :          * shared dependency information.
                               2383                 :          */
 6485 tgl                      2384 CBC          40 :         nnewmembers = aclmembers(new_acl, &newmembers);
 6485 tgl                      2385 ECB             : 
 7720 peter_e                  2386                 :         /* finished building new ACL value, now insert it */
  117 peter                    2387 GBC          40 :         replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
  117 peter                    2388 EUB             :         values[Anum_pg_largeobject_metadata_lomacl - 1]
  117 peter                    2389 CBC          40 :             = PointerGetDatum(new_acl);
 7658 tgl                      2390 ECB             : 
  117 peter                    2391 CBC          40 :         newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
  117 peter                    2392 ECB             :                                      values, nulls, replaces);
 7720 peter_e                  2393                 : 
 2259 alvherre                 2394 CBC          40 :         CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
 7720 peter_e                  2395 ECB             : 
 2559 sfrost                   2396                 :         /* Update initial privileges for extensions */
  117 peter                    2397 CBC          40 :         recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
 2559 sfrost                   2398 ECB             : 
 6485 tgl                      2399                 :         /* Update the shared dependency ACL info */
  117 peter                    2400 CBC          40 :         updateAclDependencies(LargeObjectRelationId,
  117 peter                    2401 ECB             :                               form_lo_meta->oid, 0,
 4752 tgl                      2402                 :                               ownerId,
 6485                          2403                 :                               noldmembers, oldmembers,
 6485 tgl                      2404 EUB             :                               nnewmembers, newmembers);
                               2405                 : 
  117 peter                    2406 GBC          40 :         systable_endscan(scan);
 6485 tgl                      2407 ECB             : 
 7720 peter_e                  2408 CBC          40 :         pfree(new_acl);
 7720 peter_e                  2409 ECB             : 
 6449 bruce                    2410                 :         /* prevent error when processing duplicate objects */
 6449 bruce                    2411 CBC          40 :         CommandCounterIncrement();
 7720 peter_e                  2412 ECB             :     }
 6348 alvherre                 2413                 : 
 1539 andres                   2414 CBC          37 :     table_close(relation, RowExclusiveLock);
 7720 peter_e                  2415              37 : }
 7720 peter_e                  2416 ECB             : 
                               2417                 : static void
  117 peter                    2418 GNC          53 : ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple)
 7720 peter_e                  2419 ECB             : {
                               2420                 :     Form_pg_type pg_type_tuple;
  117 peter                    2421                 : 
  117 peter                    2422 GNC          53 :     pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
  117 peter                    2423 ECB             : 
  117 peter                    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.")));
  117 peter                    2429 ECB             : 
                               2430                 :     /* Used GRANT DOMAIN on a non-domain? */
  117 peter                    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))));
 4128 peter_e                  2437 GIC          47 : }
                               2438                 : 
                               2439                 : static void
  368 tgl                      2440              49 : ExecGrant_Parameter(InternalGrant *istmt)
                               2441                 : {
                               2442                 :     Relation    relation;
  368 tgl                      2443 ECB             :     ListCell   *cell;
                               2444                 : 
  368 tgl                      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;
  368 tgl                      2457 ECB             :         AclMode     avail_goptions;
                               2458                 :         AclMode     this_privileges;
                               2459                 :         Acl        *old_acl;
  368 tgl                      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                 : 
  368 tgl                      2469 GIC          68 :         tuple = SearchSysCache1(PARAMETERACLOID, ObjectIdGetDatum(parameterId));
                               2470              68 :         if (!HeapTupleIsValid(tuple))
  368 tgl                      2471 UIC           0 :             elog(ERROR, "cache lookup failed for parameter ACL %u",
                               2472                 :                  parameterId);
  368 tgl                      2473 ECB             : 
                               2474                 :         /* We'll need the GUC's name */
   15 dgustafsson              2475 GNC          68 :         nameDatum = SysCacheGetAttrNotNull(PARAMETERACLOID, tuple,
                               2476                 :                                            Anum_pg_parameter_acl_parname);
  368 tgl                      2477 GIC          68 :         parname = TextDatumGetCString(nameDatum);
                               2478                 : 
                               2479                 :         /* Treat all parameters as belonging to the bootstrap superuser. */
                               2480              68 :         ownerId = BOOTSTRAP_SUPERUSERID;
  368 tgl                      2481 ECB             : 
                               2482                 :         /*
                               2483                 :          * Get working copy of existing ACL. If there's no ACL, substitute the
                               2484                 :          * proper default.
                               2485                 :          */
  368 tgl                      2486 GIC          68 :         aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
                               2487                 :                                    Anum_pg_parameter_acl_paracl,
                               2488                 :                                    &isNull);
                               2489                 : 
  368 tgl                      2490 CBC          68 :         if (isNull)
                               2491                 :         {
                               2492              34 :             old_acl = acldefault(istmt->objtype, ownerId);
  368 tgl                      2493 ECB             :             /* There are no old member roles according to the catalogs */
  368 tgl                      2494 GIC          34 :             noldmembers = 0;
                               2495              34 :             oldmembers = NULL;
                               2496                 :         }
                               2497                 :         else
                               2498                 :         {
  368 tgl                      2499 CBC          34 :             old_acl = DatumGetAclPCopy(aclDatum);
                               2500                 :             /* Get the roles mentioned in the existing ACL */
                               2501              34 :             noldmembers = aclmembers(old_acl, &oldmembers);
                               2502                 :         }
  368 tgl                      2503 ECB             : 
                               2504                 :         /* Determine ID to do the grant as, and available grant options */
  368 tgl                      2505 GIC          68 :         select_best_grantor(GetUserId(), istmt->privileges,
  368 tgl                      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 =
  368 tgl                      2514 GIC          68 :             restrict_and_check_grant(istmt->is_grant, avail_goptions,
  368 tgl                      2515 CBC          68 :                                      istmt->all_privs, istmt->privileges,
                               2516                 :                                      parameterId, grantorId,
                               2517                 :                                      OBJECT_PARAMETER_ACL,
                               2518                 :                                      parname,
                               2519                 :                                      0, NULL);
  368 tgl                      2520 ECB             : 
                               2521                 :         /*
                               2522                 :          * Generate new ACL.
                               2523                 :          */
  368 tgl                      2524 GIC          68 :         new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
                               2525              68 :                                        istmt->grant_option, istmt->behavior,
  368 tgl                      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                 :          */
  368 tgl                      2533 GIC          68 :         nnewmembers = aclmembers(new_acl, &newmembers);
                               2534                 : 
                               2535                 :         /*
  368 tgl                      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                 :          */
  368 tgl                      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 */
  368 tgl                      2547 ECB             :             HeapTuple   newtuple;
  267 peter                    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                 : 
  368 tgl                      2552 GIC          39 :             replaces[Anum_pg_parameter_acl_paracl - 1] = true;
                               2553              39 :             values[Anum_pg_parameter_acl_paracl - 1] = PointerGetDatum(new_acl);
  368 tgl                      2554 ECB             : 
  368 tgl                      2555 CBC          39 :             newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
  368 tgl                      2556 ECB             :                                          values, nulls, replaces);
                               2557                 : 
  368 tgl                      2558 GIC          39 :             CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
  368 tgl                      2559 ECB             :         }
                               2560                 : 
                               2561                 :         /* Update initial privileges for extensions */
  368 tgl                      2562 GIC          68 :         recordExtensionInitPriv(parameterId, ParameterAclRelationId, 0,
                               2563                 :                                 new_acl);
                               2564                 : 
                               2565                 :         /* Update the shared dependency ACL info */
                               2566              68 :         updateAclDependencies(ParameterAclRelationId, parameterId, 0,
  368 tgl                      2567 ECB             :                               ownerId,
                               2568                 :                               noldmembers, oldmembers,
                               2569                 :                               nnewmembers, newmembers);
                               2570                 : 
  368 tgl                      2571 GIC          68 :         ReleaseSysCache(tuple);
                               2572              68 :         pfree(new_acl);
                               2573                 : 
                               2574                 :         /* prevent error when processing duplicate objects */
  368 tgl                      2575 CBC          68 :         CommandCounterIncrement();
  368 tgl                      2576 ECB             :     }
                               2577                 : 
  368 tgl                      2578 GIC          49 :     table_close(relation, RowExclusiveLock);
  368 tgl                      2579 CBC          49 : }
  368 tgl                      2580 ECB             : 
                               2581                 : 
                               2582                 : static AclMode
 6494 tgl                      2583 CBC       45208 : string_to_privilege(const char *privname)
                               2584                 : {
                               2585           45208 :     if (strcmp(privname, "insert") == 0)
 6494 tgl                      2586 GIC         111 :         return ACL_INSERT;
                               2587           45097 :     if (strcmp(privname, "select") == 0)
 6494 tgl                      2588 CBC       20424 :         return ACL_SELECT;
 6494 tgl                      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;
 5326                          2593           24190 :     if (strcmp(privname, "truncate") == 0)
                               2594              17 :         return ACL_TRUNCATE;
 6494                          2595           24173 :     if (strcmp(privname, "references") == 0)
 6494 tgl                      2596 CBC           7 :         return ACL_REFERENCES;
 6494 tgl                      2597 GIC       24166 :     if (strcmp(privname, "trigger") == 0)
                               2598               4 :         return ACL_TRIGGER;
 6494 tgl                      2599 CBC       24162 :     if (strcmp(privname, "execute") == 0)
 6494 tgl                      2600 GIC       22027 :         return ACL_EXECUTE;
                               2601            2135 :     if (strcmp(privname, "usage") == 0)
 6494 tgl                      2602 GBC         821 :         return ACL_USAGE;
                               2603            1314 :     if (strcmp(privname, "create") == 0)
 6494 tgl                      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)
 6494 tgl                      2608 LBC           0 :         return ACL_CREATE_TEMP;
 6188 tgl                      2609 GIC          56 :     if (strcmp(privname, "connect") == 0)
      bruce                    2610               3 :         return ACL_CONNECT;
  368 tgl                      2611 CBC          53 :     if (strcmp(privname, "set") == 0)
  368 tgl                      2612 GIC          25 :         return ACL_SET;
                               2613              28 :     if (strcmp(privname, "alter system") == 0)
  368 tgl                      2614 CBC          12 :         return ACL_ALTER_SYSTEM;
  117 jdavis                   2615 GNC          16 :     if (strcmp(privname, "maintain") == 0)
                               2616              16 :         return ACL_MAINTAIN;
 6060 tgl                      2617 LBC           0 :     if (strcmp(privname, "rule") == 0)
 6060 tgl                      2618 UIC           0 :         return 0;               /* ignore old RULE privileges */
 6494 tgl                      2619 LBC           0 :     ereport(ERROR,
                               2620                 :             (errcode(ERRCODE_SYNTAX_ERROR),
                               2621                 :              errmsg("unrecognized privilege type \"%s\"", privname)));
 6494 tgl                      2622 ECB             :     return 0;                   /* appease compiler */
                               2623                 : }
                               2624                 : 
 7658                          2625                 : static const char *
 7658 tgl                      2626 GIC          12 : privilege_to_string(AclMode privilege)
                               2627                 : {
                               2628              12 :     switch (privilege)
                               2629                 :     {
                               2630               3 :         case ACL_INSERT:
                               2631               3 :             return "INSERT";
 7658 tgl                      2632 UIC           0 :         case ACL_SELECT:
 7658 tgl                      2633 UBC           0 :             return "SELECT";
 7658 tgl                      2634 UIC           0 :         case ACL_UPDATE:
                               2635               0 :             return "UPDATE";
                               2636               0 :         case ACL_DELETE:
                               2637               0 :             return "DELETE";
 5326                          2638               0 :         case ACL_TRUNCATE:
                               2639               0 :             return "TRUNCATE";
 7658                          2640               0 :         case ACL_REFERENCES:
                               2641               0 :             return "REFERENCES";
 7658 tgl                      2642 UBC           0 :         case ACL_TRIGGER:
                               2643               0 :             return "TRIGGER";
 7658 tgl                      2644 UIC           0 :         case ACL_EXECUTE:
                               2645               0 :             return "EXECUTE";
 7658 tgl                      2646 GBC           9 :         case ACL_USAGE:
                               2647               9 :             return "USAGE";
 7658 tgl                      2648 UBC           0 :         case ACL_CREATE:
 7658 tgl                      2649 UIC           0 :             return "CREATE";
                               2650               0 :         case ACL_CREATE_TEMP:
                               2651               0 :             return "TEMP";
 6188 bruce                    2652               0 :         case ACL_CONNECT:
 6188 tgl                      2653 UBC           0 :             return "CONNECT";
  368 tgl                      2654 UIC           0 :         case ACL_SET:
                               2655               0 :             return "SET";
  368 tgl                      2656 UBC           0 :         case ACL_ALTER_SYSTEM:
  368 tgl                      2657 UIC           0 :             return "ALTER SYSTEM";
  117 jdavis                   2658 UNC           0 :         case ACL_MAINTAIN:
                               2659               0 :             return "MAINTAIN";
 7658 tgl                      2660 UIC           0 :         default:
 7202 tgl                      2661 UBC           0 :             elog(ERROR, "unrecognized privilege: %d", (int) privilege);
 7658 tgl                      2662 EUB             :     }
                               2663                 :     return NULL;                /* appease compiler */
                               2664                 : }
                               2665                 : 
                               2666                 : /*
 7652                          2667                 :  * Standardized reporting of aclcheck permissions failures.
                               2668                 :  *
                               2669                 :  * Note: we do not double-quote the %s's below, because many callers
 7191                          2670                 :  * supply strings that might be already quoted.
                               2671                 :  */
                               2672                 : void
 1954 peter_e                  2673 GBC        1165 : aclcheck_error(AclResult aclerr, ObjectType objtype,
 7191 tgl                      2674 EUB             :                const char *objectname)
                               2675                 : {
 7202 tgl                      2676 GBC        1165 :     switch (aclerr)
                               2677                 :     {
 7652 tgl                      2678 UBC           0 :         case ACLCHECK_OK:
                               2679                 :             /* no error, so return to caller */
 7652 tgl                      2680 UIC           0 :             break;
 7652 tgl                      2681 GIC         893 :         case ACLCHECK_NO_PRIV:
                               2682                 :             {
 1906                          2683             893 :                 const char *msg = "???";
                               2684                 : 
                               2685                 :                 switch (objtype)
                               2686                 :                 {
 1954 peter_e                  2687               3 :                     case OBJECT_AGGREGATE:
                               2688               3 :                         msg = gettext_noop("permission denied for aggregate %s");
                               2689               3 :                         break;
 1954 peter_e                  2690 UIC           0 :                     case OBJECT_COLLATION:
                               2691               0 :                         msg = gettext_noop("permission denied for collation %s");
                               2692               0 :                         break;
                               2693               0 :                     case OBJECT_COLUMN:
 1954 peter_e                  2694 LBC           0 :                         msg = gettext_noop("permission denied for column %s");
 1954 peter_e                  2695 UIC           0 :                         break;
                               2696               0 :                     case OBJECT_CONVERSION:
                               2697               0 :                         msg = gettext_noop("permission denied for conversion %s");
                               2698               0 :                         break;
 1954 peter_e                  2699 GIC           9 :                     case OBJECT_DATABASE:
                               2700               9 :                         msg = gettext_noop("permission denied for database %s");
                               2701               9 :                         break;
 1954 peter_e                  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:
 1954 peter_e                  2709 LBC           0 :                         msg = gettext_noop("permission denied for extension %s");
                               2710               0 :                         break;
 1954 peter_e                  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:
 1954 peter_e                  2715 CBC          10 :                         msg = gettext_noop("permission denied for foreign server %s");
 1954 peter_e                  2716 GIC          10 :                         break;
                               2717               1 :                     case OBJECT_FOREIGN_TABLE:
 1954 peter_e                  2718 CBC           1 :                         msg = gettext_noop("permission denied for foreign table %s");
 1954 peter_e                  2719 GIC           1 :                         break;
                               2720              50 :                     case OBJECT_FUNCTION:
                               2721              50 :                         msg = gettext_noop("permission denied for function %s");
                               2722              50 :                         break;
 1954 peter_e                  2723 LBC           0 :                     case OBJECT_INDEX:
 1954 peter_e                  2724 UIC           0 :                         msg = gettext_noop("permission denied for index %s");
                               2725               0 :                         break;
 1954 peter_e                  2726 GIC           4 :                     case OBJECT_LANGUAGE:
 1954 peter_e                  2727 CBC           4 :                         msg = gettext_noop("permission denied for language %s");
                               2728               4 :                         break;
 1954 peter_e                  2729 UBC           0 :                     case OBJECT_LARGEOBJECT:
 1954 peter_e                  2730 UIC           0 :                         msg = gettext_noop("permission denied for large object %s");
                               2731               0 :                         break;
                               2732               0 :                     case OBJECT_MATVIEW:
 1954 peter_e                  2733 LBC           0 :                         msg = gettext_noop("permission denied for materialized view %s");
 1954 peter_e                  2734 UIC           0 :                         break;
 1954 peter_e                  2735 LBC           0 :                     case OBJECT_OPCLASS:
 1954 peter_e                  2736 UIC           0 :                         msg = gettext_noop("permission denied for operator class %s");
                               2737               0 :                         break;
 1954 peter_e                  2738 LBC           0 :                     case OBJECT_OPERATOR:
 1954 peter_e                  2739 UIC           0 :                         msg = gettext_noop("permission denied for operator %s");
                               2740               0 :                         break;
 1954 peter_e                  2741 LBC           0 :                     case OBJECT_OPFAMILY:
                               2742               0 :                         msg = gettext_noop("permission denied for operator family %s");
 1954 peter_e                  2743 UIC           0 :                         break;
  368 tgl                      2744               0 :                     case OBJECT_PARAMETER_ACL:
                               2745               0 :                         msg = gettext_noop("permission denied for parameter %s");
                               2746               0 :                         break;
 1954 peter_e                  2747 LBC           0 :                     case OBJECT_POLICY:
 1954 peter_e                  2748 UIC           0 :                         msg = gettext_noop("permission denied for policy %s");
                               2749               0 :                         break;
 1954 peter_e                  2750 CBC           6 :                     case OBJECT_PROCEDURE:
 1954 peter_e                  2751 GIC           6 :                         msg = gettext_noop("permission denied for procedure %s");
                               2752               6 :                         break;
 1954 peter_e                  2753 LBC           0 :                     case OBJECT_PUBLICATION:
                               2754               0 :                         msg = gettext_noop("permission denied for publication %s");
 1954 peter_e                  2755 UIC           0 :                         break;
 1954 peter_e                  2756 LBC           0 :                     case OBJECT_ROUTINE:
 1954 peter_e                  2757 UIC           0 :                         msg = gettext_noop("permission denied for routine %s");
 1954 peter_e                  2758 LBC           0 :                         break;
 1954 peter_e                  2759 GIC           7 :                     case OBJECT_SCHEMA:
 1954 peter_e                  2760 CBC           7 :                         msg = gettext_noop("permission denied for schema %s");
 1954 peter_e                  2761 GIC           7 :                         break;
 1954 peter_e                  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");
 1954 peter_e                  2767 LBC           0 :                         break;
 1954 peter_e                  2768 UIC           0 :                     case OBJECT_SUBSCRIPTION:
                               2769               0 :                         msg = gettext_noop("permission denied for subscription %s");
                               2770               0 :                         break;
 1954 peter_e                  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;
 1954 peter_e                  2777 UIC           0 :                     case OBJECT_TSCONFIGURATION:
 1954 peter_e                  2778 LBC           0 :                         msg = gettext_noop("permission denied for text search configuration %s");
                               2779               0 :                         break;
 1954 peter_e                  2780 UIC           0 :                     case OBJECT_TSDICTIONARY:
                               2781               0 :                         msg = gettext_noop("permission denied for text search dictionary %s");
                               2782               0 :                         break;
 1954 peter_e                  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 */
 1954 peter_e                  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:
 1954 peter_e                  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:
 1954 peter_e                  2806 EUB             :                     case OBJECT_TSTEMPLATE:
                               2807                 :                     case OBJECT_USER_MAPPING:
  152 peter                    2808 UNC           0 :                         elog(ERROR, "unsupported object type: %d", objtype);
                               2809                 :                 }
                               2810                 : 
 1954 peter_e                  2811 GIC         893 :                 ereport(ERROR,
 1954 peter_e                  2812 ECB             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2813                 :                          errmsg(msg, objectname)));
 1954 peter_e                  2814 EUB             :                 break;
                               2815                 :             }
 7652 tgl                      2816 GIC         272 :         case ACLCHECK_NOT_OWNER:
                               2817                 :             {
 1906 tgl                      2818 CBC         272 :                 const char *msg = "???";
                               2819                 : 
 1954 peter_e                  2820 ECB             :                 switch (objtype)
                               2821                 :                 {
 1954 peter_e                  2822 CBC           3 :                     case OBJECT_AGGREGATE:
 1954 peter_e                  2823 GIC           3 :                         msg = gettext_noop("must be owner of aggregate %s");
                               2824               3 :                         break;
 1954 peter_e                  2825 LBC           0 :                     case OBJECT_COLLATION:
                               2826               0 :                         msg = gettext_noop("must be owner of collation %s");
 1954 peter_e                  2827 UIC           0 :                         break;
 1954 peter_e                  2828 GIC           9 :                     case OBJECT_CONVERSION:
                               2829               9 :                         msg = gettext_noop("must be owner of conversion %s");
                               2830               9 :                         break;
 1954 peter_e                  2831 LBC           0 :                     case OBJECT_DATABASE:
 1954 peter_e                  2832 UIC           0 :                         msg = gettext_noop("must be owner of database %s");
                               2833               0 :                         break;
 1954 peter_e                  2834 LBC           0 :                     case OBJECT_DOMAIN:
 1954 peter_e                  2835 UIC           0 :                         msg = gettext_noop("must be owner of domain %s");
                               2836               0 :                         break;
 1954 peter_e                  2837 LBC           0 :                     case OBJECT_EVENT_TRIGGER:
                               2838               0 :                         msg = gettext_noop("must be owner of event trigger %s");
 1954 peter_e                  2839 UIC           0 :                         break;
 1954 peter_e                  2840 LBC           0 :                     case OBJECT_EXTENSION:
 1954 peter_e                  2841 UIC           0 :                         msg = gettext_noop("must be owner of extension %s");
                               2842               0 :                         break;
 1954 peter_e                  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");
 1954 peter_e                  2848 CBC          57 :                         break;
 1954 peter_e                  2849 LBC           0 :                     case OBJECT_FOREIGN_TABLE:
                               2850               0 :                         msg = gettext_noop("must be owner of foreign table %s");
                               2851               0 :                         break;
 1954 peter_e                  2852 CBC          21 :                     case OBJECT_FUNCTION:
 1954 peter_e                  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:
 1954 peter_e                  2859 CBC           6 :                         msg = gettext_noop("must be owner of language %s");
 1954 peter_e                  2860 GIC           6 :                         break;
 1954 peter_e                  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;
 1954 peter_e                  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:
 1954 peter_e                  2871 CBC           9 :                         msg = gettext_noop("must be owner of operator %s");
                               2872               9 :                         break;
 1954 peter_e                  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:
 1954 peter_e                  2877 CBC           3 :                         msg = gettext_noop("must be owner of procedure %s");
                               2878               3 :                         break;
 1954 peter_e                  2879 GBC           3 :                     case OBJECT_PUBLICATION:
 1954 peter_e                  2880 GIC           3 :                         msg = gettext_noop("must be owner of publication %s");
                               2881               3 :                         break;
 1954 peter_e                  2882 UIC           0 :                     case OBJECT_ROUTINE:
 1954 peter_e                  2883 LBC           0 :                         msg = gettext_noop("must be owner of routine %s");
 1954 peter_e                  2884 UIC           0 :                         break;
 1954 peter_e                  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:
 1954 peter_e                  2889 CBC           3 :                         msg = gettext_noop("must be owner of subscription %s");
 1954 peter_e                  2890 GIC           3 :                         break;
 1954 peter_e                  2891 CBC          44 :                     case OBJECT_TABLE:
 1954 peter_e                  2892 GIC          44 :                         msg = gettext_noop("must be owner of table %s");
 1954 peter_e                  2893 CBC          44 :                         break;
 1954 peter_e                  2894 GIC           3 :                     case OBJECT_TYPE:
 1954 peter_e                  2895 CBC           3 :                         msg = gettext_noop("must be owner of type %s");
 1954 peter_e                  2896 GIC           3 :                         break;
 1954 peter_e                  2897 CBC           9 :                     case OBJECT_VIEW:
 1954 peter_e                  2898 GBC           9 :                         msg = gettext_noop("must be owner of view %s");
 1954 peter_e                  2899 CBC           9 :                         break;
 1954 peter_e                  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");
 1954 peter_e                  2905 CBC          18 :                         break;
 1954 peter_e                  2906 UIC           0 :                     case OBJECT_TABLESPACE:
 1954 peter_e                  2907 LBC           0 :                         msg = gettext_noop("must be owner of tablespace %s");
 1954 peter_e                  2908 UIC           0 :                         break;
 1954 peter_e                  2909 CBC           9 :                     case OBJECT_TSCONFIGURATION:
 1954 peter_e                  2910 GIC           9 :                         msg = gettext_noop("must be owner of text search configuration %s");
                               2911               9 :                         break;
 1954 peter_e                  2912 CBC           9 :                     case OBJECT_TSDICTIONARY:
                               2913               9 :                         msg = gettext_noop("must be owner of text search dictionary %s");
 1954 peter_e                  2914 GIC           9 :                         break;
                               2915                 : 
                               2916                 :                         /*
                               2917                 :                          * Special cases: For these, the error message talks
 1809 tgl                      2918 ECB             :                          * about "relation", because that's where the
                               2919                 :                          * ownership is attached.  See also
                               2920                 :                          * check_object_ownership().
                               2921                 :                          */
 1954 peter_e                  2922 GIC           9 :                     case OBJECT_COLUMN:
                               2923                 :                     case OBJECT_POLICY:
 1954 peter_e                  2924 ECB             :                     case OBJECT_RULE:
                               2925                 :                     case OBJECT_TABCONSTRAINT:
                               2926                 :                     case OBJECT_TRIGGER:
 1954 peter_e                  2927 CBC           9 :                         msg = gettext_noop("must be owner of relation %s");
 1954 peter_e                  2928 GIC           9 :                         break;
 1809 tgl                      2929 ECB             :                         /* these currently aren't used */
 1954 peter_e                  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:
 1954 peter_e                  2936 ECB             :                     case OBJECT_DEFACL:
                               2937                 :                     case OBJECT_DOMCONSTRAINT:
  368 tgl                      2938                 :                     case OBJECT_PARAMETER_ACL:
  529 akapila                  2939                 :                     case OBJECT_PUBLICATION_NAMESPACE:
                               2940                 :                     case OBJECT_PUBLICATION_REL:
 1954 peter_e                  2941                 :                     case OBJECT_ROLE:
                               2942                 :                     case OBJECT_TRANSFORM:
                               2943                 :                     case OBJECT_TSPARSER:
                               2944                 :                     case OBJECT_TSTEMPLATE:
                               2945                 :                     case OBJECT_USER_MAPPING:
  152 peter                    2946 UNC           0 :                         elog(ERROR, "unsupported object type: %d", objtype);
                               2947                 :                 }
                               2948                 : 
 1954 peter_e                  2949 GIC         272 :                 ereport(ERROR,
                               2950                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2951                 :                          errmsg(msg, objectname)));
                               2952                 :                 break;
                               2953                 :             }
 7652 tgl                      2954 UIC           0 :         default:
 7202 tgl                      2955 LBC           0 :             elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
                               2956                 :             break;
                               2957                 :     }
 7652                          2958               0 : }
                               2959                 : 
                               2960                 : 
                               2961                 : void
 1954 peter_e                  2962 UIC           0 : aclcheck_error_col(AclResult aclerr, ObjectType objtype,
                               2963                 :                    const char *objectname, const char *colname)
                               2964                 : {
 5190 tgl                      2965               0 :     switch (aclerr)
                               2966                 :     {
                               2967               0 :         case ACLCHECK_OK:
                               2968                 :             /* no error, so return to caller */
 5190 tgl                      2969 LBC           0 :             break;
 5190 tgl                      2970 UIC           0 :         case ACLCHECK_NO_PRIV:
                               2971               0 :             ereport(ERROR,
 5190 tgl                      2972 ECB             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2973                 :                      errmsg("permission denied for column \"%s\" of relation \"%s\"",
 2118                          2974                 :                             colname, objectname)));
                               2975                 :             break;
 5190 tgl                      2976 LBC           0 :         case ACLCHECK_NOT_OWNER:
                               2977                 :             /* relation msg is OK since columns don't have separate owners */
 1954 peter_e                  2978 UIC           0 :             aclcheck_error(aclerr, objtype, objectname);
 5190 tgl                      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
 3950 peter_e                  2992 GIC          57 : aclcheck_error_type(AclResult aclerr, Oid typeOid)
                               2993                 : {
 3602 bruce                    2994              57 :     Oid         element_type = get_element_type(typeOid);
                               2995                 : 
 1954 peter_e                  2996              57 :     aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
 3950 peter_e                  2997 UIC           0 : }
                               2998                 : 
 3950 peter_e                  2999 ECB             : 
                               3000                 : /*
                               3001                 :  * Relay for the various pg_*_mask routines depending on object kind
                               3002                 :  */
                               3003                 : static AclMode
  147 peter                    3004 GNC          33 : pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid,
                               3005                 :            AclMode mask, AclMaskHow how)
                               3006                 : {
 1954 peter_e                  3007 GIC          33 :     switch (objtype)
                               3008                 :     {
 1954 peter_e                  3009 UIC           0 :         case OBJECT_COLUMN:
                               3010                 :             return
  147 peter                    3011 UNC           0 :                 pg_class_aclmask(object_oid, roleid, mask, how) |
                               3012               0 :                 pg_attribute_aclmask(object_oid, attnum, roleid, mask, how);
 1954 peter_e                  3013 CBC           6 :         case OBJECT_TABLE:
 1954 peter_e                  3014 ECB             :         case OBJECT_SEQUENCE:
  147 peter                    3015 GNC           6 :             return pg_class_aclmask(object_oid, roleid, mask, how);
 1954 peter_e                  3016 LBC           0 :         case OBJECT_DATABASE:
  147 peter                    3017 UNC           0 :             return object_aclmask(DatabaseRelationId, object_oid, roleid, mask, how);
 1954 peter_e                  3018 LBC           0 :         case OBJECT_FUNCTION:
  147 peter                    3019 UNC           0 :             return object_aclmask(ProcedureRelationId, object_oid, roleid, mask, how);
 1954 peter_e                  3020 CBC           3 :         case OBJECT_LANGUAGE:
  147 peter                    3021 GNC           3 :             return object_aclmask(LanguageRelationId, object_oid, roleid, mask, how);
 1954 peter_e                  3022 UIC           0 :         case OBJECT_LARGEOBJECT:
  147 peter                    3023 UNC           0 :             return pg_largeobject_aclmask_snapshot(object_oid, roleid,
                               3024                 :                                                    mask, how, NULL);
  368 tgl                      3025 UIC           0 :         case OBJECT_PARAMETER_ACL:
  147 peter                    3026 UNC           0 :             return pg_parameter_acl_aclmask(object_oid, roleid, mask, how);
 1954 peter_e                  3027 UIC           0 :         case OBJECT_SCHEMA:
  147 peter                    3028 UNC           0 :             return object_aclmask(NamespaceRelationId, object_oid, roleid, mask, how);
 1954 peter_e                  3029 UIC           0 :         case OBJECT_STATISTIC_EXT:
 2156 tgl                      3030               0 :             elog(ERROR, "grantable rights not supported for statistics objects");
                               3031                 :             /* not reached, but keep compiler quiet */
                               3032                 :             return ACL_NO_RIGHTS;
 1954 peter_e                  3033 LBC           0 :         case OBJECT_TABLESPACE:
  147 peter                    3034 UNC           0 :             return object_aclmask(TableSpaceRelationId, object_oid, roleid, mask, how);
 1954 peter_e                  3035 GIC           9 :         case OBJECT_FDW:
  147 peter                    3036 GNC           9 :             return object_aclmask(ForeignDataWrapperRelationId, object_oid, roleid, mask, how);
 1954 peter_e                  3037 GBC           9 :         case OBJECT_FOREIGN_SERVER:
  147 peter                    3038 GNC           9 :             return object_aclmask(ForeignServerRelationId, object_oid, roleid, mask, how);
 1954 peter_e                  3039 UIC           0 :         case OBJECT_EVENT_TRIGGER:
 3917 rhaas                    3040 LBC           0 :             elog(ERROR, "grantable rights not supported for event triggers");
                               3041                 :             /* not reached, but keep compiler quiet */
 3917 rhaas                    3042 ECB             :             return ACL_NO_RIGHTS;
 1954 peter_e                  3043 CBC           6 :         case OBJECT_TYPE:
  147 peter                    3044 GNC           6 :             return object_aclmask(TypeRelationId, object_oid, roleid, mask, how);
 6338 alvherre                 3045 UIC           0 :         default:
  152 peter                    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                 :     }
 6338 alvherre                 3051 ECB             : }
 6524 tgl                      3052                 : 
                               3053                 : 
 5190                          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                 :  *
 7202                          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
 5190                          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
  147 peter                    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))
  147 peter                    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                 : 
   15 dgustafsson              3110 GNC       17251 :     ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
                               3111                 :                                                       tuple,
                               3112           17251 :                                                       get_object_attnum_owner(classid)));
                               3113                 : 
  147 peter                    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
 5190 tgl                      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
 5190 tgl                      3148 GIC          90 : pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid,
                               3149                 :                      AclMode mask, AclMaskHow how)
                               3150                 : {
  739 mail                     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                 :  *
  739 mail                     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
  739 mail                     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;
 5190 tgl                      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                 :      */
 4802 rhaas                    3178 GIC        2730 :     attTuple = SearchSysCache2(ATTNUM,
                               3179                 :                                ObjectIdGetDatum(table_oid),
                               3180                 :                                Int16GetDatum(attnum));
 5190 tgl                      3181            2730 :     if (!HeapTupleIsValid(attTuple))
                               3182                 :     {
  739 mail                     3183              15 :         if (is_missing != NULL)
                               3184                 :         {
  739 mail                     3185 ECB             :             /* return "no privileges" instead of throwing an error */
  739 mail                     3186 GIC          15 :             *is_missing = true;
  739 mail                     3187 CBC          15 :             return 0;
  739 mail                     3188 ECB             :         }
                               3189                 :         else
  739 mail                     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                 : 
 5190 tgl                      3196 GIC        2715 :     attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
 5190 tgl                      3197 ECB             : 
                               3198                 :     /* Check dropped columns, too */
 5190 tgl                      3199 GIC        2715 :     if (attributeForm->attisdropped)
  739 mail                     3200 ECB             :     {
  739 mail                     3201 GIC           6 :         if (is_missing != NULL)
  739 mail                     3202 ECB             :         {
                               3203                 :             /* return "no privileges" instead of throwing an error */
  739 mail                     3204 CBC           6 :             *is_missing = true;
  739 mail                     3205 GIC           6 :             ReleaseSysCache(attTuple);
                               3206               6 :             return 0;
                               3207                 :         }
                               3208                 :         else
  739 mail                     3209 UIC           0 :             ereport(ERROR,
                               3210                 :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
  739 mail                     3211 ECB             :                      errmsg("attribute %d of relation with OID %u does not exist",
                               3212                 :                             attnum, table_oid)));
                               3213                 :     }
                               3214                 : 
 5190 tgl                      3215 GIC        2709 :     aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
                               3216                 :                                &isNull);
 5190 tgl                      3217 ECB             : 
 5175                          3218                 :     /*
                               3219                 :      * Here we hard-wire knowledge that the default ACL for a column grants no
 5050 bruce                    3220                 :      * privileges, so that we can fall out quickly in the very common case
                               3221                 :      * where attacl is null.
                               3222                 :      */
 5190 tgl                      3223 GIC        2709 :     if (isNull)
                               3224                 :     {
 5175 tgl                      3225 CBC        1481 :         ReleaseSysCache(attTuple);
                               3226            1481 :         return 0;
 5190 tgl                      3227 EUB             :     }
                               3228                 : 
                               3229                 :     /*
                               3230                 :      * Must get the relation's ownerId from pg_class.  Since we already found
 5050 bruce                    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                 :      */
 4802 rhaas                    3237 GIC        1228 :     classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
 5175 tgl                      3238            1228 :     if (!HeapTupleIsValid(classTuple))
                               3239                 :     {
 5175 tgl                      3240 UIC           0 :         ReleaseSysCache(attTuple);
                               3241               0 :         return 0;
                               3242                 :     }
 5175 tgl                      3243 GIC        1228 :     classForm = (Form_pg_class) GETSTRUCT(classTuple);
                               3244                 : 
                               3245            1228 :     ownerId = classForm->relowner;
 5175 tgl                      3246 ECB             : 
 5175 tgl                      3247 GIC        1228 :     ReleaseSysCache(classTuple);
 5175 tgl                      3248 ECB             : 
                               3249                 :     /* detoast column's ACL if necessary */
 5175 tgl                      3250 GIC        1228 :     acl = DatumGetAclP(aclDatum);
                               3251                 : 
 5190                          3252            1228 :     result = aclmask(acl, roleid, ownerId, mask, how);
 5190 tgl                      3253 ECB             : 
                               3254                 :     /* if we have a detoasted copy, free it */
 5190 tgl                      3255 GIC        1228 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
                               3256            1228 :         pfree(acl);
 5190 tgl                      3257 ECB             : 
 5190 tgl                      3258 CBC        1228 :     ReleaseSysCache(attTuple);
 5190 tgl                      3259 EUB             : 
 5190 tgl                      3260 GIC        1228 :     return result;
                               3261                 : }
                               3262                 : 
 5190 tgl                      3263 ECB             : /*
                               3264                 :  * Exported routine for examining a user's privileges for a table
                               3265                 :  */
                               3266                 : AclMode
 6494 tgl                      3267 CBC      237909 : pg_class_aclmask(Oid table_oid, Oid roleid,
                               3268                 :                  AclMode mask, AclMaskHow how)
  739 mail                     3269 ECB             : {
  739 mail                     3270 CBC      237909 :     return pg_class_aclmask_ext(table_oid, roleid, mask, how, NULL);
                               3271                 : }
                               3272                 : 
  739 mail                     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
  739 mail                     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;
 8224 tgl                      3288 ECB             :     Acl        *acl;
                               3289                 :     Oid         ownerId;
 9345 bruce                    3290                 : 
                               3291                 :     /*
                               3292                 :      * Must get the relation's tuple from pg_class
                               3293                 :      */
 4802 rhaas                    3294 CBC     1090166 :     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
 7689 tgl                      3295         1090166 :     if (!HeapTupleIsValid(tuple))
                               3296                 :     {
  739 mail                     3297 LBC           0 :         if (is_missing != NULL)
  739 mail                     3298 ECB             :         {
                               3299                 :             /* return "no privileges" instead of throwing an error */
  739 mail                     3300 LBC           0 :             *is_missing = true;
                               3301               0 :             return 0;
                               3302                 :         }
  739 mail                     3303 ECB             :         else
  739 mail                     3304 UIC           0 :             ereport(ERROR,
                               3305                 :                     (errcode(ERRCODE_UNDEFINED_TABLE),
                               3306                 :                      errmsg("relation with OID %u does not exist",
  739 mail                     3307 ECB             :                             table_oid)));
                               3308                 :     }
                               3309                 : 
 7025 tgl                      3310 GIC     1090166 :     classForm = (Form_pg_class) GETSTRUCT(tuple);
                               3311                 : 
                               3312                 :     /*
 9345 bruce                    3313 ECB             :      * Deny anyone permission to update a system catalog unless
 1227 peter                    3314                 :      * pg_authid.rolsuper is set.
                               3315                 :      *
 6797 bruce                    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.
 9345                          3319                 :      */
 5326 tgl                      3320 CBC     1416751 :     if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
 3419 rhaas                    3321 GIC      326585 :         IsSystemClass(table_oid, classForm) &&
 7025 tgl                      3322 CBC        5461 :         classForm->relkind != RELKIND_VIEW &&
 1227 peter                    3323 GIC        5461 :         !superuser_arg(roleid))
 5326 tgl                      3324              35 :         mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE);
                               3325                 : 
                               3326                 :     /*
                               3327                 :      * Otherwise, superusers bypass all permission-checking.
                               3328                 :      */
 6494                          3329         1090166 :     if (superuser_arg(roleid))
                               3330                 :     {
 8179 tgl                      3331 CBC     1075559 :         ReleaseSysCache(tuple);
 6907 tgl                      3332 GIC     1075559 :         return mask;
 9345 bruce                    3333 ECB             :     }
                               3334                 : 
                               3335                 :     /*
 8224 tgl                      3336                 :      * Normal case: get the relation's ACL from pg_class
                               3337                 :      */
 6886 tgl                      3338 GIC       14607 :     ownerId = classForm->relowner;
                               3339                 : 
 7689                          3340           14607 :     aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
 8224 tgl                      3341 ECB             :                                &isNull);
 8224 tgl                      3342 GIC       14607 :     if (isNull)
                               3343                 :     {
                               3344                 :         /* No ACL, so build default ACL */
 4481 rhaas                    3345            2939 :         switch (classForm->relkind)
 4481 rhaas                    3346 ECB             :         {
 4481 rhaas                    3347 GIC          18 :             case RELKIND_SEQUENCE:
 2006 peter_e                  3348              18 :                 acl = acldefault(OBJECT_SEQUENCE, ownerId);
 4481 rhaas                    3349 CBC          18 :                 break;
                               3350            2921 :             default:
 2006 peter_e                  3351            2921 :                 acl = acldefault(OBJECT_TABLE, ownerId);
 4481 rhaas                    3352 GIC        2921 :                 break;
                               3353                 :         }
 7978 tgl                      3354 CBC        2939 :         aclDatum = (Datum) 0;
                               3355                 :     }
                               3356                 :     else
                               3357                 :     {
                               3358                 :         /* detoast rel's ACL if necessary */
 7978 tgl                      3359 GIC       11668 :         acl = DatumGetAclP(aclDatum);
                               3360                 :     }
                               3361                 : 
 6494                          3362           14607 :     result = aclmask(acl, roleid, ownerId, mask, how);
                               3363                 : 
                               3364                 :     /* if we have a detoasted copy, free it */
 7978                          3365           14607 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
 9345 bruce                    3366 CBC       14607 :         pfree(acl);
                               3367                 : 
 8179 tgl                      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                 :      */
  734 sfrost                   3375           15555 :     if (mask & ACL_SELECT && !(result & ACL_SELECT) &&
  729 noah                     3376             948 :         has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA))
  734 sfrost                   3377               6 :         result |= ACL_SELECT;
  734 sfrost                   3378 ECB             : 
  734 sfrost                   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
  697 tgl                      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).
  734 sfrost                   3385                 :      */
  734 sfrost                   3386 CBC       14607 :     if (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE) &&
  697 tgl                      3387 GIC        2991 :         !(result & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
  729 noah                     3388 CBC         621 :         has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA))
  734 sfrost                   3389               9 :         result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
  734 sfrost                   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.
  132 andrew                   3396                 :      */
  117 jdavis                   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                 : 
 8986 bruce                    3402 GIC       14607 :     return result;
                               3403                 : }
                               3404                 : 
                               3405                 : /*
                               3406                 :  * Routine for examining a user's privileges for a configuration
  368 tgl                      3407 ECB             :  * parameter (GUC), identified by GUC name.
                               3408                 :  */
                               3409                 : static AclMode
  368 tgl                      3410 CBC          85 : pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
                               3411                 : {
                               3412                 :     AclMode     result;
  368 tgl                      3413 ECB             :     char       *parname;
                               3414                 :     text       *partext;
                               3415                 :     HeapTuple   tuple;
                               3416                 : 
                               3417                 :     /* Superusers bypass all permission checking. */
  368 tgl                      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 */
  368 tgl                      3426 CBC          84 :     tuple = SearchSysCache1(PARAMETERACLNAME, PointerGetDatum(partext));
                               3427                 : 
  368 tgl                      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                 :     {
  368 tgl                      3435 ECB             :         Datum       aclDatum;
                               3436                 :         bool        isNull;
                               3437                 :         Acl        *acl;
                               3438                 : 
  368 tgl                      3439 GIC          45 :         aclDatum = SysCacheGetAttr(PARAMETERACLNAME, tuple,
                               3440                 :                                    Anum_pg_parameter_acl_paracl,
                               3441                 :                                    &isNull);
  368 tgl                      3442 CBC          45 :         if (isNull)
  368 tgl                      3443 ECB             :         {
  368 tgl                      3444 EUB             :             /* No ACL, so build default ACL */
  368 tgl                      3445 LBC           0 :             acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
  368 tgl                      3446 UIC           0 :             aclDatum = (Datum) 0;
                               3447                 :         }
                               3448                 :         else
                               3449                 :         {
                               3450                 :             /* detoast ACL if necessary */
  368 tgl                      3451 GIC          45 :             acl = DatumGetAclP(aclDatum);
  368 tgl                      3452 ECB             :         }
                               3453                 : 
  368 tgl                      3454 CBC          45 :         result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
                               3455                 : 
  368 tgl                      3456 EUB             :         /* if we have a detoasted copy, free it */
  368 tgl                      3457 GBC          45 :         if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
  368 tgl                      3458 GIC          45 :             pfree(acl);
                               3459                 : 
                               3460              45 :         ReleaseSysCache(tuple);
                               3461                 :     }
                               3462                 : 
                               3463              84 :     pfree(parname);
  368 tgl                      3464 CBC          84 :     pfree(partext);
                               3465                 : 
  368 tgl                      3466 GIC          84 :     return result;
  368 tgl                      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
  368 tgl                      3474 LBC           0 : pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
                               3475                 : {
                               3476                 :     AclMode     result;
                               3477                 :     HeapTuple   tuple;
  368 tgl                      3478 ECB             :     Datum       aclDatum;
  368 tgl                      3479 EUB             :     bool        isNull;
                               3480                 :     Acl        *acl;
                               3481                 : 
  368 tgl                      3482 ECB             :     /* Superusers bypass all permission checking. */
  368 tgl                      3483 UIC           0 :     if (superuser_arg(roleid))
  368 tgl                      3484 LBC           0 :         return mask;
  368 tgl                      3485 ECB             : 
                               3486                 :     /* Get the ACL from pg_parameter_acl */
  368 tgl                      3487 UIC           0 :     tuple = SearchSysCache1(PARAMETERACLOID, ObjectIdGetDatum(acl_oid));
  368 tgl                      3488 LBC           0 :     if (!HeapTupleIsValid(tuple))
  368 tgl                      3489 UIC           0 :         ereport(ERROR,
                               3490                 :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                               3491                 :                  errmsg("parameter ACL with OID %u does not exist",
                               3492                 :                         acl_oid)));
  368 tgl                      3493 ECB             : 
  368 tgl                      3494 UIC           0 :     aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
  368 tgl                      3495 ECB             :                                Anum_pg_parameter_acl_paracl,
                               3496                 :                                &isNull);
  368 tgl                      3497 UIC           0 :     if (isNull)
                               3498                 :     {
  368 tgl                      3499 ECB             :         /* No ACL, so build default ACL */
  368 tgl                      3500 LBC           0 :         acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
  368 tgl                      3501 UIC           0 :         aclDatum = (Datum) 0;
  368 tgl                      3502 ECB             :     }
                               3503                 :     else
                               3504                 :     {
                               3505                 :         /* detoast ACL if necessary */
  368 tgl                      3506 LBC           0 :         acl = DatumGetAclP(aclDatum);
                               3507                 :     }
                               3508                 : 
  368 tgl                      3509 UIC           0 :     result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
  368 tgl                      3510 ECB             : 
                               3511                 :     /* if we have a detoasted copy, free it */
  368 tgl                      3512 LBC           0 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
  368 tgl                      3513 UIC           0 :         pfree(acl);
  368 tgl                      3514 ECB             : 
  368 tgl                      3515 UIC           0 :     ReleaseSysCache(tuple);
                               3516                 : 
  368 tgl                      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
 3568 rhaas                    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
 3568 rhaas                    3529 EUB             :  * snapshot, since all we do with the snapshot argument is pass it through
                               3530                 :  * to systable_beginscan().
                               3531                 :  */
                               3532                 : static AclMode
 4867 itagaki.takahiro         3533 CBC         292 : pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
                               3534                 :                                 AclMode mask, AclMaskHow how,
 4867 itagaki.takahiro         3535 ECB             :                                 Snapshot snapshot)
                               3536                 : {
                               3537                 :     AclMode     result;
                               3538                 :     Relation    pg_lo_meta;
 4790 bruce                    3539                 :     ScanKeyData entry[1];
                               3540                 :     SysScanDesc scan;
                               3541                 :     HeapTuple   tuple;
                               3542                 :     Datum       aclDatum;
 4867 itagaki.takahiro         3543                 :     bool        isNull;
                               3544                 :     Acl        *acl;
                               3545                 :     Oid         ownerId;
                               3546                 : 
                               3547                 :     /* Superusers bypass all permission checking. */
 4867 itagaki.takahiro         3548 GIC         292 :     if (superuser_arg(roleid))
                               3549             217 :         return mask;
                               3550                 : 
                               3551                 :     /*
                               3552                 :      * Get the largeobject's ACL from pg_largeobject_metadata
                               3553                 :      */
 1539 andres                   3554              75 :     pg_lo_meta = table_open(LargeObjectMetadataRelationId,
                               3555                 :                             AccessShareLock);
                               3556                 : 
 4867 itagaki.takahiro         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,
 4867 itagaki.takahiro         3564 ECB             :                               snapshot, 1, entry);
                               3565                 : 
 4867 itagaki.takahiro         3566 GIC          75 :     tuple = systable_getnext(scan);
                               3567              75 :     if (!HeapTupleIsValid(tuple))
 4867 itagaki.takahiro         3568 UIC           0 :         ereport(ERROR,
                               3569                 :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                               3570                 :                  errmsg("large object %u does not exist", lobj_oid)));
                               3571                 : 
 4867 itagaki.takahiro         3572 GIC          75 :     ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
                               3573                 : 
 4867 itagaki.takahiro         3574 CBC          75 :     aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
 4867 itagaki.takahiro         3575 ECB             :                             RelationGetDescr(pg_lo_meta), &isNull);
                               3576                 : 
 4867 itagaki.takahiro         3577 CBC          75 :     if (isNull)
                               3578                 :     {
                               3579                 :         /* No ACL, so build default ACL */
 2006 peter_e                  3580 GIC          18 :         acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
 4867 itagaki.takahiro         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))
 4867 itagaki.takahiro         3593 CBC          75 :         pfree(acl);
                               3594                 : 
 4867 itagaki.takahiro         3595 GIC          75 :     systable_endscan(scan);
                               3596                 : 
 1539 andres                   3597              75 :     table_close(pg_lo_meta, AccessShareLock);
                               3598                 : 
 4867 itagaki.takahiro         3599              75 :     return result;
                               3600                 : }
 4867 itagaki.takahiro         3601 ECB             : 
                               3602                 : /*
                               3603                 :  * Routine for examining a user's privileges for a namespace
                               3604                 :  */
                               3605                 : static AclMode
 6494 tgl                      3606 GIC      524988 : pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
 6907 tgl                      3607 ECB             :                      AclMode mask, AclMaskHow how)
                               3608                 : {
                               3609                 :     AclMode     result;
                               3610                 :     HeapTuple   tuple;
 7658                          3611                 :     Datum       aclDatum;
                               3612                 :     bool        isNull;
                               3613                 :     Acl        *acl;
                               3614                 :     Oid         ownerId;
                               3615                 : 
                               3616                 :     /* Superusers bypass all permission checking. */
 6494 tgl                      3617 GIC      524988 :     if (superuser_arg(roleid))
 6907                          3618          517205 :         return mask;
                               3619                 : 
 6892 bruce                    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
 6385                          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.
 6892                          3626                 :      *
 6347                          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
 6385                          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.
 6890 tgl                      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.
 6892 bruce                    3638                 :      */
 6890 tgl                      3639 GIC        7783 :     if (isTempNamespace(nsp_oid))
                               3640                 :     {
  147 peter                    3641 GNC          96 :         if (object_aclcheck(DatabaseRelationId, MyDatabaseId, roleid,
                               3642                 :                             ACL_CREATE_TEMP) == ACLCHECK_OK)
 2006 peter_e                  3643 CBC          96 :             return mask & ACL_ALL_RIGHTS_SCHEMA;
                               3644                 :         else
 6890 tgl                      3645 UIC           0 :             return mask & ACL_USAGE;
                               3646                 :     }
                               3647                 : 
 7720 peter_e                  3648 ECB             :     /*
 7202 tgl                      3649                 :      * Get the schema's ACL from pg_namespace
                               3650                 :      */
 4802 rhaas                    3651 GIC        7687 :     tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
 7658 tgl                      3652            7687 :     if (!HeapTupleIsValid(tuple))
 7202 tgl                      3653 UIC           0 :         ereport(ERROR,
                               3654                 :                 (errcode(ERRCODE_UNDEFINED_SCHEMA),
                               3655                 :                  errmsg("schema with OID %u does not exist", nsp_oid)));
                               3656                 : 
 6886 tgl                      3657 CBC        7687 :     ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
                               3658                 : 
 7658 tgl                      3659 GIC        7687 :     aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
 7658 tgl                      3660 ECB             :                                &isNull);
 7658 tgl                      3661 CBC        7687 :     if (isNull)
 7658 tgl                      3662 ECB             :     {
                               3663                 :         /* No ACL, so build default ACL */
 2006 peter_e                  3664 GIC         126 :         acl = acldefault(OBJECT_SCHEMA, ownerId);
 7658 tgl                      3665 CBC         126 :         aclDatum = (Datum) 0;
 7658 tgl                      3666 ECB             :     }
                               3667                 :     else
                               3668                 :     {
                               3669                 :         /* detoast ACL if necessary */
 7658 tgl                      3670 CBC        7561 :         acl = DatumGetAclP(aclDatum);
                               3671                 :     }
 7658 tgl                      3672 ECB             : 
 6494 tgl                      3673 GIC        7687 :     result = aclmask(acl, roleid, ownerId, mask, how);
                               3674                 : 
                               3675                 :     /* if we have a detoasted copy, free it */
 7720 peter_e                  3676 CBC        7687 :     if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
 7720 peter_e                  3677 GIC        7687 :         pfree(acl);
                               3678                 : 
 7720 peter_e                  3679 CBC        7687 :     ReleaseSysCache(tuple);
                               3680                 : 
  734 sfrost                   3681 ECB             :     /*
  697 tgl                      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                 :      */
  734 sfrost                   3687 GIC        7706 :     if (mask & ACL_USAGE && !(result & ACL_USAGE) &&
  729 noah                     3688              35 :         (has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA) ||
                               3689              16 :          has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA)))
  734 sfrost                   3690               6 :         result |= ACL_USAGE;
 7720 peter_e                  3691            7687 :     return result;
                               3692                 : }
                               3693                 : 
                               3694                 : /*
                               3695                 :  * Routine for examining a user's privileges for a type.
                               3696                 :  */
                               3697                 : static AclMode
 4128                          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))
 4128 peter_e                  3718 UIC           0 :         ereport(ERROR,
                               3719                 :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
                               3720                 :                  errmsg("type with OID %u does not exist",
                               3721                 :                         type_oid)));
 4128 peter_e                  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                 :      */
  851 tgl                      3728            1998 :     if (IsTrueArrayType(typeForm))
                               3729                 :     {
 3955 bruce                    3730              18 :         Oid         elttype_oid = typeForm->typelem;
                               3731                 : 
 4128 peter_e                  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))
 2491 tgl                      3737 UIC           0 :             elog(ERROR, "cache lookup failed for type %u", elttype_oid);
 4128 peter_e                  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 */
 2006                          3751            1887 :         acl = acldefault(OBJECT_TYPE, ownerId);
 4128                          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
  147 peter                    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
 5190 tgl                      3794 GIC        1576 : pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
                               3795                 :                       Oid roleid, AclMode mode)
                               3796                 : {
  739 mail                     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)
 5190 tgl                      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                 :      */
 4802 rhaas                    3852              84 :     classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
 5190 tgl                      3853              84 :     if (!HeapTupleIsValid(classTuple))
 5175 tgl                      3854 UIC           0 :         return ACLCHECK_NO_PRIV;
 5190 tgl                      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                 : 
 4802 rhaas                    3872             171 :         attTuple = SearchSysCache2(ATTNUM,
                               3873                 :                                    ObjectIdGetDatum(table_oid),
                               3874                 :                                    Int16GetDatum(curr_att));
 5190 tgl                      3875             171 :         if (!HeapTupleIsValid(attTuple))
 5175 tgl                      3876 UIC           0 :             continue;
                               3877                 : 
                               3878                 :         /* ignore dropped columns */
 5175 tgl                      3879 GIC         171 :         if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
                               3880                 :         {
                               3881               9 :             ReleaseSysCache(attTuple);
 5190                          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                 :          */
 1838 andrew                   3890             162 :         if (heap_attisnull(attTuple, Anum_pg_attribute_attacl, NULL))
 5175 tgl                      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                 :         {
 5190                          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
 6494                          3923          851220 : pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
                               3924                 : {
  739 mail                     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)
 6907 tgl                      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
  368                          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
 4867 itagaki.takahiro         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
  147 peter                    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. */
 4439 peter_e                  3982          331205 :     if (superuser_arg(roleid))
                               3983          327414 :         return true;
                               3984                 : 
  147 peter                    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))
  147 peter                    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                 : 
   15 dgustafsson              3996 GNC        3781 :         ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
                               3997                 :                                                           tuple,
                               3998            3781 :                                                           get_object_attnum_owner(classid)));
  147 peter                    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))
  147 peter                    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                 : 
  147 peter                    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                 : 
 2207 alvherre                 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
 3029                          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 *
 4934 tgl                      4096          153856 : get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
                               4097                 : {
                               4098          153856 :     Acl        *result = NULL;
                               4099                 :     HeapTuple   tuple;
                               4100                 : 
 4802 rhaas                    4101          153856 :     tuple = SearchSysCache3(DEFACLROLENSPOBJ,
                               4102                 :                             ObjectIdGetDatum(roleId),
                               4103                 :                             ObjectIdGetDatum(nsp_oid),
                               4104                 :                             CharGetDatum(objtype));
                               4105                 : 
 4934 tgl                      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 *
 2006 peter_e                  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                 :      */
 4934 tgl                      4143           76928 :     if (IsBootstrapProcessingMode())
 4934 tgl                      4144 UIC           0 :         return NULL;
                               4145                 : 
                               4146                 :     /* Check if object type is supported in pg_default_acl */
 4934 tgl                      4147 GIC       76928 :     switch (objtype)
                               4148                 :     {
 2006 peter_e                  4149           61675 :         case OBJECT_TABLE:
 4934 tgl                      4150           61675 :             defaclobjtype = DEFACLOBJ_RELATION;
                               4151           61675 :             break;
                               4152                 : 
 2006 peter_e                  4153             744 :         case OBJECT_SEQUENCE:
 4934 tgl                      4154             744 :             defaclobjtype = DEFACLOBJ_SEQUENCE;
                               4155             744 :             break;
                               4156                 : 
 2006 peter_e                  4157           11262 :         case OBJECT_FUNCTION:
 4934 tgl                      4158           11262 :             defaclobjtype = DEFACLOBJ_FUNCTION;
                               4159           11262 :             break;
                               4160                 : 
 2006 peter_e                  4161            2598 :         case OBJECT_TYPE:
 4128                          4162            2598 :             defaclobjtype = DEFACLOBJ_TYPE;
                               4163            2598 :             break;
                               4164                 : 
 2006                          4165             649 :         case OBJECT_SCHEMA:
 2203 teodor                   4166             649 :             defaclobjtype = DEFACLOBJ_NAMESPACE;
                               4167             649 :             break;
                               4168                 : 
 4934 tgl                      4169 UIC           0 :         default:
                               4170               0 :             return NULL;
                               4171                 :     }
                               4172                 : 
                               4173                 :     /* Look up the relevant pg_default_acl entries */
 4934 tgl                      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
 1612                          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
 2261 sfrost                   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))
 2261 sfrost                   4252 UIC           0 :             elog(ERROR, "cache lookup failed for relation %u", objoid);
 2261 sfrost                   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                 :          */
 1906 alvherre                 4260               7 :         if (pg_class_tuple->relkind == RELKIND_INDEX ||
 1087 tgl                      4261               7 :             pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
                               4262               7 :             pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
                               4263                 :         {
 1087 tgl                      4264 UIC           0 :             ReleaseSysCache(tuple);
 2261 sfrost                   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                 :          */
 2261 sfrost                   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))
 2261 sfrost                   4287 UIC           0 :                     continue;
                               4288                 : 
                               4289                 :                 /* ignore dropped columns */
 2261 sfrost                   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                 :          */
 1539 andres                   4339 UIC           0 :         relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
                               4340                 : 
                               4341                 :         /* There's no syscache for pg_largeobject_metadata */
 2261 sfrost                   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))
 2135 tgl                      4353               0 :             elog(ERROR, "could not find tuple for large object %u", objoid);
                               4354                 : 
 2261 sfrost                   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. */
   82 peter                    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));
 2261 sfrost                   4375 GIC          10 :         if (!HeapTupleIsValid(tuple))
   82 peter                    4376 UNC           0 :             elog(ERROR, "cache lookup failed for %s %u",
                               4377                 :                  get_object_class_descr(classoid), objoid);
                               4378                 : 
   82 peter                    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 */
 2261 sfrost                   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))
 2261 sfrost                   4411 UIC           0 :             elog(ERROR, "cache lookup failed for relation %u", objoid);
 2261 sfrost                   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                 :          */
 1906 alvherre                 4419              16 :         if (pg_class_tuple->relkind == RELKIND_INDEX ||
 1087 tgl                      4420              16 :             pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
                               4421              16 :             pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
                               4422                 :         {
 1087 tgl                      4423 UIC           0 :             ReleaseSysCache(tuple);
 2261 sfrost                   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                 :          */
 2261 sfrost                   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))
 2261 sfrost                   4445 UIC           0 :                     continue;
                               4446                 : 
                               4447                 :                 /* when removing, remove all entries, even dropped columns */
                               4448                 : 
 2261 sfrost                   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
 2559                          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                 : 
 2261                          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                 : 
 1539 andres                   4517             655 :     relation = table_open(InitPrivsRelationId, RowExclusiveLock);
                               4518                 : 
 2559 sfrost                   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                 :     {
  267 peter                    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. */
 2559 sfrost                   4546 GIC          85 :         if (new_acl)
                               4547                 :         {
 1863 tgl                      4548              57 :             values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
                               4549              57 :             replace[Anum_pg_init_privs_initprivs - 1] = true;
                               4550                 : 
 2559 sfrost                   4551              57 :             oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
                               4552                 :                                          values, nulls, replace);
                               4553                 : 
 2259 alvherre                 4554              57 :             CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
                               4555                 :         }
                               4556                 :         else
                               4557                 :         {
                               4558                 :             /* new_acl is NULL, so delete the entry we found. */
 2258 tgl                      4559              28 :             CatalogTupleDelete(relation, &oldtuple->t_self);
                               4560                 :         }
                               4561                 :     }
                               4562                 :     else
                               4563                 :     {
  267 peter                    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                 :          */
 2261 sfrost                   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                 : 
 1863 tgl                      4584             179 :             values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
                               4585                 : 
 2261 sfrost                   4586             179 :             tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
                               4587                 : 
 2259 alvherre                 4588             179 :             CatalogTupleInsert(relation, tuple);
                               4589                 :         }
                               4590                 :     }
                               4591                 : 
 2550 sfrost                   4592             655 :     systable_endscan(scan);
                               4593                 : 
                               4594                 :     /* prevent error when processing objects multiple times */
 2559                          4595             655 :     CommandCounterIncrement();
                               4596                 : 
 1539 andres                   4597             655 :     table_close(relation, RowExclusiveLock);
 2559 sfrost                   4598             655 : }
        

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