From 99b8f8451170a5c2fc130426952819502c10aea9 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 16 Dec 1999 17:24:19 +0000 Subject: [PATCH] Here's the Create/Alter/Drop Group stuff that's been really overdue. I 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. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- Peter Eisentraut Sernanders väg 10:115 --- src/backend/commands/user.c | 529 ++++++++++++++++++++++++++++++++- src/backend/parser/gram.y | 103 ++++++- src/backend/tcop/utility.c | 22 +- src/include/catalog/pg_class.h | 4 +- src/include/catalog/pg_group.h | 4 +- src/include/commands/user.h | 4 + src/include/nodes/nodes.h | 5 +- src/include/nodes/parsenodes.h | 30 +- 8 files changed, 682 insertions(+), 19 deletions(-) diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index de156171a5..cec646fc9a 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -20,12 +20,16 @@ #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(); +} + diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 25f8dd02bb..e26244e6e7 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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 opt_database1, opt_database2, location, encoding @@ -139,7 +140,7 @@ static Node *doNegate(Node *n); %type user_passwd_clause %type sysid_clause %type user_valid_clause -%type user_group_list, user_group_clause +%type user_group_list, user_group_clause, users_in_new_group_clause %type 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 diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index bfc114ba2f..6323625994 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -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 ******************************** diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 7bf6929d6c..bd49577d66 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -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(""); diff --git a/src/include/catalog/pg_group.h b/src/include/catalog/pg_group.h index 1f88e0b91b..e718c08126 100644 --- a/src/include/catalog/pg_group.h +++ b/src/include/catalog/pg_group.h @@ -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 diff --git a/src/include/commands/user.h b/src/include/commands/user.h index 3830c11045..912a5a2ea7 100644 --- a/src/include/commands/user.h +++ b/src/include/commands/user.h @@ -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 */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index d362e0a28e..94641eff08 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -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, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 45e586aad0..714f06d5db 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -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 * ----------------------