~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/catalog/pg_db_role_setting.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2011, 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.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, 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
 
 
69
                        datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
 
70
                                                                 RelationGetDescr(rel), &isnull);
 
71
 
 
72
                        if (!isnull)
 
73
                                new = GUCArrayReset(DatumGetArrayTypeP(datum));
 
74
 
 
75
                        if (new)
 
76
                        {
 
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;
 
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
                                simple_heap_update(rel, &tuple->t_self, newtuple);
 
92
 
 
93
                                /* Update indexes */
 
94
                                CatalogUpdateIndexes(rel, newtuple);
 
95
                        }
 
96
                        else
 
97
                                simple_heap_delete(rel, &tuple->t_self);
 
98
                }
 
99
        }
 
100
        else if (HeapTupleIsValid(tuple))
 
101
        {
 
102
                Datum           repl_val[Natts_pg_db_role_setting];
 
103
                bool            repl_null[Natts_pg_db_role_setting];
 
104
                bool            repl_repl[Natts_pg_db_role_setting];
 
105
                HeapTuple       newtuple;
 
106
                Datum           datum;
 
107
                bool            isnull;
 
108
                ArrayType  *a;
 
109
 
 
110
                memset(repl_repl, false, sizeof(repl_repl));
 
111
                repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
 
112
                repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
 
113
 
 
114
                /* Extract old value of setconfig */
 
115
                datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
 
116
                                                         RelationGetDescr(rel), &isnull);
 
117
                a = isnull ? NULL : DatumGetArrayTypeP(datum);
 
118
 
 
119
                /* Update (valuestr is NULL in RESET cases) */
 
120
                if (valuestr)
 
121
                        a = GUCArrayAdd(a, setstmt->name, valuestr);
 
122
                else
 
123
                        a = GUCArrayDelete(a, setstmt->name);
 
124
 
 
125
                if (a)
 
126
                {
 
127
                        repl_val[Anum_pg_db_role_setting_setconfig - 1] =
 
128
                                PointerGetDatum(a);
 
129
 
 
130
                        newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
 
131
                                                                                 repl_val, repl_null, repl_repl);
 
132
                        simple_heap_update(rel, &tuple->t_self, newtuple);
 
133
 
 
134
                        /* Update indexes */
 
135
                        CatalogUpdateIndexes(rel, newtuple);
 
136
                }
 
137
                else
 
138
                        simple_heap_delete(rel, &tuple->t_self);
 
139
        }
 
140
        else if (valuestr)
 
141
        {
 
142
                /* non-null valuestr means it's not RESET, so insert a new tuple */
 
143
                HeapTuple       newtuple;
 
144
                Datum           values[Natts_pg_db_role_setting];
 
145
                bool            nulls[Natts_pg_db_role_setting];
 
146
                ArrayType  *a;
 
147
 
 
148
                memset(nulls, false, sizeof(nulls));
 
149
 
 
150
                a = GUCArrayAdd(NULL, setstmt->name, valuestr);
 
151
 
 
152
                values[Anum_pg_db_role_setting_setdatabase - 1] =
 
153
                        ObjectIdGetDatum(databaseid);
 
154
                values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid);
 
155
                values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
 
156
                newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
 
157
 
 
158
                simple_heap_insert(rel, newtuple);
 
159
 
 
160
                /* Update indexes */
 
161
                CatalogUpdateIndexes(rel, newtuple);
 
162
        }
 
163
 
 
164
        systable_endscan(scan);
 
165
 
 
166
        /* Close pg_db_role_setting, but keep lock till commit */
 
167
        heap_close(rel, NoLock);
 
168
}
 
169
 
 
170
/*
 
171
 * Drop some settings from the catalog.  These can be for a particular
 
172
 * database, or for a particular role.  (It is of course possible to do both
 
173
 * too, but it doesn't make sense for current uses.)
 
174
 */
 
175
void
 
176
DropSetting(Oid databaseid, Oid roleid)
 
177
{
 
178
        Relation        relsetting;
 
179
        HeapScanDesc scan;
 
180
        ScanKeyData keys[2];
 
181
        HeapTuple       tup;
 
182
        int                     numkeys = 0;
 
183
 
 
184
        relsetting = heap_open(DbRoleSettingRelationId, RowExclusiveLock);
 
185
 
 
186
        if (OidIsValid(databaseid))
 
187
        {
 
188
                ScanKeyInit(&keys[numkeys],
 
189
                                        Anum_pg_db_role_setting_setdatabase,
 
190
                                        BTEqualStrategyNumber,
 
191
                                        F_OIDEQ,
 
192
                                        ObjectIdGetDatum(databaseid));
 
193
                numkeys++;
 
194
        }
 
195
        if (OidIsValid(roleid))
 
196
        {
 
197
                ScanKeyInit(&keys[numkeys],
 
198
                                        Anum_pg_db_role_setting_setrole,
 
199
                                        BTEqualStrategyNumber,
 
200
                                        F_OIDEQ,
 
201
                                        ObjectIdGetDatum(roleid));
 
202
                numkeys++;
 
203
        }
 
204
 
 
205
        scan = heap_beginscan(relsetting, SnapshotNow, numkeys, keys);
 
206
        while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
 
207
        {
 
208
                simple_heap_delete(relsetting, &tup->t_self);
 
209
        }
 
210
        heap_endscan(scan);
 
211
 
 
212
        heap_close(relsetting, RowExclusiveLock);
 
213
}
 
214
 
 
215
/*
 
216
 * Scan pg_db_role_setting looking for applicable settings, and load them on
 
217
 * the current process.
 
218
 *
 
219
 * relsetting is pg_db_role_setting, already opened and locked.
 
220
 *
 
221
 * Note: we only consider setting for the exact databaseid/roleid combination.
 
222
 * This probably needs to be called more than once, with InvalidOid passed as
 
223
 * databaseid/roleid.
 
224
 */
 
225
void
 
226
ApplySetting(Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
 
227
{
 
228
        SysScanDesc scan;
 
229
        ScanKeyData keys[2];
 
230
        HeapTuple       tup;
 
231
 
 
232
        ScanKeyInit(&keys[0],
 
233
                                Anum_pg_db_role_setting_setdatabase,
 
234
                                BTEqualStrategyNumber,
 
235
                                F_OIDEQ,
 
236
                                ObjectIdGetDatum(databaseid));
 
237
        ScanKeyInit(&keys[1],
 
238
                                Anum_pg_db_role_setting_setrole,
 
239
                                BTEqualStrategyNumber,
 
240
                                F_OIDEQ,
 
241
                                ObjectIdGetDatum(roleid));
 
242
 
 
243
        scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
 
244
                                                          SnapshotNow, 2, keys);
 
245
        while (HeapTupleIsValid(tup = systable_getnext(scan)))
 
246
        {
 
247
                bool            isnull;
 
248
                Datum           datum;
 
249
 
 
250
                datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
 
251
                                                         RelationGetDescr(relsetting), &isnull);
 
252
                if (!isnull)
 
253
                {
 
254
                        ArrayType  *a = DatumGetArrayTypeP(datum);
 
255
 
 
256
                        /*
 
257
                         * We process all the options at SUSET level.  We assume that the
 
258
                         * right to insert an option into pg_db_role_setting was checked
 
259
                         * when it was inserted.
 
260
                         */
 
261
                        ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
 
262
                }
 
263
        }
 
264
 
 
265
        systable_endscan(scan);
 
266
}