]> granicus.if.org Git - postgresql/blob - src/backend/catalog/pg_db_role_setting.c
Update copyright for the year 2010.
[postgresql] / src / backend / catalog / pg_db_role_setting.c
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-2010, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  * IDENTIFICATION
9  *              $PostgreSQL: pgsql/src/backend/catalog/pg_db_role_setting.c,v 1.2 2010/01/02 16:57:36 momjian Exp $
10  */
11 #include "postgres.h"
12
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"
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 = 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);
48
49         /*
50          * There are three cases:
51          *
52          * - in RESET ALL, simply delete the pg_db_role_setting tuple (if any)
53          *
54          * - in other commands, if there's a tuple in pg_db_role_setting, update it;
55          *   if it ends up empty, delete it
56          *
57          * - otherwise, insert a new pg_db_role_setting tuple, but only if the
58          *   command is not RESET
59          */
60         if (setstmt->kind == VAR_RESET_ALL)
61         {
62                 if (HeapTupleIsValid(tuple))
63                         simple_heap_delete(rel, &tuple->t_self);
64         }
65         else if (HeapTupleIsValid(tuple))
66         {
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];
70                 HeapTuple       newtuple;
71                 Datum           datum;
72                 bool            isnull;
73                 ArrayType  *a;
74
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;
78
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);
83
84                 /* Update (valuestr is NULL in RESET cases) */
85                 if (valuestr)
86                         a = GUCArrayAdd(a, setstmt->name, valuestr);
87                 else
88                         a = GUCArrayDelete(a, setstmt->name);
89
90                 if (a)
91                 {
92                         repl_val[Anum_pg_db_role_setting_setconfig - 1] =
93                                 PointerGetDatum(a);
94
95                         newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
96                                                                                  repl_val, repl_null, repl_repl);
97                         simple_heap_update(rel, &tuple->t_self, newtuple);
98
99                         /* Update indexes */
100                         CatalogUpdateIndexes(rel, newtuple);
101                 }
102                 else
103                         simple_heap_delete(rel, &tuple->t_self);
104         }
105         else if (valuestr)
106         {
107                 /* non-null valuestr means it's not RESET, so insert a new tuple */
108                 HeapTuple       newtuple;
109                 Datum           values[Natts_pg_db_role_setting];
110                 bool            nulls[Natts_pg_db_role_setting];
111                 ArrayType  *a;
112
113                 memset(nulls, false, sizeof(nulls));
114                 
115                 a = GUCArrayAdd(NULL, setstmt->name, valuestr);
116
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);
122
123                 simple_heap_insert(rel, newtuple);
124
125                 /* Update indexes */
126                 CatalogUpdateIndexes(rel, newtuple);
127         }
128
129         systable_endscan(scan);
130
131         /* Close pg_db_role_setting, but keep lock till commit */
132         heap_close(rel, NoLock);
133 }
134
135 /*
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.)
139  */
140 void
141 DropSetting(Oid databaseid, Oid roleid)
142 {
143         Relation                relsetting;
144         HeapScanDesc    scan;
145         ScanKeyData             keys[2];
146         HeapTuple               tup;
147         int                             numkeys = 0;
148
149         relsetting = heap_open(DbRoleSettingRelationId, RowExclusiveLock);
150
151         if (OidIsValid(databaseid))
152         {
153                 ScanKeyInit(&keys[numkeys],
154                                         Anum_pg_db_role_setting_setdatabase,
155                                         BTEqualStrategyNumber,
156                                         F_OIDEQ,
157                                         ObjectIdGetDatum(databaseid));
158                 numkeys++;
159         }
160         if (OidIsValid(roleid))
161         {
162                 ScanKeyInit(&keys[numkeys],
163                                         Anum_pg_db_role_setting_setrole,
164                                         BTEqualStrategyNumber,
165                                         F_OIDEQ,
166                                         ObjectIdGetDatum(roleid));
167                 numkeys++;
168         }
169
170         scan = heap_beginscan(relsetting, SnapshotNow, numkeys, keys);
171         while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
172         {
173                 simple_heap_delete(relsetting, &tup->t_self);
174         }
175         heap_endscan(scan);
176
177         heap_close(relsetting, RowExclusiveLock);
178 }
179
180 /*
181  * Scan pg_db_role_setting looking for applicable settings, and load them on
182  * the current process.
183  *
184  * relsetting is pg_db_role_setting, already opened and locked.
185  *
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
188  * databaseid/roleid.
189  */
190 void
191 ApplySetting(Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
192 {
193         SysScanDesc             scan;
194         ScanKeyData             keys[2];
195         HeapTuple               tup;
196
197         ScanKeyInit(&keys[0],
198                                 Anum_pg_db_role_setting_setdatabase,
199                                 BTEqualStrategyNumber,
200                                 F_OIDEQ,
201                                 ObjectIdGetDatum(databaseid));
202         ScanKeyInit(&keys[1],
203                                 Anum_pg_db_role_setting_setrole,
204                                 BTEqualStrategyNumber,
205                                 F_OIDEQ,
206                                 ObjectIdGetDatum(roleid));
207
208         scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
209                                                           SnapshotNow, 2, keys);
210         while (HeapTupleIsValid(tup = systable_getnext(scan)))
211         {
212                 bool    isnull;
213                 Datum   datum;
214
215                 datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
216                                                          RelationGetDescr(relsetting), &isnull);
217                 if (!isnull)
218                 {
219                         ArrayType  *a = DatumGetArrayTypeP(datum);
220
221                         /*
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.
225                          */
226                         ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
227                 }
228         }
229
230         systable_endscan(scan);
231 }