--- ./src/backend/commands/user.c.orig Tue Jul 3 06:22:08 2001 +++ ./src/backend/commands/user.c Tue Jul 10 05:17:58 2001 @@ -193,12 +193,72 @@ sysid_exists = false, havesysid; int max_id = -1; - List *item; + List *item, *option; - havesysid = stmt->sysid > 0; + char *password = NULL; /* PostgreSQL user password */ + int sysid = -1; /* PgSQL system id (-1 if don't care) */ + bool createdb = NULL; /* Can the user create databases? */ + bool createuser = NULL; /* Can this user create users? */ + List *groupElts = NULL; /* The groups the user is a member of */ + char *validUntil = NULL; /* The time the login is valid until */ + + DefElem *dpassword = NULL; + DefElem *dsysid = NULL; + DefElem *dcreatedb = NULL; + DefElem *dcreateuser = NULL; + DefElem *dgroupElts = NULL; + DefElem *dvalidUntil = NULL; + + foreach(option,stmt->options) { + DefElem *defel = (DefElem *)lfirst(option); + + if (!strcasecmp(defel->defname, "password")) { + if (dpassword) + elog(ERROR, "CREATE USER: conflicting options"); + dpassword = defel; + } + else if (!strcasecmp(defel->defname, "sysid")) { + if(dsysid) + elog(ERROR, "CREATE USER: conflicting options"); + dsysid = defel; + } + else if (!strcasecmp(defel->defname, "createdb")) { + if(dcreatedb) + elog(ERROR, "CREATE USER: conflicting options"); + dcreatedb = defel; + } + else if (!strcasecmp(defel->defname, "createuser")) { + if(dcreateuser) + elog(ERROR, "CREATE USER: conflicting options"); + dcreateuser = defel; + } + else if (!strcasecmp(defel->defname, "groupElts")) { + if(dgroupElts) + elog(ERROR, "CREATE USER: conflicting options"); + dgroupElts = defel; + } + else if (!strcasecmp(defel->defname, "validUntil")) { + if(dvalidUntil) + elog(ERROR, "CREATE USER: conflicting options"); + dvalidUntil = defel; + } + else + elog(ERROR,"CREATE USER: option \"%s\" not recognized", + defel->defname); + } + + if(dcreatedb) createdb = intVal(dcreatedb->arg); + if(dcreateuser) createuser = intVal(dcreateuser->arg); + if(dsysid) sysid = intVal(dsysid->arg); + else sysid = -1; + if(dvalidUntil) validUntil = strVal(dvalidUntil->arg); + if(dpassword) password = strVal(dpassword->arg); + if(dgroupElts) groupElts = (List *)dgroupElts->arg; + + havesysid = sysid > 0; /* Check some permissions first */ - if (stmt->password) + if (password) CheckPgUserAclNotNull(); if (!superuser()) @@ -224,7 +284,7 @@ datum = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null); if (havesysid) /* customized id wanted */ - sysid_exists = datum && !null && ((int) datum == stmt->sysid); + sysid_exists = datum && !null && ((int) datum == sysid); else /* pick 1 + max */ { @@ -240,7 +300,7 @@ if (user_exists) elog(ERROR, "CREATE USER: user name \"%s\" already exists", stmt->user); else - elog(ERROR, "CREATE USER: sysid %d is already assigned", stmt->sysid); + elog(ERROR, "CREATE USER: sysid %d is already assigned", sysid); return; } @@ -249,22 +309,22 @@ */ new_record[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein, CStringGetDatum(stmt->user)); - new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(havesysid ? stmt->sysid : max_id + 1); + new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(havesysid ? sysid : max_id + 1); - AssertState(BoolIsValid(stmt->createdb)); - new_record[Anum_pg_shadow_usecreatedb - 1] = (Datum) (stmt->createdb); + AssertState(BoolIsValid(createdb)); + new_record[Anum_pg_shadow_usecreatedb - 1] = (Datum) (createdb); new_record[Anum_pg_shadow_usetrace - 1] = (Datum) (false); - AssertState(BoolIsValid(stmt->createuser)); - new_record[Anum_pg_shadow_usesuper - 1] = (Datum) (stmt->createuser); + AssertState(BoolIsValid(createuser)); + new_record[Anum_pg_shadow_usesuper - 1] = (Datum) (createuser); /* superuser gets catupd right by default */ - new_record[Anum_pg_shadow_usecatupd - 1] = (Datum) (stmt->createuser); + new_record[Anum_pg_shadow_usecatupd - 1] = (Datum) (createuser); - if (stmt->password) + if (password) new_record[Anum_pg_shadow_passwd - 1] = - DirectFunctionCall1(textin, CStringGetDatum(stmt->password)); - if (stmt->validUntil) + DirectFunctionCall1(textin, CStringGetDatum(password)); + if (validUntil) new_record[Anum_pg_shadow_valuntil - 1] = - DirectFunctionCall1(nabstimein, CStringGetDatum(stmt->validUntil)); + DirectFunctionCall1(nabstimein, CStringGetDatum(validUntil)); new_record_nulls[Anum_pg_shadow_usename - 1] = ' '; new_record_nulls[Anum_pg_shadow_usesysid - 1] = ' '; @@ -274,8 +334,8 @@ new_record_nulls[Anum_pg_shadow_usesuper - 1] = ' '; new_record_nulls[Anum_pg_shadow_usecatupd - 1] = ' '; - new_record_nulls[Anum_pg_shadow_passwd - 1] = stmt->password ? ' ' : 'n'; - new_record_nulls[Anum_pg_shadow_valuntil - 1] = stmt->validUntil ? ' ' : 'n'; + new_record_nulls[Anum_pg_shadow_passwd - 1] = password ? ' ' : 'n'; + new_record_nulls[Anum_pg_shadow_valuntil - 1] = validUntil ? ' ' : 'n'; tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls); Assert(tuple); @@ -304,7 +364,7 @@ * Add the user to the groups specified. We'll just call the below * AlterGroup for this. */ - foreach(item, stmt->groupElts) + foreach(item, groupElts) { AlterGroupStmt ags; @@ -312,7 +372,7 @@ * this in */ ags.action = +1; ags.listUsers = makeList1(makeInteger(havesysid ? - stmt->sysid : max_id + 1)); + sysid : max_id + 1)); AlterGroup(&ags, "CREATE USER"); } @@ -343,17 +403,68 @@ new_tuple; bool null; - if (stmt->password) + List *option; + + char *password = NULL; /* PostgreSQL user password */ + int createdb = NULL; /* Can the user create databases? */ + int createuser = NULL; /* Can this user create users? */ + char *validUntil = NULL; /* The time the login is valid until */ + + DefElem *dpassword = NULL; + DefElem *dcreatedb = NULL; + DefElem *dcreateuser = NULL; + DefElem *dvalidUntil = NULL; + + foreach(option,stmt->options) { + DefElem *defel = (DefElem *)lfirst(option); + + if (!strcasecmp(defel->defname, "password")) { + if (dpassword) + elog(ERROR, "ALTER USER: conflicting options"); + dpassword = defel; + } + else if (!strcasecmp(defel->defname, "createdb")) { + if(dcreatedb) + elog(ERROR, "ALTER USER: conflicting options"); + dcreatedb = defel; + } + else if (!strcasecmp(defel->defname, "createuser")) { + if(dcreateuser) + elog(ERROR, "ALTER USER: conflicting options"); + dcreateuser = defel; + } + else if (!strcasecmp(defel->defname, "validUntil")) { + if(dvalidUntil) + elog(ERROR, "ALTER USER: conflicting options"); + dvalidUntil = defel; + } + else + elog(ERROR,"ALTER USER: option \"%s\" not recognized", + defel->defname); + } + + if(dcreatedb) { + createdb = intVal(dcreatedb->arg); + if(createdb == 0) createdb = -1; + } + if(dcreateuser) { + createuser = intVal(dcreateuser->arg); + if(createuser == 0) createuser = -1; + } + if(dvalidUntil) validUntil = strVal(dvalidUntil->arg); + if(dpassword) password = strVal(dpassword->arg); + + if (password) CheckPgUserAclNotNull(); /* must be superuser or just want to change your own password */ if (!superuser() && - !(stmt->createdb == 0 && stmt->createuser == 0 && !stmt->validUntil - && stmt->password && strcmp(GetUserName(GetUserId()), stmt->user) == 0)) + !(createdb == 0 && createuser == 0 && !validUntil + && password && strcmp(GetUserName(GetUserId()), stmt->user) == 0)) elog(ERROR, "ALTER USER: permission denied"); /* changes to the flat password file cannot be rolled back */ - if (IsTransactionBlock() && stmt->password) + if (IsTransactionBlock() && password) elog(NOTICE, "ALTER USER: password changes cannot be rolled back"); /* @@ -385,7 +496,7 @@ new_record_nulls[Anum_pg_shadow_usesysid - 1] = null ? 'n' : ' '; /* createdb */ - if (stmt->createdb == 0) + if (createdb == 0) { /* don't change */ new_record[Anum_pg_shadow_usecreatedb - 1] = heap_getattr(tuple, Anum_pg_shadow_usecreatedb, pg_shadow_dsc, &null); @@ -393,7 +504,7 @@ } else { - new_record[Anum_pg_shadow_usecreatedb - 1] = (Datum) (stmt->createdb > 0 ? true : false); + new_record[Anum_pg_shadow_usecreatedb - 1] = (Datum) (createdb > 0 ? true : false); new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = ' '; } @@ -402,7 +513,7 @@ new_record_nulls[Anum_pg_shadow_usetrace - 1] = null ? 'n' : ' '; /* createuser (superuser) */ - if (stmt->createuser == 0) + if (createuser == 0) { /* don't change */ new_record[Anum_pg_shadow_usesuper - 1] = heap_getattr(tuple, Anum_pg_shadow_usesuper, pg_shadow_dsc, &null); @@ -410,12 +521,12 @@ } else { - new_record[Anum_pg_shadow_usesuper - 1] = (Datum) (stmt->createuser > 0 ? true : false); + new_record[Anum_pg_shadow_usesuper - 1] = (Datum) (createuser > 0 ? true : false); new_record_nulls[Anum_pg_shadow_usesuper - 1] = ' '; } /* catupd - set to false if someone's superuser priv is being yanked */ - if (stmt->createuser < 0) + if (createuser < 0) { new_record[Anum_pg_shadow_usecatupd - 1] = (Datum) (false); new_record_nulls[Anum_pg_shadow_usecatupd - 1] = ' '; @@ -428,10 +539,10 @@ } /* password */ - if (stmt->password) + if (password) { new_record[Anum_pg_shadow_passwd - 1] = - DirectFunctionCall1(textin, CStringGetDatum(stmt->password)); + DirectFunctionCall1(textin, CStringGetDatum(password)); new_record_nulls[Anum_pg_shadow_passwd - 1] = ' '; } else @@ -443,10 +554,10 @@ } /* valid until */ - if (stmt->validUntil) + if (validUntil) { new_record[Anum_pg_shadow_valuntil - 1] = - DirectFunctionCall1(nabstimein, CStringGetDatum(stmt->validUntil)); + DirectFunctionCall1(nabstimein, CStringGetDatum(validUntil)); new_record_nulls[Anum_pg_shadow_valuntil - 1] = ' '; } else --- ./src/backend/nodes/copyfuncs.c.orig Mon Jul 9 09:37:55 2001 +++ ./src/backend/nodes/copyfuncs.c Mon Jul 9 09:05:19 2001 @@ -2355,14 +2355,7 @@ if (from->user) newnode->user = pstrdup(from->user); - if (from->password) - newnode->password = pstrdup(from->password); - newnode->sysid = from->sysid; - newnode->createdb = from->createdb; - newnode->createuser = from->createuser; - Node_Copy(from, newnode, groupElts); - if (from->validUntil) - newnode->validUntil = pstrdup(from->validUntil); + Node_Copy(from, newnode, options); return newnode; } @@ -2374,12 +2367,7 @@ if (from->user) newnode->user = pstrdup(from->user); - if (from->password) - newnode->password = pstrdup(from->password); - newnode->createdb = from->createdb; - newnode->createuser = from->createuser; - if (from->validUntil) - newnode->validUntil = pstrdup(from->validUntil); + Node_Copy(from, newnode, options); return newnode; } --- ./src/backend/nodes/equalfuncs.c.orig Mon Jul 9 09:38:05 2001 +++ ./src/backend/nodes/equalfuncs.c Mon Jul 9 09:04:24 2001 @@ -1253,17 +1253,7 @@ { if (!equalstr(a->user, b->user)) return false; - if (!equalstr(a->password, b->password)) - return false; - if (a->sysid != b->sysid) - return false; - if (a->createdb != b->createdb) - return false; - if (a->createuser != b->createuser) - return false; - if (!equal(a->groupElts, b->groupElts)) - return false; - if (!equalstr(a->validUntil, b->validUntil)) + if (!equal(a->options, b->options)) return false; return true; @@ -1274,13 +1264,7 @@ { if (!equalstr(a->user, b->user)) return false; - if (!equalstr(a->password, b->password)) - return false; - if (a->createdb != b->createdb) - return false; - if (a->createuser != b->createuser) - return false; - if (!equalstr(a->validUntil, b->validUntil)) + if (!equal(a->options, b->options)) return false; return true; --- ./src/backend/parser/gram.y.orig Fri Jun 22 11:44:54 2001 +++ ./src/backend/parser/gram.y Mon Jul 9 08:46:31 2001 @@ -155,11 +155,10 @@ %type opt_lock, lock_type %type opt_lmode, opt_force -%type user_createdb_clause, user_createuser_clause -%type user_passwd_clause -%type sysid_clause -%type user_valid_clause -%type user_list, user_group_clause, users_in_new_group_clause +%type user_list, users_in_new_group_clause + +%type OptUserList +%type OptUserElem %type TriggerActionTime, TriggerForSpec, PLangTrusted, opt_procedural @@ -486,32 +485,18 @@ * *****************************************************************************/ -CreateUserStmt: CREATE USER UserId - user_createdb_clause user_createuser_clause user_group_clause - user_valid_clause +CreateUserStmt: CREATE USER UserId OptUserList { CreateUserStmt *n = makeNode(CreateUserStmt); n->user = $3; - n->sysid = -1; - n->password = NULL; - n->createdb = $4 == +1 ? TRUE : FALSE; - n->createuser = $5 == +1 ? TRUE : FALSE; - n->groupElts = $6; - n->validUntil = $7; + n->options = $4; $$ = (Node *)n; } - | CREATE USER UserId WITH sysid_clause user_passwd_clause - user_createdb_clause user_createuser_clause user_group_clause - user_valid_clause + | CREATE USER UserId WITH OptUserList { CreateUserStmt *n = makeNode(CreateUserStmt); n->user = $3; - n->sysid = $5; - n->password = $6; - n->createdb = $7 == +1 ? TRUE : FALSE; - n->createuser = $8 == +1 ? TRUE : FALSE; - n->groupElts = $9; - n->validUntil = $10; + n->options = $5; $$ = (Node *)n; } ; @@ -523,27 +508,18 @@ * *****************************************************************************/ -AlterUserStmt: ALTER USER UserId user_createdb_clause - user_createuser_clause user_valid_clause +AlterUserStmt: ALTER USER UserId OptUserList { AlterUserStmt *n = makeNode(AlterUserStmt); n->user = $3; - n->password = NULL; - n->createdb = $4; - n->createuser = $5; - n->validUntil = $6; + n->options = $4; $$ = (Node *)n; } - | ALTER USER UserId WITH PASSWORD Sconst - user_createdb_clause - user_createuser_clause user_valid_clause + | ALTER USER UserId WITH OptUserList { AlterUserStmt *n = makeNode(AlterUserStmt); n->user = $3; - n->password = $6; - n->createdb = $7; - n->createuser = $8; - n->validUntil = $9; + n->options = $5; $$ = (Node *)n; } ; @@ -552,7 +528,7 @@ * * Drop a postgresql DBMS user * - * + * *****************************************************************************/ DropUserStmt: DROP USER user_list @@ -563,28 +539,67 @@ } ; -user_passwd_clause: PASSWORD Sconst { $$ = $2; } - | /*EMPTY*/ { $$ = NULL; } +OptUserList: OptUserList OptUserElem + { $$ = lappend($1, $2); } + | { $$ = NIL; } ; -sysid_clause: SYSID Iconst +OptUserElem: PASSWORD Sconst + { + $$ = makeNode(DefElem); + $$->defname = "password"; + $$->arg = (Node *)makeString($2); + } + + | SYSID Iconst { - if ($2 <= 0) - elog(ERROR, "sysid must be positive"); - $$ = $2; + $$ = makeNode(DefElem); + $$->defname = "sysid"; + $$->arg = (Node *)makeInteger($2); } - | /*EMPTY*/ { $$ = -1; } - ; -user_createdb_clause: CREATEDB { $$ = +1; } - | NOCREATEDB { $$ = -1; } - | /*EMPTY*/ { $$ = 0; } - ; + | CREATEDB + { + $$ = makeNode(DefElem); + $$->defname = "createdb"; + $$->arg = (Node *)makeInteger(TRUE); + } -user_createuser_clause: CREATEUSER { $$ = +1; } - | NOCREATEUSER { $$ = -1; } - | /*EMPTY*/ { $$ = 0; } - ; + | NOCREATEDB + { + $$ = makeNode(DefElem); + $$->defname = "createdb"; + $$->arg = (Node *)makeInteger(FALSE); + } + + | CREATEUSER + { + $$ = makeNode(DefElem); + $$->defname = "createuser"; + $$->arg = (Node *)makeInteger(TRUE); + } + + | NOCREATEUSER + { + $$ = makeNode(DefElem); + $$->defname = "createuser"; + $$->arg = (Node *)makeInteger(FALSE); + } + + | IN GROUP user_list + { + $$ = makeNode(DefElem); + $$->defname = "groupElts"; + $$->arg = (Node *)$3; + } + + | VALID UNTIL SCONST + { + $$ = makeNode(DefElem); + $$->defname = "validUntil"; + $$->arg = (Node *)makeString($3); + } + ; user_list: user_list ',' UserId { @@ -596,13 +611,6 @@ } ; -user_group_clause: IN GROUP user_list { $$ = $3; } - | /*EMPTY*/ { $$ = NULL; } - ; - -user_valid_clause: VALID UNTIL SCONST { $$ = $3; } - | /*EMPTY*/ { $$ = NULL; } - ; /***************************************************************************** @@ -620,7 +628,7 @@ n->initUsers = NULL; $$ = (Node *)n; } - | CREATE GROUP UserId WITH sysid_clause users_in_new_group_clause + | CREATE GROUP UserId WITH Iconst users_in_new_group_clause { CreateGroupStmt *n = makeNode(CreateGroupStmt); n->name = $3; --- ./doc/src/sgml/ref/create_user.sgml.orig Tue Jul 10 10:12:27 2001 +++ ./doc/src/sgml/ref/create_user.sgml Tue Jul 10 10:12:31 2001 @@ -23,13 +23,14 @@ 1999-07-20 -CREATE USER username - [ WITH - [ SYSID uid ] - [ PASSWORD 'password' ] ] - [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ] - [ IN GROUP groupname [, ...] ] - [ VALID UNTIL 'abstime' ] +CREATE USER username [ [ WITH ] option [ ... ] ] + +option: SYSID uid + | PASSWORD 'password' + | CREATEDB | NOCREATEDB + | CREATEUSER | NOCREATEUSER + | IN GROUP groupname [, ...] + | VALID UNTIL 'abstime' --- ./doc/src/sgml/ref/alter_user.sgml.orig Tue Jul 10 10:12:53 2001 +++ ./doc/src/sgml/ref/alter_user.sgml Tue Jul 10 10:15:41 2001 @@ -23,10 +23,12 @@ 1999-07-20 -ALTER USER username - [ WITH PASSWORD 'password' ] - [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ] - [ VALID UNTIL 'abstime' ] +ALTER USER username [ [ WITH ] option [ ... ] ] + +option: PASSWORD 'password' + | CREATEDB | NOCREATEDB + | CREATEUSER | NOCREATEUSER + | VALID UNTIL 'abstime' --- ./src/include/nodes/parsenodes.h.orig Tue Jul 3 06:18:30 2001 +++ ./src/include/nodes/parsenodes.h Mon Jul 9 09:05:36 2001 @@ -326,22 +326,14 @@ { NodeTag type; char *user; /* PostgreSQL user login */ - char *password; /* PostgreSQL user password */ - int sysid; /* PgSQL system id (-1 if don't care) */ - bool createdb; /* Can the user create databases? */ - bool createuser; /* Can this user create users? */ - List *groupElts; /* The groups the user is a member of */ - char *validUntil; /* The time the login is valid until */ + List *options; } CreateUserStmt; typedef struct AlterUserStmt { NodeTag type; char *user; /* PostgreSQL user login */ - char *password; /* PostgreSQL user password */ - int createdb; /* Can the user create databases? */ - int createuser; /* Can this user create users? */ - char *validUntil; /* The time the login is valid until */ + List *options; } AlterUserStmt; typedef struct DropUserStmt