1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

Make it possibly to specify GUC params per user and per database.

Create a new catalog pg_db_role_setting where they are now stored, and better
encapsulate the code that deals with settings into its realm.  The old
datconfig and rolconfig columns are removed.

psql has gained a \drds command to display the settings.

Backwards compatibility warning: while the backwards-compatible system views
still have the config columns, they no longer completely represent the
configuration for a user or database.

Catalog version bumped.
This commit is contained in:
Alvaro Herrera
2009-10-07 22:14:26 +00:00
parent 07cefdfb7a
commit 2eda8dfb52
32 changed files with 738 additions and 279 deletions

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.188 2009/09/01 02:54:51 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.189 2009/10/07 22:14:19 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,7 +19,10 @@
#include "catalog/indexing.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/user.h"
#include "libpq/md5.h"
#include "miscadmin.h"
@ -27,7 +30,6 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
@ -341,8 +343,6 @@ CreateRole(CreateRoleStmt *stmt)
else
new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = true;
new_record_nulls[Anum_pg_authid_rolconfig - 1] = true;
tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
/*
@ -715,30 +715,29 @@ AlterRole(AlterRoleStmt *stmt)
void
AlterRoleSet(AlterRoleSetStmt *stmt)
{
char *valuestr;
HeapTuple oldtuple,
newtuple;
Relation rel;
Datum repl_val[Natts_pg_authid];
bool repl_null[Natts_pg_authid];
bool repl_repl[Natts_pg_authid];
HeapTuple roletuple;
Oid databaseid = InvalidOid;
valuestr = ExtractSetVariableArgs(stmt->setstmt);
roletuple = SearchSysCache(AUTHNAME,
PointerGetDatum(stmt->role),
0, 0, 0);
rel = heap_open(AuthIdRelationId, RowExclusiveLock);
oldtuple = SearchSysCache(AUTHNAME,
PointerGetDatum(stmt->role),
0, 0, 0);
if (!HeapTupleIsValid(oldtuple))
if (!HeapTupleIsValid(roletuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", stmt->role)));
/*
* Obtain a lock on the role and make sure it didn't go away in the
* meantime.
*/
shdepLockAndCheckObject(AuthIdRelationId, HeapTupleGetOid(roletuple));
/*
* To mess with a superuser you gotta be superuser; else you need
* createrole, or just want to change your own settings
*/
if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)
if (((Form_pg_authid) GETSTRUCT(roletuple))->rolsuper)
{
if (!superuser())
ereport(ERROR,
@ -748,54 +747,25 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
else
{
if (!have_createrole_privilege() &&
HeapTupleGetOid(oldtuple) != GetUserId())
HeapTupleGetOid(roletuple) != GetUserId())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied")));
}
memset(repl_repl, false, sizeof(repl_repl));
repl_repl[Anum_pg_authid_rolconfig - 1] = true;
if (stmt->setstmt->kind == VAR_RESET_ALL)
/* look up and lock the database, if specified */
if (stmt->database != NULL)
{
/* RESET ALL, so just set rolconfig to null */
repl_null[Anum_pg_authid_rolconfig - 1] = true;
repl_val[Anum_pg_authid_rolconfig - 1] = (Datum) 0;
}
else
{
Datum datum;
bool isnull;
ArrayType *array;
repl_null[Anum_pg_authid_rolconfig - 1] = false;
/* Extract old value of rolconfig */
datum = SysCacheGetAttr(AUTHNAME, oldtuple,
Anum_pg_authid_rolconfig, &isnull);
array = isnull ? NULL : DatumGetArrayTypeP(datum);
/* Update (valuestr is NULL in RESET cases) */
if (valuestr)
array = GUCArrayAdd(array, stmt->setstmt->name, valuestr);
else
array = GUCArrayDelete(array, stmt->setstmt->name);
if (array)
repl_val[Anum_pg_authid_rolconfig - 1] = PointerGetDatum(array);
else
repl_null[Anum_pg_authid_rolconfig - 1] = true;
databaseid = get_database_oid(stmt->database);
if (!OidIsValid(databaseid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("database \"%s\" not found", stmt->database)));
shdepLockAndCheckObject(DatabaseRelationId, databaseid);
}
newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
simple_heap_update(rel, &oldtuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
ReleaseSysCache(oldtuple);
heap_close(rel, RowExclusiveLock);
AlterSetting(databaseid, HeapTupleGetOid(roletuple), stmt->setstmt);
ReleaseSysCache(roletuple);
}
@ -943,6 +913,11 @@ DropRole(DropRoleStmt *stmt)
*/
DeleteSharedComments(roleid, AuthIdRelationId);
/*
* Remove settings for this role.
*/
DropSetting(InvalidOid, roleid);
/*
* Advance command counter so that later iterations of this loop will
* see the changes already made. This is essential if, for example,