Header And Logo

PostgreSQL
| The world's most advanced open source database.

pg_db_role_setting.c

Go to the documentation of this file.
00001 /*
00002  * pg_db_role_setting.c
00003  *      Routines to support manipulation of the pg_db_role_setting relation
00004  *
00005  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00006  * Portions Copyright (c) 1994, Regents of the University of California
00007  *
00008  * IDENTIFICATION
00009  *      src/backend/catalog/pg_db_role_setting.c
00010  */
00011 #include "postgres.h"
00012 
00013 #include "access/genam.h"
00014 #include "access/heapam.h"
00015 #include "access/htup_details.h"
00016 #include "catalog/indexing.h"
00017 #include "catalog/objectaccess.h"
00018 #include "catalog/pg_db_role_setting.h"
00019 #include "utils/fmgroids.h"
00020 #include "utils/rel.h"
00021 #include "utils/tqual.h"
00022 
00023 void
00024 AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
00025 {
00026     char       *valuestr;
00027     HeapTuple   tuple;
00028     Relation    rel;
00029     ScanKeyData scankey[2];
00030     SysScanDesc scan;
00031 
00032     valuestr = ExtractSetVariableArgs(setstmt);
00033 
00034     /* Get the old tuple, if any. */
00035 
00036     rel = heap_open(DbRoleSettingRelationId, RowExclusiveLock);
00037     ScanKeyInit(&scankey[0],
00038                 Anum_pg_db_role_setting_setdatabase,
00039                 BTEqualStrategyNumber, F_OIDEQ,
00040                 ObjectIdGetDatum(databaseid));
00041     ScanKeyInit(&scankey[1],
00042                 Anum_pg_db_role_setting_setrole,
00043                 BTEqualStrategyNumber, F_OIDEQ,
00044                 ObjectIdGetDatum(roleid));
00045     scan = systable_beginscan(rel, DbRoleSettingDatidRolidIndexId, true,
00046                               SnapshotNow, 2, scankey);
00047     tuple = systable_getnext(scan);
00048 
00049     /*
00050      * There are three cases:
00051      *
00052      * - in RESET ALL, request GUC to reset the settings array and update the
00053      * catalog if there's anything left, delete it otherwise
00054      *
00055      * - in other commands, if there's a tuple in pg_db_role_setting, update
00056      * it; if it ends up empty, delete it
00057      *
00058      * - otherwise, insert a new pg_db_role_setting tuple, but only if the
00059      * command is not RESET
00060      */
00061     if (setstmt->kind == VAR_RESET_ALL)
00062     {
00063         if (HeapTupleIsValid(tuple))
00064         {
00065             ArrayType  *new = NULL;
00066             Datum       datum;
00067             bool        isnull;
00068 
00069             datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
00070                                  RelationGetDescr(rel), &isnull);
00071 
00072             if (!isnull)
00073                 new = GUCArrayReset(DatumGetArrayTypeP(datum));
00074 
00075             if (new)
00076             {
00077                 Datum       repl_val[Natts_pg_db_role_setting];
00078                 bool        repl_null[Natts_pg_db_role_setting];
00079                 bool        repl_repl[Natts_pg_db_role_setting];
00080                 HeapTuple   newtuple;
00081 
00082                 memset(repl_repl, false, sizeof(repl_repl));
00083 
00084                 repl_val[Anum_pg_db_role_setting_setconfig - 1] =
00085                     PointerGetDatum(new);
00086                 repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
00087                 repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
00088 
00089                 newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
00090                                              repl_val, repl_null, repl_repl);
00091                 simple_heap_update(rel, &tuple->t_self, newtuple);
00092 
00093                 /* Update indexes */
00094                 CatalogUpdateIndexes(rel, newtuple);
00095             }
00096             else
00097                 simple_heap_delete(rel, &tuple->t_self);
00098         }
00099     }
00100     else if (HeapTupleIsValid(tuple))
00101     {
00102         Datum       repl_val[Natts_pg_db_role_setting];
00103         bool        repl_null[Natts_pg_db_role_setting];
00104         bool        repl_repl[Natts_pg_db_role_setting];
00105         HeapTuple   newtuple;
00106         Datum       datum;
00107         bool        isnull;
00108         ArrayType  *a;
00109 
00110         memset(repl_repl, false, sizeof(repl_repl));
00111         repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
00112         repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
00113 
00114         /* Extract old value of setconfig */
00115         datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
00116                              RelationGetDescr(rel), &isnull);
00117         a = isnull ? NULL : DatumGetArrayTypeP(datum);
00118 
00119         /* Update (valuestr is NULL in RESET cases) */
00120         if (valuestr)
00121             a = GUCArrayAdd(a, setstmt->name, valuestr);
00122         else
00123             a = GUCArrayDelete(a, setstmt->name);
00124 
00125         if (a)
00126         {
00127             repl_val[Anum_pg_db_role_setting_setconfig - 1] =
00128                 PointerGetDatum(a);
00129 
00130             newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
00131                                          repl_val, repl_null, repl_repl);
00132             simple_heap_update(rel, &tuple->t_self, newtuple);
00133 
00134             /* Update indexes */
00135             CatalogUpdateIndexes(rel, newtuple);
00136         }
00137         else
00138             simple_heap_delete(rel, &tuple->t_self);
00139     }
00140     else if (valuestr)
00141     {
00142         /* non-null valuestr means it's not RESET, so insert a new tuple */
00143         HeapTuple   newtuple;
00144         Datum       values[Natts_pg_db_role_setting];
00145         bool        nulls[Natts_pg_db_role_setting];
00146         ArrayType  *a;
00147 
00148         memset(nulls, false, sizeof(nulls));
00149 
00150         a = GUCArrayAdd(NULL, setstmt->name, valuestr);
00151 
00152         values[Anum_pg_db_role_setting_setdatabase - 1] =
00153             ObjectIdGetDatum(databaseid);
00154         values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid);
00155         values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
00156         newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
00157 
00158         simple_heap_insert(rel, newtuple);
00159 
00160         /* Update indexes */
00161         CatalogUpdateIndexes(rel, newtuple);
00162     }
00163 
00164     InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
00165                                  databaseid, 0, roleid, false);
00166 
00167     systable_endscan(scan);
00168 
00169     /* Close pg_db_role_setting, but keep lock till commit */
00170     heap_close(rel, NoLock);
00171 }
00172 
00173 /*
00174  * Drop some settings from the catalog.  These can be for a particular
00175  * database, or for a particular role.  (It is of course possible to do both
00176  * too, but it doesn't make sense for current uses.)
00177  */
00178 void
00179 DropSetting(Oid databaseid, Oid roleid)
00180 {
00181     Relation    relsetting;
00182     HeapScanDesc scan;
00183     ScanKeyData keys[2];
00184     HeapTuple   tup;
00185     int         numkeys = 0;
00186 
00187     relsetting = heap_open(DbRoleSettingRelationId, RowExclusiveLock);
00188 
00189     if (OidIsValid(databaseid))
00190     {
00191         ScanKeyInit(&keys[numkeys],
00192                     Anum_pg_db_role_setting_setdatabase,
00193                     BTEqualStrategyNumber,
00194                     F_OIDEQ,
00195                     ObjectIdGetDatum(databaseid));
00196         numkeys++;
00197     }
00198     if (OidIsValid(roleid))
00199     {
00200         ScanKeyInit(&keys[numkeys],
00201                     Anum_pg_db_role_setting_setrole,
00202                     BTEqualStrategyNumber,
00203                     F_OIDEQ,
00204                     ObjectIdGetDatum(roleid));
00205         numkeys++;
00206     }
00207 
00208     scan = heap_beginscan(relsetting, SnapshotNow, numkeys, keys);
00209     while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
00210     {
00211         simple_heap_delete(relsetting, &tup->t_self);
00212     }
00213     heap_endscan(scan);
00214 
00215     heap_close(relsetting, RowExclusiveLock);
00216 }
00217 
00218 /*
00219  * Scan pg_db_role_setting looking for applicable settings, and load them on
00220  * the current process.
00221  *
00222  * relsetting is pg_db_role_setting, already opened and locked.
00223  *
00224  * Note: we only consider setting for the exact databaseid/roleid combination.
00225  * This probably needs to be called more than once, with InvalidOid passed as
00226  * databaseid/roleid.
00227  */
00228 void
00229 ApplySetting(Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
00230 {
00231     SysScanDesc scan;
00232     ScanKeyData keys[2];
00233     HeapTuple   tup;
00234 
00235     ScanKeyInit(&keys[0],
00236                 Anum_pg_db_role_setting_setdatabase,
00237                 BTEqualStrategyNumber,
00238                 F_OIDEQ,
00239                 ObjectIdGetDatum(databaseid));
00240     ScanKeyInit(&keys[1],
00241                 Anum_pg_db_role_setting_setrole,
00242                 BTEqualStrategyNumber,
00243                 F_OIDEQ,
00244                 ObjectIdGetDatum(roleid));
00245 
00246     scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
00247                               SnapshotNow, 2, keys);
00248     while (HeapTupleIsValid(tup = systable_getnext(scan)))
00249     {
00250         bool        isnull;
00251         Datum       datum;
00252 
00253         datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
00254                              RelationGetDescr(relsetting), &isnull);
00255         if (!isnull)
00256         {
00257             ArrayType  *a = DatumGetArrayTypeP(datum);
00258 
00259             /*
00260              * We process all the options at SUSET level.  We assume that the
00261              * right to insert an option into pg_db_role_setting was checked
00262              * when it was inserted.
00263              */
00264             ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
00265         }
00266     }
00267 
00268     systable_endscan(scan);
00269 }