3 * Routines to support manipulation of the pg_db_role_setting relation
5 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
9 * $PostgreSQL: pgsql/src/backend/catalog/pg_db_role_setting.c,v 1.2 2010/01/02 16:57:36 momjian Exp $
13 #include "access/genam.h"
14 #include "access/heapam.h"
15 #include "access/htup.h"
16 #include "access/skey.h"
17 #include "catalog/indexing.h"
18 #include "catalog/pg_db_role_setting.h"
19 #include "utils/fmgroids.h"
20 #include "utils/rel.h"
21 #include "utils/tqual.h"
24 AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
29 ScanKeyData scankey[2];
32 valuestr = ExtractSetVariableArgs(setstmt);
34 /* Get the old tuple, if any. */
36 rel = heap_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 SnapshotNow, 2, scankey);
47 tuple = systable_getnext(scan);
50 * There are three cases:
52 * - in RESET ALL, simply delete the pg_db_role_setting tuple (if any)
54 * - in other commands, if there's a tuple in pg_db_role_setting, update it;
55 * if it ends up empty, delete it
57 * - otherwise, insert a new pg_db_role_setting tuple, but only if the
58 * command is not RESET
60 if (setstmt->kind == VAR_RESET_ALL)
62 if (HeapTupleIsValid(tuple))
63 simple_heap_delete(rel, &tuple->t_self);
65 else if (HeapTupleIsValid(tuple))
67 Datum repl_val[Natts_pg_db_role_setting];
68 bool repl_null[Natts_pg_db_role_setting];
69 bool repl_repl[Natts_pg_db_role_setting];
75 memset(repl_repl, false, sizeof(repl_repl));
76 repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
77 repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
79 /* Extract old value of setconfig */
80 datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
81 RelationGetDescr(rel), &isnull);
82 a = isnull ? NULL : DatumGetArrayTypeP(datum);
84 /* Update (valuestr is NULL in RESET cases) */
86 a = GUCArrayAdd(a, setstmt->name, valuestr);
88 a = GUCArrayDelete(a, setstmt->name);
92 repl_val[Anum_pg_db_role_setting_setconfig - 1] =
95 newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
96 repl_val, repl_null, repl_repl);
97 simple_heap_update(rel, &tuple->t_self, newtuple);
100 CatalogUpdateIndexes(rel, newtuple);
103 simple_heap_delete(rel, &tuple->t_self);
107 /* non-null valuestr means it's not RESET, so insert a new tuple */
109 Datum values[Natts_pg_db_role_setting];
110 bool nulls[Natts_pg_db_role_setting];
113 memset(nulls, false, sizeof(nulls));
115 a = GUCArrayAdd(NULL, setstmt->name, valuestr);
117 values[Anum_pg_db_role_setting_setdatabase - 1] =
118 ObjectIdGetDatum(databaseid);
119 values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid);
120 values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
121 newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
123 simple_heap_insert(rel, newtuple);
126 CatalogUpdateIndexes(rel, newtuple);
129 systable_endscan(scan);
131 /* Close pg_db_role_setting, but keep lock till commit */
132 heap_close(rel, NoLock);
136 * Drop some settings from the catalog. These can be for a particular
137 * database, or for a particular role. (It is of course possible to do both
138 * too, but it doesn't make sense for current uses.)
141 DropSetting(Oid databaseid, Oid roleid)
149 relsetting = heap_open(DbRoleSettingRelationId, RowExclusiveLock);
151 if (OidIsValid(databaseid))
153 ScanKeyInit(&keys[numkeys],
154 Anum_pg_db_role_setting_setdatabase,
155 BTEqualStrategyNumber,
157 ObjectIdGetDatum(databaseid));
160 if (OidIsValid(roleid))
162 ScanKeyInit(&keys[numkeys],
163 Anum_pg_db_role_setting_setrole,
164 BTEqualStrategyNumber,
166 ObjectIdGetDatum(roleid));
170 scan = heap_beginscan(relsetting, SnapshotNow, numkeys, keys);
171 while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
173 simple_heap_delete(relsetting, &tup->t_self);
177 heap_close(relsetting, RowExclusiveLock);
181 * Scan pg_db_role_setting looking for applicable settings, and load them on
182 * the current process.
184 * relsetting is pg_db_role_setting, already opened and locked.
186 * Note: we only consider setting for the exact databaseid/roleid combination.
187 * This probably needs to be called more than once, with InvalidOid passed as
191 ApplySetting(Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
197 ScanKeyInit(&keys[0],
198 Anum_pg_db_role_setting_setdatabase,
199 BTEqualStrategyNumber,
201 ObjectIdGetDatum(databaseid));
202 ScanKeyInit(&keys[1],
203 Anum_pg_db_role_setting_setrole,
204 BTEqualStrategyNumber,
206 ObjectIdGetDatum(roleid));
208 scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
209 SnapshotNow, 2, keys);
210 while (HeapTupleIsValid(tup = systable_getnext(scan)))
215 datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
216 RelationGetDescr(relsetting), &isnull);
219 ArrayType *a = DatumGetArrayTypeP(datum);
222 * We process all the options at SUSET level. We assume that the
223 * right to insert an option into pg_db_role_setting was checked
224 * when it was inserted.
226 ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
230 systable_endscan(scan);