Define __EXTENSIONS__ on Solaris, too.
[pgsql.git] / src / backend / catalog / pg_db_role_setting.c
blob8c20f519fc05e32764d46deba34ed46b17936620
1 /*
2 * pg_db_role_setting.c
3 * Routines to support manipulation of the pg_db_role_setting relation
5 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
8 * IDENTIFICATION
9 * src/backend/catalog/pg_db_role_setting.c
11 #include "postgres.h"
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"
23 void
24 AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
26 char *valuestr;
27 HeapTuple tuple;
28 Relation rel;
29 ScanKeyData scankey[2];
30 SysScanDesc scan;
32 valuestr = ExtractSetVariableArgs(setstmt);
34 /* Get the old tuple, if any. */
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);
50 * There are three cases:
52 * - in RESET ALL, request GUC to reset the settings array and update the
53 * catalog if there's anything left, delete it otherwise
55 * - in other commands, if there's a tuple in pg_db_role_setting, update
56 * it; if it ends up empty, delete it
58 * - otherwise, insert a new pg_db_role_setting tuple, but only if the
59 * command is not RESET
61 if (setstmt->kind == VAR_RESET_ALL)
63 if (HeapTupleIsValid(tuple))
65 ArrayType *new = NULL;
66 Datum datum;
67 bool isnull;
69 datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
70 RelationGetDescr(rel), &isnull);
72 if (!isnull)
73 new = GUCArrayReset(DatumGetArrayTypeP(datum));
75 if (new)
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;
82 memset(repl_repl, false, sizeof(repl_repl));
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;
89 newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
90 repl_val, repl_null, repl_repl);
91 CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
93 else
94 CatalogTupleDelete(rel, &tuple->t_self);
97 else if (HeapTupleIsValid(tuple))
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;
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;
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);
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);
122 if (a)
124 repl_val[Anum_pg_db_role_setting_setconfig - 1] =
125 PointerGetDatum(a);
127 newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
128 repl_val, repl_null, repl_repl);
129 CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
131 else
132 CatalogTupleDelete(rel, &tuple->t_self);
134 else if (valuestr)
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;
142 memset(nulls, false, sizeof(nulls));
144 a = GUCArrayAdd(NULL, setstmt->name, valuestr);
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);
152 CatalogTupleInsert(rel, newtuple);
155 InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
156 databaseid, 0, roleid, false);
158 systable_endscan(scan);
160 /* Close pg_db_role_setting, but keep lock till commit */
161 table_close(rel, NoLock);
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.)
169 void
170 DropSetting(Oid databaseid, Oid roleid)
172 Relation relsetting;
173 TableScanDesc scan;
174 ScanKeyData keys[2];
175 HeapTuple tup;
176 int numkeys = 0;
178 relsetting = table_open(DbRoleSettingRelationId, RowExclusiveLock);
180 if (OidIsValid(databaseid))
182 ScanKeyInit(&keys[numkeys],
183 Anum_pg_db_role_setting_setdatabase,
184 BTEqualStrategyNumber,
185 F_OIDEQ,
186 ObjectIdGetDatum(databaseid));
187 numkeys++;
189 if (OidIsValid(roleid))
191 ScanKeyInit(&keys[numkeys],
192 Anum_pg_db_role_setting_setrole,
193 BTEqualStrategyNumber,
194 F_OIDEQ,
195 ObjectIdGetDatum(roleid));
196 numkeys++;
199 scan = table_beginscan_catalog(relsetting, numkeys, keys);
200 while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
202 CatalogTupleDelete(relsetting, &tup->t_self);
204 table_endscan(scan);
206 table_close(relsetting, RowExclusiveLock);
210 * Scan pg_db_role_setting looking for applicable settings, and load them on
211 * the current process.
213 * relsetting is pg_db_role_setting, already opened and locked.
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.
219 void
220 ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid,
221 Relation relsetting, GucSource source)
223 SysScanDesc scan;
224 ScanKeyData keys[2];
225 HeapTuple tup;
227 ScanKeyInit(&keys[0],
228 Anum_pg_db_role_setting_setdatabase,
229 BTEqualStrategyNumber,
230 F_OIDEQ,
231 ObjectIdGetDatum(databaseid));
232 ScanKeyInit(&keys[1],
233 Anum_pg_db_role_setting_setrole,
234 BTEqualStrategyNumber,
235 F_OIDEQ,
236 ObjectIdGetDatum(roleid));
238 scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
239 snapshot, 2, keys);
240 while (HeapTupleIsValid(tup = systable_getnext(scan)))
242 bool isnull;
243 Datum datum;
245 datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
246 RelationGetDescr(relsetting), &isnull);
247 if (!isnull)
249 ArrayType *a = DatumGetArrayTypeP(datum);
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.
256 ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
260 systable_endscan(scan);