Commit d42cf5a4 authored by Tom Lane's avatar Tom Lane

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.
parent b1258771
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.109 2005/07/26 16:38:25 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.110 2005/07/31 17:19:16 tgl Exp $
--> -->
<chapter id="catalogs"> <chapter id="catalogs">
...@@ -1018,6 +1018,16 @@ ...@@ -1018,6 +1018,16 @@
</entry> </entry>
</row> </row>
<row>
<entry><structfield>rolconnlimit</structfield></entry>
<entry><type>int4</type></entry>
<entry></entry>
<entry>
For roles that can log in, this sets maximum number of concurrent
connections this role can make. -1 means no limit.
</entry>
</row>
<row> <row>
<entry><structfield>rolpassword</structfield></entry> <entry><structfield>rolpassword</structfield></entry>
<entry><type>text</type></entry> <entry><type>text</type></entry>
...@@ -1921,6 +1931,16 @@ ...@@ -1921,6 +1931,16 @@
</entry> </entry>
</row> </row>
<row>
<entry><structfield>datconnlimit</structfield></entry>
<entry><type>int4</type></entry>
<entry></entry>
<entry>
Sets maximum number of concurrent connections that can be made
to this database. -1 means no limit.
</entry>
</row>
<row> <row>
<entry><structfield>datlastsysoid</structfield></entry> <entry><structfield>datlastsysoid</structfield></entry>
<entry><type>oid</type></entry> <entry><type>oid</type></entry>
...@@ -4811,6 +4831,16 @@ ...@@ -4811,6 +4831,16 @@
</entry> </entry>
</row> </row>
<row>
<entry><structfield>rolconnlimit</structfield></entry>
<entry><type>int4</type></entry>
<entry></entry>
<entry>
For roles that can log in, this sets maximum number of concurrent
connections this role can make. -1 means no limit.
</entry>
</row>
<row> <row>
<entry><structfield>rolpassword</structfield></entry> <entry><structfield>rolpassword</structfield></entry>
<entry><type>text</type></entry> <entry><type>text</type></entry>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_database.sgml,v 1.15 2005/01/05 14:22:39 petere Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/alter_database.sgml,v 1.16 2005/07/31 17:19:16 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -20,6 +20,12 @@ PostgreSQL documentation ...@@ -20,6 +20,12 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
where <replaceable class="PARAMETER">option</replaceable> can be:
CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> SET <replaceable>parameter</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT } ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> SET <replaceable>parameter</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT }
ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET <replaceable>parameter</replaceable> ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET <replaceable>parameter</replaceable>
...@@ -38,7 +44,12 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla ...@@ -38,7 +44,12 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla
</para> </para>
<para> <para>
The first two forms change the session default for a run-time The first form changes certain per-database settings. (See below for
details.) Only the database owner or a superuser can change these settings.
</para>
<para>
The second and third forms change the session default for a run-time
configuration variable for a <productname>PostgreSQL</productname> configuration variable for a <productname>PostgreSQL</productname>
database. Whenever a new session is subsequently started in that database. Whenever a new session is subsequently started in that
database, the specified value becomes the session default value. database, the specified value becomes the session default value.
...@@ -51,7 +62,7 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla ...@@ -51,7 +62,7 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla
</para> </para>
<para> <para>
The third form changes the name of the database. Only the database The fourth form changes the name of the database. Only the database
owner or a superuser can rename a database; non-superuser owners must owner or a superuser can rename a database; non-superuser owners must
also have the also have the
<literal>CREATEDB</literal> privilege. The current database cannot <literal>CREATEDB</literal> privilege. The current database cannot
...@@ -60,7 +71,7 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla ...@@ -60,7 +71,7 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla
</para> </para>
<para> <para>
The fourth form changes the owner of the database. Only a superuser The fifth form changes the owner of the database. Only a superuser
can change the database's owner. can change the database's owner.
</para> </para>
</refsect1> </refsect1>
...@@ -78,6 +89,16 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla ...@@ -78,6 +89,16 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><replaceable class="parameter">connlimit</replaceable></term>
<listitem>
<para>
How many concurrent connections can be made
to this database. -1 means no limit.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>parameter</replaceable></term> <term><replaceable>parameter</replaceable></term>
<term><replaceable>value</replaceable></term> <term><replaceable>value</replaceable></term>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_role.sgml,v 1.1 2005/07/26 23:24:02 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/alter_role.sgml,v 1.2 2005/07/31 17:19:17 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be: ...@@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
| CREATEUSER | NOCREATEUSER | CREATEUSER | NOCREATEUSER
| INHERIT | NOINHERIT | INHERIT | NOINHERIT
| LOGIN | NOLOGIN | LOGIN | NOLOGIN
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>' | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>' | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
...@@ -118,6 +119,7 @@ ALTER ROLE <replaceable class="PARAMETER">name</replaceable> RESET <replaceable> ...@@ -118,6 +119,7 @@ ALTER ROLE <replaceable class="PARAMETER">name</replaceable> RESET <replaceable>
<term><literal>NOINHERIT</literal></term> <term><literal>NOINHERIT</literal></term>
<term><literal>LOGIN</literal></term> <term><literal>LOGIN</literal></term>
<term><literal>NOLOGIN</literal></term> <term><literal>NOLOGIN</literal></term>
<term><literal>CONNECTION LIMIT</literal> <replaceable class="parameter">connlimit</replaceable></term>
<term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term> <term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term>
<term><literal>ENCRYPTED</></term> <term><literal>ENCRYPTED</></term>
<term><literal>UNENCRYPTED</></term> <term><literal>UNENCRYPTED</></term>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_user.sgml,v 1.38 2005/07/26 23:24:02 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/alter_user.sgml,v 1.39 2005/07/31 17:19:17 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be: ...@@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
| CREATEUSER | NOCREATEUSER | CREATEUSER | NOCREATEUSER
| INHERIT | NOINHERIT | INHERIT | NOINHERIT
| LOGIN | NOLOGIN | LOGIN | NOLOGIN
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>' | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>' | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_database.sgml,v 1.43 2004/10/29 03:17:22 neilc Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/create_database.sgml,v 1.44 2005/07/31 17:19:17 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -24,7 +24,8 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable> ...@@ -24,7 +24,8 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable>
[ [ WITH ] [ OWNER [=] <replaceable class="parameter">dbowner</replaceable> ] [ [ WITH ] [ OWNER [=] <replaceable class="parameter">dbowner</replaceable> ]
[ TEMPLATE [=] <replaceable class="parameter">template</replaceable> ] [ TEMPLATE [=] <replaceable class="parameter">template</replaceable> ]
[ ENCODING [=] <replaceable class="parameter">encoding</replaceable> ] [ ENCODING [=] <replaceable class="parameter">encoding</replaceable> ]
[ TABLESPACE [=] <replaceable class="parameter">tablespace</replaceable> ] ] [ TABLESPACE [=] <replaceable class="parameter">tablespace</replaceable> ]
[ CONNECTION LIMIT [=] <replaceable class="parameter">connlimit</replaceable> ] ]
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -123,6 +124,16 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable> ...@@ -123,6 +124,16 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable>
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><replaceable class="parameter">connlimit</replaceable></term>
<listitem>
<para>
How many concurrent connections can be made
to this database. -1 (the default) means no limit.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
<para> <para>
...@@ -161,6 +172,13 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable> ...@@ -161,6 +172,13 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable>
We recommend that databases used as templates be treated as read-only. We recommend that databases used as templates be treated as read-only.
See <xref linkend="manage-ag-templatedbs"> for more information. See <xref linkend="manage-ag-templatedbs"> for more information.
</para> </para>
<para>
The <literal>CONNECTION LIMIT</> option is only enforced approximately;
if two new sessions start at about the same time when just one
connection <quote>slot</> remains for the database, it is possible that
both will fail. Also, the limit is not enforced against superusers.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_role.sgml,v 1.1 2005/07/26 23:24:02 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/create_role.sgml,v 1.2 2005/07/31 17:19:17 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be: ...@@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
| CREATEUSER | NOCREATEUSER | CREATEUSER | NOCREATEUSER
| INHERIT | NOINHERIT | INHERIT | NOINHERIT
| LOGIN | NOLOGIN | LOGIN | NOLOGIN
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>' | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>' | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
| IN ROLE <replaceable class="PARAMETER">rolename</replaceable> [, ...] | IN ROLE <replaceable class="PARAMETER">rolename</replaceable> [, ...]
...@@ -172,6 +173,16 @@ where <replaceable class="PARAMETER">option</replaceable> can be: ...@@ -172,6 +173,16 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>CONNECTION LIMIT</literal> <replaceable class="parameter">connlimit</replaceable></term>
<listitem>
<para>
If role can log in, this specifies how many concurrent connections
the role can make. -1 (the default) means no limit.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term> <term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term>
<listitem> <listitem>
...@@ -327,6 +338,13 @@ where <replaceable class="PARAMETER">option</replaceable> can be: ...@@ -327,6 +338,13 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
the same functionality as <command>CREATE ROLE</command> (in fact, the same functionality as <command>CREATE ROLE</command> (in fact,
it calls this command) but can be run from the command shell. it calls this command) but can be run from the command shell.
</para> </para>
<para>
The <literal>CONNECTION LIMIT</> option is only enforced approximately;
if two new sessions start at about the same time when just one
connection <quote>slot</> remains for the role, it is possible that
both will fail. Also, the limit is never enforced for superusers.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_user.sgml,v 1.37 2005/07/26 23:24:02 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/create_user.sgml,v 1.38 2005/07/31 17:19:17 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be: ...@@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
| CREATEUSER | NOCREATEUSER | CREATEUSER | NOCREATEUSER
| INHERIT | NOINHERIT | INHERIT | NOINHERIT
| LOGIN | NOLOGIN | LOGIN | NOLOGIN
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>' | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>' | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
| IN ROLE <replaceable class="PARAMETER">rolename</replaceable> [, ...] | IN ROLE <replaceable class="PARAMETER">rolename</replaceable> [, ...]
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.8 2005/07/04 04:51:44 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.9 2005/07/31 17:19:17 tgl Exp $
* *
* NOTES * NOTES
* Each global transaction is associated with a global transaction * Each global transaction is associated with a global transaction
...@@ -272,6 +272,7 @@ MarkAsPreparing(TransactionId xid, const char *gid, ...@@ -272,6 +272,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
gxact->proc.xmin = InvalidTransactionId; gxact->proc.xmin = InvalidTransactionId;
gxact->proc.pid = 0; gxact->proc.pid = 0;
gxact->proc.databaseId = databaseid; gxact->proc.databaseId = databaseid;
gxact->proc.roleId = owner;
gxact->proc.lwWaiting = false; gxact->proc.lwWaiting = false;
gxact->proc.lwExclusive = false; gxact->proc.lwExclusive = false;
gxact->proc.lwWaitLink = NULL; gxact->proc.lwWaitLink = NULL;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright (c) 1996-2005, PostgreSQL Global Development Group * Copyright (c) 1996-2005, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.17 2005/07/26 16:38:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.18 2005/07/31 17:19:17 tgl Exp $
*/ */
CREATE VIEW pg_roles AS CREATE VIEW pg_roles AS
...@@ -15,6 +15,7 @@ CREATE VIEW pg_roles AS ...@@ -15,6 +15,7 @@ CREATE VIEW pg_roles AS
rolcreatedb, rolcreatedb,
rolcatupdate, rolcatupdate,
rolcanlogin, rolcanlogin,
rolconnlimit,
'********'::text as rolpassword, '********'::text as rolpassword,
rolvaliduntil, rolvaliduntil,
rolconfig, rolconfig,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -92,10 +92,12 @@ createdb(const CreatedbStmt *stmt)
DefElem *downer = NULL; DefElem *downer = NULL;
DefElem *dtemplate = NULL; DefElem *dtemplate = NULL;
DefElem *dencoding = NULL; DefElem *dencoding = NULL;
DefElem *dconnlimit = NULL;
char *dbname = stmt->dbname; char *dbname = stmt->dbname;
char *dbowner = NULL; char *dbowner = NULL;
const char *dbtemplate = NULL; const char *dbtemplate = NULL;
int encoding = -1; int encoding = -1;
int dbconnlimit = -1;
#ifndef WIN32 #ifndef WIN32
char buf[2 * MAXPGPATH + 100]; char buf[2 * MAXPGPATH + 100];
...@@ -141,6 +143,14 @@ createdb(const CreatedbStmt *stmt) ...@@ -141,6 +143,14 @@ createdb(const CreatedbStmt *stmt)
errmsg("conflicting or redundant options"))); errmsg("conflicting or redundant options")));
dencoding = defel; 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) else if (strcmp(defel->defname, "location") == 0)
{ {
ereport(WARNING, ereport(WARNING,
...@@ -186,6 +196,8 @@ createdb(const CreatedbStmt *stmt) ...@@ -186,6 +196,8 @@ createdb(const CreatedbStmt *stmt)
elog(ERROR, "unrecognized node type: %d", elog(ERROR, "unrecognized node type: %d",
nodeTag(dencoding->arg)); nodeTag(dencoding->arg));
} }
if (dconnlimit && dconnlimit->arg)
dbconnlimit = intVal(dconnlimit->arg);
/* obtain OID of proposed owner */ /* obtain OID of proposed owner */
if (dbowner) if (dbowner)
...@@ -484,6 +496,7 @@ createdb(const CreatedbStmt *stmt) ...@@ -484,6 +496,7 @@ createdb(const CreatedbStmt *stmt)
new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding); new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding);
new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(false); new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(false);
new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(true); 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_datlastsysoid - 1] = ObjectIdGetDatum(src_lastsysoid);
new_record[Anum_pg_database_datvacuumxid - 1] = TransactionIdGetDatum(src_vacuumxid); new_record[Anum_pg_database_datvacuumxid - 1] = TransactionIdGetDatum(src_vacuumxid);
new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid); new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid);
...@@ -790,6 +803,98 @@ RenameDatabase(const char *oldname, const char *newname) ...@@ -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 ... * ALTER DATABASE name SET ...
*/ */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) ...@@ -86,6 +86,7 @@ CreateRole(CreateRoleStmt *stmt)
bool createrole = false; /* Can this user create roles? */ bool createrole = false; /* Can this user create roles? */
bool createdb = false; /* Can the user create databases? */ bool createdb = false; /* Can the user create databases? */
bool canlogin = false; /* Can this user login? */ bool canlogin = false; /* Can this user login? */
int connlimit = -1; /* maximum connections allowed */
List *addroleto = NIL; /* roles to make this a member of */ List *addroleto = NIL; /* roles to make this a member of */
List *rolemembers = NIL; /* roles to be members of this role */ List *rolemembers = NIL; /* roles to be members of this role */
List *adminmembers = NIL; /* roles to be admins of this role */ List *adminmembers = NIL; /* roles to be admins of this role */
...@@ -96,6 +97,7 @@ CreateRole(CreateRoleStmt *stmt) ...@@ -96,6 +97,7 @@ CreateRole(CreateRoleStmt *stmt)
DefElem *dcreaterole = NULL; DefElem *dcreaterole = NULL;
DefElem *dcreatedb = NULL; DefElem *dcreatedb = NULL;
DefElem *dcanlogin = NULL; DefElem *dcanlogin = NULL;
DefElem *dconnlimit = NULL;
DefElem *daddroleto = NULL; DefElem *daddroleto = NULL;
DefElem *drolemembers = NULL; DefElem *drolemembers = NULL;
DefElem *dadminmembers = NULL; DefElem *dadminmembers = NULL;
...@@ -178,6 +180,14 @@ CreateRole(CreateRoleStmt *stmt) ...@@ -178,6 +180,14 @@ CreateRole(CreateRoleStmt *stmt)
errmsg("conflicting or redundant options"))); errmsg("conflicting or redundant options")));
dcanlogin = defel; 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) else if (strcmp(defel->defname, "addroleto") == 0)
{ {
if (daddroleto) if (daddroleto)
...@@ -227,6 +237,8 @@ CreateRole(CreateRoleStmt *stmt) ...@@ -227,6 +237,8 @@ CreateRole(CreateRoleStmt *stmt)
createdb = intVal(dcreatedb->arg) != 0; createdb = intVal(dcreatedb->arg) != 0;
if (dcanlogin) if (dcanlogin)
canlogin = intVal(dcanlogin->arg) != 0; canlogin = intVal(dcanlogin->arg) != 0;
if (dconnlimit)
connlimit = intVal(dconnlimit->arg);
if (daddroleto) if (daddroleto)
addroleto = (List *) daddroleto->arg; addroleto = (List *) daddroleto->arg;
if (drolemembers) if (drolemembers)
...@@ -292,6 +304,7 @@ CreateRole(CreateRoleStmt *stmt) ...@@ -292,6 +304,7 @@ CreateRole(CreateRoleStmt *stmt)
/* superuser gets catupdate right by default */ /* superuser gets catupdate right by default */
new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper); new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper);
new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin); new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
if (password) if (password)
{ {
...@@ -401,6 +414,7 @@ AlterRole(AlterRoleStmt *stmt) ...@@ -401,6 +414,7 @@ AlterRole(AlterRoleStmt *stmt)
int createrole = -1; /* Can this user create roles? */ int createrole = -1; /* Can this user create roles? */
int createdb = -1; /* Can the user create databases? */ int createdb = -1; /* Can the user create databases? */
int canlogin = -1; /* Can this user login? */ int canlogin = -1; /* Can this user login? */
int connlimit = -1; /* maximum connections allowed */
List *rolemembers = NIL; /* roles to be added/removed */ List *rolemembers = NIL; /* roles to be added/removed */
char *validUntil = NULL; /* time the login is valid until */ char *validUntil = NULL; /* time the login is valid until */
DefElem *dpassword = NULL; DefElem *dpassword = NULL;
...@@ -409,6 +423,7 @@ AlterRole(AlterRoleStmt *stmt) ...@@ -409,6 +423,7 @@ AlterRole(AlterRoleStmt *stmt)
DefElem *dcreaterole = NULL; DefElem *dcreaterole = NULL;
DefElem *dcreatedb = NULL; DefElem *dcreatedb = NULL;
DefElem *dcanlogin = NULL; DefElem *dcanlogin = NULL;
DefElem *dconnlimit = NULL;
DefElem *drolemembers = NULL; DefElem *drolemembers = NULL;
DefElem *dvalidUntil = NULL; DefElem *dvalidUntil = NULL;
Oid roleid; Oid roleid;
...@@ -472,6 +487,14 @@ AlterRole(AlterRoleStmt *stmt) ...@@ -472,6 +487,14 @@ AlterRole(AlterRoleStmt *stmt)
errmsg("conflicting or redundant options"))); errmsg("conflicting or redundant options")));
dcanlogin = defel; 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 && else if (strcmp(defel->defname, "rolemembers") == 0 &&
stmt->action != 0) stmt->action != 0)
{ {
...@@ -506,6 +529,8 @@ AlterRole(AlterRoleStmt *stmt) ...@@ -506,6 +529,8 @@ AlterRole(AlterRoleStmt *stmt)
createdb = intVal(dcreatedb->arg); createdb = intVal(dcreatedb->arg);
if (dcanlogin) if (dcanlogin)
canlogin = intVal(dcanlogin->arg); canlogin = intVal(dcanlogin->arg);
if (dconnlimit)
connlimit = intVal(dconnlimit->arg);
if (drolemembers) if (drolemembers)
rolemembers = (List *) drolemembers->arg; rolemembers = (List *) drolemembers->arg;
if (dvalidUntil) if (dvalidUntil)
...@@ -545,6 +570,7 @@ AlterRole(AlterRoleStmt *stmt) ...@@ -545,6 +570,7 @@ AlterRole(AlterRoleStmt *stmt)
createrole < 0 && createrole < 0 &&
createdb < 0 && createdb < 0 &&
canlogin < 0 && canlogin < 0 &&
!dconnlimit &&
!rolemembers && !rolemembers &&
!validUntil && !validUntil &&
password && password &&
...@@ -602,6 +628,12 @@ AlterRole(AlterRoleStmt *stmt) ...@@ -602,6 +628,12 @@ AlterRole(AlterRoleStmt *stmt)
new_record_repl[Anum_pg_authid_rolcanlogin - 1] = 'r'; 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 */ /* password */
if (password) if (password)
{ {
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.312 2005/07/26 16:38:27 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.313 2005/07/31 17:19:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2204,6 +2204,17 @@ _copyCreatedbStmt(CreatedbStmt *from) ...@@ -2204,6 +2204,17 @@ _copyCreatedbStmt(CreatedbStmt *from)
return newnode; return newnode;
} }
static AlterDatabaseStmt *
_copyAlterDatabaseStmt(AlterDatabaseStmt *from)
{
AlterDatabaseStmt *newnode = makeNode(AlterDatabaseStmt);
COPY_STRING_FIELD(dbname);
COPY_NODE_FIELD(options);
return newnode;
}
static AlterDatabaseSetStmt * static AlterDatabaseSetStmt *
_copyAlterDatabaseSetStmt(AlterDatabaseSetStmt *from) _copyAlterDatabaseSetStmt(AlterDatabaseSetStmt *from)
{ {
...@@ -3011,6 +3022,9 @@ copyObject(void *from) ...@@ -3011,6 +3022,9 @@ copyObject(void *from)
case T_CreatedbStmt: case T_CreatedbStmt:
retval = _copyCreatedbStmt(from); retval = _copyCreatedbStmt(from);
break; break;
case T_AlterDatabaseStmt:
retval = _copyAlterDatabaseStmt(from);
break;
case T_AlterDatabaseSetStmt: case T_AlterDatabaseSetStmt:
retval = _copyAlterDatabaseSetStmt(from); retval = _copyAlterDatabaseSetStmt(from);
break; break;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.249 2005/07/26 16:38:27 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.250 2005/07/31 17:19:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1151,6 +1151,15 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b) ...@@ -1151,6 +1151,15 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
return true; return true;
} }
static bool
_equalAlterDatabaseStmt(AlterDatabaseStmt *a, AlterDatabaseStmt *b)
{
COMPARE_STRING_FIELD(dbname);
COMPARE_NODE_FIELD(options);
return true;
}
static bool static bool
_equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b) _equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
{ {
...@@ -2059,6 +2068,9 @@ equal(void *a, void *b) ...@@ -2059,6 +2068,9 @@ equal(void *a, void *b)
case T_CreatedbStmt: case T_CreatedbStmt:
retval = _equalCreatedbStmt(a, b); retval = _equalCreatedbStmt(a, b);
break; break;
case T_AlterDatabaseStmt:
retval = _equalAlterDatabaseStmt(a, b);
break;
case T_AlterDatabaseSetStmt: case T_AlterDatabaseSetStmt:
retval = _equalAlterDatabaseSetStmt(a, b); retval = _equalAlterDatabaseSetStmt(a, b);
break; break;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.504 2005/07/26 22:37:50 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.505 2005/07/31 17:19:18 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -131,9 +131,9 @@ static void doNegateFloat(Value *v); ...@@ -131,9 +131,9 @@ static void doNegateFloat(Value *v);
} }
%type <node> stmt schema_stmt %type <node> stmt schema_stmt
AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt AlterOwnerStmt AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt
AlterSeqStmt AlterTableStmt AlterUserStmt AlterUserSetStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
AlterRoleStmt AlterRoleSetStmt AlterUserStmt AlterUserSetStmt AlterRoleStmt AlterRoleSetStmt
AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
CreateDomainStmt CreateGroupStmt CreateOpClassStmt CreatePLangStmt CreateDomainStmt CreateGroupStmt CreateOpClassStmt CreatePLangStmt
...@@ -165,8 +165,10 @@ static void doNegateFloat(Value *v); ...@@ -165,8 +165,10 @@ static void doNegateFloat(Value *v);
%type <dbehavior> opt_drop_behavior %type <dbehavior> opt_drop_behavior
%type <list> createdb_opt_list copy_opt_list transaction_mode_list %type <list> createdb_opt_list alterdb_opt_list copy_opt_list
%type <defelt> createdb_opt_item copy_opt_item transaction_mode_item transaction_mode_list
%type <defelt> createdb_opt_item alterdb_opt_item copy_opt_item
transaction_mode_item
%type <ival> opt_lock lock_type cast_context %type <ival> opt_lock lock_type cast_context
%type <boolean> opt_force opt_or_replace %type <boolean> opt_force opt_or_replace
...@@ -257,7 +259,7 @@ static void doNegateFloat(Value *v); ...@@ -257,7 +259,7 @@ static void doNegateFloat(Value *v);
%type <boolean> copy_from opt_hold %type <boolean> copy_from opt_hold
%type <ival> fetch_count opt_column event cursor_options %type <ival> opt_column event cursor_options
%type <objtype> reindex_type drop_type comment_type %type <objtype> reindex_type drop_type comment_type
%type <node> fetch_direction select_limit_value select_offset_value %type <node> fetch_direction select_limit_value select_offset_value
...@@ -302,7 +304,7 @@ static void doNegateFloat(Value *v); ...@@ -302,7 +304,7 @@ static void doNegateFloat(Value *v);
%type <ival> opt_numeric opt_decimal %type <ival> opt_numeric opt_decimal
%type <boolean> opt_varying opt_timezone %type <boolean> opt_varying opt_timezone
%type <ival> Iconst %type <ival> Iconst SignedIconst
%type <str> Sconst comment_text %type <str> Sconst comment_text
%type <str> RoleId opt_granted_by opt_boolean ColId_or_Sconst %type <str> RoleId opt_granted_by opt_boolean ColId_or_Sconst
%type <list> var_list var_list_or_default %type <list> var_list var_list_or_default
...@@ -342,7 +344,7 @@ static void doNegateFloat(Value *v); ...@@ -342,7 +344,7 @@ static void doNegateFloat(Value *v);
CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
COMMITTED CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB COMMITTED CONNECTION CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB
CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME
CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
...@@ -486,7 +488,8 @@ stmtmulti: stmtmulti ';' stmt ...@@ -486,7 +488,8 @@ stmtmulti: stmtmulti ';' stmt
; ;
stmt : stmt :
AlterDatabaseSetStmt AlterDatabaseStmt
| AlterDatabaseSetStmt
| AlterDomainStmt | AlterDomainStmt
| AlterFunctionStmt | AlterFunctionStmt
| AlterGroupStmt | AlterGroupStmt
...@@ -672,6 +675,10 @@ OptRoleElem: ...@@ -672,6 +675,10 @@ OptRoleElem:
{ {
$$ = makeDefElem("canlogin", (Node *)makeInteger(FALSE)); $$ = makeDefElem("canlogin", (Node *)makeInteger(FALSE));
} }
| CONNECTION LIMIT SignedIconst
{
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($3));
}
| IN_P ROLE name_list | IN_P ROLE name_list
{ {
$$ = makeDefElem("addroleto", (Node *)$3); $$ = makeDefElem("addroleto", (Node *)$3);
...@@ -2238,17 +2245,8 @@ FloatOnly: FCONST { $$ = makeFloat($1); } ...@@ -2238,17 +2245,8 @@ FloatOnly: FCONST { $$ = makeFloat($1); }
} }
; ;
IntegerOnly: IntegerOnly: SignedIconst { $$ = makeInteger($1); };
Iconst
{
$$ = makeInteger($1);
}
| '-' Iconst
{
$$ = makeInteger($2);
$$->val.ival = - $$->val.ival;
}
;
/***************************************************************************** /*****************************************************************************
* *
...@@ -3044,21 +3042,21 @@ fetch_direction: ...@@ -3044,21 +3042,21 @@ fetch_direction:
n->howMany = -1; n->howMany = -1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ABSOLUTE_P fetch_count | ABSOLUTE_P SignedIconst
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_ABSOLUTE; n->direction = FETCH_ABSOLUTE;
n->howMany = $2; n->howMany = $2;
$$ = (Node *)n; $$ = (Node *)n;
} }
| RELATIVE_P fetch_count | RELATIVE_P SignedIconst
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_RELATIVE; n->direction = FETCH_RELATIVE;
n->howMany = $2; n->howMany = $2;
$$ = (Node *)n; $$ = (Node *)n;
} }
| fetch_count | SignedIconst
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD; n->direction = FETCH_FORWARD;
...@@ -3079,7 +3077,7 @@ fetch_direction: ...@@ -3079,7 +3077,7 @@ fetch_direction:
n->howMany = 1; n->howMany = 1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| FORWARD fetch_count | FORWARD SignedIconst
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD; n->direction = FETCH_FORWARD;
...@@ -3100,7 +3098,7 @@ fetch_direction: ...@@ -3100,7 +3098,7 @@ fetch_direction:
n->howMany = 1; n->howMany = 1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| BACKWARD fetch_count | BACKWARD SignedIconst
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_BACKWARD; n->direction = FETCH_BACKWARD;
...@@ -3116,11 +3114,6 @@ fetch_direction: ...@@ -3116,11 +3114,6 @@ fetch_direction:
} }
; ;
fetch_count:
Iconst { $$ = $1; }
| '-' Iconst { $$ = - $2; }
;
from_in: FROM {} from_in: FROM {}
| IN_P {} | IN_P {}
; ;
...@@ -4473,6 +4466,10 @@ createdb_opt_item: ...@@ -4473,6 +4466,10 @@ createdb_opt_item:
{ {
$$ = makeDefElem("encoding", NULL); $$ = makeDefElem("encoding", NULL);
} }
| CONNECTION LIMIT opt_equal SignedIconst
{
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($4));
}
| OWNER opt_equal name | OWNER opt_equal name
{ {
$$ = makeDefElem("owner", (Node *)makeString($3)); $$ = makeDefElem("owner", (Node *)makeString($3));
...@@ -4485,8 +4482,7 @@ createdb_opt_item: ...@@ -4485,8 +4482,7 @@ createdb_opt_item:
/* /*
* Though the equals sign doesn't match other WITH options, pg_dump uses * Though the equals sign doesn't match other WITH options, pg_dump uses
* equals for backward compability, and it doesn't seem worth removing it. * equals for backward compatibility, and it doesn't seem worth removing it.
* 2002-02-25
*/ */
opt_equal: '=' {} opt_equal: '=' {}
| /*EMPTY*/ {} | /*EMPTY*/ {}
...@@ -4499,6 +4495,16 @@ opt_equal: '=' {} ...@@ -4499,6 +4495,16 @@ opt_equal: '=' {}
* *
*****************************************************************************/ *****************************************************************************/
AlterDatabaseStmt:
ALTER DATABASE database_name opt_with alterdb_opt_list
{
AlterDatabaseStmt *n = makeNode(AlterDatabaseStmt);
n->dbname = $3;
n->options = $5;
$$ = (Node *)n;
}
;
AlterDatabaseSetStmt: AlterDatabaseSetStmt:
ALTER DATABASE database_name SET set_rest ALTER DATABASE database_name SET set_rest
{ {
...@@ -4519,6 +4525,19 @@ AlterDatabaseSetStmt: ...@@ -4519,6 +4525,19 @@ AlterDatabaseSetStmt:
; ;
alterdb_opt_list:
alterdb_opt_list alterdb_opt_item { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
;
alterdb_opt_item:
CONNECTION LIMIT opt_equal SignedIconst
{
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($4));
}
;
/***************************************************************************** /*****************************************************************************
* *
* DROP DATABASE * DROP DATABASE
...@@ -7875,6 +7894,10 @@ Iconst: ICONST { $$ = $1; }; ...@@ -7875,6 +7894,10 @@ Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; }; Sconst: SCONST { $$ = $1; };
RoleId: ColId { $$ = $1; }; RoleId: ColId { $$ = $1; };
SignedIconst: ICONST { $$ = $1; }
| '-' ICONST { $$ = - $2; }
;
/* /*
* Name classification hierarchy. * Name classification hierarchy.
* *
...@@ -7959,6 +7982,7 @@ unreserved_keyword: ...@@ -7959,6 +7982,7 @@ unreserved_keyword:
| COMMENT | COMMENT
| COMMIT | COMMIT
| COMMITTED | COMMITTED
| CONNECTION
| CONSTRAINTS | CONSTRAINTS
| CONVERSION_P | CONVERSION_P
| COPY | COPY
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.163 2005/07/26 16:38:27 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.164 2005/07/31 17:19:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -83,6 +83,7 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -83,6 +83,7 @@ static const ScanKeyword ScanKeywords[] = {
{"comment", COMMENT}, {"comment", COMMENT},
{"commit", COMMIT}, {"commit", COMMIT},
{"committed", COMMITTED}, {"committed", COMMITTED},
{"connection", CONNECTION},
{"constraint", CONSTRAINT}, {"constraint", CONSTRAINT},
{"constraints", CONSTRAINTS}, {"constraints", CONSTRAINTS},
{"conversion", CONVERSION_P}, {"conversion", CONVERSION_P},
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.3 2005/06/17 22:32:45 tgl Exp $ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.4 2005/07/31 17:19:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -733,6 +733,60 @@ CountActiveBackends(void) ...@@ -733,6 +733,60 @@ CountActiveBackends(void)
return count; return count;
} }
/*
* CountDBBackends --- count backends that are using specified database
*/
int
CountDBBackends(Oid databaseid)
{
ProcArrayStruct *arrayP = procArray;
int count = 0;
int index;
LWLockAcquire(ProcArrayLock, LW_SHARED);
for (index = 0; index < arrayP->numProcs; index++)
{
PGPROC *proc = arrayP->procs[index];
if (proc->pid == 0)
continue; /* do not count prepared xacts */
if (proc->databaseId == databaseid)
count++;
}
LWLockRelease(ProcArrayLock);
return count;
}
/*
* CountUserBackends --- count backends that are used by specified user
*/
int
CountUserBackends(Oid roleid)
{
ProcArrayStruct *arrayP = procArray;
int count = 0;
int index;
LWLockAcquire(ProcArrayLock, LW_SHARED);
for (index = 0; index < arrayP->numProcs; index++)
{
PGPROC *proc = arrayP->procs[index];
if (proc->pid == 0)
continue; /* do not count prepared xacts */
if (proc->roleId == roleid)
count++;
}
LWLockRelease(ProcArrayLock);
return count;
}
#define XidCacheRemove(i) \ #define XidCacheRemove(i) \
do { \ do { \
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.160 2005/06/17 22:32:45 tgl Exp $ * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.161 2005/07/31 17:19:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -254,6 +254,8 @@ InitProcess(void) ...@@ -254,6 +254,8 @@ InitProcess(void)
MyProc->xmin = InvalidTransactionId; MyProc->xmin = InvalidTransactionId;
MyProc->pid = MyProcPid; MyProc->pid = MyProcPid;
MyProc->databaseId = MyDatabaseId; MyProc->databaseId = MyDatabaseId;
/* Will be set properly after the session role id is determined */
MyProc->roleId = InvalidOid;
MyProc->lwWaiting = false; MyProc->lwWaiting = false;
MyProc->lwExclusive = false; MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL; MyProc->lwWaitLink = NULL;
...@@ -331,6 +333,7 @@ InitDummyProcess(int proctype) ...@@ -331,6 +333,7 @@ InitDummyProcess(int proctype)
MyProc->xid = InvalidTransactionId; MyProc->xid = InvalidTransactionId;
MyProc->xmin = InvalidTransactionId; MyProc->xmin = InvalidTransactionId;
MyProc->databaseId = MyDatabaseId; MyProc->databaseId = MyDatabaseId;
MyProc->roleId = InvalidOid;
MyProc->lwWaiting = false; MyProc->lwWaiting = false;
MyProc->lwExclusive = false; MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL; MyProc->lwWaitLink = NULL;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.241 2005/07/14 05:13:41 tgl Exp $ * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.242 2005/07/31 17:19:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -275,6 +275,7 @@ check_xact_readonly(Node *parsetree) ...@@ -275,6 +275,7 @@ check_xact_readonly(Node *parsetree)
switch (nodeTag(parsetree)) switch (nodeTag(parsetree))
{ {
case T_AlterDatabaseStmt:
case T_AlterDatabaseSetStmt: case T_AlterDatabaseSetStmt:
case T_AlterDomainStmt: case T_AlterDomainStmt:
case T_AlterFunctionStmt: case T_AlterFunctionStmt:
...@@ -788,6 +789,10 @@ ProcessUtility(Node *parsetree, ...@@ -788,6 +789,10 @@ ProcessUtility(Node *parsetree,
createdb((CreatedbStmt *) parsetree); createdb((CreatedbStmt *) parsetree);
break; break;
case T_AlterDatabaseStmt:
AlterDatabase((AlterDatabaseStmt *) parsetree);
break;
case T_AlterDatabaseSetStmt: case T_AlterDatabaseSetStmt:
AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree); AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
break; break;
...@@ -1504,6 +1509,10 @@ CreateCommandTag(Node *parsetree) ...@@ -1504,6 +1509,10 @@ CreateCommandTag(Node *parsetree)
tag = "CREATE DATABASE"; tag = "CREATE DATABASE";
break; break;
case T_AlterDatabaseStmt:
tag = "ALTER DATABASE";
break;
case T_AlterDatabaseSetStmt: case T_AlterDatabaseSetStmt:
tag = "ALTER DATABASE"; tag = "ALTER DATABASE";
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.147 2005/07/25 22:12:33 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.148 2005/07/31 17:19:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include "storage/fd.h" #include "storage/fd.h"
#include "storage/ipc.h" #include "storage/ipc.h"
#include "storage/pg_shmem.h" #include "storage/pg_shmem.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/guc.h" #include "utils/guc.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
...@@ -404,17 +406,52 @@ InitializeSessionUserId(const char *rolename) ...@@ -404,17 +406,52 @@ InitializeSessionUserId(const char *rolename)
rform = (Form_pg_authid) GETSTRUCT(roleTup); rform = (Form_pg_authid) GETSTRUCT(roleTup);
roleid = HeapTupleGetOid(roleTup); roleid = HeapTupleGetOid(roleTup);
if (!rform->rolcanlogin)
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("role \"%s\" is not permitted to log in", rolename)));
AuthenticatedUserId = roleid; AuthenticatedUserId = roleid;
AuthenticatedUserIsSuperuser = rform->rolsuper; AuthenticatedUserIsSuperuser = rform->rolsuper;
/* This sets OuterUserId/CurrentUserId too */ /* This sets OuterUserId/CurrentUserId too */
SetSessionUserId(roleid, AuthenticatedUserIsSuperuser); SetSessionUserId(roleid, AuthenticatedUserIsSuperuser);
/* Also mark our PGPROC entry with the authenticated user id */
/* (We assume this is an atomic store so no lock is needed) */
MyProc->roleId = roleid;
/*
* These next checks are not enforced when in standalone mode, so that
* there is a way to recover from sillinesses like
* "UPDATE pg_authid SET rolcanlogin = false;".
*
* We do not enforce them for the autovacuum process either.
*/
if (IsUnderPostmaster && !IsAutoVacuumProcess())
{
/*
* Is role allowed to login at all?
*/
if (!rform->rolcanlogin)
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("role \"%s\" is not permitted to log in",
rolename)));
/*
* Check connection limit for this role.
*
* There is a race condition here --- we create our PGPROC before
* checking for other PGPROCs. If two backends did this at about the
* same time, they might both think they were over the limit, while
* ideally one should succeed and one fail. Getting that to work
* exactly seems more trouble than it is worth, however; instead
* we just document that the connection limit is approximate.
*/
if (rform->rolconnlimit >= 0 &&
!AuthenticatedUserIsSuperuser &&
CountUserBackends(roleid) > rform->rolconnlimit)
ereport(FATAL,
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("too many connections for role \"%s\"",
rolename)));
}
/* Record username and superuser status as GUC settings too */ /* Record username and superuser status as GUC settings too */
SetConfigOption("session_authorization", rolename, SetConfigOption("session_authorization", rolename,
PGC_BACKEND, PGC_S_OVERRIDE); PGC_BACKEND, PGC_S_OVERRIDE);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.154 2005/07/29 19:30:05 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.155 2005/07/31 17:19:19 tgl Exp $
* *
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
...@@ -169,18 +169,43 @@ ReverifyMyDatabase(const char *name) ...@@ -169,18 +169,43 @@ ReverifyMyDatabase(const char *name)
name, MyDatabaseId))); name, MyDatabaseId)));
} }
dbform = (Form_pg_database) GETSTRUCT(tup);
/* /*
* Also check that the database is currently allowing connections. * These next checks are not enforced when in standalone mode, so that
* (We do not enforce this in standalone mode, however, so that there is * there is a way to recover from disabling all access to all databases,
* a way to recover from "UPDATE pg_database SET datallowconn = false;". * for example "UPDATE pg_database SET datallowconn = false;".
* We do not enforce it for the autovacuum process either.) *
* We do not enforce them for the autovacuum process either.
*/ */
dbform = (Form_pg_database) GETSTRUCT(tup); if (IsUnderPostmaster && !IsAutoVacuumProcess())
if (IsUnderPostmaster && !IsAutoVacuumProcess() && !dbform->datallowconn) {
ereport(FATAL, /*
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), * Check that the database is currently allowing connections.
errmsg("database \"%s\" is not currently accepting connections", */
name))); if (!dbform->datallowconn)
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("database \"%s\" is not currently accepting connections",
name)));
/*
* Check connection limit for this database.
*
* There is a race condition here --- we create our PGPROC before
* checking for other PGPROCs. If two backends did this at about the
* same time, they might both think they were over the limit, while
* ideally one should succeed and one fail. Getting that to work
* exactly seems more trouble than it is worth, however; instead
* we just document that the connection limit is approximate.
*/
if (dbform->datconnlimit >= 0 &&
!superuser() &&
CountDBBackends(MyDatabaseId) > dbform->datconnlimit)
ereport(FATAL,
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("too many connections for database \"%s\"",
name)));
}
/* /*
* OK, we're golden. Next to-do item is to save the encoding * OK, we're golden. Next to-do item is to save the encoding
......
This diff is collapsed.
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.293 2005/07/29 15:04:22 momjian Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.294 2005/07/31 17:19:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200507291 #define CATALOG_VERSION_NO 200507301
#endif #endif
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_authid.h,v 1.2 2005/07/26 16:38:28 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_authid.h,v 1.3 2005/07/31 17:19:21 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -49,6 +49,7 @@ CATALOG(pg_authid,1260) BKI_SHARED_RELATION ...@@ -49,6 +49,7 @@ CATALOG(pg_authid,1260) BKI_SHARED_RELATION
bool rolcreatedb; /* allowed to create databases? */ bool rolcreatedb; /* allowed to create databases? */
bool rolcatupdate; /* allowed to alter catalogs manually? */ bool rolcatupdate; /* allowed to alter catalogs manually? */
bool rolcanlogin; /* allowed to log in as session user? */ bool rolcanlogin; /* allowed to log in as session user? */
int4 rolconnlimit; /* max connections allowed (-1=no limit) */
/* remaining fields may be null; use heap_getattr to read them! */ /* remaining fields may be null; use heap_getattr to read them! */
text rolpassword; /* password, if any */ text rolpassword; /* password, if any */
...@@ -70,7 +71,7 @@ typedef FormData_pg_authid *Form_pg_authid; ...@@ -70,7 +71,7 @@ typedef FormData_pg_authid *Form_pg_authid;
* compiler constants for pg_authid * compiler constants for pg_authid
* ---------------- * ----------------
*/ */
#define Natts_pg_authid 10 #define Natts_pg_authid 11
#define Anum_pg_authid_rolname 1 #define Anum_pg_authid_rolname 1
#define Anum_pg_authid_rolsuper 2 #define Anum_pg_authid_rolsuper 2
#define Anum_pg_authid_rolinherit 3 #define Anum_pg_authid_rolinherit 3
...@@ -78,9 +79,10 @@ typedef FormData_pg_authid *Form_pg_authid; ...@@ -78,9 +79,10 @@ typedef FormData_pg_authid *Form_pg_authid;
#define Anum_pg_authid_rolcreatedb 5 #define Anum_pg_authid_rolcreatedb 5
#define Anum_pg_authid_rolcatupdate 6 #define Anum_pg_authid_rolcatupdate 6
#define Anum_pg_authid_rolcanlogin 7 #define Anum_pg_authid_rolcanlogin 7
#define Anum_pg_authid_rolpassword 8 #define Anum_pg_authid_rolconnlimit 8
#define Anum_pg_authid_rolvaliduntil 9 #define Anum_pg_authid_rolpassword 9
#define Anum_pg_authid_rolconfig 10 #define Anum_pg_authid_rolvaliduntil 10
#define Anum_pg_authid_rolconfig 11
/* ---------------- /* ----------------
* initial contents of pg_authid * initial contents of pg_authid
...@@ -89,7 +91,7 @@ typedef FormData_pg_authid *Form_pg_authid; ...@@ -89,7 +91,7 @@ typedef FormData_pg_authid *Form_pg_authid;
* user choices. * user choices.
* ---------------- * ----------------
*/ */
DATA(insert OID = 10 ( "POSTGRES" t t t t t t _null_ _null_ _null_ )); DATA(insert OID = 10 ( "POSTGRES" t t t t t t -1 _null_ _null_ _null_ ));
#define BOOTSTRAP_SUPERUSERID 10 #define BOOTSTRAP_SUPERUSERID 10
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.36 2005/06/28 05:09:06 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.37 2005/07/31 17:19:21 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -40,6 +40,7 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION ...@@ -40,6 +40,7 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION
int4 encoding; /* character encoding */ int4 encoding; /* character encoding */
bool datistemplate; /* allowed as CREATE DATABASE template? */ bool datistemplate; /* allowed as CREATE DATABASE template? */
bool datallowconn; /* new connections allowed? */ bool datallowconn; /* new connections allowed? */
int4 datconnlimit; /* max connections allowed (-1=no limit) */
Oid datlastsysoid; /* highest OID to consider a system OID */ Oid datlastsysoid; /* highest OID to consider a system OID */
TransactionId datvacuumxid; /* all XIDs before this are vacuumed */ TransactionId datvacuumxid; /* all XIDs before this are vacuumed */
TransactionId datfrozenxid; /* all XIDs before this are frozen */ TransactionId datfrozenxid; /* all XIDs before this are frozen */
...@@ -59,20 +60,21 @@ typedef FormData_pg_database *Form_pg_database; ...@@ -59,20 +60,21 @@ typedef FormData_pg_database *Form_pg_database;
* compiler constants for pg_database * compiler constants for pg_database
* ---------------- * ----------------
*/ */
#define Natts_pg_database 11 #define Natts_pg_database 12
#define Anum_pg_database_datname 1 #define Anum_pg_database_datname 1
#define Anum_pg_database_datdba 2 #define Anum_pg_database_datdba 2
#define Anum_pg_database_encoding 3 #define Anum_pg_database_encoding 3
#define Anum_pg_database_datistemplate 4 #define Anum_pg_database_datistemplate 4
#define Anum_pg_database_datallowconn 5 #define Anum_pg_database_datallowconn 5
#define Anum_pg_database_datlastsysoid 6 #define Anum_pg_database_datconnlimit 6
#define Anum_pg_database_datvacuumxid 7 #define Anum_pg_database_datlastsysoid 7
#define Anum_pg_database_datfrozenxid 8 #define Anum_pg_database_datvacuumxid 8
#define Anum_pg_database_dattablespace 9 #define Anum_pg_database_datfrozenxid 9
#define Anum_pg_database_datconfig 10 #define Anum_pg_database_dattablespace 10
#define Anum_pg_database_datacl 11 #define Anum_pg_database_datconfig 11
#define Anum_pg_database_datacl 12
DATA(insert OID = 1 ( template1 PGUID ENCODING t t 0 0 0 1663 _null_ _null_ )); DATA(insert OID = 1 ( template1 PGUID ENCODING t t -1 0 0 0 1663 _null_ _null_ ));
DESCR("Default template database"); DESCR("Default template database");
#define TemplateDbOid 1 #define TemplateDbOid 1
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.40 2005/07/08 04:12:27 neilc Exp $ * $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.41 2005/07/31 17:19:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -55,6 +55,7 @@ typedef struct xl_dbase_drop_rec ...@@ -55,6 +55,7 @@ typedef struct xl_dbase_drop_rec
extern void createdb(const CreatedbStmt *stmt); extern void createdb(const CreatedbStmt *stmt);
extern void dropdb(const char *dbname); extern void dropdb(const char *dbname);
extern void RenameDatabase(const char *oldname, const char *newname); extern void RenameDatabase(const char *oldname, const char *newname);
extern void AlterDatabase(AlterDatabaseStmt *stmt);
extern void AlterDatabaseSet(AlterDatabaseSetStmt *stmt); extern void AlterDatabaseSet(AlterDatabaseSetStmt *stmt);
extern void AlterDatabaseOwner(const char *dbname, Oid newOwnerId); extern void AlterDatabaseOwner(const char *dbname, Oid newOwnerId);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.172 2005/06/28 05:09:13 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.173 2005/07/31 17:19:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -270,6 +270,7 @@ typedef enum NodeTag ...@@ -270,6 +270,7 @@ typedef enum NodeTag
T_ReindexStmt, T_ReindexStmt,
T_CheckPointStmt, T_CheckPointStmt,
T_CreateSchemaStmt, T_CreateSchemaStmt,
T_AlterDatabaseStmt,
T_AlterDatabaseSetStmt, T_AlterDatabaseSetStmt,
T_AlterRoleSetStmt, T_AlterRoleSetStmt,
T_CreateConversionStmt, T_CreateConversionStmt,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.286 2005/07/26 16:38:28 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.287 2005/07/31 17:19:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1624,6 +1624,13 @@ typedef struct CreatedbStmt ...@@ -1624,6 +1624,13 @@ typedef struct CreatedbStmt
* Alter Database * Alter Database
* ---------------------- * ----------------------
*/ */
typedef struct AlterDatabaseStmt
{
NodeTag type;
char *dbname; /* name of database to alter */
List *options; /* List of DefElem nodes */
} AlterDatabaseStmt;
typedef struct AlterDatabaseSetStmt typedef struct AlterDatabaseSetStmt
{ {
NodeTag type; NodeTag type;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.79 2005/06/17 22:32:50 tgl Exp $ * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.80 2005/07/31 17:19:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -71,6 +71,7 @@ struct PGPROC ...@@ -71,6 +71,7 @@ struct PGPROC
int pid; /* This backend's process id, or 0 */ int pid; /* This backend's process id, or 0 */
Oid databaseId; /* OID of database this backend is using */ Oid databaseId; /* OID of database this backend is using */
Oid roleId; /* OID of role using this backend */
/* Info about LWLock the process is currently waiting for, if any. */ /* Info about LWLock the process is currently waiting for, if any. */
bool lwWaiting; /* true if waiting for an LW lock */ bool lwWaiting; /* true if waiting for an LW lock */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.2 2005/06/17 22:32:50 tgl Exp $ * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.3 2005/07/31 17:19:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,6 +31,8 @@ extern bool IsBackendPid(int pid); ...@@ -31,6 +31,8 @@ extern bool IsBackendPid(int pid);
extern bool DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself); extern bool DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself);
extern int CountActiveBackends(void); extern int CountActiveBackends(void);
extern int CountDBBackends(Oid databaseid);
extern int CountUserBackends(Oid roleid);
extern void XidCacheRemoveRunningXids(TransactionId xid, extern void XidCacheRemoveRunningXids(TransactionId xid,
int nxids, TransactionId *xids); int nxids, TransactionId *xids);
......
...@@ -1281,7 +1281,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem ...@@ -1281,7 +1281,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char")); pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
pg_locks | SELECT l.locktype, l."database", l.relation, l.page, l.tuple, l.transactionid, l.classid, l.objid, l.objsubid, l."transaction", l.pid, l."mode", l."granted" FROM pg_lock_status() l(locktype text, "database" oid, relation oid, page integer, tuple smallint, transactionid xid, classid oid, objid oid, objsubid smallint, "transaction" xid, pid integer, "mode" text, "granted" boolean); pg_locks | SELECT l.locktype, l."database", l.relation, l.page, l.tuple, l.transactionid, l.classid, l.objid, l.objsubid, l."transaction", l.pid, l."mode", l."granted" FROM pg_lock_status() l(locktype text, "database" oid, relation oid, page integer, tuple smallint, transactionid xid, classid oid, objid oid, objsubid smallint, "transaction" xid, pid integer, "mode" text, "granted" boolean);
pg_prepared_xacts | SELECT p."transaction", p.gid, p."prepared", u.rolname AS "owner", d.datname AS "database" FROM ((pg_prepared_xact() p("transaction" xid, gid text, "prepared" timestamp with time zone, ownerid oid, dbid oid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid))); pg_prepared_xacts | SELECT p."transaction", p.gid, p."prepared", u.rolname AS "owner", d.datname AS "database" FROM ((pg_prepared_xact() p("transaction" xid, gid text, "prepared" timestamp with time zone, ownerid oid, dbid oid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid)));
pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid; pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid;
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name); pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text); pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin; pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment