mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
User and database-specific session defaults for run-time configuration
variables. New commands ALTER DATABASE ... SET and ALTER USER ... SET.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.83 2002/02/24 20:20:19 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.84 2002/03/01 22:45:08 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -32,8 +32,10 @@
|
||||
#include "miscadmin.h"
|
||||
#include "storage/freespace.h"
|
||||
#include "storage/sinval.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
@@ -287,6 +289,7 @@ createdb(const char *dbname, const char *dbowner,
|
||||
DirectFunctionCall1(textin, CStringGetDatum(dbpath ? dbpath : ""));
|
||||
|
||||
memset(new_record_nulls, ' ', sizeof(new_record_nulls));
|
||||
new_record_nulls[Anum_pg_database_datconfig - 1] = 'n';
|
||||
|
||||
tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls);
|
||||
|
||||
@@ -446,6 +449,80 @@ dropdb(const char *dbname)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ALTER DATABASE name SET ...
|
||||
*/
|
||||
void
|
||||
AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
||||
{
|
||||
char *valuestr;
|
||||
HeapTuple tuple,
|
||||
newtuple;
|
||||
Relation rel;
|
||||
ScanKeyData scankey;
|
||||
HeapScanDesc scan;
|
||||
Datum repl_val[Natts_pg_database];
|
||||
char repl_null[Natts_pg_database];
|
||||
char repl_repl[Natts_pg_database];
|
||||
int i;
|
||||
|
||||
valuestr = (stmt->value
|
||||
? ((A_Const *) lfirst(stmt->value))->val.val.str
|
||||
: NULL);
|
||||
|
||||
rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
|
||||
ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname,
|
||||
F_NAMEEQ, NameGetDatum(stmt->dbname));
|
||||
scan = heap_beginscan(rel, 0, SnapshotNow, 1, &scankey);
|
||||
tuple = heap_getnext(scan, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "database \"%s\" does not exist", stmt->dbname);
|
||||
|
||||
if (!(superuser()
|
||||
|| ((Form_pg_database) GETSTRUCT(tuple))->datdba == GetUserId()))
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
for (i = 0; i < Natts_pg_database; i++)
|
||||
repl_repl[i] = ' ';
|
||||
|
||||
repl_repl[Anum_pg_database_datconfig-1] = 'r';
|
||||
if (strcmp(stmt->variable, "all")==0 && stmt->value == NULL)
|
||||
/* RESET ALL */
|
||||
repl_null[Anum_pg_database_datconfig-1] = 'n';
|
||||
else
|
||||
{
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
ArrayType *a;
|
||||
|
||||
repl_null[Anum_pg_database_datconfig-1] = ' ';
|
||||
|
||||
datum = heap_getattr(tuple, Anum_pg_database_datconfig,
|
||||
RelationGetDescr(rel), &isnull);
|
||||
|
||||
if (valuestr)
|
||||
a = GUCArrayAdd(isnull
|
||||
? NULL
|
||||
: (ArrayType *) pg_detoast_datum((struct varlena *)datum),
|
||||
stmt->variable, valuestr);
|
||||
else
|
||||
a = GUCArrayDelete(isnull
|
||||
? NULL
|
||||
: (ArrayType *) pg_detoast_datum((struct varlena *)datum),
|
||||
stmt->variable);
|
||||
|
||||
repl_val[Anum_pg_database_datconfig-1] = PointerGetDatum(a);
|
||||
}
|
||||
|
||||
newtuple = heap_modifytuple(tuple, rel, repl_val, repl_null, repl_repl);
|
||||
simple_heap_update(rel, &tuple->t_self, newtuple);
|
||||
|
||||
heap_endscan(scan);
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.90 2001/11/05 17:46:25 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.91 2002/03/01 22:45:08 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
@@ -406,6 +407,8 @@ CreateUser(CreateUserStmt *stmt)
|
||||
new_record_nulls[Anum_pg_shadow_passwd - 1] = password ? ' ' : 'n';
|
||||
new_record_nulls[Anum_pg_shadow_valuntil - 1] = validUntil ? ' ' : 'n';
|
||||
|
||||
new_record_nulls[Anum_pg_shadow_useconfig - 1] = 'n';
|
||||
|
||||
tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls);
|
||||
|
||||
/*
|
||||
@@ -653,6 +656,11 @@ AlterUser(AlterUserStmt *stmt)
|
||||
new_record_nulls[Anum_pg_shadow_valuntil - 1] = null ? 'n' : ' ';
|
||||
}
|
||||
|
||||
/* leave useconfig as is */
|
||||
new_record[Anum_pg_shadow_useconfig - 1] =
|
||||
heap_getattr(tuple, Anum_pg_shadow_useconfig, pg_shadow_dsc, &null);
|
||||
new_record_nulls[Anum_pg_shadow_useconfig - 1] = null ? 'n' : ' ';
|
||||
|
||||
new_tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls);
|
||||
simple_heap_update(pg_shadow_rel, &tuple->t_self, new_tuple);
|
||||
|
||||
@@ -684,6 +692,85 @@ AlterUser(AlterUserStmt *stmt)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ALTER USER ... SET
|
||||
*/
|
||||
void
|
||||
AlterUserSet(AlterUserSetStmt *stmt)
|
||||
{
|
||||
char *valuestr;
|
||||
HeapTuple oldtuple,
|
||||
newtuple;
|
||||
Relation rel;
|
||||
Datum repl_val[Natts_pg_shadow];
|
||||
char repl_null[Natts_pg_shadow];
|
||||
char repl_repl[Natts_pg_shadow];
|
||||
int i;
|
||||
|
||||
valuestr = (stmt->value
|
||||
? ((A_Const *) lfirst(stmt->value))->val.val.str
|
||||
: NULL);
|
||||
|
||||
rel = heap_openr(ShadowRelationName, RowExclusiveLock);
|
||||
oldtuple = SearchSysCache(SHADOWNAME,
|
||||
PointerGetDatum(stmt->user),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(oldtuple))
|
||||
elog(ERROR, "user \"%s\" does not exist", stmt->user);
|
||||
|
||||
if (!(superuser()
|
||||
|| ((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetUserId()))
|
||||
elog(ERROR, "permission denied");
|
||||
|
||||
for (i = 0; i < Natts_pg_shadow; i++)
|
||||
repl_repl[i] = ' ';
|
||||
|
||||
repl_repl[Anum_pg_shadow_useconfig-1] = 'r';
|
||||
if (strcmp(stmt->variable, "all")==0 && stmt->value == NULL)
|
||||
/* RESET ALL */
|
||||
repl_null[Anum_pg_shadow_useconfig-1] = 'n';
|
||||
else
|
||||
{
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
ArrayType *a;
|
||||
|
||||
repl_null[Anum_pg_shadow_useconfig-1] = ' ';
|
||||
|
||||
datum = SysCacheGetAttr(SHADOWNAME, oldtuple,
|
||||
Anum_pg_shadow_useconfig, &isnull);
|
||||
|
||||
if (valuestr)
|
||||
a = GUCArrayAdd(isnull
|
||||
? NULL
|
||||
: (ArrayType *) pg_detoast_datum((struct varlena *)datum),
|
||||
stmt->variable, valuestr);
|
||||
else
|
||||
a = GUCArrayDelete(isnull
|
||||
? NULL
|
||||
: (ArrayType *) pg_detoast_datum((struct varlena *)datum),
|
||||
stmt->variable);
|
||||
|
||||
repl_val[Anum_pg_shadow_useconfig-1] = PointerGetDatum(a);
|
||||
}
|
||||
|
||||
newtuple = heap_modifytuple(oldtuple, rel, repl_val, repl_null, repl_repl);
|
||||
simple_heap_update(rel, &oldtuple->t_self, newtuple);
|
||||
|
||||
{
|
||||
Relation idescs[Num_pg_shadow_indices];
|
||||
|
||||
CatalogOpenIndices(Num_pg_shadow_indices, Name_pg_shadow_indices, idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_shadow_indices, rel, newtuple);
|
||||
CatalogCloseIndices(Num_pg_shadow_indices, idescs);
|
||||
}
|
||||
|
||||
ReleaseSysCache(oldtuple);
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* DROP USER
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.164 2002/03/01 06:01:18 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.165 2002/03/01 22:45:11 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2245,6 +2245,20 @@ _copyCreatedbStmt(CreatedbStmt *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static AlterDatabaseSetStmt *
|
||||
_copyAlterDatabaseSetStmt(AlterDatabaseSetStmt *from)
|
||||
{
|
||||
AlterDatabaseSetStmt *newnode = makeNode(AlterDatabaseSetStmt);
|
||||
|
||||
if (from->dbname)
|
||||
newnode->dbname = pstrdup(from->dbname);
|
||||
if (from->variable)
|
||||
newnode->variable = pstrdup(from->variable);
|
||||
Node_Copy(from, newnode, value);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static DropdbStmt *
|
||||
_copyDropdbStmt(DropdbStmt *from)
|
||||
{
|
||||
@@ -2427,6 +2441,20 @@ _copyAlterUserStmt(AlterUserStmt *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static AlterUserSetStmt *
|
||||
_copyAlterUserSetStmt(AlterUserSetStmt *from)
|
||||
{
|
||||
AlterUserSetStmt *newnode = makeNode(AlterUserSetStmt);
|
||||
|
||||
if (from->user)
|
||||
newnode->user = pstrdup(from->user);
|
||||
if (from->variable)
|
||||
newnode->user = pstrdup(from->variable);
|
||||
Node_Copy(from, newnode, value);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static DropUserStmt *
|
||||
_copyDropUserStmt(DropUserStmt *from)
|
||||
{
|
||||
@@ -2845,6 +2873,9 @@ copyObject(void *from)
|
||||
case T_CreatedbStmt:
|
||||
retval = _copyCreatedbStmt(from);
|
||||
break;
|
||||
case T_AlterDatabaseSetStmt:
|
||||
retval = _copyAlterDatabaseSetStmt(from);
|
||||
break;
|
||||
case T_DropdbStmt:
|
||||
retval = _copyDropdbStmt(from);
|
||||
break;
|
||||
@@ -2884,6 +2915,9 @@ copyObject(void *from)
|
||||
case T_AlterUserStmt:
|
||||
retval = _copyAlterUserStmt(from);
|
||||
break;
|
||||
case T_AlterUserSetStmt:
|
||||
retval = _copyAlterUserSetStmt(from);
|
||||
break;
|
||||
case T_DropUserStmt:
|
||||
retval = _copyDropUserStmt(from);
|
||||
break;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.111 2002/02/26 22:47:05 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.112 2002/03/01 22:45:12 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1112,6 +1112,19 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
|
||||
{
|
||||
if (!equalstr(a->dbname, b->dbname))
|
||||
return false;
|
||||
if (!equalstr(a->variable, b->variable))
|
||||
return false;
|
||||
if (!equal(a->value, b->value))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalDropdbStmt(DropdbStmt *a, DropdbStmt *b)
|
||||
{
|
||||
@@ -1289,6 +1302,19 @@ _equalAlterUserStmt(AlterUserStmt *a, AlterUserStmt *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalAlterUserSetStmt(AlterUserSetStmt *a, AlterUserSetStmt *b)
|
||||
{
|
||||
if (!equalstr(a->user, b->user))
|
||||
return false;
|
||||
if (!equalstr(a->variable, b->variable))
|
||||
return false;
|
||||
if (!equal(a->value, b->value))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
|
||||
{
|
||||
@@ -1988,6 +2014,9 @@ equal(void *a, void *b)
|
||||
case T_CreatedbStmt:
|
||||
retval = _equalCreatedbStmt(a, b);
|
||||
break;
|
||||
case T_AlterDatabaseSetStmt:
|
||||
retval = _equalAlterDatabaseSetStmt(a, b);
|
||||
break;
|
||||
case T_DropdbStmt:
|
||||
retval = _equalDropdbStmt(a, b);
|
||||
break;
|
||||
@@ -2027,6 +2056,9 @@ equal(void *a, void *b)
|
||||
case T_AlterUserStmt:
|
||||
retval = _equalAlterUserStmt(a, b);
|
||||
break;
|
||||
case T_AlterUserSetStmt:
|
||||
retval = _equalAlterUserSetStmt(a, b);
|
||||
break;
|
||||
case T_DropUserStmt:
|
||||
retval = _equalDropUserStmt(a, b);
|
||||
break;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.281 2002/02/25 03:37:14 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.282 2002/03/01 22:45:12 petere Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -130,8 +130,8 @@ static void doNegateFloat(Value *v);
|
||||
}
|
||||
|
||||
%type <node> stmt,
|
||||
AlterGroupStmt, AlterSchemaStmt, AlterTableStmt, AlterUserStmt,
|
||||
AnalyzeStmt,
|
||||
AlterDatabaseSetStmt, AlterGroupStmt, AlterSchemaStmt, AlterTableStmt,
|
||||
AlterUserStmt, AlterUserSetStmt, AnalyzeStmt,
|
||||
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
|
||||
CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
|
||||
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
|
||||
@@ -436,10 +436,12 @@ stmtmulti: stmtmulti ';' stmt
|
||||
}
|
||||
;
|
||||
|
||||
stmt : AlterSchemaStmt
|
||||
| AlterTableStmt
|
||||
stmt : AlterDatabaseSetStmt
|
||||
| AlterGroupStmt
|
||||
| AlterSchemaStmt
|
||||
| AlterTableStmt
|
||||
| AlterUserStmt
|
||||
| AlterUserSetStmt
|
||||
| ClosePortalStmt
|
||||
| CopyStmt
|
||||
| CreateStmt
|
||||
@@ -539,6 +541,26 @@ AlterUserStmt: ALTER USER UserId OptUserList
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
AlterUserSetStmt: ALTER USER UserId VariableSetStmt
|
||||
{
|
||||
AlterUserSetStmt *n = makeNode(AlterUserSetStmt);
|
||||
n->user = $3;
|
||||
n->variable = ((VariableSetStmt *)$4)->name;
|
||||
n->value = ((VariableSetStmt *)$4)->args;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER USER UserId VariableResetStmt
|
||||
{
|
||||
AlterUserSetStmt *n = makeNode(AlterUserSetStmt);
|
||||
n->user = $3;
|
||||
n->variable = ((VariableResetStmt *)$4)->name;
|
||||
n->value = NULL;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Drop a postgresql DBMS user
|
||||
@@ -3163,6 +3185,33 @@ opt_equal: '=' { $$ = TRUE; }
|
||||
| /*EMPTY*/ { $$ = FALSE; }
|
||||
;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* ALTER DATABASE
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt
|
||||
{
|
||||
AlterDatabaseSetStmt *n = makeNode(AlterDatabaseSetStmt);
|
||||
n->dbname = $3;
|
||||
n->variable = ((VariableSetStmt *)$4)->name;
|
||||
n->value = ((VariableSetStmt *)$4)->args;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER DATABASE database_name VariableResetStmt
|
||||
{
|
||||
AlterDatabaseSetStmt *n = makeNode(AlterDatabaseSetStmt);
|
||||
n->dbname = $3;
|
||||
n->variable = ((VariableResetStmt *)$4)->name;
|
||||
n->value = NULL;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* DROP DATABASE
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.250 2002/02/27 23:16:07 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.251 2002/03/01 22:45:13 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@@ -1707,7 +1707,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
puts("\nPOSTGRES backend interactive interface ");
|
||||
puts("$Revision: 1.250 $ $Date: 2002/02/27 23:16:07 $\n");
|
||||
puts("$Revision: 1.251 $ $Date: 2002/03/01 22:45:13 $\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2265,6 +2265,10 @@ CreateCommandTag(Node *parsetree)
|
||||
tag = "CREATE DATABASE";
|
||||
break;
|
||||
|
||||
case T_AlterDatabaseSetStmt:
|
||||
tag = "ALTER DATABASE";
|
||||
break;
|
||||
|
||||
case T_DropdbStmt:
|
||||
tag = "DROP DATABASE";
|
||||
break;
|
||||
@@ -2342,6 +2346,10 @@ CreateCommandTag(Node *parsetree)
|
||||
tag = "ALTER USER";
|
||||
break;
|
||||
|
||||
case T_AlterUserSetStmt:
|
||||
tag = "ALTER USER";
|
||||
break;
|
||||
|
||||
case T_DropUserStmt:
|
||||
tag = "DROP USER";
|
||||
break;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.127 2002/02/26 22:47:09 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.128 2002/03/01 22:45:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -600,6 +600,10 @@ ProcessUtility(Node *parsetree,
|
||||
}
|
||||
break;
|
||||
|
||||
case T_AlterDatabaseSetStmt:
|
||||
AlterDatabaseSet((AlterDatabaseSetStmt *)parsetree);
|
||||
break;
|
||||
|
||||
case T_DropdbStmt:
|
||||
{
|
||||
DropdbStmt *stmt = (DropdbStmt *) parsetree;
|
||||
@@ -748,6 +752,10 @@ ProcessUtility(Node *parsetree,
|
||||
AlterUser((AlterUserStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterUserSetStmt:
|
||||
AlterUserSet((AlterUserSetStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_DropUserStmt:
|
||||
DropUser((DropUserStmt *) parsetree);
|
||||
break;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.82 2002/01/09 19:13:41 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.83 2002/03/01 22:45:15 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "libpq/libpq-be.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
@@ -437,6 +438,8 @@ void
|
||||
InitializeSessionUserId(const char *username)
|
||||
{
|
||||
HeapTuple userTup;
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
|
||||
/*
|
||||
* Don't do scans if we're bootstrapping, none of the system catalogs
|
||||
@@ -457,6 +460,21 @@ InitializeSessionUserId(const char *username)
|
||||
|
||||
AuthenticatedUserIsSuperuser = ((Form_pg_shadow) GETSTRUCT(userTup))->usesuper;
|
||||
|
||||
/*
|
||||
* Set up user-specific configuration variables. This is a good
|
||||
* place to do it so we don't have to read pg_shadow twice during
|
||||
* session startup.
|
||||
*/
|
||||
datum = SysCacheGetAttr(SHADOWNAME, userTup,
|
||||
Anum_pg_shadow_useconfig, &isnull);
|
||||
if (!isnull)
|
||||
{
|
||||
ArrayType *a;
|
||||
|
||||
a = (ArrayType *) pg_detoast_datum((struct varlena *)datum);
|
||||
ProcessGUCArray(a, PGC_S_USER);
|
||||
}
|
||||
|
||||
ReleaseSysCache(userTup);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.98 2002/02/19 20:11:18 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.99 2002/03/01 22:45:15 petere Exp $
|
||||
*
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "storage/sinval.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/portal.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
@@ -70,6 +71,10 @@ static bool ThereIsAtLeastOneUser(void);
|
||||
*
|
||||
* This is also a handy place to fetch the database encoding info out
|
||||
* of pg_database, if we are in MULTIBYTE mode.
|
||||
*
|
||||
* To avoid having to read pg_database more times than necessary
|
||||
* during session startup, this place is also fitting to set up any
|
||||
* database-specific configuration variables.
|
||||
* --------------------------------
|
||||
*/
|
||||
static void
|
||||
@@ -132,6 +137,25 @@ ReverifyMyDatabase(const char *name)
|
||||
dbform->encoding);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set up datbase-specific configuration variables.
|
||||
*/
|
||||
if (IsUnderPostmaster)
|
||||
{
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
|
||||
datum = heap_getattr(tup, Anum_pg_database_datconfig,
|
||||
RelationGetDescr(pgdbrel), &isnull);
|
||||
if (!isnull)
|
||||
{
|
||||
ArrayType *a;
|
||||
|
||||
a = (ArrayType *) pg_detoast_datum((struct varlena *)datum);
|
||||
ProcessGUCArray(a, PGC_S_DATABASE);
|
||||
}
|
||||
}
|
||||
|
||||
heap_endscan(pgdbscan);
|
||||
heap_close(pgdbrel, AccessShareLock);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Support for grand unified configuration scheme, including SET
|
||||
* command, configuration file, and command line options.
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.59 2002/02/23 01:31:36 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.60 2002/03/01 22:45:16 petere Exp $
|
||||
*
|
||||
* Copyright 2000 by PostgreSQL Global Development Group
|
||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||
@@ -36,6 +36,8 @@
|
||||
#include "storage/lock.h"
|
||||
#include "storage/proc.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/datetime.h"
|
||||
#include "pgstat.h"
|
||||
|
||||
@@ -89,6 +91,7 @@ bool Password_encryption = false;
|
||||
#define PG_KRB_SRVTAB ""
|
||||
#endif
|
||||
|
||||
static bool guc_session_init = false; /* XXX mildly bogus */
|
||||
|
||||
/*
|
||||
* Declarations for GUC tables
|
||||
@@ -882,7 +885,12 @@ set_config_option(const char *name, const char *value,
|
||||
int elevel;
|
||||
bool makeDefault;
|
||||
|
||||
elevel = (context == PGC_SIGHUP) ? DEBUG : ERROR;
|
||||
if (context == PGC_SIGHUP)
|
||||
elevel = DEBUG;
|
||||
else if (guc_session_init)
|
||||
elevel = NOTICE;
|
||||
else
|
||||
elevel = ERROR;
|
||||
|
||||
type = find_option(name, &record);
|
||||
if (type == PGC_NONE)
|
||||
@@ -1362,3 +1370,147 @@ assign_defaultxactisolevel(const char *value)
|
||||
else
|
||||
elog(ERROR, "bogus transaction isolation level");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ProcessGUCArray(ArrayType *array, GucSource source)
|
||||
{
|
||||
int i;
|
||||
|
||||
Assert(array);
|
||||
|
||||
for (i = 1; i <= ARR_DIMS(array)[0]; i++)
|
||||
{
|
||||
Datum d;
|
||||
bool isnull;
|
||||
char *s;
|
||||
char *name;
|
||||
char *value;
|
||||
|
||||
d = array_ref(array, 1, &i,
|
||||
false /*notbyvalue*/,
|
||||
-1 /*varlenelem*/,
|
||||
-1 /*varlenarray*/,
|
||||
&isnull);
|
||||
|
||||
if (isnull)
|
||||
continue;
|
||||
|
||||
s = DatumGetCString(DirectFunctionCall1(textout, d));
|
||||
ParseLongOption(s, &name, &value);
|
||||
if (!value)
|
||||
{
|
||||
elog(NOTICE, "cannot to parse setting \"%s\"", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* prevent errors from incorrect options */
|
||||
guc_session_init = true;
|
||||
|
||||
SetConfigOption(name, value, PGC_SUSET, source);
|
||||
|
||||
guc_session_init = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ArrayType *
|
||||
GUCArrayAdd(ArrayType *array, const char *name, const char *value)
|
||||
{
|
||||
Datum datum;
|
||||
char *newval;
|
||||
ArrayType *a;
|
||||
|
||||
Assert(name);
|
||||
Assert(value);
|
||||
|
||||
/* test if the option is valid */
|
||||
set_config_option(name, value,
|
||||
superuser() ? PGC_SUSET : PGC_USERSET,
|
||||
false, PGC_S_INFINITY);
|
||||
|
||||
newval = palloc(strlen(name) + 1 + strlen(value) + 1);
|
||||
sprintf(newval, "%s=%s", name, value);
|
||||
datum = DirectFunctionCall1(textin, CStringGetDatum(newval));
|
||||
|
||||
if (array)
|
||||
{
|
||||
int index;
|
||||
bool isnull;
|
||||
int i;
|
||||
|
||||
index = ARR_DIMS(array)[0] + 1; /* add after end */
|
||||
|
||||
for (i = 1; i <= ARR_DIMS(array)[0]; i++)
|
||||
{
|
||||
Datum d;
|
||||
char *current;
|
||||
|
||||
d = array_ref(array, 1, &i,
|
||||
false /*notbyvalue*/,
|
||||
-1 /*varlenelem*/,
|
||||
-1 /*varlenarray*/,
|
||||
&isnull);
|
||||
current = DatumGetCString(DirectFunctionCall1(textout, d));
|
||||
if (strncmp(current, newval, strlen(name) + 1)==0)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
isnull = false;
|
||||
a = array_set(array, 1, &index, datum, false/*notbyval*/, -1, -1, &isnull);
|
||||
}
|
||||
else
|
||||
a = construct_array(&datum, 1, false, -1, 'i');
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ArrayType *
|
||||
GUCArrayDelete(ArrayType *array, const char *name)
|
||||
{
|
||||
ArrayType *newarray;
|
||||
int i;
|
||||
int index;
|
||||
|
||||
Assert(name);
|
||||
Assert(array);
|
||||
|
||||
/* test if the option is valid */
|
||||
set_config_option(name, NULL,
|
||||
superuser() ? PGC_SUSET : PGC_USERSET,
|
||||
false, PGC_S_INFINITY);
|
||||
|
||||
newarray = construct_array(NULL, 0, false, -1, 'i');
|
||||
index = 1;
|
||||
|
||||
for (i = 1; i <= ARR_DIMS(array)[0]; i++)
|
||||
{
|
||||
Datum d;
|
||||
char *val;
|
||||
bool isnull;
|
||||
|
||||
d = array_ref(array, 1, &i,
|
||||
false /*notbyvalue*/,
|
||||
-1 /*varlenelem*/,
|
||||
-1 /*varlenarray*/,
|
||||
&isnull);
|
||||
val = DatumGetCString(DirectFunctionCall1(textout, d));
|
||||
|
||||
if (strncmp(val, name, strlen(name))==0
|
||||
&& val[strlen(name)] == '=')
|
||||
continue;
|
||||
|
||||
isnull = false;
|
||||
newarray = array_set(newarray, 1, &index, d, false/*notbyval*/, -1, -1, &isnull);
|
||||
index++;
|
||||
}
|
||||
|
||||
return newarray;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user