1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
/*
* pg_db_role_setting.c
* Routines to support manipulation of the pg_db_role_setting relation
*
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_db_role_setting.c,v 1.3 2010/02/26 02:00:37 momjian Exp $
*/
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup.h"
#include "access/skey.h"
#include "catalog/indexing.h"
#include "catalog/pg_db_role_setting.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
#include "utils/tqual.h"
void
AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
{
char *valuestr;
HeapTuple tuple;
Relation rel;
ScanKeyData scankey[2];
SysScanDesc scan;
valuestr = ExtractSetVariableArgs(setstmt);
/* Get the old tuple, if any. */
rel = heap_open(DbRoleSettingRelationId, RowExclusiveLock);
ScanKeyInit(&scankey[0],
Anum_pg_db_role_setting_setdatabase,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(databaseid));
ScanKeyInit(&scankey[1],
Anum_pg_db_role_setting_setrole,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(roleid));
scan = systable_beginscan(rel, DbRoleSettingDatidRolidIndexId, true,
SnapshotNow, 2, scankey);
tuple = systable_getnext(scan);
/*
* There are three cases:
*
* - in RESET ALL, simply delete the pg_db_role_setting tuple (if any)
*
* - in other commands, if there's a tuple in pg_db_role_setting, update
* it; if it ends up empty, delete it
*
* - otherwise, insert a new pg_db_role_setting tuple, but only if the
* command is not RESET
*/
if (setstmt->kind == VAR_RESET_ALL)
{
if (HeapTupleIsValid(tuple))
simple_heap_delete(rel, &tuple->t_self);
}
else if (HeapTupleIsValid(tuple))
{
Datum repl_val[Natts_pg_db_role_setting];
bool repl_null[Natts_pg_db_role_setting];
bool repl_repl[Natts_pg_db_role_setting];
HeapTuple newtuple;
Datum datum;
bool isnull;
ArrayType *a;
memset(repl_repl, false, sizeof(repl_repl));
repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
/* Extract old value of setconfig */
datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
RelationGetDescr(rel), &isnull);
a = isnull ? NULL : DatumGetArrayTypeP(datum);
/* Update (valuestr is NULL in RESET cases) */
if (valuestr)
a = GUCArrayAdd(a, setstmt->name, valuestr);
else
a = GUCArrayDelete(a, setstmt->name);
if (a)
{
repl_val[Anum_pg_db_role_setting_setconfig - 1] =
PointerGetDatum(a);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
simple_heap_update(rel, &tuple->t_self, newtuple);
/* Update indexes */
CatalogUpdateIndexes(rel, newtuple);
}
else
simple_heap_delete(rel, &tuple->t_self);
}
else if (valuestr)
{
/* non-null valuestr means it's not RESET, so insert a new tuple */
HeapTuple newtuple;
Datum values[Natts_pg_db_role_setting];
bool nulls[Natts_pg_db_role_setting];
ArrayType *a;
memset(nulls, false, sizeof(nulls));
a = GUCArrayAdd(NULL, setstmt->name, valuestr);
values[Anum_pg_db_role_setting_setdatabase - 1] =
ObjectIdGetDatum(databaseid);
values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid);
values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
simple_heap_insert(rel, newtuple);
/* Update indexes */
CatalogUpdateIndexes(rel, newtuple);
}
systable_endscan(scan);
/* Close pg_db_role_setting, but keep lock till commit */
heap_close(rel, NoLock);
}
/*
* Drop some settings from the catalog. These can be for a particular
* database, or for a particular role. (It is of course possible to do both
* too, but it doesn't make sense for current uses.)
*/
void
DropSetting(Oid databaseid, Oid roleid)
{
Relation relsetting;
HeapScanDesc scan;
ScanKeyData keys[2];
HeapTuple tup;
int numkeys = 0;
relsetting = heap_open(DbRoleSettingRelationId, RowExclusiveLock);
if (OidIsValid(databaseid))
{
ScanKeyInit(&keys[numkeys],
Anum_pg_db_role_setting_setdatabase,
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(databaseid));
numkeys++;
}
if (OidIsValid(roleid))
{
ScanKeyInit(&keys[numkeys],
Anum_pg_db_role_setting_setrole,
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(roleid));
numkeys++;
}
scan = heap_beginscan(relsetting, SnapshotNow, numkeys, keys);
while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
{
simple_heap_delete(relsetting, &tup->t_self);
}
heap_endscan(scan);
heap_close(relsetting, RowExclusiveLock);
}
/*
* Scan pg_db_role_setting looking for applicable settings, and load them on
* the current process.
*
* relsetting is pg_db_role_setting, already opened and locked.
*
* Note: we only consider setting for the exact databaseid/roleid combination.
* This probably needs to be called more than once, with InvalidOid passed as
* databaseid/roleid.
*/
void
ApplySetting(Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
{
SysScanDesc scan;
ScanKeyData keys[2];
HeapTuple tup;
ScanKeyInit(&keys[0],
Anum_pg_db_role_setting_setdatabase,
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(databaseid));
ScanKeyInit(&keys[1],
Anum_pg_db_role_setting_setrole,
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(roleid));
scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
SnapshotNow, 2, keys);
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
bool isnull;
Datum datum;
datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
RelationGetDescr(relsetting), &isnull);
if (!isnull)
{
ArrayType *a = DatumGetArrayTypeP(datum);
/*
* We process all the options at SUSET level. We assume that the
* right to insert an option into pg_db_role_setting was checked
* when it was inserted.
*/
ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
}
}
systable_endscan(scan);
}
|