]> granicus.if.org Git - postgresql/commitdiff
Here's the Create/Alter/Drop Group stuff that's been really overdue. I
authorBruce Momjian <bruce@momjian.us>
Thu, 16 Dec 1999 17:24:19 +0000 (17:24 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 16 Dec 1999 17:24:19 +0000 (17:24 +0000)
didn't have time for documentation yet, but I'll write some. There are
still some things to work out what happens when you alter or drop users,
but the group stuff in and by itself is done.

--
Peter Eisentraut                  Sernanders väg 10:115

src/backend/commands/user.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/include/catalog/pg_class.h
src/include/catalog/pg_group.h
src/include/commands/user.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h

index de156171a5f9736bb07339d35fa0e9faac237cd8..cec646fc9a9cbeb89266f78e86cc69c5c93da5d0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: user.c,v 1.44 1999/12/14 00:17:33 momjian Exp $
+ * $Id: user.c,v 1.45 1999/12/16 17:24:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "catalog/catname.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_shadow.h"
+#include "catalog/pg_group.h"
+#include "catalog/indexing.h"
 #include "commands/copy.h"
 #include "commands/user.h"
 #include "libpq/crypt.h"
 #include "miscadmin.h"
+#include "nodes/pg_list.h"
 #include "tcop/tcopprot.h"
 #include "utils/acl.h"
+#include "utils/array.h"
 #include "utils/syscache.h"
 
 static void CheckPgUserAclNotNull(void);
@@ -118,6 +122,7 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
                                havepassword,
                                havevaluntil;
        int                     max_id = -1;
+    List       *item;
 
     havesysid    = stmt->sysid >= 0;
        havepassword = stmt->password && stmt->password[0];
@@ -218,8 +223,18 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
        pg_exec_query_dest(sql, dest, false);
 
        /*
-        * Add stuff here for groups?
+        * Add the user to the groups specified. We'll just call the below
+     * AlterGroup for this.
         */
+    foreach(item, stmt->groupElts)
+    {
+        AlterGroupStmt ags;
+
+        ags.name = strVal(lfirst(item));
+        ags.action = +1;
+        ags.listUsers = lcons((void*)makeString(stmt->user), NIL);
+        AlterGroup(&ags, dest);
+    }
 
        /*
         * Write the updated pg_shadow data to the flat password file.
@@ -367,6 +382,8 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest)
        /*
         * Add stuff here for groups?
         */
+    if (stmt->groupElts)
+        elog(NOTICE, "IN GROUP is not implemented for ALTER USER.");
 
        /*
         * Write the updated pg_shadow data to the flat password file.
@@ -546,3 +563,511 @@ CheckPgUserAclNotNull()
 
        return;
 }
+
+
+/*** GROUP THINGS ***/
+
+void
+CreateGroup(CreateGroupStmt *stmt, CommandDest dest)
+{
+       Relation        pg_group_rel;
+       HeapScanDesc scan;
+       HeapTuple       tuple;
+    TupleDesc   pg_group_dsc;
+       bool            inblock;
+    bool        group_exists = false,
+                sysid_exists = false;
+    int         max_id = -1;
+    Datum       new_record[Natts_pg_group];
+    char        new_record_nulls[Natts_pg_group];
+    List       *item, *newlist=NULL;
+    ArrayType  *userarray;
+
+
+       if (!(inblock = IsTransactionBlock()))
+               BeginTransactionBlock();
+
+       /*
+        * Make sure the user can do this.
+        */
+       if (pg_aclcheck(GroupRelationName, GetPgUserName(), ACL_RD | ACL_AP) != ACLCHECK_OK)
+       {
+               UserAbortTransactionBlock();
+               elog(ERROR, "CreateGroup: Permission denied.");
+       }
+
+       pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock);
+       pg_group_dsc = RelationGetDescr(pg_group_rel);
+
+       scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL);
+       while (!group_exists && !sysid_exists && HeapTupleIsValid(tuple = heap_getnext(scan, false)))
+       {
+        Datum          datum;
+        bool        null;
+
+               datum = heap_getattr(tuple, Anum_pg_group_groname, pg_group_dsc, &null);
+               group_exists = datum && !null && (strcmp((char *) datum, stmt->name) == 0);
+
+               datum = heap_getattr(tuple, Anum_pg_group_grosysid, pg_group_dsc, &null);
+        if (stmt->sysid >= 0) /* customized id wanted */
+            sysid_exists = datum && !null && ((int)datum == stmt->sysid);
+        else /* pick 1 + max */
+        {
+            if ((int) datum > max_id)
+                max_id = (int) datum;
+        }
+       }
+       heap_endscan(scan);
+
+       if (group_exists || sysid_exists)
+       {
+               heap_close(pg_group_rel, AccessExclusiveLock);
+               UserAbortTransactionBlock();
+        if (group_exists)
+            elog(ERROR, "CreateGroup: Group name \"%s\" already exists.", stmt->name);
+        else
+            elog(ERROR, "CreateGroup: Group sysid %d is already assigned.", stmt->sysid);
+       }
+
+    /*
+     * Translate the given user names to ids
+     */
+
+    foreach(item, stmt->initUsers)
+    {
+        const char * groupuser = strVal(lfirst(item));
+        Value *v;
+
+        tuple = SearchSysCacheTuple(SHADOWNAME,
+                                    PointerGetDatum(groupuser),
+                                    0, 0, 0);
+        if (!HeapTupleIsValid(tuple))
+        {
+            heap_close(pg_group_rel, AccessExclusiveLock);
+            UserAbortTransactionBlock();
+            elog(ERROR, "CreateGroup: User \"%s\" does not exist.", groupuser);
+        }
+
+        v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid);
+        if (!member(v, newlist))
+            newlist = lcons(v, newlist);
+    }
+
+    /* build an array to insert */
+    if (newlist)
+    {
+        int i;
+
+        userarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32));
+        ARR_SIZE(userarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32);
+        ARR_FLAGS(userarray) = 0x0;
+        ARR_NDIM(userarray) = 1; /* one dimensional array */
+        ARR_LBOUND(userarray)[0] = 1; /* axis starts at one */
+        ARR_DIMS(userarray)[0] = length(newlist); /* axis is this long */
+        /* fill the array */
+        i = 0;
+        foreach(item, newlist)
+        {
+            ((int*)ARR_DATA_PTR(userarray))[i++] = intVal(lfirst(item));
+        }
+    }
+    else
+        userarray = NULL;
+
+    /*
+     * Form a tuple to insert
+     */
+    if (stmt->sysid >=0)
+        max_id = stmt->sysid;
+    else 
+        max_id++;
+
+    new_record[Anum_pg_group_groname-1] = (Datum)(stmt->name);
+    new_record[Anum_pg_group_grosysid-1] = (Datum)(max_id);
+    new_record[Anum_pg_group_grolist-1] = (Datum)userarray;
+
+    new_record_nulls[Anum_pg_group_groname-1] = ' ';
+    new_record_nulls[Anum_pg_group_grosysid-1] = ' ';
+    new_record_nulls[Anum_pg_group_grolist-1] = userarray ? ' ' : 'n';
+
+    tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
+
+    /*
+     * Insert a new record in the pg_group_table
+     */
+    heap_insert(pg_group_rel, tuple);
+
+    /*
+     * Update indexes
+     */
+    if (RelationGetForm(pg_group_rel)->relhasindex) {
+        Relation idescs[Num_pg_group_indices];
+      
+        CatalogOpenIndices(Num_pg_group_indices, 
+                           Name_pg_group_indices, idescs);
+        CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, 
+                           tuple);
+        CatalogCloseIndices(Num_pg_group_indices, idescs);
+    }
+
+       heap_close(pg_group_rel, NoLock);
+
+       if (IsTransactionBlock() && !inblock)
+               EndTransactionBlock();
+}
+
+
+
+void
+AlterGroup(AlterGroupStmt *stmt, CommandDest dest)
+{
+       Relation        pg_group_rel;
+    TupleDesc   pg_group_dsc;
+       bool            inblock;
+    HeapTuple   group_tuple;
+
+       if (!(inblock = IsTransactionBlock()))
+               BeginTransactionBlock();
+
+       /*
+        * Make sure the user can do this.
+        */
+       if (pg_aclcheck(GroupRelationName, GetPgUserName(), ACL_RD | ACL_WR) != ACLCHECK_OK)
+       {
+               UserAbortTransactionBlock();
+               elog(ERROR, "AlterGroup: Permission denied.");
+       }
+
+    pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock);
+    pg_group_dsc = RelationGetDescr(pg_group_rel);
+
+    /*
+     * Verify that group exists.
+     * If we find a tuple, will take that the rest of the way and make our
+     * modifications on it.
+     */
+    if (!HeapTupleIsValid(group_tuple = SearchSysCacheTupleCopy(GRONAME, PointerGetDatum(stmt->name), 0, 0, 0)))
+       {
+        heap_close(pg_group_rel, AccessExclusiveLock);
+               UserAbortTransactionBlock();
+               elog(ERROR, "AlterGroup: Group \"%s\" does not exist.", stmt->name);
+       }
+
+    /*
+     * Now decide what to do.
+     */
+    if (stmt->action == 0) /* change sysid */
+    {
+        bool          sysid_exists = false;
+        ScanKeyData   keys[2];
+        HeapTuple        tuple;
+        HeapScanDesc  scan;
+        Datum       new_record[Natts_pg_group];
+        char        new_record_nulls[Natts_pg_group];
+        bool null;
+
+        /*
+         * First check if the id is already assigned.
+         */
+        ScanKeyEntryInitialize(&keys[0], 0x0, Anum_pg_group_grosysid, F_INT4EQ,
+                               Int32GetDatum(stmt->sysid));
+        ScanKeyEntryInitialize(&keys[1], 0x0, Anum_pg_group_groname, F_NAMENE,
+                               PointerGetDatum(stmt->name));
+        scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 2, keys);
+
+        if (HeapTupleIsValid(heap_getnext(scan, false)))
+        {
+            heap_endscan(scan);
+            heap_close(pg_group_rel, AccessExclusiveLock);
+            UserAbortTransactionBlock();
+            elog(ERROR, "AlterGroup: Group sysid %d is already assigned.", stmt->sysid);
+        }
+        heap_endscan(scan);
+
+        /*
+         * Insert the new tuple with the updated sysid
+         */
+        new_record[Anum_pg_group_groname-1] = (Datum)(stmt->name);
+        new_record[Anum_pg_group_grosysid-1] = (Datum)(stmt->sysid);
+        new_record[Anum_pg_group_grolist-1] = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null);
+        new_record_nulls[Anum_pg_group_groname-1] = ' ';
+        new_record_nulls[Anum_pg_group_grosysid-1] = ' ';
+        new_record_nulls[Anum_pg_group_grolist-1] = null ? 'n' : ' ';
+
+        tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
+        heap_update(pg_group_rel, &group_tuple->t_self, tuple, NULL);
+
+        /* Update indexes */
+        if (RelationGetForm(pg_group_rel)->relhasindex) {
+            Relation idescs[Num_pg_group_indices];
+      
+            CatalogOpenIndices(Num_pg_group_indices, 
+                               Name_pg_group_indices, idescs);
+            CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, 
+                               tuple);
+            CatalogCloseIndices(Num_pg_group_indices, idescs);
+        }
+    }
+
+    /*
+     * add users to group 
+     */
+    else if (stmt->action > 0)
+    {
+        Datum       new_record[Natts_pg_group];
+        char        new_record_nulls[Natts_pg_group] = { ' ', ' ', ' '};
+        ArrayType *newarray, *oldarray;
+        List * newlist = NULL, *item;
+        HeapTuple tuple;
+        bool null = false;
+        Datum datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null);
+        int i;
+        
+        oldarray = (ArrayType*)datum;
+        Assert(null || ARR_NDIM(oldarray) == 1);
+        /* first add the old array to the hitherto empty list */
+        if (!null)
+            for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++)
+            {
+                int index, arrval;
+                Value *v;
+                bool valueNull;
+                index = i;
+                arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true/*by value*/,
+                                                 sizeof(int), 0, &valueNull));
+                v = makeInteger(arrval);
+                /* filter out duplicates */
+                if (!member(v, newlist))
+                    newlist = lcons(v, newlist);
+            }
+
+        /* 
+         * now convert the to be added usernames to sysids and add them
+         * to the list
+         */
+        foreach(item, stmt->listUsers)
+        {
+            Value *v;
+            /* Get the uid of the proposed user to add. */
+            tuple = SearchSysCacheTuple(SHADOWNAME,
+                                        PointerGetDatum(strVal(lfirst(item))),
+                                        0, 0, 0);
+            if (!HeapTupleIsValid(tuple))
+            {
+                heap_close(pg_group_rel, AccessExclusiveLock);
+                UserAbortTransactionBlock();
+                elog(ERROR, "AlterGroup: User \"%s\" does not exist.", strVal(lfirst(item)));
+            }
+            
+            v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid);
+            if (!member(v, newlist))
+                newlist = lcons(v, newlist);
+            else
+                elog(NOTICE, "AlterGroup: User \"%s\" is already in group \"%s\".", strVal(lfirst(item)), stmt->name);
+        }
+             
+        newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32));
+        ARR_SIZE(newarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32);
+        ARR_FLAGS(newarray) = 0x0;
+        ARR_NDIM(newarray) = 1; /* one dimensional array */
+        ARR_LBOUND(newarray)[0] = 1; /* axis starts at one */
+        ARR_DIMS(newarray)[0] = length(newlist); /* axis is this long */
+        /* fill the array */
+        i = 0;
+        foreach(item, newlist)
+        {
+            ((int*)ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item));
+        }
+        
+        /*
+         * Form a tuple with the new array and write it back.
+         */
+        new_record[Anum_pg_group_groname-1] = (Datum)(stmt->name);
+        new_record[Anum_pg_group_grosysid-1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null);
+        new_record[Anum_pg_group_grolist-1] = PointerGetDatum(newarray);
+
+        tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
+        heap_update(pg_group_rel, &group_tuple->t_self, tuple, NULL);
+
+        /* Update indexes */
+        if (RelationGetForm(pg_group_rel)->relhasindex) {
+            Relation idescs[Num_pg_group_indices];
+      
+            CatalogOpenIndices(Num_pg_group_indices, 
+                               Name_pg_group_indices, idescs);
+            CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, 
+                               tuple);
+            CatalogCloseIndices(Num_pg_group_indices, idescs);
+        }
+    } /* endif alter group add user */
+
+    /*
+     * drop users from group
+     */
+    else if (stmt->action < 0)
+    {
+        Datum         datum;
+        bool          null;
+        
+        datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null);
+        if (null)
+            elog(NOTICE, "AlterGroup: Group \"%s\"'s membership is NULL.", stmt->name);
+        else
+        {
+            HeapTuple    tuple;
+            Datum       new_record[Natts_pg_group];
+            char        new_record_nulls[Natts_pg_group] = { ' ', ' ', ' '};
+            ArrayType    *oldarray, *newarray;
+            List * newlist = NULL, *item;
+            int i;
+
+            oldarray = (ArrayType*)datum;
+            Assert(ARR_NDIM(oldarray) == 1);
+            /* first add the old array to the hitherto empty list */
+            for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++)
+            {
+                int index, arrval;
+                Value *v;
+                bool valueNull;
+                index = i;
+                arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true/*by value*/,
+                                                 sizeof(int), 0, &valueNull));
+                v = makeInteger(arrval);
+                /* filter out duplicates */
+                if (!member(v, newlist))
+                    newlist = lcons(v, newlist);
+            }
+
+            /* 
+             * now convert the to be dropped usernames to sysids and remove
+             * them from the list
+             */
+            foreach(item, stmt->listUsers)
+            {
+                Value *v;
+                /* Get the uid of the proposed user to drop. */
+                tuple = SearchSysCacheTuple(SHADOWNAME,
+                                            PointerGetDatum(strVal(lfirst(item))),
+                                            0, 0, 0);
+                if (!HeapTupleIsValid(tuple))
+                {
+                    heap_close(pg_group_rel, AccessExclusiveLock);
+                    UserAbortTransactionBlock();
+                    elog(ERROR, "AlterGroup: User \"%s\" does not exist.", strVal(lfirst(item)));
+                }
+            
+                v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid);
+                if (member(v, newlist))
+                    newlist = LispRemove(v, newlist);
+                else
+                    elog(NOTICE, "AlterGroup: User \"%s\" is not in group \"%s\".", strVal(lfirst(item)), stmt->name);
+            }
+
+            newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32));
+            ARR_SIZE(newarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32);
+            ARR_FLAGS(newarray) = 0x0;
+            ARR_NDIM(newarray) = 1; /* one dimensional array */
+            ARR_LBOUND(newarray)[0] = 1; /* axis starts at one */
+            ARR_DIMS(newarray)[0] = length(newlist); /* axis is this long */
+            /* fill the array */
+            i = 0;
+            foreach(item, newlist)
+            {
+                ((int*)ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item));
+            }
+        
+            /*
+             * Insert the new tuple with the updated user list
+             */
+            new_record[Anum_pg_group_groname-1] = (Datum)(stmt->name);
+            new_record[Anum_pg_group_grosysid-1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null);
+            new_record[Anum_pg_group_grolist-1] = PointerGetDatum(newarray);
+
+            tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
+            heap_update(pg_group_rel, &group_tuple->t_self, tuple, NULL);
+
+            /* Update indexes */
+            if (RelationGetForm(pg_group_rel)->relhasindex) {
+                Relation idescs[Num_pg_group_indices];
+      
+                CatalogOpenIndices(Num_pg_group_indices, 
+                                   Name_pg_group_indices, idescs);
+                CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, 
+                                   tuple);
+                CatalogCloseIndices(Num_pg_group_indices, idescs);
+            }
+
+        } /* endif group not null */
+    } /* endif alter group drop user */
+
+    heap_close(pg_group_rel, NoLock);
+
+    pfree(group_tuple);
+
+       if (IsTransactionBlock() && !inblock)
+               EndTransactionBlock();
+}
+
+
+
+void
+DropGroup(DropGroupStmt *stmt, CommandDest dest)
+{
+       Relation        pg_group_rel;
+       HeapScanDesc scan;
+       HeapTuple       tuple;
+    TupleDesc   pg_group_dsc;
+       bool            inblock;
+    bool        gro_exists = false;
+
+       if (!(inblock = IsTransactionBlock()))
+               BeginTransactionBlock();
+
+       /*
+        * Make sure the user can do this.
+        */
+       if (pg_aclcheck(GroupRelationName, GetPgUserName(), ACL_RD | ACL_WR) != ACLCHECK_OK)
+       {
+               UserAbortTransactionBlock();
+               elog(ERROR, "DropGroup: Permission denied.");
+       }
+
+    /*
+     * Scan the pg_group table and delete all matching users.
+     */
+       pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock);
+       pg_group_dsc = RelationGetDescr(pg_group_rel);
+       scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL);
+
+       while (HeapTupleIsValid(tuple = heap_getnext(scan, false)))
+       {
+        Datum datum;
+        bool null;
+
+        datum = heap_getattr(tuple, Anum_pg_group_groname, pg_group_dsc, &null);
+        if (datum && !null && strcmp((char*)datum, stmt->name)==0)
+        {
+            gro_exists = true;
+            heap_delete(pg_group_rel, &tuple->t_self, NULL);
+        }
+
+       }
+
+       heap_endscan(scan);
+
+    /*
+     * Did we find any?
+     */
+    if (!gro_exists)
+    {
+        heap_close(pg_group_rel, AccessExclusiveLock);
+               UserAbortTransactionBlock();
+               elog(ERROR, "DropGroup: Group \"%s\" does not exist.", stmt->name);
+    }
+
+       heap_close(pg_group_rel, NoLock);
+
+       if (IsTransactionBlock() && !inblock)
+               EndTransactionBlock();
+}
+
index 25f8dd02bb8a12a3e5ec8cbcbf770ce8bbdbdaa7..e26244e6e7c891bd17b64282ad908b331575760b 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.122 1999/12/14 00:08:15 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.123 1999/12/16 17:24:14 momjian Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -129,6 +129,7 @@ static Node *doNegate(Node *n);
                ClusterStmt, ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
                CreateUserStmt, AlterUserStmt, DropUserStmt, RuleActionStmt,
                RuleActionStmtOrEmpty, ConstraintsSetStmt,
+                CreateGroupStmt, AlterGroupStmt, DropGroupStmt
 
 %type <str>            opt_database1, opt_database2, location, encoding
 
@@ -139,7 +140,7 @@ static Node *doNegate(Node *n);
 %type <str>            user_passwd_clause
 %type <ival>            sysid_clause
 %type <str>            user_valid_clause
-%type <list>   user_group_list, user_group_clause
+%type <list>   user_group_list, user_group_clause, users_in_new_group_clause
 
 %type <boolean>        TriggerActionTime, TriggerForSpec, PLangTrusted
 
@@ -391,11 +392,13 @@ stmtmulti:  stmtmulti ';' stmt
                ;
 
 stmt :   AddAttrStmt
+                | AlterGroupStmt
                | AlterUserStmt
                | ClosePortalStmt
                | CopyStmt
                | CreateStmt
                | CreateAsStmt
+                | CreateGroupStmt
                | CreateSeqStmt
                | CreatePLangStmt
                | CreateTrigStmt
@@ -405,6 +408,7 @@ stmt :        AddAttrStmt
                | DropStmt              
                | TruncateStmt
                | CommentStmt
+                | DropGroupStmt
                | DropPLangStmt
                | DropTrigStmt
                | DropUserStmt
@@ -575,20 +579,99 @@ user_group_list:  user_group_list ',' UserId
                                }
                ;
 
-user_group_clause:  IN GROUP user_group_list
-                                {
-                                        /* the backend doesn't actually process this,
-                                         * so an error message is probably fairer */
-                                        yyerror("IN GROUP is not implemented");
-                                        /* $$ = $3; */
-                                }
-                       | /*EMPTY*/                                                     { $$ = NULL; }
+user_group_clause:  IN GROUP user_group_list    { $$ = $3; }
+                       | /*EMPTY*/             { $$ = NULL; }
                ;
 
 user_valid_clause:  VALID UNTIL SCONST                 { $$ = $3; }
                        | /*EMPTY*/                                                     { $$ = NULL; }
                ;
 
+
+/*****************************************************************************
+ *
+ * Create a postresql group
+ *
+ *
+ *****************************************************************************/
+
+CreateGroupStmt:  CREATE GROUP UserId 
+                  {
+                        CreateGroupStmt *n = makeNode(CreateGroupStmt);
+                       n->name = $3;
+                        n->sysid = -1;
+                        n->initUsers = NULL;
+                        $$ = (Node *)n;
+                  }
+                  |
+                  CREATE GROUP UserId WITH sysid_clause users_in_new_group_clause
+                  {
+                        CreateGroupStmt *n = makeNode(CreateGroupStmt);
+                       n->name = $3;
+                        n->sysid = $5;
+                        n->initUsers = $6;
+                        $$ = (Node *)n;
+                  }
+                ;
+
+users_in_new_group_clause:  USER user_group_list   { $$ = $2; }
+                            | /* EMPTY */          { $$ = NULL; }
+                ;                         
+
+/*****************************************************************************
+ *
+ * Alter a postresql group
+ *
+ *
+ *****************************************************************************/
+
+AlterGroupStmt: ALTER GROUP UserId WITH SYSID Iconst
+                {
+                        AlterGroupStmt *n = makeNode(AlterGroupStmt);
+                       n->name = $3;
+                        n->sysid = $6;
+                        n->action = 0;
+                        n->listUsers = NULL;
+                        $$ = (Node *)n;
+                }
+                |
+                ALTER GROUP UserId ADD USER user_group_list
+                {
+                        AlterGroupStmt *n = makeNode(AlterGroupStmt);
+                       n->name = $3;
+                        n->sysid = -1;
+                        n->action = +1;
+                        n->listUsers = $6;
+                        $$ = (Node *)n;
+                }
+                |
+                ALTER GROUP UserId DROP USER user_group_list
+                {
+                        AlterGroupStmt *n = makeNode(AlterGroupStmt);
+                       n->name = $3;
+                        n->sysid = -1;
+                        n->action = -1;
+                        n->listUsers = $6;
+                        $$ = (Node *)n;
+                }
+                ;
+
+/*****************************************************************************
+ *
+ * Drop a postresql group
+ *
+ *
+ *****************************************************************************/
+
+DropGroupStmt: DROP GROUP UserId
+               {
+                        DropGroupStmt *n = makeNode(DropGroupStmt);
+                       n->name = $3;
+                        $$ = (Node *)n;
+               }
+                ;
+
+
 /*****************************************************************************
  *
  * Set PG internal variable
index bfc114ba2f733fc43ad9d3feaa005280fc702113..63236259945924386c3e76646bda52a01cd37612 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.74 1999/12/14 00:08:17 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.75 1999/12/16 17:24:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -809,6 +809,26 @@ ProcessUtility(Node *parsetree,
                        DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
                        break;
 
+        case T_CreateGroupStmt:
+            PS_SET_STATUS(commandTag = "CREATE GROUP");
+                       CHECK_IF_ABORTED();
+
+            CreateGroup((CreateGroupStmt *) parsetree, dest);
+            break;
+
+        case T_AlterGroupStmt:
+            PS_SET_STATUS(commandTag = "ALTER GROUP");
+                       CHECK_IF_ABORTED();
+
+            AlterGroup((AlterGroupStmt *) parsetree, dest);
+            break;
+
+        case T_DropGroupStmt:
+            PS_SET_STATUS(commandTag = "DROP GROUP");
+                       CHECK_IF_ABORTED();
+
+            DropGroup((DropGroupStmt *) parsetree, dest);
+            break;
 
                        /*
                         * ******************************** default ********************************
index 7bf6929d6ce06ed6f00f901426b8418aab0c234f..bd49577d660355372b34b3a82fdc55a7b2c14538 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_class.h,v 1.30 1999/09/29 16:06:16 wieck Exp $
+ * $Id: pg_class.h,v 1.31 1999/12/16 17:24:17 momjian Exp $
  *
  * NOTES
  *       ``pg_relation'' is being replaced by ``pg_class''.  currently
@@ -136,7 +136,7 @@ DATA(insert OID = 1259 (  pg_class 83                 PGUID 0 0 0 f f r 18 0 0 0 0 0 f f _nul
 DESCR("");
 DATA(insert OID = 1260 (  pg_shadow 86           PGUID 0 0 0 f t r 8  0 0 0 0 0 f f _null_ ));
 DESCR("");
-DATA(insert OID = 1261 (  pg_group 87            PGUID 0 0 0 f t s 3  0 0 0 0 0 f f _null_ ));
+DATA(insert OID = 1261 (  pg_group 87            PGUID 0 0 0 f t r 3  0 0 0 0 0 f f _null_ ));
 DESCR("");
 DATA(insert OID = 1262 (  pg_database 88         PGUID 0 0 0 f t r 4  0 0 0 0 0 f f _null_ ));
 DESCR("");
index 1f88e0b91b4da8541b4ebd471dbf56ffaafb91f6..e718c08126a54ccb52a2f49cc9384747278a6bd1 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_group.h,v 1.6 1999/02/13 23:21:09 momjian Exp $
+ * $Id: pg_group.h,v 1.7 1999/12/16 17:24:17 momjian Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -35,7 +35,7 @@ CATALOG(pg_group) BOOTSTRAP
 
 typedef FormData_pg_group *Form_pg_group;
 
-#define Natts_pg_group                 1
+#define Natts_pg_group                 3
 #define Anum_pg_group_groname  1
 #define Anum_pg_group_grosysid 2
 #define Anum_pg_group_grolist  3
index 3830c110458a742b462acbc45cb6276fd799ba5d..912a5a2ea7aef97211ecbeaa2bd69e3c7c2ab5a2 100644 (file)
@@ -17,4 +17,8 @@ extern void DefineUser(CreateUserStmt *stmt, CommandDest);
 extern void AlterUser(AlterUserStmt *stmt, CommandDest);
 extern void RemoveUser(char *user, CommandDest);
 
+extern void CreateGroup(CreateGroupStmt *stmt, CommandDest dest);
+extern void AlterGroup(AlterGroupStmt *stmt, CommandDest dest);
+extern void DropGroup(DropGroupStmt *stmt, CommandDest dest);
+
 #endif  /* USER_H */
index d362e0a28e995c4e4f02a716c29c10b3f8de21c8..94641eff086a93586e4e99ce4d78ea2fdf1648bb 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.58 1999/12/10 03:56:09 momjian Exp $
+ * $Id: nodes.h,v 1.59 1999/12/16 17:24:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -189,6 +189,9 @@ typedef enum NodeTag
        T_DropUserStmt,
        T_LockStmt,
        T_ConstraintsSetStmt,
+    T_CreateGroupStmt,
+    T_AlterGroupStmt,
+    T_DropGroupStmt,
 
        T_A_Expr = 700,
        T_Attr,
index 45e586aad0c72294845e5f0d7b0f50619dd1f4c0..714f06d5db07bf38cea03bb4657e6869af6ed397 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.91 1999/12/14 00:08:21 momjian Exp $
+ * $Id: parsenodes.h,v 1.92 1999/12/16 17:24:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -285,6 +285,34 @@ typedef struct DropUserStmt
 } DropUserStmt;
 
 
+/* ----------------------
+ *      Create/Alter/Drop Group Statements
+ * ----------------------
+ */
+typedef struct CreateGroupStmt
+{
+    NodeTag     type;
+    char       *name;           /* name of the new group */
+    int         sysid;          /* group id (-1 if pick default) */
+    List       *initUsers;      /* list of initial users */
+} CreateGroupStmt;
+
+typedef struct AlterGroupStmt
+{
+    NodeTag     type;
+    char       *name;           /* name of group to alter */
+    int         action;         /* +1 = add, -1 = drop, 0 = other (HACK!) */
+    int         sysid;          /* sysid change */
+    List       *listUsers;      /* list of users to add/drop */
+} AlterGroupStmt;
+
+typedef struct DropGroupStmt
+{
+    NodeTag     type;
+    char       *name;
+} DropGroupStmt;
+
+
 /* ----------------------
  *             Create SEQUENCE Statement
  * ----------------------