mirror of
https://github.com/postgres/postgres.git
synced 2025-09-08 00:47:37 +03:00
Add per-user and per-database connection limit options.
This patch also includes preliminary update of pg_dumpall for roles. Petr Jelinek, with review by Bruce Momjian and Tom Lane.
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.167 2005/07/14 21:46:29 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.168 2005/07/31 17:19:17 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -92,10 +92,12 @@ createdb(const CreatedbStmt *stmt)
|
||||
DefElem *downer = NULL;
|
||||
DefElem *dtemplate = NULL;
|
||||
DefElem *dencoding = NULL;
|
||||
DefElem *dconnlimit = NULL;
|
||||
char *dbname = stmt->dbname;
|
||||
char *dbowner = NULL;
|
||||
const char *dbtemplate = NULL;
|
||||
int encoding = -1;
|
||||
int dbconnlimit = -1;
|
||||
|
||||
#ifndef WIN32
|
||||
char buf[2 * MAXPGPATH + 100];
|
||||
@@ -141,6 +143,14 @@ createdb(const CreatedbStmt *stmt)
|
||||
errmsg("conflicting or redundant options")));
|
||||
dencoding = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "connectionlimit") == 0)
|
||||
{
|
||||
if (dconnlimit)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dconnlimit = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "location") == 0)
|
||||
{
|
||||
ereport(WARNING,
|
||||
@@ -186,6 +196,8 @@ createdb(const CreatedbStmt *stmt)
|
||||
elog(ERROR, "unrecognized node type: %d",
|
||||
nodeTag(dencoding->arg));
|
||||
}
|
||||
if (dconnlimit && dconnlimit->arg)
|
||||
dbconnlimit = intVal(dconnlimit->arg);
|
||||
|
||||
/* obtain OID of proposed owner */
|
||||
if (dbowner)
|
||||
@@ -484,6 +496,7 @@ createdb(const CreatedbStmt *stmt)
|
||||
new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding);
|
||||
new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(false);
|
||||
new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(true);
|
||||
new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
|
||||
new_record[Anum_pg_database_datlastsysoid - 1] = ObjectIdGetDatum(src_lastsysoid);
|
||||
new_record[Anum_pg_database_datvacuumxid - 1] = TransactionIdGetDatum(src_vacuumxid);
|
||||
new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid);
|
||||
@@ -790,6 +803,98 @@ RenameDatabase(const char *oldname, const char *newname)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ALTER DATABASE name ...
|
||||
*/
|
||||
void
|
||||
AlterDatabase(AlterDatabaseStmt *stmt)
|
||||
{
|
||||
Relation rel;
|
||||
HeapTuple tuple,
|
||||
newtuple;
|
||||
ScanKeyData scankey;
|
||||
SysScanDesc scan;
|
||||
ListCell *option;
|
||||
int connlimit = -1;
|
||||
DefElem *dconnlimit = NULL;
|
||||
Datum new_record[Natts_pg_database];
|
||||
char new_record_nulls[Natts_pg_database];
|
||||
char new_record_repl[Natts_pg_database];
|
||||
|
||||
/* Extract options from the statement node tree */
|
||||
foreach(option, stmt->options)
|
||||
{
|
||||
DefElem *defel = (DefElem *) lfirst(option);
|
||||
|
||||
if (strcmp(defel->defname, "connectionlimit") == 0)
|
||||
{
|
||||
if (dconnlimit)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dconnlimit = defel;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "option \"%s\" not recognized",
|
||||
defel->defname);
|
||||
}
|
||||
|
||||
if (dconnlimit)
|
||||
connlimit = intVal(dconnlimit->arg);
|
||||
|
||||
/*
|
||||
* We don't need ExclusiveLock since we aren't updating the
|
||||
* flat file.
|
||||
*/
|
||||
rel = heap_open(DatabaseRelationId, RowExclusiveLock);
|
||||
ScanKeyInit(&scankey,
|
||||
Anum_pg_database_datname,
|
||||
BTEqualStrategyNumber, F_NAMEEQ,
|
||||
NameGetDatum(stmt->dbname));
|
||||
scan = systable_beginscan(rel, DatabaseNameIndexId, true,
|
||||
SnapshotNow, 1, &scankey);
|
||||
tuple = systable_getnext(scan);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_DATABASE),
|
||||
errmsg("database \"%s\" does not exist", stmt->dbname)));
|
||||
|
||||
if (!pg_database_ownercheck(HeapTupleGetOid(tuple), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
|
||||
stmt->dbname);
|
||||
|
||||
/*
|
||||
* Build an updated tuple, perusing the information just obtained
|
||||
*/
|
||||
MemSet(new_record, 0, sizeof(new_record));
|
||||
MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
|
||||
MemSet(new_record_repl, ' ', sizeof(new_record_repl));
|
||||
|
||||
if (dconnlimit)
|
||||
{
|
||||
new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(connlimit);
|
||||
new_record_repl[Anum_pg_database_datconnlimit - 1] = 'r';
|
||||
}
|
||||
|
||||
newtuple = heap_modifytuple(tuple, RelationGetDescr(rel), new_record,
|
||||
new_record_nulls, new_record_repl);
|
||||
simple_heap_update(rel, &tuple->t_self, newtuple);
|
||||
|
||||
/* Update indexes */
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
systable_endscan(scan);
|
||||
|
||||
/* Close pg_database, but keep lock till commit */
|
||||
heap_close(rel, NoLock);
|
||||
|
||||
/*
|
||||
* We don't bother updating the flat file since the existing options
|
||||
* for ALTER DATABASE don't affect it.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ALTER DATABASE name SET ...
|
||||
*/
|
||||
|
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.159 2005/07/26 22:37:49 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.160 2005/07/31 17:19:17 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -86,6 +86,7 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
bool createrole = false; /* Can this user create roles? */
|
||||
bool createdb = false; /* Can the user create databases? */
|
||||
bool canlogin = false; /* Can this user login? */
|
||||
int connlimit = -1; /* maximum connections allowed */
|
||||
List *addroleto = NIL; /* roles to make this a member of */
|
||||
List *rolemembers = NIL; /* roles to be members of this role */
|
||||
List *adminmembers = NIL; /* roles to be admins of this role */
|
||||
@@ -96,6 +97,7 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
DefElem *dcreaterole = NULL;
|
||||
DefElem *dcreatedb = NULL;
|
||||
DefElem *dcanlogin = NULL;
|
||||
DefElem *dconnlimit = NULL;
|
||||
DefElem *daddroleto = NULL;
|
||||
DefElem *drolemembers = NULL;
|
||||
DefElem *dadminmembers = NULL;
|
||||
@@ -178,6 +180,14 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
errmsg("conflicting or redundant options")));
|
||||
dcanlogin = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "connectionlimit") == 0)
|
||||
{
|
||||
if (dconnlimit)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dconnlimit = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "addroleto") == 0)
|
||||
{
|
||||
if (daddroleto)
|
||||
@@ -227,6 +237,8 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
createdb = intVal(dcreatedb->arg) != 0;
|
||||
if (dcanlogin)
|
||||
canlogin = intVal(dcanlogin->arg) != 0;
|
||||
if (dconnlimit)
|
||||
connlimit = intVal(dconnlimit->arg);
|
||||
if (daddroleto)
|
||||
addroleto = (List *) daddroleto->arg;
|
||||
if (drolemembers)
|
||||
@@ -292,6 +304,7 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
/* superuser gets catupdate right by default */
|
||||
new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper);
|
||||
new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
|
||||
new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
|
||||
|
||||
if (password)
|
||||
{
|
||||
@@ -401,6 +414,7 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
int createrole = -1; /* Can this user create roles? */
|
||||
int createdb = -1; /* Can the user create databases? */
|
||||
int canlogin = -1; /* Can this user login? */
|
||||
int connlimit = -1; /* maximum connections allowed */
|
||||
List *rolemembers = NIL; /* roles to be added/removed */
|
||||
char *validUntil = NULL; /* time the login is valid until */
|
||||
DefElem *dpassword = NULL;
|
||||
@@ -409,6 +423,7 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
DefElem *dcreaterole = NULL;
|
||||
DefElem *dcreatedb = NULL;
|
||||
DefElem *dcanlogin = NULL;
|
||||
DefElem *dconnlimit = NULL;
|
||||
DefElem *drolemembers = NULL;
|
||||
DefElem *dvalidUntil = NULL;
|
||||
Oid roleid;
|
||||
@@ -472,6 +487,14 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
errmsg("conflicting or redundant options")));
|
||||
dcanlogin = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "connectionlimit") == 0)
|
||||
{
|
||||
if (dconnlimit)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dconnlimit = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "rolemembers") == 0 &&
|
||||
stmt->action != 0)
|
||||
{
|
||||
@@ -506,6 +529,8 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
createdb = intVal(dcreatedb->arg);
|
||||
if (dcanlogin)
|
||||
canlogin = intVal(dcanlogin->arg);
|
||||
if (dconnlimit)
|
||||
connlimit = intVal(dconnlimit->arg);
|
||||
if (drolemembers)
|
||||
rolemembers = (List *) drolemembers->arg;
|
||||
if (dvalidUntil)
|
||||
@@ -545,6 +570,7 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
createrole < 0 &&
|
||||
createdb < 0 &&
|
||||
canlogin < 0 &&
|
||||
!dconnlimit &&
|
||||
!rolemembers &&
|
||||
!validUntil &&
|
||||
password &&
|
||||
@@ -602,6 +628,12 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
new_record_repl[Anum_pg_authid_rolcanlogin - 1] = 'r';
|
||||
}
|
||||
|
||||
if (dconnlimit)
|
||||
{
|
||||
new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
|
||||
new_record_repl[Anum_pg_authid_rolconnlimit - 1] = 'r';
|
||||
}
|
||||
|
||||
/* password */
|
||||
if (password)
|
||||
{
|
||||
|
Reference in New Issue
Block a user