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 * ----------------------