Stephen Frost wrote:

This should almost certainly be a pg_database_ownercheck() call instead.
Right there wasn't pg_database_ownercheck at the time I was writing it, fixed

The rest needs to be updated for roles, but looks like it should be pretty easy to do. Much of it just needs to be repatched, the parts that do need to be changed look to be pretty simple changes.
Done.

I believe the use of SessionUserId is probably correct in this patch.
This does mean that this patch will only be for canlogin roles, but that
seems like it's probably correct.  Handling roles w/ members would
require much more thought.
I don't think that having max connection for roles w/ members is doable because you can have 5 roles which has 1 user as member and each role has different number of max conections and there is no right way to decide what to do.


New version which works with roles is attached (diffed against cvs), everything else is mostly same. I also had to readd roleid to flatfiles because I need it in InitProcess() function.

--
Regards
Petr Jelinek (PJMODOS)


Index: src/backend/commands/dbcommands.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/dbcommands.c,v
retrieving revision 1.164
diff -c -r1.164 dbcommands.c
*** src/backend/commands/dbcommands.c   30 Jun 2005 00:00:50 -0000      1.164
--- src/backend/commands/dbcommands.c   3 Jul 2005 22:47:39 -0000
***************
*** 53,60 ****
  
  /* non-export function prototypes */
  static bool get_db_info(const char *name, Oid *dbIdP, Oid *ownerIdP,
!                       int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
!                       Oid *dbLastSysOidP,
                        TransactionId *dbVacuumXidP, TransactionId 
*dbFrozenXidP,
                        Oid *dbTablespace);
  static bool have_createdb_privilege(void);
--- 53,60 ----
  
  /* non-export function prototypes */
  static bool get_db_info(const char *name, Oid *dbIdP, Oid *ownerIdP,
!                       int *encodingP, int *dbMaxConnP, bool *dbIsTemplateP, 
!                       bool *dbAllowConnP,     Oid *dbLastSysOidP,
                        TransactionId *dbVacuumXidP, TransactionId 
*dbFrozenXidP,
                        Oid *dbTablespace);
  static bool have_createdb_privilege(void);
***************
*** 74,79 ****
--- 74,80 ----
        int                     src_encoding;
        bool            src_istemplate;
        bool            src_allowconn;
+       int                     src_maxconn;
        Oid                     src_lastsysoid;
        TransactionId src_vacuumxid;
        TransactionId src_frozenxid;
***************
*** 91,100 ****
--- 92,103 ----
        DefElem    *downer = NULL;
        DefElem    *dtemplate = NULL;
        DefElem    *dencoding = NULL;
+       DefElem    *dmaxconn = NULL;
        char       *dbname = stmt->dbname;
        char       *dbowner = NULL;
        const char *dbtemplate = NULL;
        int                     encoding = -1;
+       int                     dbmaxconn = -1;
  
  #ifndef WIN32
        char            buf[2 * MAXPGPATH + 100];
***************
*** 140,145 ****
--- 143,156 ----
                                                 errmsg("conflicting or 
redundant options")));
                        dencoding = defel;
                }
+               else if (strcmp(defel->defname, "maxconnections") == 0)
+               {
+                       if (dmaxconn)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                                errmsg("conflicting or 
redundant options")));
+                       dmaxconn = defel;
+               }
                else if (strcmp(defel->defname, "location") == 0)
                {
                        ereport(WARNING,
***************
*** 185,190 ****
--- 196,203 ----
                        elog(ERROR, "unrecognized node type: %d",
                                 nodeTag(dencoding->arg));
        }
+       if (dmaxconn && dmaxconn->arg)
+               dbmaxconn = intVal(dmaxconn->arg);
  
        /* obtain OID of proposed owner */
        if (dbowner)
***************
*** 218,224 ****
         * idea, so accept possibility of race to create.  We will check again
         * after we grab the exclusive lock.
         */
!       if (get_db_info(dbname, NULL, NULL, NULL,
                                        NULL, NULL, NULL, NULL, NULL, NULL))
                ereport(ERROR,
                                (errcode(ERRCODE_DUPLICATE_DATABASE),
--- 231,237 ----
         * idea, so accept possibility of race to create.  We will check again
         * after we grab the exclusive lock.
         */
!       if (get_db_info(dbname, NULL, NULL, NULL, NULL,
                                        NULL, NULL, NULL, NULL, NULL, NULL))
                ereport(ERROR,
                                (errcode(ERRCODE_DUPLICATE_DATABASE),
***************
*** 231,238 ****
                dbtemplate = "template1";               /* Default template 
database name */
  
        if (!get_db_info(dbtemplate, &src_dboid, &src_owner, &src_encoding,
!                                        &src_istemplate, &src_allowconn, 
&src_lastsysoid,
!                                        &src_vacuumxid, &src_frozenxid, 
&src_deftablespace))
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_DATABASE),
                 errmsg("template database \"%s\" does not exist", 
dbtemplate)));
--- 244,252 ----
                dbtemplate = "template1";               /* Default template 
database name */
  
        if (!get_db_info(dbtemplate, &src_dboid, &src_owner, &src_encoding,
!                                        &src_maxconn, &src_istemplate, 
&src_allowconn, 
!                                        &src_lastsysoid, &src_vacuumxid, 
&src_frozenxid, 
!                                        &src_deftablespace))
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_DATABASE),
                 errmsg("template database \"%s\" does not exist", 
dbtemplate)));
***************
*** 266,271 ****
--- 280,289 ----
        if (encoding < 0)
                encoding = src_encoding;
  
+       /* If dbmaxconn is defaulted, use source's dbmaxconn */
+       if (dbmaxconn < 0)
+               dbmaxconn = src_maxconn;
+ 
        /* Some encodings are client only */
        if (!PG_VALID_BE_ENCODING(encoding))
                ereport(ERROR,
***************
*** 461,467 ****
        pg_database_rel = heap_open(DatabaseRelationId, ExclusiveLock);
  
        /* Check to see if someone else created same DB name meanwhile. */
!       if (get_db_info(dbname, NULL, NULL, NULL,
                                        NULL, NULL, NULL, NULL, NULL, NULL))
        {
                /* Don't hold lock while doing recursive remove */
--- 479,485 ----
        pg_database_rel = heap_open(DatabaseRelationId, ExclusiveLock);
  
        /* Check to see if someone else created same DB name meanwhile. */
!       if (get_db_info(dbname, NULL, NULL, NULL, NULL,
                                        NULL, NULL, NULL, NULL, NULL, NULL))
        {
                /* Don't hold lock while doing recursive remove */
***************
*** 487,492 ****
--- 505,511 ----
        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_datmaxconn - 1] = Int32GetDatum(dbmaxconn);
        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);
***************
*** 587,593 ****
         */
        pgdbrel = heap_open(DatabaseRelationId, ExclusiveLock);
  
!       if (!get_db_info(dbname, &db_id, NULL, NULL,
                                         &db_istemplate, NULL, NULL, NULL, 
NULL, NULL))
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_DATABASE),
--- 606,612 ----
         */
        pgdbrel = heap_open(DatabaseRelationId, ExclusiveLock);
  
!       if (!get_db_info(dbname, &db_id, NULL, NULL, NULL,
                                         &db_istemplate, NULL, NULL, NULL, 
NULL, NULL))
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_DATABASE),
***************
*** 783,788 ****
--- 802,892 ----
  
  
  /*
+  * ALTER DATABASE name ...
+  */
+ void
+ AlterDatabase(AlterDatabaseStmt *stmt)
+ {
+       Datum           new_record[Natts_pg_database];
+       char            new_record_nulls[Natts_pg_database];
+       char            new_record_repl[Natts_pg_database];
+       Relation        rel;
+       HeapTuple       tuple,
+                               newtuple;
+       ScanKeyData scankey;
+       SysScanDesc scan;
+       ListCell   *option;
+       int                     maxconn = -1;   /* Maximum connections allowed 
*/
+ 
+       DefElem    *dmaxconn = NULL;
+ 
+       /* Extract options from the statement node tree */
+       foreach(option, stmt->options)
+       {
+               DefElem    *defel = (DefElem *) lfirst(option);
+ 
+               if (strcmp(defel->defname, "maxconnections") == 0)
+               {
+                       if (dmaxconn)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                                errmsg("conflicting or 
redundant options")));
+                       dmaxconn = defel;
+               }
+       }
+ 
+       if (dmaxconn)
+               maxconn = intVal(dmaxconn->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 (!have_createdb_privilege())
+               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 (maxconn >= 0)
+       {
+               new_record[Anum_pg_database_datmaxconn - 1] = 
Int32GetDatum(maxconn);
+               new_record_repl[Anum_pg_database_datmaxconn - 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);
+ }
+ 
+ 
+ /*
   * ALTER DATABASE name SET ...
   */
  void
***************
*** 971,978 ****
  
  static bool
  get_db_info(const char *name, Oid *dbIdP, Oid *ownerIdP,
!                       int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
!                       Oid *dbLastSysOidP,
                        TransactionId *dbVacuumXidP, TransactionId 
*dbFrozenXidP,
                        Oid *dbTablespace)
  {
--- 1075,1082 ----
  
  static bool
  get_db_info(const char *name, Oid *dbIdP, Oid *ownerIdP,
!                       int *encodingP, int *dbMaxConnP, bool *dbIsTemplateP, 
!                       bool *dbAllowConnP,     Oid *dbLastSysOidP,
                        TransactionId *dbVacuumXidP, TransactionId 
*dbFrozenXidP,
                        Oid *dbTablespace)
  {
***************
*** 1017,1022 ****
--- 1121,1129 ----
                /* allowing connections? */
                if (dbAllowConnP)
                        *dbAllowConnP = dbform->datallowconn;
+               /* maximum connections */
+               if (dbMaxConnP)
+                       *dbMaxConnP = dbform->datmaxconn;
                /* last system OID used in database */
                if (dbLastSysOidP)
                        *dbLastSysOidP = dbform->datlastsysoid;
Index: src/backend/commands/user.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/user.c,v
retrieving revision 1.155
diff -c -r1.155 user.c
*** src/backend/commands/user.c 29 Jun 2005 20:34:13 -0000      1.155
--- src/backend/commands/user.c 3 Jul 2005 22:47:54 -0000
***************
*** 85,90 ****
--- 85,91 ----
        bool            createrole = false;             /* Can this user create 
roles? */
        bool            createdb = false;               /* Can the user create 
databases? */
        bool            canlogin = false;               /* Can this user login? 
*/
+       int                     maxconn = 0;                    /* 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 */
***************
*** 94,99 ****
--- 95,101 ----
        DefElem    *dcreaterole = NULL;
        DefElem    *dcreatedb = NULL;
        DefElem    *dcanlogin = NULL;
+       DefElem    *dmaxconn = NULL;
        DefElem    *daddroleto = NULL;
        DefElem    *drolemembers = NULL;
        DefElem    *dadminmembers = NULL;
***************
*** 155,160 ****
--- 157,170 ----
                                                 errmsg("conflicting or 
redundant options")));
                        dcanlogin = defel;
                }
+               else if (strcmp(defel->defname, "maxconnections") == 0)
+               {
+                       if (dmaxconn)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                                errmsg("conflicting or 
redundant options")));
+                       dmaxconn = defel;
+               }
                else if (strcmp(defel->defname, "addroleto") == 0)
                {
                        if (daddroleto)
***************
*** 202,207 ****
--- 212,230 ----
                createdb = intVal(dcreatedb->arg) != 0;
        if (dcanlogin)
                canlogin = intVal(dcanlogin->arg) != 0;
+       if (dmaxconn)
+       {
+               maxconn = intVal(dmaxconn->arg);
+               if (maxconn < 0)
+                       ereport(ERROR,
+                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("MAX CONNECTIONS must not be 
negative")));
+ 
+               if (!canlogin && maxconn > 0)
+                       ereport(ERROR,
+                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("MAX CONNECTIONS can be 
specified only for roles which can login")));
+       }
        if (daddroleto)
                addroleto = (List *) daddroleto->arg;
        if (drolemembers)
***************
*** 265,270 ****
--- 288,294 ----
        /* 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_rolmaxconn - 1] = Int32GetDatum(maxconn);
  
        if (password)
        {
***************
*** 369,374 ****
--- 393,399 ----
        int                     createrole = -1;                /* Can this 
user create roles? */
        int                     createdb = -1;                  /* Can the user 
create databases? */
        int                     canlogin = -1;                  /* Can this 
user login? */
+       int                     maxconn = -1;                   /* maximum 
connections allowed */
        List       *rolemembers = NIL;          /* roles to be added/removed */
        char       *validUntil = NULL;          /* time the login is valid 
until */
        DefElem    *dpassword = NULL;
***************
*** 376,381 ****
--- 401,407 ----
        DefElem    *dcreaterole = NULL;
        DefElem    *dcreatedb = NULL;
        DefElem    *dcanlogin = NULL;
+       DefElem    *dmaxconn = NULL;
        DefElem    *drolemembers = NULL;
        DefElem    *dvalidUntil = NULL;
        Oid                     roleid;
***************
*** 431,436 ****
--- 457,470 ----
                                                 errmsg("conflicting or 
redundant options")));
                        dcanlogin = defel;
                }
+               else if (strcmp(defel->defname, "maxconnections") == 0)
+               {
+                       if (dmaxconn)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                                errmsg("conflicting or 
redundant options")));
+                       dmaxconn = defel;
+               }
                else if (strcmp(defel->defname, "rolemembers") == 0 &&
                                 stmt->action != 0)
                {
***************
*** 463,468 ****
--- 497,515 ----
                createdb = intVal(dcreatedb->arg);
        if (dcanlogin)
                canlogin = intVal(dcanlogin->arg);
+       if (dmaxconn)
+       {
+               maxconn = intVal(dmaxconn->arg);
+               if (maxconn < 0)
+                       ereport(ERROR,
+                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("MAX CONNECTIONS must not be 
negative")));
+ 
+               if (canlogin == 0 && maxconn > 0)
+                       ereport(ERROR,
+                                       
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("MAX CONNECTIONS can be 
specified only for roles which can login")));
+       }
        if (drolemembers)
                rolemembers = (List *) drolemembers->arg;
        if (dvalidUntil)
***************
*** 502,507 ****
--- 549,555 ----
                        !(createrole < 0 &&
                          createdb < 0 &&
                          canlogin < 0 &&
+                         maxconn < 0 &&
                          !rolemembers &&
                          !validUntil &&
                          password &&
***************
*** 553,558 ****
--- 601,612 ----
                new_record_repl[Anum_pg_authid_rolcanlogin - 1] = 'r';
        }
  
+       if (maxconn >= 0)
+       {
+               new_record[Anum_pg_authid_rolmaxconn - 1] = 
Int32GetDatum(maxconn);
+               new_record_repl[Anum_pg_authid_rolmaxconn - 1] = 'r';
+       }
+ 
        /* password */
        if (password)
        {
Index: src/backend/libpq/crypt.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/libpq/crypt.c,v
retrieving revision 1.64
diff -c -r1.64 crypt.c
*** src/backend/libpq/crypt.c   29 Jun 2005 22:51:54 -0000      1.64
--- src/backend/libpq/crypt.c   3 Jul 2005 22:47:57 -0000
***************
*** 42,52 ****
        if ((line = get_role_line(role)) == NULL)
                return STATUS_ERROR;
  
!       /* Skip over rolename */
        token = list_head(*line);
        if (token)
                token = lnext(token);
        if (token)
        {
                shadow_pass = (char *) lfirst(token);
                token = lnext(token);
--- 42,54 ----
        if ((line = get_role_line(role)) == NULL)
                return STATUS_ERROR;
  
!       /* Skip over rolename and roleid */
        token = list_head(*line);
        if (token)
                token = lnext(token);
        if (token)
+               token = lnext(token);
+       if (token)
        {
                shadow_pass = (char *) lfirst(token);
                token = lnext(token);
Index: src/backend/libpq/hba.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/libpq/hba.c,v
retrieving revision 1.144
diff -c -r1.144 hba.c
*** src/backend/libpq/hba.c     28 Jun 2005 22:16:45 -0000      1.144
--- src/backend/libpq/hba.c     3 Jul 2005 22:48:12 -0000
***************
*** 494,505 ****
                return true;
  
        /*
!        * skip over the role name, password, valuntil, examine all the
         * membership entries
         */
!       if (list_length(*line) < 4)
                return false;
!       for_each_cell(line_item, lnext(lnext(lnext(list_head(*line)))))
        {
                if (strcmp((char *) lfirst(line_item), role) == 0)
                        return true;
--- 494,505 ----
                return true;
  
        /*
!        * skip over the role name, id, password, valuntil, examine all the
         * membership entries
         */
!       if (list_length(*line) < 5)
                return false;
!       for_each_cell(line_item, lnext(lnext(lnext(lnext(list_head(*line))))))
        {
                if (strcmp((char *) lfirst(line_item), role) == 0)
                        return true;
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.311
diff -c -r1.311 copyfuncs.c
*** src/backend/nodes/copyfuncs.c       2 Jul 2005 23:00:39 -0000       1.311
--- src/backend/nodes/copyfuncs.c       3 Jul 2005 22:48:36 -0000
***************
*** 2204,2209 ****
--- 2204,2220 ----
        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)
  {
***************
*** 3010,3015 ****
--- 3021,3029 ----
                case T_CreatedbStmt:
                        retval = _copyCreatedbStmt(from);
                        break;
+               case T_AlterDatabaseStmt:
+                       retval = _copyAlterDatabaseStmt(from);
+                       break;
                case T_AlterDatabaseSetStmt:
                        retval = _copyAlterDatabaseSetStmt(from);
                        break;
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.248
diff -c -r1.248 equalfuncs.c
*** src/backend/nodes/equalfuncs.c      2 Jul 2005 23:00:39 -0000       1.248
--- src/backend/nodes/equalfuncs.c      3 Jul 2005 22:48:53 -0000
***************
*** 1152,1157 ****
--- 1152,1166 ----
  }
  
  static bool
+ _equalAlterDatabaseStmt(AlterDatabaseStmt *a, AlterDatabaseStmt *b)
+ {
+       COMPARE_STRING_FIELD(dbname);
+       COMPARE_NODE_FIELD(options);
+ 
+       return true;
+ }
+ 
+ static bool
  _equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
  {
        COMPARE_STRING_FIELD(dbname);
***************
*** 2058,2063 ****
--- 2067,2075 ----
                case T_CreatedbStmt:
                        retval = _equalCreatedbStmt(a, b);
                        break;
+               case T_AlterDatabaseStmt:
+                       retval = _equalAlterDatabaseStmt(a, b);
+                       break;
                case T_AlterDatabaseSetStmt:
                        retval = _equalAlterDatabaseSetStmt(a, b);
                        break;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.501
diff -c -r2.501 gram.y
*** src/backend/parser/gram.y   29 Jun 2005 20:34:13 -0000      2.501
--- src/backend/parser/gram.y   3 Jul 2005 22:50:20 -0000
***************
*** 131,139 ****
  }
  
  %type <node>  stmt schema_stmt
!               AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt 
AlterOwnerStmt
!               AlterSeqStmt AlterTableStmt AlterUserStmt AlterUserSetStmt
!               AlterRoleStmt AlterRoleSetStmt
                AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
                ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
                CreateDomainStmt CreateGroupStmt CreateOpClassStmt 
CreatePLangStmt
--- 131,139 ----
  }
  
  %type <node>  stmt schema_stmt
!               AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt 
AlterGroupStmt
!               AlterOwnerStmt AlterSeqStmt AlterTableStmt 
!               AlterUserStmt AlterUserSetStmt AlterRoleStmt AlterRoleSetStmt
                AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
                ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
                CreateDomainStmt CreateGroupStmt CreateOpClassStmt 
CreatePLangStmt
***************
*** 165,172 ****
  
  %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 <ival>  opt_lock lock_type cast_context
  %type <boolean>       opt_force opt_or_replace
--- 165,174 ----
  
  %type <dbehavior>     opt_drop_behavior
  
! %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
***************
*** 342,348 ****
        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
        CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME
        CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
  
--- 344,350 ----
        CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P
        CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
        CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
!       COMMITTED CONNECTIONS CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY 
CREATE CREATEDB
        CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME
        CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
  
***************
*** 373,379 ****
        LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
        LOCK_P LOGIN_P
  
!       MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
  
        NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
        NOCREATEROLE NOCREATEUSER NOLOGIN_P NONE NOSUPERUSER NOT NOTHING NOTIFY
--- 375,381 ----
        LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
        LOCK_P LOGIN_P
  
!       MATCH MAX MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
  
        NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
        NOCREATEROLE NOCREATEUSER NOLOGIN_P NONE NOSUPERUSER NOT NOTHING NOTIFY
***************
*** 486,492 ****
                ;
  
  stmt :
!                       AlterDatabaseSetStmt
                        | AlterDomainStmt
                        | AlterFunctionStmt
                        | AlterGroupStmt
--- 488,495 ----
                ;
  
  stmt :
!                       AlterDatabaseStmt
!                       | AlterDatabaseSetStmt
                        | AlterDomainStmt
                        | AlterFunctionStmt
                        | AlterGroupStmt
***************
*** 663,668 ****
--- 666,675 ----
                                {
                                        $$ = makeDefElem("canlogin", (Node 
*)makeInteger(FALSE));
                                }
+                       | MAX CONNECTIONS Iconst
+                               {
+                                       $$ = makeDefElem("maxconnections", 
(Node *)makeInteger($3));
+                               }
                        | IN_P ROLE name_list
                                {
                                        $$ = makeDefElem("addroleto", (Node 
*)$3);
***************
*** 4455,4460 ****
--- 4462,4471 ----
                                {
                                        $$ = makeDefElem("encoding", NULL);
                                }
+                       | MAX CONNECTIONS opt_equal Iconst
+                               {
+                                       $$ = makeDefElem("maxconnections", 
(Node *)makeInteger($4));
+                               }
                        | OWNER opt_equal name
                                {
                                        $$ = makeDefElem("owner", (Node 
*)makeString($3));
***************
*** 4481,4486 ****
--- 4492,4507 ----
   *
   
*****************************************************************************/
  
+ 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
                                {
***************
*** 4501,4506 ****
--- 4522,4540 ----
                ;
  
  
+ alterdb_opt_list:
+                       alterdb_opt_list alterdb_opt_item               { $$ = 
lappend($1, $2); }
+                       | /* EMPTY */                                           
        { $$ = NIL; }
+               ;
+ 
+ alterdb_opt_item:
+                       MAX CONNECTIONS opt_equal Iconst
+                               {
+                                       $$ = makeDefElem("maxconnections", 
(Node *)makeInteger($4));
+                               }
+               ;
+ 
+ 
  /*****************************************************************************
   *
   *            DROP DATABASE
***************
*** 7941,7946 ****
--- 7975,7981 ----
                        | COMMENT
                        | COMMIT
                        | COMMITTED
+                       | CONNECTIONS
                        | CONSTRAINTS
                        | CONVERSION_P
                        | COPY
***************
*** 8009,8014 ****
--- 8044,8050 ----
                        | LOCK_P
                        | LOGIN_P
                        | MATCH
+                       | MAX
                        | MAXVALUE
                        | MINUTE_P
                        | MINVALUE
Index: src/backend/parser/keywords.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.162
diff -c -r1.162 keywords.c
*** src/backend/parser/keywords.c       29 Jun 2005 20:34:14 -0000      1.162
--- src/backend/parser/keywords.c       3 Jul 2005 22:50:24 -0000
***************
*** 83,88 ****
--- 83,89 ----
        {"comment", COMMENT},
        {"commit", COMMIT},
        {"committed", COMMITTED},
+       {"connections", CONNECTIONS},
        {"constraint", CONSTRAINT},
        {"constraints", CONSTRAINTS},
        {"conversion", CONVERSION_P},
***************
*** 203,208 ****
--- 204,210 ----
        {"lock", LOCK_P},
        {"login", LOGIN_P},
        {"match", MATCH},
+       {"max", MAX},
        {"maxvalue", MAXVALUE},
        {"minute", MINUTE_P},
        {"minvalue", MINVALUE},
Index: src/backend/storage/ipc/procarray.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/ipc/procarray.c,v
retrieving revision 1.3
diff -c -r1.3 procarray.c
*** src/backend/storage/ipc/procarray.c 17 Jun 2005 22:32:45 -0000      1.3
--- src/backend/storage/ipc/procarray.c 3 Jul 2005 22:50:36 -0000
***************
*** 734,739 ****
--- 734,790 ----
  }
  
  
+ /*
+  * 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 && 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 && proc->roleId == roleid)
+                       count++;
+       }
+ 
+       LWLockRelease(ProcArrayLock);
+ 
+       return count;
+ }
+ 
+ 
  #define XidCacheRemove(i) \
        do { \
                MyProc->subxids.xids[i] = 
MyProc->subxids.xids[MyProc->subxids.nxids - 1]; \
Index: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.160
diff -c -r1.160 proc.c
*** src/backend/storage/lmgr/proc.c     17 Jun 2005 22:32:45 -0000      1.160
--- src/backend/storage/lmgr/proc.c     3 Jul 2005 22:50:51 -0000
***************
*** 254,259 ****
--- 254,260 ----
        MyProc->xmin = InvalidTransactionId;
        MyProc->pid = MyProcPid;
        MyProc->databaseId = MyDatabaseId;
+       MyProc->roleId = GetSessionUserId();
        MyProc->lwWaiting = false;
        MyProc->lwExclusive = false;
        MyProc->lwWaitLink = NULL;
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.240
diff -c -r1.240 utility.c
*** src/backend/tcop/utility.c  30 Jun 2005 00:00:51 -0000      1.240
--- src/backend/tcop/utility.c  3 Jul 2005 22:51:06 -0000
***************
*** 275,280 ****
--- 275,281 ----
  
        switch (nodeTag(parsetree))
        {
+               case T_AlterDatabaseStmt:
                case T_AlterDatabaseSetStmt:
                case T_AlterDomainStmt:
                case T_AlterFunctionStmt:
***************
*** 788,793 ****
--- 789,798 ----
                        createdb((CreatedbStmt *) parsetree);
                        break;
  
+               case T_AlterDatabaseStmt:
+                       AlterDatabase((AlterDatabaseStmt *) parsetree);
+                       break;
+ 
                case T_AlterDatabaseSetStmt:
                        AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
                        break;
***************
*** 1504,1509 ****
--- 1509,1518 ----
                        tag = "CREATE DATABASE";
                        break;
  
+               case T_AlterDatabaseStmt:
+                       tag = "ALTER DATABASE";
+                       break;
+ 
                case T_AlterDatabaseSetStmt:
                        tag = "ALTER DATABASE";
                        break;
Index: src/backend/utils/init/flatfiles.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/init/flatfiles.c,v
retrieving revision 1.11
diff -c -r1.11 flatfiles.c
*** src/backend/utils/init/flatfiles.c  29 Jun 2005 20:34:15 -0000      1.11
--- src/backend/utils/init/flatfiles.c  3 Jul 2005 22:51:18 -0000
***************
*** 629,635 ****
                        ListCell *mem;
  
                        fputs_quote(arole->rolname, fp);
!                       fputs(" ", fp);
                        fputs_quote(arole->rolpassword, fp);
                        fputs(" ", fp);
                        fputs_quote(arole->rolvaliduntil, fp);
--- 629,635 ----
                        ListCell *mem;
  
                        fputs_quote(arole->rolname, fp);
!                       fprintf(fp, " %u ", arole->roleid);
                        fputs_quote(arole->rolpassword, fp);
                        fputs(" ", fp);
                        fputs_quote(arole->rolvaliduntil, fp);
Index: src/backend/utils/init/miscinit.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/init/miscinit.c,v
retrieving revision 1.144
diff -c -r1.144 miscinit.c
*** src/backend/utils/init/miscinit.c   28 Jun 2005 22:16:45 -0000      1.144
--- src/backend/utils/init/miscinit.c   3 Jul 2005 22:51:29 -0000
***************
*** 39,44 ****
--- 39,45 ----
  #include "utils/guc.h"
  #include "utils/lsyscache.h"
  #include "utils/syscache.h"
+ #include "storage/procarray.h" 
  
  
  ProcessingMode Mode = InitProcessing;
***************
*** 347,352 ****
--- 348,365 ----
  
        SetSessionUserId(roleid);       /* sets CurrentUserId too */
  
+       /*
+        * Check connection limit for user
+        */
+       if (rform->rolmaxconn > 0 && !AuthenticatedUserIsSuperuser &&
+                       CountUserBackends(AuthenticatedUserId) > 
rform->rolmaxconn)
+       {
+               ereport(FATAL,
+                       (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
+                errmsg("sorry, too many clients already for role \"%s\"",
+                       rolename)));
+       }
+ 
        /* Record username and superuser status as GUC settings too */
        SetConfigOption("session_authorization", rolename,
                                        PGC_BACKEND, PGC_S_OVERRIDE);
Index: src/backend/utils/init/postinit.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/init/postinit.c,v
retrieving revision 1.151
diff -c -r1.151 postinit.c
*** src/backend/utils/init/postinit.c   28 Jun 2005 19:51:23 -0000      1.151
--- src/backend/utils/init/postinit.c   3 Jul 2005 22:51:37 -0000
***************
*** 47,52 ****
--- 47,53 ----
  
  
  static bool FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace);
+ static bool FindMyRole(const char *name, Oid *role_id);
  static void ReverifyMyDatabase(const char *name);
  static void InitCommunication(void);
  static void ShutdownPostgres(int code, Datum arg);
***************
*** 101,106 ****
--- 102,136 ----
  }
  
  /*
+  * Get roleid from flatfiles 
+  * 
+  * We need this because we need to know userid before 
+  * InitProcess() is called
+  */
+ static bool
+ FindMyRole(const char *name, Oid *role_id)
+ {
+       List      **line; 
+       ListCell   *token; 
+ 
+       if ((line = get_role_line(name)) == NULL) 
+               ereport(FATAL,
+                               (ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION,
+                                errmsg("could not find role \"%s\"", name)));
+ 
+       token = list_head(*line);
+       if (token)
+               token = lnext(token);
+       if (token)
+       {
+               *role_id = atoi((char*)lfirst(token));
+               return true;
+       }
+ 
+       return false;
+ }
+ 
+ /*
   * ReverifyMyDatabase -- recheck info obtained by FindMyDatabase
   *
   * Since FindMyDatabase cannot lock pg_database, the information it read
***************
*** 166,182 ****
                                                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;")
-        */
        dbform = (Form_pg_database) GETSTRUCT(tup);
!       if (IsUnderPostmaster && !dbform->datallowconn)
!               ereport(FATAL,
!                               
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
!                errmsg("database \"%s\" is not currently accepting 
connections",
                                name)));
  
        /*
         * OK, we're golden.  Next to-do item is to save the encoding
--- 196,230 ----
                                                name, MyDatabaseId)));
        }
  
        dbform = (Form_pg_database) GETSTRUCT(tup);
!       if (IsUnderPostmaster)
!       {
!               /*
!                * 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;")
!                */
!               if (!dbform->datallowconn)
!               {
!                       ereport(FATAL,
!                                       
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
!                        errmsg("database \"%s\" is not currently accepting 
connections",
!                                       name)));
!               }
! 
!               /*
!                * Here we check cxonenction limit for this database
!                */
!               if (dbform->datmaxconn > 0 && !superuser() &&
!                               CountDBBackends(MyDatabaseId) > 
dbform->datmaxconn)
!               {
!                       ereport(FATAL,
!                               (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
!                        errmsg("sorry, too many clients already for database 
\"%s\"",
                                name)));
+               }
+       }
+ 
  
        /*
         * OK, we're golden.  Next to-do item is to save the encoding
***************
*** 352,357 ****
--- 400,424 ----
         */
  
        /*
+        * We need to know roleid in InitProcess() so we have read it from
+        * flatfile, real user inicialization is done later
+        */
+       if (IsUnderPostmaster)
+       {
+               Oid roleid;
+ 
+               if (!FindMyRole(username, &roleid))
+                       ereport(FATAL,
+                                       
(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION,
+                                        errmsg("role \"%s\" does not exist",
+                                                       username)));
+ 
+               SetSessionUserId(roleid);
+       }
+       else
+               SetSessionUserId(BOOTSTRAP_SUPERUSERID);
+       
+       /*
         * Set up my per-backend PGPROC struct in shared memory.        (We need
         * to know MyDatabaseId before we can do this, since it's entered into
         * the PGPROC struct.)
Index: src/include/catalog/pg_authid.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_authid.h,v
retrieving revision 1.1
diff -c -r1.1 pg_authid.h
*** src/include/catalog/pg_authid.h     28 Jun 2005 05:09:05 -0000      1.1
--- src/include/catalog/pg_authid.h     3 Jul 2005 22:51:50 -0000
***************
*** 48,53 ****
--- 48,54 ----
        bool            rolcreatedb;    /* allowed to create databases? */
        bool            rolcatupdate;   /* allowed to alter catalogs manually? 
*/
        bool            rolcanlogin;    /* allowed to log in as session user? */
+       int4            rolmaxconn;             /* maximum connections allowed 
*/
  
        /* remaining fields may be null; use heap_getattr to read them! */
        text            rolpassword;    /* password, if any */
***************
*** 69,84 ****
   *            compiler constants for pg_authid
   * ----------------
   */
! #define Natts_pg_authid                                       9
  #define Anum_pg_authid_rolname                        1
  #define Anum_pg_authid_rolsuper                       2
  #define Anum_pg_authid_rolcreaterole  3
  #define Anum_pg_authid_rolcreatedb            4
  #define Anum_pg_authid_rolcatupdate           5
  #define Anum_pg_authid_rolcanlogin            6
! #define Anum_pg_authid_rolpassword            7
! #define Anum_pg_authid_rolvaliduntil  8
! #define Anum_pg_authid_rolconfig              9
  
  /* ----------------
   *            initial contents of pg_authid
--- 70,86 ----
   *            compiler constants for pg_authid
   * ----------------
   */
! #define Natts_pg_authid                                       10
  #define Anum_pg_authid_rolname                        1
  #define Anum_pg_authid_rolsuper                       2
  #define Anum_pg_authid_rolcreaterole  3
  #define Anum_pg_authid_rolcreatedb            4
  #define Anum_pg_authid_rolcatupdate           5
  #define Anum_pg_authid_rolcanlogin            6
! #define Anum_pg_authid_rolmaxconn             7
! #define Anum_pg_authid_rolpassword            8
! #define Anum_pg_authid_rolvaliduntil  9
! #define Anum_pg_authid_rolconfig              10
  
  /* ----------------
   *            initial contents of pg_authid
***************
*** 87,93 ****
   * user choices.
   * ----------------
   */
! DATA(insert OID = 10 ( "POSTGRES" t t t t t _null_ _null_ _null_ ));
  
  #define BOOTSTRAP_SUPERUSERID 10
  
--- 89,95 ----
   * user choices.
   * ----------------
   */
! DATA(insert OID = 10 ( "POSTGRES" t t t t t 0 _null_ _null_ _null_ ));
  
  #define BOOTSTRAP_SUPERUSERID 10
  
Index: src/include/catalog/pg_database.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_database.h,v
retrieving revision 1.36
diff -c -r1.36 pg_database.h
*** src/include/catalog/pg_database.h   28 Jun 2005 05:09:06 -0000      1.36
--- src/include/catalog/pg_database.h   3 Jul 2005 22:51:51 -0000
***************
*** 40,45 ****
--- 40,46 ----
        int4            encoding;               /* character encoding */
        bool            datistemplate;  /* allowed as CREATE DATABASE template? 
*/
        bool            datallowconn;   /* new connections allowed? */
+       int4            datmaxconn;             /* maximum connections allowed 
*/
        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,78 ****
   *            compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database                             11
  #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
  
! DATA(insert OID = 1 (  template1 PGUID ENCODING t t 0 0 0 1663 _null_ _null_ 
));
  DESCR("Default template database");
  #define TemplateDbOid                 1
  
--- 60,80 ----
   *            compiler constants for pg_database
   * ----------------
   */
! #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_datmaxconn           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 0 1663 _null_ 
_null_ ));
  DESCR("Default template database");
  #define TemplateDbOid                 1
  
Index: src/include/commands/dbcommands.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/commands/dbcommands.h,v
retrieving revision 1.39
diff -c -r1.39 dbcommands.h
*** src/include/commands/dbcommands.h   28 Jun 2005 05:09:12 -0000      1.39
--- src/include/commands/dbcommands.h   3 Jul 2005 22:51:53 -0000
***************
*** 64,69 ****
--- 64,70 ----
  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);
  
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.172
diff -c -r1.172 nodes.h
*** src/include/nodes/nodes.h   28 Jun 2005 05:09:13 -0000      1.172
--- src/include/nodes/nodes.h   3 Jul 2005 22:52:00 -0000
***************
*** 270,275 ****
--- 270,276 ----
        T_ReindexStmt,
        T_CheckPointStmt,
        T_CreateSchemaStmt,
+       T_AlterDatabaseStmt,
        T_AlterDatabaseSetStmt,
        T_AlterRoleSetStmt,
        T_CreateConversionStmt,
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.285
diff -c -r1.285 parsenodes.h
*** src/include/nodes/parsenodes.h      28 Jun 2005 19:51:24 -0000      1.285
--- src/include/nodes/parsenodes.h      3 Jul 2005 22:52:25 -0000
***************
*** 1611,1616 ****
--- 1611,1623 ----
   *    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;
Index: src/include/storage/proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/storage/proc.h,v
retrieving revision 1.79
diff -c -r1.79 proc.h
*** src/include/storage/proc.h  17 Jun 2005 22:32:50 -0000      1.79
--- src/include/storage/proc.h  3 Jul 2005 22:52:29 -0000
***************
*** 71,76 ****
--- 71,77 ----
  
        int                     pid;                    /* This backend's 
process id, or 0 */
        Oid                     databaseId;             /* OID of database this 
backend is using */
+       Oid                     roleId;                 /* OID of role using 
conencted to backend */
  
        /* Info about LWLock the process is currently waiting for, if any. */
        bool            lwWaiting;              /* true if waiting for an LW 
lock */
Index: src/include/storage/procarray.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/storage/procarray.h,v
retrieving revision 1.2
diff -c -r1.2 procarray.h
*** src/include/storage/procarray.h     17 Jun 2005 22:32:50 -0000      1.2
--- src/include/storage/procarray.h     3 Jul 2005 22:52:30 -0000
***************
*** 31,36 ****
--- 31,38 ----
  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);
Index: src/tools/pgindent/pgindent
===================================================================
RCS file: /projects/cvsroot/pgsql/src/tools/pgindent/pgindent,v
retrieving revision 1.75
diff -c -r1.75 pgindent
*** src/tools/pgindent/pgindent 28 Jun 2005 23:55:30 -0000      1.75
--- src/tools/pgindent/pgindent 3 Jul 2005 22:53:03 -0000
***************
*** 177,182 ****
--- 177,183 ----
  -TAllocSetContext \
  -TAllocateDesc \
  -TAllocateDescKind \
+ -TAlterDatabaseStmt \
  -TAlterDatabaseSetStmt \
  -TAlterDomainStmt \
  -TAlterFunctionStmt \
---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]

Reply via email to