PostgreSQL Source Code  git master
pg_db_role_setting.c
Go to the documentation of this file.
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-2024, 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"
20 #include "utils/fmgroids.h"
21 #include "utils/rel.h"
22 
23 void
24 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  valuestr = ExtractSetVariableArgs(setstmt);
33 
34  /* Get the old tuple, if any. */
35 
36  rel = table_open(DbRoleSettingRelationId, RowExclusiveLock);
37  ScanKeyInit(&scankey[0],
38  Anum_pg_db_role_setting_setdatabase,
39  BTEqualStrategyNumber, F_OIDEQ,
40  ObjectIdGetDatum(databaseid));
41  ScanKeyInit(&scankey[1],
42  Anum_pg_db_role_setting_setrole,
43  BTEqualStrategyNumber, F_OIDEQ,
44  ObjectIdGetDatum(roleid));
45  scan = systable_beginscan(rel, DbRoleSettingDatidRolidIndexId, true,
46  NULL, 2, scankey);
47  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  if (setstmt->kind == VAR_RESET_ALL)
62  {
63  if (HeapTupleIsValid(tuple))
64  {
65  ArrayType *new = NULL;
66  Datum datum;
67  bool isnull;
68 
69  datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
70  RelationGetDescr(rel), &isnull);
71 
72  if (!isnull)
73  new = GUCArrayReset(DatumGetArrayTypeP(datum));
74 
75  if (new)
76  {
77  Datum repl_val[Natts_pg_db_role_setting];
78  bool repl_null[Natts_pg_db_role_setting];
79  bool repl_repl[Natts_pg_db_role_setting];
80  HeapTuple newtuple;
81 
82  memset(repl_repl, false, sizeof(repl_repl));
83 
84  repl_val[Anum_pg_db_role_setting_setconfig - 1] =
85  PointerGetDatum(new);
86  repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
87  repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
88 
89  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
90  repl_val, repl_null, repl_repl);
91  CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
92  }
93  else
94  CatalogTupleDelete(rel, &tuple->t_self);
95  }
96  }
97  else if (HeapTupleIsValid(tuple))
98  {
99  Datum repl_val[Natts_pg_db_role_setting];
100  bool repl_null[Natts_pg_db_role_setting];
101  bool repl_repl[Natts_pg_db_role_setting];
102  HeapTuple newtuple;
103  Datum datum;
104  bool isnull;
105  ArrayType *a;
106 
107  memset(repl_repl, false, sizeof(repl_repl));
108  repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
109  repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
110 
111  /* Extract old value of setconfig */
112  datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
113  RelationGetDescr(rel), &isnull);
114  a = isnull ? NULL : DatumGetArrayTypeP(datum);
115 
116  /* Update (valuestr is NULL in RESET cases) */
117  if (valuestr)
118  a = GUCArrayAdd(a, setstmt->name, valuestr);
119  else
120  a = GUCArrayDelete(a, setstmt->name);
121 
122  if (a)
123  {
124  repl_val[Anum_pg_db_role_setting_setconfig - 1] =
126 
127  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
128  repl_val, repl_null, repl_repl);
129  CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
130  }
131  else
132  CatalogTupleDelete(rel, &tuple->t_self);
133  }
134  else if (valuestr)
135  {
136  /* non-null valuestr means it's not RESET, so insert a new tuple */
137  HeapTuple newtuple;
138  Datum values[Natts_pg_db_role_setting];
139  bool nulls[Natts_pg_db_role_setting];
140  ArrayType *a;
141 
142  memset(nulls, false, sizeof(nulls));
143 
144  a = GUCArrayAdd(NULL, setstmt->name, valuestr);
145 
146  values[Anum_pg_db_role_setting_setdatabase - 1] =
147  ObjectIdGetDatum(databaseid);
148  values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid);
149  values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
150  newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
151 
152  CatalogTupleInsert(rel, newtuple);
153  }
154 
155  InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
156  databaseid, 0, roleid, false);
157 
158  systable_endscan(scan);
159 
160  /* Close pg_db_role_setting, but keep lock till commit */
161  table_close(rel, NoLock);
162 }
163 
164 /*
165  * Drop some settings from the catalog. These can be for a particular
166  * database, or for a particular role. (It is of course possible to do both
167  * too, but it doesn't make sense for current uses.)
168  */
169 void
170 DropSetting(Oid databaseid, Oid roleid)
171 {
172  Relation relsetting;
173  TableScanDesc scan;
174  ScanKeyData keys[2];
175  HeapTuple tup;
176  int numkeys = 0;
177 
178  relsetting = table_open(DbRoleSettingRelationId, RowExclusiveLock);
179 
180  if (OidIsValid(databaseid))
181  {
182  ScanKeyInit(&keys[numkeys],
183  Anum_pg_db_role_setting_setdatabase,
185  F_OIDEQ,
186  ObjectIdGetDatum(databaseid));
187  numkeys++;
188  }
189  if (OidIsValid(roleid))
190  {
191  ScanKeyInit(&keys[numkeys],
192  Anum_pg_db_role_setting_setrole,
194  F_OIDEQ,
195  ObjectIdGetDatum(roleid));
196  numkeys++;
197  }
198 
199  scan = table_beginscan_catalog(relsetting, numkeys, keys);
201  {
202  CatalogTupleDelete(relsetting, &tup->t_self);
203  }
204  table_endscan(scan);
205 
206  table_close(relsetting, RowExclusiveLock);
207 }
208 
209 /*
210  * Scan pg_db_role_setting looking for applicable settings, and load them on
211  * the current process.
212  *
213  * relsetting is pg_db_role_setting, already opened and locked.
214  *
215  * Note: we only consider setting for the exact databaseid/roleid combination.
216  * This probably needs to be called more than once, with InvalidOid passed as
217  * databaseid/roleid.
218  */
219 void
220 ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid,
221  Relation relsetting, GucSource source)
222 {
223  SysScanDesc scan;
224  ScanKeyData keys[2];
225  HeapTuple tup;
226 
227  ScanKeyInit(&keys[0],
228  Anum_pg_db_role_setting_setdatabase,
230  F_OIDEQ,
231  ObjectIdGetDatum(databaseid));
232  ScanKeyInit(&keys[1],
233  Anum_pg_db_role_setting_setrole,
235  F_OIDEQ,
236  ObjectIdGetDatum(roleid));
237 
238  scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
239  snapshot, 2, keys);
240  while (HeapTupleIsValid(tup = systable_getnext(scan)))
241  {
242  bool isnull;
243  Datum datum;
244 
245  datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
246  RelationGetDescr(relsetting), &isnull);
247  if (!isnull)
248  {
249  ArrayType *a = DatumGetArrayTypeP(datum);
250 
251  /*
252  * We process all the options at SUSET level. We assume that the
253  * right to insert an option into pg_db_role_setting was checked
254  * when it was inserted.
255  */
257  }
258  }
259 
260  systable_endscan(scan);
261 }
#define DatumGetArrayTypeP(X)
Definition: array.h:261
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define OidIsValid(objectId)
Definition: c.h:754
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:511
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
ArrayType * GUCArrayReset(ArrayType *array)
Definition: guc.c:6636
void ProcessGUCArray(ArrayType *array, GucContext context, GucSource source, GucAction action)
Definition: guc.c:6456
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:6488
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:6566
@ GUC_ACTION_SET
Definition: guc.h:199
GucSource
Definition: guc.h:108
@ PGC_SUSET
Definition: guc.h:74
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc_funcs.c:167
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1243
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1209
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
int a
Definition: isn.c:68
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHookArg(classId, objectId, subId, auxiliaryId, is_internal)
Definition: objectaccess.h:200
@ VAR_RESET_ALL
Definition: parsenodes.h:2624
void DropSetting(Oid databaseid, Oid roleid)
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
void ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
static rewind_source * source
Definition: pg_rewind.c:89
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:531
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
@ ForwardScanDirection
Definition: sdir.h:28
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
VariableSetKind kind
Definition: parsenodes.h:2632
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1028