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:
parent
b125877107
commit
d42cf5a42a
@ -1,6 +1,6 @@
|
||||
<!--
|
||||
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">
|
||||
@ -1018,6 +1018,16 @@
|
||||
</entry>
|
||||
</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>
|
||||
<entry><structfield>rolpassword</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
@ -1921,6 +1931,16 @@
|
||||
</entry>
|
||||
</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>
|
||||
<entry><structfield>datlastsysoid</structfield></entry>
|
||||
<entry><type>oid</type></entry>
|
||||
@ -4811,6 +4831,16 @@
|
||||
</entry>
|
||||
</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>
|
||||
<entry><structfield>rolpassword</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -20,6 +20,12 @@ PostgreSQL documentation
|
||||
|
||||
<refsynopsisdiv>
|
||||
<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> RESET <replaceable>parameter</replaceable>
|
||||
|
||||
@ -38,7 +44,12 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla
|
||||
</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>
|
||||
database. Whenever a new session is subsequently started in that
|
||||
database, the specified value becomes the session default value.
|
||||
@ -51,7 +62,7 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla
|
||||
</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
|
||||
also have the
|
||||
<literal>CREATEDB</literal> privilege. The current database cannot
|
||||
@ -60,7 +71,7 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla
|
||||
</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.
|
||||
</para>
|
||||
</refsect1>
|
||||
@ -78,6 +89,16 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> OWNER TO <repla
|
||||
</listitem>
|
||||
</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>
|
||||
<term><replaceable>parameter</replaceable></term>
|
||||
<term><replaceable>value</replaceable></term>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
|
||||
| CREATEUSER | NOCREATEUSER
|
||||
| INHERIT | NOINHERIT
|
||||
| LOGIN | NOLOGIN
|
||||
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
|
||||
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
|
||||
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
|
||||
|
||||
@ -118,6 +119,7 @@ ALTER ROLE <replaceable class="PARAMETER">name</replaceable> RESET <replaceable>
|
||||
<term><literal>NOINHERIT</literal></term>
|
||||
<term><literal>LOGIN</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>ENCRYPTED</></term>
|
||||
<term><literal>UNENCRYPTED</></term>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
|
||||
| CREATEUSER | NOCREATEUSER
|
||||
| INHERIT | NOINHERIT
|
||||
| LOGIN | NOLOGIN
|
||||
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
|
||||
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
|
||||
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -24,7 +24,8 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable>
|
||||
[ [ WITH ] [ OWNER [=] <replaceable class="parameter">dbowner</replaceable> ]
|
||||
[ TEMPLATE [=] <replaceable class="parameter">template</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>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@ -123,6 +124,16 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable>
|
||||
</para>
|
||||
</listitem>
|
||||
</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>
|
||||
|
||||
<para>
|
||||
@ -161,6 +172,13 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable>
|
||||
We recommend that databases used as templates be treated as read-only.
|
||||
See <xref linkend="manage-ag-templatedbs"> for more information.
|
||||
</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>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
|
||||
| CREATEUSER | NOCREATEUSER
|
||||
| INHERIT | NOINHERIT
|
||||
| LOGIN | NOLOGIN
|
||||
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
|
||||
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
|
||||
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
|
||||
| IN ROLE <replaceable class="PARAMETER">rolename</replaceable> [, ...]
|
||||
@ -172,6 +173,16 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
|
||||
</listitem>
|
||||
</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>
|
||||
<term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term>
|
||||
<listitem>
|
||||
@ -327,6 +338,13 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
|
||||
the same functionality as <command>CREATE ROLE</command> (in fact,
|
||||
it calls this command) but can be run from the command shell.
|
||||
</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>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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
|
||||
-->
|
||||
|
||||
@ -30,6 +30,7 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
|
||||
| CREATEUSER | NOCREATEUSER
|
||||
| INHERIT | NOINHERIT
|
||||
| LOGIN | NOLOGIN
|
||||
| CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
|
||||
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
|
||||
| VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
|
||||
| IN ROLE <replaceable class="PARAMETER">rolename</replaceable> [, ...]
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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
|
||||
* Each global transaction is associated with a global transaction
|
||||
@ -272,6 +272,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
|
||||
gxact->proc.xmin = InvalidTransactionId;
|
||||
gxact->proc.pid = 0;
|
||||
gxact->proc.databaseId = databaseid;
|
||||
gxact->proc.roleId = owner;
|
||||
gxact->proc.lwWaiting = false;
|
||||
gxact->proc.lwExclusive = false;
|
||||
gxact->proc.lwWaitLink = NULL;
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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
|
||||
@ -15,6 +15,7 @@ CREATE VIEW pg_roles AS
|
||||
rolcreatedb,
|
||||
rolcatupdate,
|
||||
rolcanlogin,
|
||||
rolconnlimit,
|
||||
'********'::text as rolpassword,
|
||||
rolvaliduntil,
|
||||
rolconfig,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static AlterDatabaseStmt *
|
||||
_copyAlterDatabaseStmt(AlterDatabaseStmt *from)
|
||||
{
|
||||
AlterDatabaseStmt *newnode = makeNode(AlterDatabaseStmt);
|
||||
|
||||
COPY_STRING_FIELD(dbname);
|
||||
COPY_NODE_FIELD(options);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static AlterDatabaseSetStmt *
|
||||
_copyAlterDatabaseSetStmt(AlterDatabaseSetStmt *from)
|
||||
{
|
||||
@ -3011,6 +3022,9 @@ copyObject(void *from)
|
||||
case T_CreatedbStmt:
|
||||
retval = _copyCreatedbStmt(from);
|
||||
break;
|
||||
case T_AlterDatabaseStmt:
|
||||
retval = _copyAlterDatabaseStmt(from);
|
||||
break;
|
||||
case T_AlterDatabaseSetStmt:
|
||||
retval = _copyAlterDatabaseSetStmt(from);
|
||||
break;
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalAlterDatabaseStmt(AlterDatabaseStmt *a, AlterDatabaseStmt *b)
|
||||
{
|
||||
COMPARE_STRING_FIELD(dbname);
|
||||
COMPARE_NODE_FIELD(options);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
|
||||
{
|
||||
@ -2059,6 +2068,9 @@ equal(void *a, void *b)
|
||||
case T_CreatedbStmt:
|
||||
retval = _equalCreatedbStmt(a, b);
|
||||
break;
|
||||
case T_AlterDatabaseStmt:
|
||||
retval = _equalAlterDatabaseStmt(a, b);
|
||||
break;
|
||||
case T_AlterDatabaseSetStmt:
|
||||
retval = _equalAlterDatabaseSetStmt(a, b);
|
||||
break;
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -131,9 +131,9 @@ static void doNegateFloat(Value *v);
|
||||
}
|
||||
|
||||
%type <node> stmt schema_stmt
|
||||
AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt AlterOwnerStmt
|
||||
AlterSeqStmt AlterTableStmt AlterUserStmt AlterUserSetStmt
|
||||
AlterRoleStmt AlterRoleSetStmt
|
||||
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt
|
||||
AlterOwnerStmt AlterSeqStmt AlterTableStmt
|
||||
AlterUserStmt AlterUserSetStmt AlterRoleStmt AlterRoleSetStmt
|
||||
AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
|
||||
ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
|
||||
CreateDomainStmt CreateGroupStmt CreateOpClassStmt CreatePLangStmt
|
||||
@ -165,8 +165,10 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
%type <dbehavior> opt_drop_behavior
|
||||
|
||||
%type <list> createdb_opt_list copy_opt_list transaction_mode_list
|
||||
%type <defelt> createdb_opt_item copy_opt_item transaction_mode_item
|
||||
%type <list> createdb_opt_list alterdb_opt_list copy_opt_list
|
||||
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 <boolean> opt_force opt_or_replace
|
||||
@ -257,7 +259,7 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
%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 <node> fetch_direction select_limit_value select_offset_value
|
||||
@ -302,7 +304,7 @@ static void doNegateFloat(Value *v);
|
||||
%type <ival> opt_numeric opt_decimal
|
||||
%type <boolean> opt_varying opt_timezone
|
||||
|
||||
%type <ival> Iconst
|
||||
%type <ival> Iconst SignedIconst
|
||||
%type <str> Sconst comment_text
|
||||
%type <str> RoleId opt_granted_by opt_boolean ColId_or_Sconst
|
||||
%type <list> var_list var_list_or_default
|
||||
@ -342,7 +344,7 @@ static void doNegateFloat(Value *v);
|
||||
CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P
|
||||
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
|
||||
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
|
||||
CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
|
||||
|
||||
@ -486,7 +488,8 @@ stmtmulti: stmtmulti ';' stmt
|
||||
;
|
||||
|
||||
stmt :
|
||||
AlterDatabaseSetStmt
|
||||
AlterDatabaseStmt
|
||||
| AlterDatabaseSetStmt
|
||||
| AlterDomainStmt
|
||||
| AlterFunctionStmt
|
||||
| AlterGroupStmt
|
||||
@ -672,6 +675,10 @@ OptRoleElem:
|
||||
{
|
||||
$$ = makeDefElem("canlogin", (Node *)makeInteger(FALSE));
|
||||
}
|
||||
| CONNECTION LIMIT SignedIconst
|
||||
{
|
||||
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($3));
|
||||
}
|
||||
| IN_P ROLE name_list
|
||||
{
|
||||
$$ = makeDefElem("addroleto", (Node *)$3);
|
||||
@ -2238,17 +2245,8 @@ FloatOnly: FCONST { $$ = makeFloat($1); }
|
||||
}
|
||||
;
|
||||
|
||||
IntegerOnly:
|
||||
Iconst
|
||||
{
|
||||
$$ = makeInteger($1);
|
||||
}
|
||||
| '-' Iconst
|
||||
{
|
||||
$$ = makeInteger($2);
|
||||
$$->val.ival = - $$->val.ival;
|
||||
}
|
||||
;
|
||||
IntegerOnly: SignedIconst { $$ = makeInteger($1); };
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
@ -3044,21 +3042,21 @@ fetch_direction:
|
||||
n->howMany = -1;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ABSOLUTE_P fetch_count
|
||||
| ABSOLUTE_P SignedIconst
|
||||
{
|
||||
FetchStmt *n = makeNode(FetchStmt);
|
||||
n->direction = FETCH_ABSOLUTE;
|
||||
n->howMany = $2;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| RELATIVE_P fetch_count
|
||||
| RELATIVE_P SignedIconst
|
||||
{
|
||||
FetchStmt *n = makeNode(FetchStmt);
|
||||
n->direction = FETCH_RELATIVE;
|
||||
n->howMany = $2;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| fetch_count
|
||||
| SignedIconst
|
||||
{
|
||||
FetchStmt *n = makeNode(FetchStmt);
|
||||
n->direction = FETCH_FORWARD;
|
||||
@ -3079,7 +3077,7 @@ fetch_direction:
|
||||
n->howMany = 1;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| FORWARD fetch_count
|
||||
| FORWARD SignedIconst
|
||||
{
|
||||
FetchStmt *n = makeNode(FetchStmt);
|
||||
n->direction = FETCH_FORWARD;
|
||||
@ -3100,7 +3098,7 @@ fetch_direction:
|
||||
n->howMany = 1;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| BACKWARD fetch_count
|
||||
| BACKWARD SignedIconst
|
||||
{
|
||||
FetchStmt *n = makeNode(FetchStmt);
|
||||
n->direction = FETCH_BACKWARD;
|
||||
@ -3116,11 +3114,6 @@ fetch_direction:
|
||||
}
|
||||
;
|
||||
|
||||
fetch_count:
|
||||
Iconst { $$ = $1; }
|
||||
| '-' Iconst { $$ = - $2; }
|
||||
;
|
||||
|
||||
from_in: FROM {}
|
||||
| IN_P {}
|
||||
;
|
||||
@ -4473,6 +4466,10 @@ createdb_opt_item:
|
||||
{
|
||||
$$ = makeDefElem("encoding", NULL);
|
||||
}
|
||||
| CONNECTION LIMIT opt_equal SignedIconst
|
||||
{
|
||||
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($4));
|
||||
}
|
||||
| OWNER opt_equal name
|
||||
{
|
||||
$$ = makeDefElem("owner", (Node *)makeString($3));
|
||||
@ -4485,8 +4482,7 @@ createdb_opt_item:
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 2002-02-25
|
||||
* equals for backward compatibility, and it doesn't seem worth removing it.
|
||||
*/
|
||||
opt_equal: '=' {}
|
||||
| /*EMPTY*/ {}
|
||||
@ -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:
|
||||
ALTER DATABASE database_name SET set_rest
|
||||
{
|
||||
@ -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
|
||||
@ -7875,6 +7894,10 @@ Iconst: ICONST { $$ = $1; };
|
||||
Sconst: SCONST { $$ = $1; };
|
||||
RoleId: ColId { $$ = $1; };
|
||||
|
||||
SignedIconst: ICONST { $$ = $1; }
|
||||
| '-' ICONST { $$ = - $2; }
|
||||
;
|
||||
|
||||
/*
|
||||
* Name classification hierarchy.
|
||||
*
|
||||
@ -7959,6 +7982,7 @@ unreserved_keyword:
|
||||
| COMMENT
|
||||
| COMMIT
|
||||
| COMMITTED
|
||||
| CONNECTION
|
||||
| CONSTRAINTS
|
||||
| CONVERSION_P
|
||||
| COPY
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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[] = {
|
||||
{"comment", COMMENT},
|
||||
{"commit", COMMIT},
|
||||
{"committed", COMMITTED},
|
||||
{"connection", CONNECTION},
|
||||
{"constraint", CONSTRAINT},
|
||||
{"constraints", CONSTRAINTS},
|
||||
{"conversion", CONVERSION_P},
|
||||
|
@ -23,7 +23,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
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) \
|
||||
do { \
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
MyProc->xmin = InvalidTransactionId;
|
||||
MyProc->pid = MyProcPid;
|
||||
MyProc->databaseId = MyDatabaseId;
|
||||
/* Will be set properly after the session role id is determined */
|
||||
MyProc->roleId = InvalidOid;
|
||||
MyProc->lwWaiting = false;
|
||||
MyProc->lwExclusive = false;
|
||||
MyProc->lwWaitLink = NULL;
|
||||
@ -331,6 +333,7 @@ InitDummyProcess(int proctype)
|
||||
MyProc->xid = InvalidTransactionId;
|
||||
MyProc->xmin = InvalidTransactionId;
|
||||
MyProc->databaseId = MyDatabaseId;
|
||||
MyProc->roleId = InvalidOid;
|
||||
MyProc->lwWaiting = false;
|
||||
MyProc->lwExclusive = false;
|
||||
MyProc->lwWaitLink = NULL;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
|
||||
switch (nodeTag(parsetree))
|
||||
{
|
||||
case T_AlterDatabaseStmt:
|
||||
case T_AlterDatabaseSetStmt:
|
||||
case T_AlterDomainStmt:
|
||||
case T_AlterFunctionStmt:
|
||||
@ -788,6 +789,10 @@ ProcessUtility(Node *parsetree,
|
||||
createdb((CreatedbStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterDatabaseStmt:
|
||||
AlterDatabase((AlterDatabaseStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_AlterDatabaseSetStmt:
|
||||
AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
|
||||
break;
|
||||
@ -1504,6 +1509,10 @@ CreateCommandTag(Node *parsetree)
|
||||
tag = "CREATE DATABASE";
|
||||
break;
|
||||
|
||||
case T_AlterDatabaseStmt:
|
||||
tag = "ALTER DATABASE";
|
||||
break;
|
||||
|
||||
case T_AlterDatabaseSetStmt:
|
||||
tag = "ALTER DATABASE";
|
||||
break;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 @@
|
||||
#include "storage/fd.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/pg_shmem.h"
|
||||
#include "storage/proc.h"
|
||||
#include "storage/procarray.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/lsyscache.h"
|
||||
@ -404,17 +406,52 @@ InitializeSessionUserId(const char *rolename)
|
||||
rform = (Form_pg_authid) GETSTRUCT(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;
|
||||
AuthenticatedUserIsSuperuser = rform->rolsuper;
|
||||
|
||||
/* This sets OuterUserId/CurrentUserId too */
|
||||
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 */
|
||||
SetConfigOption("session_authorization", rolename,
|
||||
PGC_BACKEND, PGC_S_OVERRIDE);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
name, MyDatabaseId)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Also check that the database is currently allowing connections.
|
||||
* (We do not enforce this in standalone mode, however, so that there is
|
||||
* a way to recover from "UPDATE pg_database SET datallowconn = false;".
|
||||
* We do not enforce it for the autovacuum process either.)
|
||||
*/
|
||||
dbform = (Form_pg_database) GETSTRUCT(tup);
|
||||
if (IsUnderPostmaster && !IsAutoVacuumProcess() && !dbform->datallowconn)
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("database \"%s\" is not currently accepting connections",
|
||||
name)));
|
||||
|
||||
/*
|
||||
* These next checks are not enforced when in standalone mode, so that
|
||||
* there is a way to recover from disabling all access to all databases,
|
||||
* for example "UPDATE pg_database SET datallowconn = false;".
|
||||
*
|
||||
* We do not enforce them for the autovacuum process either.
|
||||
*/
|
||||
if (IsUnderPostmaster && !IsAutoVacuumProcess())
|
||||
{
|
||||
/*
|
||||
* Check that the database is currently allowing connections.
|
||||
*/
|
||||
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
|
||||
|
@ -1,18 +1,19 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pg_dumpall
|
||||
* pg_dumpall.c
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.65 2005/07/25 04:52:32 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.66 2005/07/31 17:19:19 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres_fe.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#ifdef ENABLE_NLS
|
||||
#include <locale.h>
|
||||
@ -20,8 +21,6 @@
|
||||
#ifndef HAVE_STRDUP
|
||||
#include "strdup.h"
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "getopt_long.h"
|
||||
|
||||
@ -43,7 +42,8 @@ static const char *progname;
|
||||
|
||||
static void help(void);
|
||||
|
||||
static void dumpUsers(PGconn *conn, bool initdbonly);
|
||||
static void dumpRoles(PGconn *conn, bool initdbonly);
|
||||
static void dumpRoleMembership(PGconn *conn);
|
||||
static void dumpGroups(PGconn *conn);
|
||||
static void dumpTablespaces(PGconn *conn);
|
||||
static void dumpCreateDB(PGconn *conn);
|
||||
@ -57,19 +57,20 @@ static int runPgDump(const char *dbname);
|
||||
static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
||||
const char *pguser, bool require_password, bool fail_on_error);
|
||||
static PGresult *executeQuery(PGconn *conn, const char *query);
|
||||
static void executeCommand(PGconn *conn, const char *query);
|
||||
|
||||
char pg_dump_bin[MAXPGPATH];
|
||||
PQExpBuffer pgdumpopts;
|
||||
bool output_clean = false;
|
||||
bool skip_acls = false;
|
||||
bool verbose = false;
|
||||
static bool ignoreVersion = false;
|
||||
int server_version;
|
||||
|
||||
static char pg_dump_bin[MAXPGPATH];
|
||||
static PQExpBuffer pgdumpopts;
|
||||
static bool output_clean = false;
|
||||
static bool skip_acls = false;
|
||||
static bool verbose = false;
|
||||
static bool ignoreVersion = false;
|
||||
/* flags for -X long options */
|
||||
int disable_dollar_quoting = 0;
|
||||
int disable_triggers = 0;
|
||||
int use_setsessauth = 0;
|
||||
static int disable_dollar_quoting = 0;
|
||||
static int disable_triggers = 0;
|
||||
static int use_setsessauth = 0;
|
||||
static int server_version;
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
@ -316,14 +317,22 @@ main(int argc, char *argv[])
|
||||
if (!data_only)
|
||||
{
|
||||
/* Dump all users excluding the initdb user */
|
||||
dumpUsers(conn, false);
|
||||
dumpGroups(conn);
|
||||
dumpRoles(conn, false);
|
||||
|
||||
/* Dump role memberships --- need different method for pre-8.1 */
|
||||
if (server_version >= 80100)
|
||||
dumpRoleMembership(conn);
|
||||
else
|
||||
dumpGroups(conn);
|
||||
|
||||
if (server_version >= 80000)
|
||||
dumpTablespaces(conn);
|
||||
|
||||
if (!globals_only)
|
||||
dumpCreateDB(conn);
|
||||
|
||||
/* Dump alter command for initdb user */
|
||||
dumpUsers(conn, true);
|
||||
dumpRoles(conn, true);
|
||||
}
|
||||
|
||||
if (!globals_only)
|
||||
@ -384,81 +393,151 @@ help(void)
|
||||
|
||||
|
||||
/*
|
||||
* Dump users
|
||||
* Dump roles
|
||||
*
|
||||
* Is able to dump all non initdb users or just the initdb user.
|
||||
*/
|
||||
static void
|
||||
dumpUsers(PGconn *conn, bool initdbonly)
|
||||
dumpRoles(PGconn *conn, bool initdbonly)
|
||||
{
|
||||
PQExpBuffer buf = createPQExpBuffer();
|
||||
PGresult *res;
|
||||
int i_rolname,
|
||||
i_rolsuper,
|
||||
i_rolinherit,
|
||||
i_rolcreaterole,
|
||||
i_rolcreatedb,
|
||||
i_rolcatupdate,
|
||||
i_rolcanlogin,
|
||||
i_rolconnlimit,
|
||||
i_rolpassword,
|
||||
i_rolvaliduntil,
|
||||
i_clusterowner;
|
||||
int i;
|
||||
|
||||
if (server_version >= 70100)
|
||||
res = executeQuery(conn,
|
||||
"SELECT usename, usesysid, passwd, usecreatedb, "
|
||||
"usesuper, valuntil, "
|
||||
"(usesysid = (SELECT datdba FROM pg_database WHERE datname = 'template0')) AS clusterowner "
|
||||
"FROM pg_shadow");
|
||||
/* note: rolconfig is dumped later */
|
||||
if (server_version >= 80100)
|
||||
printfPQExpBuffer(buf,
|
||||
"SELECT rolname, rolsuper, rolinherit, "
|
||||
"rolcreaterole, rolcreatedb, rolcatupdate, "
|
||||
"rolcanlogin, rolconnlimit, rolpassword, "
|
||||
"rolvaliduntil, "
|
||||
"(oid = (SELECT datdba FROM pg_database WHERE datname = 'template0')) AS clusterowner "
|
||||
"FROM pg_authid");
|
||||
else
|
||||
res = executeQuery(conn,
|
||||
"SELECT usename, usesysid, passwd, usecreatedb, "
|
||||
"usesuper, valuntil, "
|
||||
"(usesysid = (SELECT datdba FROM pg_database WHERE datname = 'template1')) AS clusterowner "
|
||||
"FROM pg_shadow");
|
||||
printfPQExpBuffer(buf,
|
||||
"SELECT usename as rolname, "
|
||||
"usesuper as rolsuper, "
|
||||
"true as rolinherit, "
|
||||
"usesuper as rolcreaterole, "
|
||||
"usecreatedb as rolcreatedb, "
|
||||
"usecatupd as rolcatupdate, "
|
||||
"true as rolcanlogin, "
|
||||
"-1 as rolconnlimit, "
|
||||
"passwd as rolpassword, "
|
||||
"valuntil as rolvaliduntil, "
|
||||
"(usesysid = (SELECT datdba FROM pg_database WHERE datname = '%s')) AS clusterowner "
|
||||
"FROM pg_shadow "
|
||||
"UNION ALL "
|
||||
"SELECT groname as rolname, "
|
||||
"false as rolsuper, "
|
||||
"true as rolinherit, "
|
||||
"false as rolcreaterole, "
|
||||
"false as rolcreatedb, "
|
||||
"false as rolcatupdate, "
|
||||
"false as rolcanlogin, "
|
||||
"-1 as rolconnlimit, "
|
||||
"null::text as rolpassword, "
|
||||
"null::abstime as rolvaliduntil, "
|
||||
"false AS clusterowner "
|
||||
"FROM pg_group",
|
||||
(server_version >= 70100) ? "template0" : "template1");
|
||||
|
||||
res = executeQuery(conn, buf->data);
|
||||
|
||||
i_rolname = PQfnumber(res, "rolname");
|
||||
i_rolsuper = PQfnumber(res, "rolsuper");
|
||||
i_rolinherit = PQfnumber(res, "rolinherit");
|
||||
i_rolcreaterole = PQfnumber(res, "rolcreaterole");
|
||||
i_rolcreatedb = PQfnumber(res, "rolcreatedb");
|
||||
i_rolcatupdate = PQfnumber(res, "rolcatupdate");
|
||||
i_rolcanlogin = PQfnumber(res, "rolcanlogin");
|
||||
i_rolconnlimit = PQfnumber(res, "rolconnlimit");
|
||||
i_rolpassword = PQfnumber(res, "rolpassword");
|
||||
i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
|
||||
i_clusterowner = PQfnumber(res, "clusterowner");
|
||||
|
||||
if (PQntuples(res) > 0 || (!initdbonly && output_clean))
|
||||
printf("--\n-- Users\n--\n\n");
|
||||
printf("--\n-- Roles\n--\n\n");
|
||||
if (!initdbonly && output_clean)
|
||||
printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
const char *username;
|
||||
const char *rolename;
|
||||
bool clusterowner;
|
||||
|
||||
username = PQgetvalue(res, i, 0);
|
||||
clusterowner = (strcmp(PQgetvalue(res, i, 6), "t") == 0);
|
||||
rolename = PQgetvalue(res, i, i_rolname);
|
||||
clusterowner = (strcmp(PQgetvalue(res, i, i_clusterowner), "t") == 0);
|
||||
|
||||
/* Check which pass we're on */
|
||||
if ((initdbonly && !clusterowner) || (!initdbonly && clusterowner))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Dump ALTER USER for the cluster owner and CREATE USER for all
|
||||
* other users
|
||||
* Dump ALTER ROLE for the cluster owner and CREATE ROLE for all
|
||||
* other roles
|
||||
*/
|
||||
if (!clusterowner)
|
||||
printfPQExpBuffer(buf, "CREATE USER %s WITH", fmtId(username));
|
||||
printfPQExpBuffer(buf, "CREATE ROLE %s WITH", fmtId(rolename));
|
||||
else
|
||||
printfPQExpBuffer(buf, "ALTER USER %s WITH", fmtId(username));
|
||||
printfPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
|
||||
|
||||
if (!PQgetisnull(res, i, 2))
|
||||
{
|
||||
appendPQExpBuffer(buf, " PASSWORD ");
|
||||
appendStringLiteral(buf, PQgetvalue(res, i, 2), true);
|
||||
}
|
||||
if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
|
||||
appendPQExpBuffer(buf, " SUPERUSER");
|
||||
else
|
||||
appendPQExpBuffer(buf, " NOSUPERUSER");
|
||||
|
||||
if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
|
||||
if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
|
||||
appendPQExpBuffer(buf, " INHERIT");
|
||||
else
|
||||
appendPQExpBuffer(buf, " NOINHERIT");
|
||||
|
||||
if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
|
||||
appendPQExpBuffer(buf, " CREATEROLE");
|
||||
else
|
||||
appendPQExpBuffer(buf, " NOCREATEROLE");
|
||||
|
||||
if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
|
||||
appendPQExpBuffer(buf, " CREATEDB");
|
||||
else
|
||||
appendPQExpBuffer(buf, " NOCREATEDB");
|
||||
|
||||
if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
|
||||
appendPQExpBuffer(buf, " CREATEUSER");
|
||||
if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
|
||||
appendPQExpBuffer(buf, " LOGIN");
|
||||
else
|
||||
appendPQExpBuffer(buf, " NOCREATEUSER");
|
||||
appendPQExpBuffer(buf, " NOLOGIN");
|
||||
|
||||
if (!PQgetisnull(res, i, 5))
|
||||
if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
|
||||
appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
|
||||
PQgetvalue(res, i, i_rolconnlimit));
|
||||
|
||||
if (!PQgetisnull(res, i, i_rolpassword))
|
||||
{
|
||||
appendPQExpBuffer(buf, " PASSWORD ");
|
||||
appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true);
|
||||
}
|
||||
|
||||
if (!PQgetisnull(res, i, i_rolvaliduntil))
|
||||
appendPQExpBuffer(buf, " VALID UNTIL '%s'",
|
||||
PQgetvalue(res, i, 5));
|
||||
PQgetvalue(res, i, i_rolvaliduntil));
|
||||
|
||||
appendPQExpBuffer(buf, ";\n");
|
||||
|
||||
printf("%s", buf->data);
|
||||
|
||||
if (server_version >= 70300)
|
||||
dumpUserConfig(conn, username);
|
||||
dumpUserConfig(conn, rolename);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
@ -469,63 +548,109 @@ dumpUsers(PGconn *conn, bool initdbonly)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dump role memberships. This code is used for 8.1 and later servers.
|
||||
*
|
||||
* Note: we expect dumpRoles already created all the roles, but there is
|
||||
* no membership yet.
|
||||
*/
|
||||
static void
|
||||
dumpRoleMembership(PGconn *conn)
|
||||
{
|
||||
PGresult *res;
|
||||
int i;
|
||||
|
||||
res = executeQuery(conn, "SELECT ur.rolname AS roleid, "
|
||||
"um.rolname AS member, "
|
||||
"ug.rolname AS grantor, "
|
||||
"a.admin_option "
|
||||
"FROM pg_auth_members a "
|
||||
"LEFT JOIN pg_authid ur on ur.oid = a.roleid "
|
||||
"LEFT JOIN pg_authid um on um.oid = a.member "
|
||||
"LEFT JOIN pg_authid ug on ug.oid = a.grantor");
|
||||
|
||||
if (PQntuples(res) > 0 || output_clean)
|
||||
printf("--\n-- Role memberships\n--\n\n");
|
||||
if (output_clean)
|
||||
printf("DELETE FROM pg_auth_members;\n\n");
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
char *roleid = PQgetvalue(res, i, 0);
|
||||
char *member = PQgetvalue(res, i, 1);
|
||||
char *grantor = PQgetvalue(res, i, 2);
|
||||
char *option = PQgetvalue(res, i, 3);
|
||||
|
||||
printf("GRANT %s", fmtId(roleid));
|
||||
printf(" TO %s", fmtId(member));
|
||||
if (*option == 't')
|
||||
printf(" WITH ADMIN OPTION");
|
||||
printf(" GRANTED BY %s;\n", fmtId(grantor));
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump groups.
|
||||
* Dump group memberships from a pre-8.1 server. It's annoying that we
|
||||
* can't share any useful amount of code with the post-8.1 case, but
|
||||
* the catalog representations are too different.
|
||||
*
|
||||
* Note: we expect dumpRoles already created all the roles, but there is
|
||||
* no membership yet.
|
||||
*/
|
||||
static void
|
||||
dumpGroups(PGconn *conn)
|
||||
{
|
||||
PQExpBuffer buf = createPQExpBuffer();
|
||||
PGresult *res;
|
||||
int i;
|
||||
|
||||
res = executeQuery(conn, "SELECT groname, grolist FROM pg_group");
|
||||
|
||||
if (PQntuples(res) > 0 || output_clean)
|
||||
printf("--\n-- Groups\n--\n\n");
|
||||
printf("--\n-- Role memberships\n--\n\n");
|
||||
if (output_clean)
|
||||
printf("DELETE FROM pg_group;\n\n");
|
||||
printf("DELETE FROM pg_auth_members;\n\n");
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
PQExpBuffer buf = createPQExpBuffer();
|
||||
char *groname = PQgetvalue(res, i, 0);
|
||||
char *val;
|
||||
char *tok;
|
||||
|
||||
appendPQExpBuffer(buf, "CREATE GROUP %s;\n",
|
||||
fmtId(PQgetvalue(res, i, 0)));
|
||||
|
||||
val = strdup(PQgetvalue(res, i, 1));
|
||||
|
||||
tok = strtok(val, ",{}");
|
||||
while (tok)
|
||||
{
|
||||
PGresult *res2;
|
||||
PQExpBuffer buf2 = createPQExpBuffer();
|
||||
int j;
|
||||
|
||||
appendPQExpBuffer(buf2, "SELECT usename FROM pg_shadow WHERE usesysid = %s;", tok);
|
||||
res2 = executeQuery(conn, buf2->data);
|
||||
destroyPQExpBuffer(buf2);
|
||||
printfPQExpBuffer(buf,
|
||||
"SELECT usename FROM pg_shadow WHERE usesysid = %s",
|
||||
tok);
|
||||
|
||||
res2 = executeQuery(conn, buf->data);
|
||||
|
||||
for (j = 0; j < PQntuples(res2); j++)
|
||||
{
|
||||
appendPQExpBuffer(buf, "ALTER GROUP %s ",
|
||||
fmtId(PQgetvalue(res, i, 0)));
|
||||
appendPQExpBuffer(buf, "ADD USER %s;\n",
|
||||
fmtId(PQgetvalue(res2, j, 0)));
|
||||
printf("GRANT %s", fmtId(groname));
|
||||
printf(" TO %s;\n", fmtId(PQgetvalue(res2, j, 0)));
|
||||
}
|
||||
|
||||
PQclear(res2);
|
||||
|
||||
tok = strtok(NULL, "{},");
|
||||
tok = strtok(NULL, ",{}");
|
||||
}
|
||||
free(val);
|
||||
|
||||
printf("%s", buf->data);
|
||||
destroyPQExpBuffer(buf);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
destroyPQExpBuffer(buf);
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
@ -607,17 +732,27 @@ dumpTablespaces(PGconn *conn)
|
||||
static void
|
||||
dumpCreateDB(PGconn *conn)
|
||||
{
|
||||
PQExpBuffer buf = createPQExpBuffer();
|
||||
PGresult *res;
|
||||
int i;
|
||||
|
||||
printf("--\n-- Database creation\n--\n\n");
|
||||
|
||||
if (server_version >= 80000)
|
||||
if (server_version >= 80100)
|
||||
res = executeQuery(conn,
|
||||
"SELECT datname, "
|
||||
"coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
|
||||
"pg_encoding_to_char(d.encoding), "
|
||||
"datistemplate, datacl, datconnlimit, "
|
||||
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
|
||||
"FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
|
||||
"WHERE datallowconn ORDER BY 1");
|
||||
else if (server_version >= 80000)
|
||||
res = executeQuery(conn,
|
||||
"SELECT datname, "
|
||||
"coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
|
||||
"pg_encoding_to_char(d.encoding), "
|
||||
"datistemplate, datacl, "
|
||||
"datistemplate, datacl, -1 as datconnlimit, "
|
||||
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
|
||||
"FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
|
||||
"WHERE datallowconn ORDER BY 1");
|
||||
@ -626,7 +761,7 @@ dumpCreateDB(PGconn *conn)
|
||||
"SELECT datname, "
|
||||
"coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
|
||||
"pg_encoding_to_char(d.encoding), "
|
||||
"datistemplate, datacl, "
|
||||
"datistemplate, datacl, -1 as datconnlimit, "
|
||||
"'pg_default' AS dattablespace "
|
||||
"FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
|
||||
"WHERE datallowconn ORDER BY 1");
|
||||
@ -637,7 +772,7 @@ dumpCreateDB(PGconn *conn)
|
||||
"(select usename from pg_shadow where usesysid=datdba), "
|
||||
"(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
|
||||
"pg_encoding_to_char(d.encoding), "
|
||||
"datistemplate, '' as datacl, "
|
||||
"datistemplate, '' as datacl, -1 as datconnlimit, "
|
||||
"'pg_default' AS dattablespace "
|
||||
"FROM pg_database d "
|
||||
"WHERE datallowconn ORDER BY 1");
|
||||
@ -652,7 +787,7 @@ dumpCreateDB(PGconn *conn)
|
||||
"(select usename from pg_shadow where usesysid=datdba), "
|
||||
"pg_encoding_to_char(d.encoding), "
|
||||
"'f' as datistemplate, "
|
||||
"'' as datacl, "
|
||||
"'' as datacl, -1 as datconnlimit, "
|
||||
"'pg_default' AS dattablespace "
|
||||
"FROM pg_database d "
|
||||
"ORDER BY 1");
|
||||
@ -660,18 +795,19 @@ dumpCreateDB(PGconn *conn)
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
PQExpBuffer buf;
|
||||
char *dbname = PQgetvalue(res, i, 0);
|
||||
char *dbowner = PQgetvalue(res, i, 1);
|
||||
char *dbencoding = PQgetvalue(res, i, 2);
|
||||
char *dbistemplate = PQgetvalue(res, i, 3);
|
||||
char *dbacl = PQgetvalue(res, i, 4);
|
||||
char *dbtablespace = PQgetvalue(res, i, 5);
|
||||
char *dbconnlimit = PQgetvalue(res, i, 5);
|
||||
char *dbtablespace = PQgetvalue(res, i, 6);
|
||||
char *fdbname;
|
||||
|
||||
buf = createPQExpBuffer();
|
||||
fdbname = strdup(fmtId(dbname));
|
||||
|
||||
resetPQExpBuffer(buf);
|
||||
|
||||
/*
|
||||
* Skip the CREATE DATABASE commands for "template1" and "postgres",
|
||||
* since they are presumably already there in the destination cluster.
|
||||
@ -698,6 +834,10 @@ dumpCreateDB(PGconn *conn)
|
||||
appendPQExpBuffer(buf, " TABLESPACE = %s",
|
||||
fmtId(dbtablespace));
|
||||
|
||||
if (strcmp(dbconnlimit, "-1") != 0)
|
||||
appendPQExpBuffer(buf, " CONNECTION LIMIT = %s",
|
||||
dbconnlimit);
|
||||
|
||||
appendPQExpBuffer(buf, ";\n");
|
||||
|
||||
if (strcmp(dbistemplate, "t") == 0)
|
||||
@ -723,11 +863,12 @@ dumpCreateDB(PGconn *conn)
|
||||
if (server_version >= 70300)
|
||||
dumpDatabaseConfig(conn, dbname);
|
||||
|
||||
destroyPQExpBuffer(buf);
|
||||
free(fdbname);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
destroyPQExpBuffer(buf);
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
@ -782,14 +923,17 @@ dumpUserConfig(PGconn *conn, const char *username)
|
||||
{
|
||||
PGresult *res;
|
||||
|
||||
printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
|
||||
if (server_version >= 80100)
|
||||
printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
|
||||
else
|
||||
printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
|
||||
appendStringLiteral(buf, username, true);
|
||||
appendPQExpBuffer(buf, ";");
|
||||
|
||||
res = executeQuery(conn, buf->data);
|
||||
if (!PQgetisnull(res, 0, 0))
|
||||
{
|
||||
makeAlterConfigCommand(PQgetvalue(res, 0, 0), "USER", username);
|
||||
makeAlterConfigCommand(PQgetvalue(res, 0, 0), "ROLE", username);
|
||||
PQclear(res);
|
||||
count++;
|
||||
}
|
||||
@ -1041,11 +1185,17 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* On 7.3 and later, make sure we are not fooled by non-system schemas
|
||||
* in the search path.
|
||||
*/
|
||||
if (server_version >= 70300)
|
||||
executeCommand(conn, "SET search_path = pg_catalog");
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Run a query, return the results, exit program on failure.
|
||||
*/
|
||||
@ -1061,8 +1211,10 @@ executeQuery(PGconn *conn, const char *query)
|
||||
if (!res ||
|
||||
PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn));
|
||||
fprintf(stderr, _("%s: query was: %s\n"), progname, query);
|
||||
fprintf(stderr, _("%s: query failed: %s"),
|
||||
progname, PQerrorMessage(conn));
|
||||
fprintf(stderr, _("%s: query was: %s\n"),
|
||||
progname, query);
|
||||
PQfinish(conn);
|
||||
exit(1);
|
||||
}
|
||||
@ -1070,6 +1222,32 @@ executeQuery(PGconn *conn, const char *query)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* As above for a SQL command (which returns nothing).
|
||||
*/
|
||||
static void
|
||||
executeCommand(PGconn *conn, const char *query)
|
||||
{
|
||||
PGresult *res;
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, _("%s: executing %s\n"), progname, query);
|
||||
|
||||
res = PQexec(conn, query);
|
||||
if (!res ||
|
||||
PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
{
|
||||
fprintf(stderr, _("%s: query failed: %s"),
|
||||
progname, PQerrorMessage(conn));
|
||||
fprintf(stderr, _("%s: query was: %s\n"),
|
||||
progname, query);
|
||||
PQfinish(conn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dumpTimestamp
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* 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 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200507291
|
||||
#define CATALOG_VERSION_NO 200507301
|
||||
|
||||
#endif
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* 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
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -49,6 +49,7 @@ CATALOG(pg_authid,1260) BKI_SHARED_RELATION
|
||||
bool rolcreatedb; /* allowed to create databases? */
|
||||
bool rolcatupdate; /* allowed to alter catalogs manually? */
|
||||
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! */
|
||||
text rolpassword; /* password, if any */
|
||||
@ -70,7 +71,7 @@ typedef FormData_pg_authid *Form_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_rolsuper 2
|
||||
#define Anum_pg_authid_rolinherit 3
|
||||
@ -78,9 +79,10 @@ typedef FormData_pg_authid *Form_pg_authid;
|
||||
#define Anum_pg_authid_rolcreatedb 5
|
||||
#define Anum_pg_authid_rolcatupdate 6
|
||||
#define Anum_pg_authid_rolcanlogin 7
|
||||
#define Anum_pg_authid_rolpassword 8
|
||||
#define Anum_pg_authid_rolvaliduntil 9
|
||||
#define Anum_pg_authid_rolconfig 10
|
||||
#define Anum_pg_authid_rolconnlimit 8
|
||||
#define Anum_pg_authid_rolpassword 9
|
||||
#define Anum_pg_authid_rolvaliduntil 10
|
||||
#define Anum_pg_authid_rolconfig 11
|
||||
|
||||
/* ----------------
|
||||
* initial contents of pg_authid
|
||||
@ -89,7 +91,7 @@ typedef FormData_pg_authid *Form_pg_authid;
|
||||
* 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
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* 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
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -40,6 +40,7 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION
|
||||
int4 encoding; /* character encoding */
|
||||
bool datistemplate; /* allowed as CREATE DATABASE template? */
|
||||
bool datallowconn; /* new connections allowed? */
|
||||
int4 datconnlimit; /* max connections allowed (-1=no limit) */
|
||||
Oid datlastsysoid; /* highest OID to consider a system OID */
|
||||
TransactionId datvacuumxid; /* all XIDs before this are vacuumed */
|
||||
TransactionId datfrozenxid; /* all XIDs before this are frozen */
|
||||
@ -59,20 +60,21 @@ typedef FormData_pg_database *Form_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_datdba 2
|
||||
#define Anum_pg_database_encoding 3
|
||||
#define Anum_pg_database_datistemplate 4
|
||||
#define Anum_pg_database_datallowconn 5
|
||||
#define Anum_pg_database_datlastsysoid 6
|
||||
#define Anum_pg_database_datvacuumxid 7
|
||||
#define Anum_pg_database_datfrozenxid 8
|
||||
#define Anum_pg_database_dattablespace 9
|
||||
#define Anum_pg_database_datconfig 10
|
||||
#define Anum_pg_database_datacl 11
|
||||
#define Anum_pg_database_datconnlimit 6
|
||||
#define Anum_pg_database_datlastsysoid 7
|
||||
#define Anum_pg_database_datvacuumxid 8
|
||||
#define Anum_pg_database_datfrozenxid 9
|
||||
#define Anum_pg_database_dattablespace 10
|
||||
#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");
|
||||
#define TemplateDbOid 1
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* 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
|
||||
extern void createdb(const CreatedbStmt *stmt);
|
||||
extern void dropdb(const char *dbname);
|
||||
extern void RenameDatabase(const char *oldname, const char *newname);
|
||||
extern void AlterDatabase(AlterDatabaseStmt *stmt);
|
||||
extern void AlterDatabaseSet(AlterDatabaseSetStmt *stmt);
|
||||
extern void AlterDatabaseOwner(const char *dbname, Oid newOwnerId);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* 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
|
||||
T_ReindexStmt,
|
||||
T_CheckPointStmt,
|
||||
T_CreateSchemaStmt,
|
||||
T_AlterDatabaseStmt,
|
||||
T_AlterDatabaseSetStmt,
|
||||
T_AlterRoleSetStmt,
|
||||
T_CreateConversionStmt,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* 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
|
||||
* Alter Database
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct AlterDatabaseStmt
|
||||
{
|
||||
NodeTag type;
|
||||
char *dbname; /* name of database to alter */
|
||||
List *options; /* List of DefElem nodes */
|
||||
} AlterDatabaseStmt;
|
||||
|
||||
typedef struct AlterDatabaseSetStmt
|
||||
{
|
||||
NodeTag type;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* 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
|
||||
|
||||
int pid; /* This backend's process id, or 0 */
|
||||
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. */
|
||||
bool lwWaiting; /* true if waiting for an LW lock */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* 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);
|
||||
extern bool DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself);
|
||||
|
||||
extern int CountActiveBackends(void);
|
||||
extern int CountDBBackends(Oid databaseid);
|
||||
extern int CountUserBackends(Oid roleid);
|
||||
|
||||
extern void XidCacheRemoveRunningXids(TransactionId xid,
|
||||
int nxids, TransactionId *xids);
|
||||
|
@ -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_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_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_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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user