LCOV - differential code coverage report
Current view: top level - src/backend/catalog - pg_db_role_setting.c (source / functions) Coverage Total Hit LBC GBC GIC GNC CBC ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 98.9 % 92 91 1 1 41 21 28 60 2
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 3 3 2 1 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*
       2                 :  * pg_db_role_setting.c
       3                 :  *      Routines to support manipulation of the pg_db_role_setting relation
       4                 :  *
       5                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       6                 :  * Portions Copyright (c) 1994, Regents of the University of California
       7                 :  *
       8                 :  * IDENTIFICATION
       9                 :  *      src/backend/catalog/pg_db_role_setting.c
      10                 :  */
      11                 : #include "postgres.h"
      12                 : 
      13                 : #include "access/genam.h"
      14                 : #include "access/heapam.h"
      15                 : #include "access/htup_details.h"
      16                 : #include "access/tableam.h"
      17                 : #include "catalog/indexing.h"
      18                 : #include "catalog/objectaccess.h"
      19                 : #include "catalog/pg_db_role_setting.h"
      20                 : #include "utils/fmgroids.h"
      21                 : #include "utils/rel.h"
      22                 : 
      23                 : void
      24 CBC         558 : AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
      25                 : {
      26                 :     char       *valuestr;
      27                 :     HeapTuple   tuple;
      28                 :     Relation    rel;
      29                 :     ScanKeyData scankey[2];
      30                 :     SysScanDesc scan;
      31                 : 
      32             558 :     valuestr = ExtractSetVariableArgs(setstmt);
      33                 : 
      34                 :     /* Get the old tuple, if any. */
      35                 : 
      36             558 :     rel = table_open(DbRoleSettingRelationId, RowExclusiveLock);
      37             558 :     ScanKeyInit(&scankey[0],
      38                 :                 Anum_pg_db_role_setting_setdatabase,
      39                 :                 BTEqualStrategyNumber, F_OIDEQ,
      40                 :                 ObjectIdGetDatum(databaseid));
      41             558 :     ScanKeyInit(&scankey[1],
      42                 :                 Anum_pg_db_role_setting_setrole,
      43                 :                 BTEqualStrategyNumber, F_OIDEQ,
      44                 :                 ObjectIdGetDatum(roleid));
      45             558 :     scan = systable_beginscan(rel, DbRoleSettingDatidRolidIndexId, true,
      46                 :                               NULL, 2, scankey);
      47             558 :     tuple = systable_getnext(scan);
      48                 : 
      49                 :     /*
      50                 :      * There are three cases:
      51                 :      *
      52                 :      * - in RESET ALL, request GUC to reset the settings array and update the
      53                 :      * catalog if there's anything left, delete it otherwise
      54                 :      *
      55                 :      * - in other commands, if there's a tuple in pg_db_role_setting, update
      56                 :      * it; if it ends up empty, delete it
      57                 :      *
      58                 :      * - otherwise, insert a new pg_db_role_setting tuple, but only if the
      59                 :      * command is not RESET
      60                 :      */
      61             558 :     if (setstmt->kind == VAR_RESET_ALL)
      62                 :     {
      63               1 :         if (HeapTupleIsValid(tuple))
      64                 :         {
      65               1 :             ArrayType  *new = NULL;
      66                 :             ArrayType  *usersetArray;
      67                 :             Datum       datum;
      68                 :             Datum       usersetDatum;
      69                 :             bool        isnull;
      70                 :             bool        usersetIsnull;
      71                 : 
      72 GIC           1 :             datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
      73                 :                                  RelationGetDescr(rel), &isnull);
      74 GNC           1 :             usersetDatum = heap_getattr(tuple, Anum_pg_db_role_setting_setuser,
      75                 :                                         RelationGetDescr(rel), &usersetIsnull);
      76                 : 
      77 CBC           1 :             if (!isnull)
      78                 :             {
      79 GNC           1 :                 Assert(!usersetIsnull);
      80               1 :                 usersetArray = DatumGetArrayTypeP(usersetDatum);
      81               1 :                 new = GUCArrayReset(DatumGetArrayTypeP(datum), &usersetArray);
      82                 :             }
      83 ECB             : 
      84 GIC           1 :             if (new)
      85                 :             {
      86 ECB             :                 Datum       repl_val[Natts_pg_db_role_setting];
      87                 :                 bool        repl_null[Natts_pg_db_role_setting];
      88                 :                 bool        repl_repl[Natts_pg_db_role_setting];
      89                 :                 HeapTuple   newtuple;
      90                 : 
      91 GIC           1 :                 memset(repl_repl, false, sizeof(repl_repl));
      92                 : 
      93 CBC           1 :                 repl_val[Anum_pg_db_role_setting_setconfig - 1] =
      94 GIC           1 :                     PointerGetDatum(new);
      95               1 :                 repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
      96               1 :                 repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
      97                 : 
      98 GNC           1 :                 repl_val[Anum_pg_db_role_setting_setuser - 1] =
      99               1 :                     PointerGetDatum(usersetArray);
     100               1 :                 repl_repl[Anum_pg_db_role_setting_setuser - 1] = true;
     101               1 :                 repl_null[Anum_pg_db_role_setting_setuser - 1] = false;
     102                 : 
     103 GIC           1 :                 newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
     104                 :                                              repl_val, repl_null, repl_repl);
     105 CBC           1 :                 CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
     106                 :             }
     107 ECB             :             else
     108 LBC           0 :                 CatalogTupleDelete(rel, &tuple->t_self);
     109 ECB             :         }
     110                 :     }
     111 GIC         557 :     else if (HeapTupleIsValid(tuple))
     112 ECB             :     {
     113                 :         Datum       repl_val[Natts_pg_db_role_setting];
     114                 :         bool        repl_null[Natts_pg_db_role_setting];
     115                 :         bool        repl_repl[Natts_pg_db_role_setting];
     116                 :         HeapTuple   newtuple;
     117                 :         Datum       datum;
     118                 :         Datum       usersetDatum;
     119                 :         bool        isnull;
     120                 :         bool        usersetIsnull;
     121                 :         ArrayType  *a;
     122                 :         ArrayType  *usersetArray;
     123                 : 
     124 GIC         452 :         memset(repl_repl, false, sizeof(repl_repl));
     125 GBC         452 :         repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
     126 GIC         452 :         repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
     127 GNC         452 :         repl_repl[Anum_pg_db_role_setting_setuser - 1] = true;
     128             452 :         repl_null[Anum_pg_db_role_setting_setuser - 1] = false;
     129                 : 
     130                 :         /* Extract old values of setconfig and setuser */
     131 GIC         452 :         datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
     132                 :                              RelationGetDescr(rel), &isnull);
     133             452 :         a = isnull ? NULL : DatumGetArrayTypeP(datum);
     134                 : 
     135 GNC         452 :         usersetDatum = heap_getattr(tuple, Anum_pg_db_role_setting_setuser,
     136                 :                                     RelationGetDescr(rel), &usersetIsnull);
     137             452 :         usersetArray = usersetIsnull ? NULL : DatumGetArrayTypeP(usersetDatum);
     138                 : 
     139                 :         /* Update (valuestr is NULL in RESET cases) */
     140 GIC         452 :         if (valuestr)
     141 GNC         441 :             a = GUCArrayAdd(a, &usersetArray, setstmt->name, valuestr, setstmt->user_set);
     142                 :         else
     143              11 :             a = GUCArrayDelete(a, &usersetArray, setstmt->name);
     144                 : 
     145 GIC         450 :         if (a)
     146                 :         {
     147 CBC         440 :             repl_val[Anum_pg_db_role_setting_setconfig - 1] =
     148             440 :                 PointerGetDatum(a);
     149 GNC         440 :             repl_val[Anum_pg_db_role_setting_setuser - 1] =
     150             440 :                 PointerGetDatum(usersetArray);
     151 ECB             : 
     152 CBC         440 :             newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
     153 ECB             :                                          repl_val, repl_null, repl_repl);
     154 GIC         440 :             CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
     155                 :         }
     156 ECB             :         else
     157 GIC          10 :             CatalogTupleDelete(rel, &tuple->t_self);
     158 ECB             :     }
     159 GIC         105 :     else if (valuestr)
     160 ECB             :     {
     161                 :         /* non-null valuestr means it's not RESET, so insert a new tuple */
     162                 :         HeapTuple   newtuple;
     163                 :         Datum       values[Natts_pg_db_role_setting];
     164                 :         bool        nulls[Natts_pg_db_role_setting];
     165                 :         ArrayType  *a,
     166                 :                    *usersetArray;
     167                 : 
     168 GIC         103 :         memset(nulls, false, sizeof(nulls));
     169 ECB             : 
     170 GNC         103 :         a = GUCArrayAdd(NULL, &usersetArray, setstmt->name, valuestr, setstmt->user_set);
     171 ECB             : 
     172 GIC         101 :         values[Anum_pg_db_role_setting_setdatabase - 1] =
     173 CBC         101 :             ObjectIdGetDatum(databaseid);
     174             101 :         values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid);
     175             101 :         values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
     176 GNC         101 :         values[Anum_pg_db_role_setting_setuser - 1] = PointerGetDatum(usersetArray);
     177 CBC         101 :         newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
     178                 : 
     179             101 :         CatalogTupleInsert(rel, newtuple);
     180                 :     }
     181 ECB             : 
     182 GIC         554 :     InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
     183                 :                                  databaseid, 0, roleid, false);
     184 ECB             : 
     185 GIC         554 :     systable_endscan(scan);
     186 ECB             : 
     187                 :     /* Close pg_db_role_setting, but keep lock till commit */
     188 GIC         554 :     table_close(rel, NoLock);
     189             554 : }
     190                 : 
     191                 : /*
     192                 :  * Drop some settings from the catalog.  These can be for a particular
     193                 :  * database, or for a particular role.  (It is of course possible to do both
     194                 :  * too, but it doesn't make sense for current uses.)
     195 ECB             :  */
     196                 : void
     197 CBC         639 : DropSetting(Oid databaseid, Oid roleid)
     198                 : {
     199 ECB             :     Relation    relsetting;
     200                 :     TableScanDesc scan;
     201                 :     ScanKeyData keys[2];
     202                 :     HeapTuple   tup;
     203 CBC         639 :     int         numkeys = 0;
     204 ECB             : 
     205 GIC         639 :     relsetting = table_open(DbRoleSettingRelationId, RowExclusiveLock);
     206 ECB             : 
     207 GIC         639 :     if (OidIsValid(databaseid))
     208                 :     {
     209 CBC          20 :         ScanKeyInit(&keys[numkeys],
     210                 :                     Anum_pg_db_role_setting_setdatabase,
     211                 :                     BTEqualStrategyNumber,
     212 ECB             :                     F_OIDEQ,
     213                 :                     ObjectIdGetDatum(databaseid));
     214 GIC          20 :         numkeys++;
     215 ECB             :     }
     216 CBC         639 :     if (OidIsValid(roleid))
     217                 :     {
     218 GIC         619 :         ScanKeyInit(&keys[numkeys],
     219                 :                     Anum_pg_db_role_setting_setrole,
     220                 :                     BTEqualStrategyNumber,
     221                 :                     F_OIDEQ,
     222                 :                     ObjectIdGetDatum(roleid));
     223             619 :         numkeys++;
     224 ECB             :     }
     225                 : 
     226 GIC         639 :     scan = table_beginscan_catalog(relsetting, numkeys, keys);
     227             643 :     while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
     228                 :     {
     229               4 :         CatalogTupleDelete(relsetting, &tup->t_self);
     230 ECB             :     }
     231 GIC         639 :     table_endscan(scan);
     232 ECB             : 
     233 GIC         639 :     table_close(relsetting, RowExclusiveLock);
     234 CBC         639 : }
     235                 : 
     236 ECB             : /*
     237                 :  * Scan pg_db_role_setting looking for applicable settings, and load them on
     238                 :  * the current process.
     239                 :  *
     240                 :  * relsetting is pg_db_role_setting, already opened and locked.
     241                 :  *
     242                 :  * Note: we only consider setting for the exact databaseid/roleid combination.
     243                 :  * This probably needs to be called more than once, with InvalidOid passed as
     244                 :  * databaseid/roleid.
     245                 :  */
     246                 : void
     247 GIC       39121 : ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid,
     248                 :              Relation relsetting, GucSource source)
     249                 : {
     250 ECB             :     SysScanDesc scan;
     251                 :     ScanKeyData keys[2];
     252                 :     HeapTuple   tup;
     253                 : 
     254 CBC       39121 :     ScanKeyInit(&keys[0],
     255                 :                 Anum_pg_db_role_setting_setdatabase,
     256 ECB             :                 BTEqualStrategyNumber,
     257                 :                 F_OIDEQ,
     258                 :                 ObjectIdGetDatum(databaseid));
     259 GIC       39121 :     ScanKeyInit(&keys[1],
     260 ECB             :                 Anum_pg_db_role_setting_setrole,
     261                 :                 BTEqualStrategyNumber,
     262                 :                 F_OIDEQ,
     263                 :                 ObjectIdGetDatum(roleid));
     264                 : 
     265 GIC       39121 :     scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
     266                 :                               snapshot, 2, keys);
     267           42142 :     while (HeapTupleIsValid(tup = systable_getnext(scan)))
     268                 :     {
     269                 :         bool        isnull;
     270                 :         bool        usersetIsnull;
     271                 :         Datum       datum;
     272                 :         Datum       usersetDatum;
     273                 : 
     274            3022 :         datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
     275                 :                              RelationGetDescr(relsetting), &isnull);
     276 GNC        3022 :         usersetDatum = heap_getattr(tup, Anum_pg_db_role_setting_setuser,
     277                 :                                     RelationGetDescr(relsetting), &usersetIsnull);
     278 CBC        3022 :         if (!isnull)
     279                 :         {
     280 GIC        3022 :             ArrayType  *a = DatumGetArrayTypeP(datum);
     281 GNC        3022 :             ArrayType  *usersetArray = DatumGetArrayTypeP(usersetDatum);
     282                 : 
     283                 :             /*
     284                 :              * We process all the options at SUSET level.  We assume that the
     285                 :              * right to insert an option into pg_db_role_setting was checked
     286 ECB             :              * when it was inserted.
     287                 :              */
     288 GNC        3022 :             ProcessGUCArray(a, usersetArray, PGC_SUSET, source, GUC_ACTION_SET);
     289                 :         }
     290                 :     }
     291 ECB             : 
     292 GIC       39120 :     systable_endscan(scan);
     293           39120 : }
        

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