PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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 "catalog/indexing.h"
17 #include "catalog/objectaccess.h"
19 #include "utils/fmgroids.h"
20 #include "utils/rel.h"
21 #include "utils/tqual.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 
37  ScanKeyInit(&scankey[0],
39  BTEqualStrategyNumber, F_OIDEQ,
40  ObjectIdGetDatum(databaseid));
41  ScanKeyInit(&scankey[1],
43  BTEqualStrategyNumber, F_OIDEQ,
44  ObjectIdGetDatum(roleid));
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 
70  RelationGetDescr(rel), &isnull);
71 
72  if (!isnull)
73  new = GUCArrayReset(DatumGetArrayTypeP(datum));
74 
75  if (new)
76  {
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  {
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 */
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] =
125  PointerGetDatum(a);
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;
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 
147  ObjectIdGetDatum(databaseid);
150  newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
151 
152  CatalogTupleInsert(rel, newtuple);
153  }
154 
156  databaseid, 0, roleid, false);
157 
158  systable_endscan(scan);
159 
160  /* Close pg_db_role_setting, but keep lock till commit */
161  heap_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  HeapScanDesc scan;
174  ScanKeyData keys[2];
175  HeapTuple tup;
176  int numkeys = 0;
177 
179 
180  if (OidIsValid(databaseid))
181  {
182  ScanKeyInit(&keys[numkeys],
185  F_OIDEQ,
186  ObjectIdGetDatum(databaseid));
187  numkeys++;
188  }
189  if (OidIsValid(roleid))
190  {
191  ScanKeyInit(&keys[numkeys],
194  F_OIDEQ,
195  ObjectIdGetDatum(roleid));
196  numkeys++;
197  }
198 
199  scan = heap_beginscan_catalog(relsetting, numkeys, keys);
201  {
202  CatalogTupleDelete(relsetting, &tup->t_self);
203  }
204  heap_endscan(scan);
205 
206  heap_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],
230  F_OIDEQ,
231  ObjectIdGetDatum(databaseid));
232  ScanKeyInit(&keys[1],
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 
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 }
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:9423
#define Anum_pg_db_role_setting_setdatabase
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1581
VariableSetKind kind
Definition: parsenodes.h:1864
ArrayType * GUCArrayReset(ArrayType *array)
Definition: guc.c:9575
#define Anum_pg_db_role_setting_setrole
#define RelationGetDescr(relation)
Definition: rel.h:425
#define PointerGetDatum(X)
Definition: postgres.h:564
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
#define DbRoleSettingDatidRolidIndexId
Definition: indexing.h:303
#define Natts_pg_db_role_setting
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
GucSource
Definition: guc.h:105
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
Definition: guc.h:75
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define InvokeObjectPostAlterHookArg(classId, objectId, subId,auxiliaryId, is_internal)
Definition: objectaccess.h:166
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1402
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:9503
uintptr_t Datum
Definition: postgres.h:374
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1781
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
void ProcessGUCArray(ArrayType *array, GucContext context, GucSource source, GucAction action)
Definition: guc.c:9365
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define Anum_pg_db_role_setting_setconfig
void ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
#define DbRoleSettingRelationId
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc.c:7363
void DropSetting(Oid databaseid, Oid roleid)
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define DatumGetArrayTypeP(X)
Definition: array.h:242