Hi, this is revised version. > Kyotaro HORIGUCHI wrote: > > > - Storage for new information > > > > The new struct NameId stores an identifier which telling what it > > logically is using the new enum NameIdTypes. > > I think NameId is a bad name for this. My point is that NameId, as it > stands, might be a name for anything, not just a role; and the object it > identifies is not an Id either. Maybe RoleSpec?
Yeah! I felt it no good even if it were a generic type for various "Name of something or its oid". RoleSpec sounds much better. > Do we need a public_ok > argument to get_nameid_oid() (get a better name for this function too) Maybe get_rolespec_oid() as a name ofter its parameter type? > so that callers don't have to check for InvalidOid argument? I think > the arrangement you propose is not very convenient; it'd be best to > avoid duplicating the check for InvalidOid in all callers of the new > function, particularly where there was no check before. I agree that It'd be better keeping away from duplicated InvalidOid checks, but public_ok seems a bit myopic. Since there's no reasonable border between functions accepting 'public' and others, such kind of solution would not be reasonable.. What about checking it being a PUBLIC or not *before* calling get_rolespec_oid()? The attached patch modified in the following points. - rename NameId to RoleSpec and NameIdType to RoleSpecTypes. - rename get_nameid_oid() to get_rolespec_oid(). - rename roleNamesToIds() to roleSpecsToIds(). - some struct members are changed such as authname to authrole. - check if rolespec is "public" or not before calling get_rolespec_oid() - ExecAlterDefaultPrivilegesStmt and ExecuteGrantStmt does slightly different things about ACL_ID_PUBLIC but I unified it to the latter. - rebased to the current master regards, -- Kyotaro Horiguchi NTT Open Source Software Center CreateStmt->authrole = NULL => ?
>From 307249654c97b6449261febbfd84190fbad9111d Mon Sep 17 00:00:00 2001 From: Kyotaro Horiguchi <horiguchi.kyot...@lab.ntt.co.jp> Date: Fri, 14 Nov 2014 17:37:22 +0900 Subject: [PATCH] ALTER USER CURRENT_USER v3 --- src/backend/catalog/aclchk.c | 30 +++--- src/backend/commands/alter.c | 2 +- src/backend/commands/extension.c | 2 +- src/backend/commands/foreigncmds.c | 57 +++++------ src/backend/commands/schemacmds.c | 30 +++++- src/backend/commands/tablecmds.c | 4 +- src/backend/commands/tablespace.c | 2 +- src/backend/commands/user.c | 86 +++++++++-------- src/backend/nodes/copyfuncs.c | 37 +++++--- src/backend/nodes/equalfuncs.c | 35 ++++--- src/backend/parser/gram.y | 190 +++++++++++++++++++++++++++---------- src/backend/parser/parse_utilcmd.c | 4 +- src/backend/utils/adt/acl.c | 34 +++++++ src/include/commands/user.h | 2 +- src/include/nodes/nodes.h | 1 + src/include/nodes/parsenodes.h | 48 +++++++--- src/include/utils/acl.h | 2 +- 17 files changed, 385 insertions(+), 181 deletions(-) diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index d30612c..24811c6 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -430,13 +430,16 @@ ExecuteGrantStmt(GrantStmt *stmt) foreach(cell, stmt->grantees) { PrivGrantee *grantee = (PrivGrantee *) lfirst(cell); + Oid grantee_uid = ACL_ID_PUBLIC; - if (grantee->rolname == NULL) - istmt.grantees = lappend_oid(istmt.grantees, ACL_ID_PUBLIC); - else - istmt.grantees = - lappend_oid(istmt.grantees, - get_role_oid(grantee->rolname, false)); + /* "public" is mapped to ACL_ID_PUBLIC */ + if (grantee->role->roltype != ROLESPEC_PUBLIC) + { + grantee_uid = get_rolespec_oid(grantee->role, false); + if (!OidIsValid(grantee_uid)) + grantee_uid = ACL_ID_PUBLIC; + } + istmt.grantees = lappend_oid(istmt.grantees, grantee_uid); } /* @@ -913,13 +916,16 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt) foreach(cell, action->grantees) { PrivGrantee *grantee = (PrivGrantee *) lfirst(cell); + Oid grantee_uid = ACL_ID_PUBLIC; - if (grantee->rolname == NULL) - iacls.grantees = lappend_oid(iacls.grantees, ACL_ID_PUBLIC); - else - iacls.grantees = - lappend_oid(iacls.grantees, - get_role_oid(grantee->rolname, false)); + /* "public" is mapped to ACL_ID_PUBLIC */ + if (grantee->role->roltype != ROLESPEC_PUBLIC) + { + grantee_uid = get_rolespec_oid(grantee->role, false); + if (!OidIsValid(grantee_uid)) + grantee_uid = ACL_ID_PUBLIC; + } + iacls.grantees = lappend_oid(iacls.grantees, grantee_uid); } /* diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index c9a9baf..c53d4e5 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -678,7 +678,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid) Oid ExecAlterOwnerStmt(AlterOwnerStmt *stmt) { - Oid newowner = get_role_oid(stmt->newowner, false); + Oid newowner = get_rolespec_oid(stmt->newowner, false); switch (stmt->objectType) { diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 9a0afa4..52d4190 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -1370,7 +1370,7 @@ CreateExtension(CreateExtensionStmt *stmt) CreateSchemaStmt *csstmt = makeNode(CreateSchemaStmt); csstmt->schemaname = schemaName; - csstmt->authid = NULL; /* will be created by current user */ + csstmt->authrole = NULL; /* will be created by current user */ csstmt->schemaElts = NIL; csstmt->if_not_exists = false; CreateSchemaCommand(csstmt, NULL); diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index ab4ed6c..d4c4442 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -198,24 +198,6 @@ transformGenericOptions(Oid catalogId, /* - * Convert the user mapping user name to OID - */ -static Oid -GetUserOidFromMapping(const char *username, bool missing_ok) -{ - if (!username) - /* PUBLIC user mapping */ - return InvalidOid; - - if (strcmp(username, "current_user") == 0) - /* map to the owner */ - return GetUserId(); - - /* map to provided user */ - return get_role_oid(username, missing_ok); -} - -/* * Internal workhorse for changing a data wrapper's owner. * * Allow this only for superusers; also the new owner must be a @@ -1090,7 +1072,7 @@ CreateUserMapping(CreateUserMappingStmt *stmt) Datum values[Natts_pg_user_mapping]; bool nulls[Natts_pg_user_mapping]; HeapTuple tuple; - Oid useId; + Oid useId = InvalidOid; Oid umId; ObjectAddress myself; ObjectAddress referenced; @@ -1099,7 +1081,9 @@ CreateUserMapping(CreateUserMappingStmt *stmt) rel = heap_open(UserMappingRelationId, RowExclusiveLock); - useId = GetUserOidFromMapping(stmt->username, false); + /* "public" is mapped to userId = InvalidOid */ + if (stmt->user->roltype != ROLESPEC_PUBLIC) + useId = get_rolespec_oid(stmt->user, false); /* Check that the server exists. */ srv = GetForeignServerByName(stmt->servername, false); @@ -1188,13 +1172,16 @@ AlterUserMapping(AlterUserMappingStmt *stmt) Datum repl_val[Natts_pg_user_mapping]; bool repl_null[Natts_pg_user_mapping]; bool repl_repl[Natts_pg_user_mapping]; - Oid useId; + Oid useId = InvalidOid; Oid umId; ForeignServer *srv; rel = heap_open(UserMappingRelationId, RowExclusiveLock); - useId = GetUserOidFromMapping(stmt->username, false); + /* "public" is mapped to userId = InvalidOid */ + if (stmt->user->roltype != ROLESPEC_PUBLIC) + useId = get_rolespec_oid(stmt->user, false); + srv = GetForeignServerByName(stmt->servername, false); umId = GetSysCacheOid2(USERMAPPINGUSERSERVER, @@ -1272,23 +1259,29 @@ Oid RemoveUserMapping(DropUserMappingStmt *stmt) { ObjectAddress object; - Oid useId; + Oid useId = InvalidOid; Oid umId; ForeignServer *srv; - useId = GetUserOidFromMapping(stmt->username, stmt->missing_ok); - srv = GetForeignServerByName(stmt->servername, true); - if (stmt->username && !OidIsValid(useId)) + /* "public" is mapped to userId = InvalidOid */ + if (stmt->user->roltype != ROLESPEC_PUBLIC) { - /* - * IF EXISTS specified, role not found and not public. Notice this and - * leave. - */ - elog(NOTICE, "role \"%s\" does not exist, skipping", stmt->username); - return InvalidOid; + useId = get_rolespec_oid(stmt->user, stmt->missing_ok); + if (!OidIsValid(useId)) + { + /* + * IF EXISTS specified, role not found and not public. Notice this + * and leave. + */ + elog(NOTICE, "role \"%s\" does not exist, skipping", + stmt->user->str); + return InvalidOid; + } } + srv = GetForeignServerByName(stmt->servername, true); + if (!srv) { if (!stmt->missing_ok) diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 03f5514..3420d2d 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -21,6 +21,7 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/pg_authid.h" #include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "commands/dbcommands.h" @@ -42,8 +43,8 @@ static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerI Oid CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString) { - const char *schemaName = stmt->schemaname; - const char *authId = stmt->authid; + const char *schemaName = stmt->schemaname; + const RoleSpec *authrole = stmt->authrole; Oid namespaceId; OverrideSearchPath *overridePath; List *parsetree_list; @@ -58,11 +59,32 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString) /* * Who is supposed to own the new schema? */ - if (authId) - owner_uid = get_role_oid(authId, false); + if (authrole) + { + owner_uid = get_rolespec_oid(authrole, false); + if (!OidIsValid(owner_uid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("role \"%s\" does not exist", authrole->str))); + + } else owner_uid = saved_uid; + /* fill schema name with the user name if not specified */ + if (!schemaName) + { + HeapTuple tuple; + + tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(owner_uid)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("invalid role oid: %u", owner_uid))); + schemaName = + pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname)); + ReleaseSysCache(tuple); + } /* * To create a schema, must have schema-create privilege on the current * database and must be able to become the target role (this does not diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 714a9f1..ce58196 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3474,7 +3474,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, break; case AT_ChangeOwner: /* ALTER OWNER */ ATExecChangeOwner(RelationGetRelid(rel), - get_role_oid(cmd->name, false), + get_rolespec_oid(cmd->newowner, false), false, lockmode); break; case AT_ClusterOn: /* CLUSTER ON */ @@ -9330,7 +9330,7 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt) HeapTuple tuple; Oid orig_tablespaceoid; Oid new_tablespaceoid; - List *role_oids = roleNamesToIds(stmt->roles); + List *role_oids = roleSpecsToIds(stmt->roles); /* Ensure we were not asked to move something we can't */ if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX && diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 616308b..6025dc6 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -252,7 +252,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) /* However, the eventual owner of the tablespace need not be */ if (stmt->owner) - ownerId = get_role_oid(stmt->owner, false); + ownerId = get_rolespec_oid(stmt->owner, false); else ownerId = GetUserId(); diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 1a73fd8..377c7c6 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -310,13 +310,6 @@ CreateRole(CreateRoleStmt *stmt) errmsg("permission denied to create role"))); } - if (strcmp(stmt->role, "public") == 0 || - strcmp(stmt->role, "none") == 0) - ereport(ERROR, - (errcode(ERRCODE_RESERVED_NAME), - errmsg("role name \"%s\" is reserved", - stmt->role))); - /* * Check the pg_authid relation to be certain the role doesn't already * exist. @@ -445,10 +438,10 @@ CreateRole(CreateRoleStmt *stmt) * option, rolemembers don't. */ AddRoleMems(stmt->role, roleid, - adminmembers, roleNamesToIds(adminmembers), + adminmembers, roleSpecsToIds(adminmembers), GetUserId(), true); AddRoleMems(stmt->role, roleid, - rolemembers, roleNamesToIds(rolemembers), + rolemembers, roleSpecsToIds(rolemembers), GetUserId(), false); /* Post creation hook for new role */ @@ -481,6 +474,7 @@ AlterRole(AlterRoleStmt *stmt) HeapTuple tuple, new_tuple; ListCell *option; + char *rolename = NULL; char *password = NULL; /* user password */ bool encrypt_password = Password_encryption; /* encrypt password? */ char encrypted_password[MD5_PASSWD_LEN + 1]; @@ -649,18 +643,25 @@ AlterRole(AlterRoleStmt *stmt) pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock); pg_authid_dsc = RelationGetDescr(pg_authid_rel); - tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role)); - if (!HeapTupleIsValid(tuple)) + roleid = get_rolespec_oid(stmt->role, false); + if (!OidIsValid(roleid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("role \"%s\" does not exist", stmt->role))); - - roleid = HeapTupleGetOid(tuple); + errmsg("role \"%s\" does not exist", stmt->role->str))); /* * To mess with a superuser you gotta be superuser; else you need * createrole, or just want to change your own password */ + tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("invalid role oid: %u", roleid))); + + rolename = + pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname)); + if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper || issuper >= 0) { if (!superuser()) @@ -720,12 +721,12 @@ AlterRole(AlterRoleStmt *stmt) * Call the password checking hook if there is one defined */ if (check_password_hook && password) - (*check_password_hook) (stmt->role, - password, - isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT, - validUntil_datum, - validUntil_null); - + (*check_password_hook)(rolename , + password, + isMD5(password) ? PASSWORD_TYPE_MD5 : PASSWORD_TYPE_PLAINTEXT, + validUntil_datum, + validUntil_null); + /* * Build an updated tuple, perusing the information just obtained */ @@ -794,7 +795,7 @@ AlterRole(AlterRoleStmt *stmt) CStringGetTextDatum(password); else { - if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role), + if (!pg_md5_encrypt(password, rolename, strlen(rolename), encrypted_password)) elog(ERROR, "password encryption failed"); new_record[Anum_pg_authid_rolpassword - 1] = @@ -841,12 +842,12 @@ AlterRole(AlterRoleStmt *stmt) CommandCounterIncrement(); if (stmt->action == +1) /* add members to role */ - AddRoleMems(stmt->role, roleid, - rolemembers, roleNamesToIds(rolemembers), + AddRoleMems(rolename, roleid, + rolemembers, roleSpecsToIds(rolemembers), GetUserId(), false); else if (stmt->action == -1) /* drop members from role */ - DelRoleMems(stmt->role, roleid, - rolemembers, roleNamesToIds(rolemembers), + DelRoleMems(rolename, roleid, + rolemembers, roleSpecsToIds(rolemembers), false); /* @@ -870,12 +871,20 @@ AlterRoleSet(AlterRoleSetStmt *stmt) if (stmt->role) { - roletuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role)); + roleid = get_rolespec_oid(stmt->role, false); + + if (!OidIsValid(roleid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("role \"%s\" does not exist", stmt->role->str))); + + + roletuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid)); if (!HeapTupleIsValid(roletuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("role \"%s\" does not exist", stmt->role))); + errmsg("invalid role oid: %u", roleid))); roleid = HeapTupleGetOid(roletuple); @@ -1163,13 +1172,6 @@ RenameRole(const char *oldname, const char *newname) (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("role \"%s\" already exists", newname))); - if (strcmp(newname, "public") == 0 || - strcmp(newname, "none") == 0) - ereport(ERROR, - (errcode(ERRCODE_RESERVED_NAME), - errmsg("role name \"%s\" is reserved", - newname))); - /* * createrole is enough privilege unless you want to mess with a superuser */ @@ -1240,11 +1242,11 @@ GrantRole(GrantRoleStmt *stmt) ListCell *item; if (stmt->grantor) - grantor = get_role_oid(stmt->grantor, false); + grantor = get_rolespec_oid(stmt->grantor, false); else grantor = GetUserId(); - grantee_ids = roleNamesToIds(stmt->grantee_roles); + grantee_ids = roleSpecsToIds(stmt->grantee_roles); /* AccessShareLock is enough since we aren't modifying pg_authid */ pg_authid_rel = heap_open(AuthIdRelationId, AccessShareLock); @@ -1293,7 +1295,7 @@ GrantRole(GrantRoleStmt *stmt) void DropOwnedObjects(DropOwnedStmt *stmt) { - List *role_ids = roleNamesToIds(stmt->roles); + List *role_ids = roleSpecsToIds(stmt->roles); ListCell *cell; /* Check privileges */ @@ -1319,7 +1321,7 @@ DropOwnedObjects(DropOwnedStmt *stmt) void ReassignOwnedObjects(ReassignOwnedStmt *stmt) { - List *role_ids = roleNamesToIds(stmt->roles); + List *role_ids = roleSpecsToIds(stmt->roles); ListCell *cell; Oid newrole; @@ -1335,7 +1337,7 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt) } /* Must have privileges on the receiving side too */ - newrole = get_role_oid(stmt->newrole, false); + newrole = get_rolespec_oid(stmt->newrole, false); if (!has_privs_of_role(GetUserId(), newrole)) ereport(ERROR, @@ -1353,15 +1355,15 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt) * in the same order. */ List * -roleNamesToIds(List *memberNames) +roleSpecsToIds(List *memberNames) { List *result = NIL; ListCell *l; foreach(l, memberNames) { - char *rolename = strVal(lfirst(l)); - Oid roleid = get_role_oid(rolename, false); + RoleSpec *rolespec = (RoleSpec*) lfirst(l); + Oid roleid = get_rolespec_oid(rolespec, false); result = lappend_oid(result, roleid); } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index e76b5b3..effb062 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2493,6 +2493,17 @@ _copyXmlSerialize(const XmlSerialize *from) return newnode; } +static RoleSpec * +_copyRoleSpec(const RoleSpec *from) +{ + RoleSpec *newnode = makeNode(RoleSpec); + + COPY_SCALAR_FIELD(roltype); + COPY_STRING_FIELD(str); + + return newnode; +} + static Query * _copyQuery(const Query *from) { @@ -2639,6 +2650,7 @@ _copyAlterTableCmd(const AlterTableCmd *from) COPY_SCALAR_FIELD(subtype); COPY_STRING_FIELD(name); + COPY_NODE_FIELD(newowner); COPY_NODE_FIELD(def); COPY_SCALAR_FIELD(behavior); COPY_SCALAR_FIELD(missing_ok); @@ -2683,7 +2695,7 @@ _copyPrivGrantee(const PrivGrantee *from) { PrivGrantee *newnode = makeNode(PrivGrantee); - COPY_STRING_FIELD(rolname); + COPY_NODE_FIELD(role); return newnode; } @@ -2719,7 +2731,7 @@ _copyGrantRoleStmt(const GrantRoleStmt *from) COPY_NODE_FIELD(grantee_roles); COPY_SCALAR_FIELD(is_grant); COPY_SCALAR_FIELD(admin_opt); - COPY_STRING_FIELD(grantor); + COPY_NODE_FIELD(grantor); COPY_SCALAR_FIELD(behavior); return newnode; @@ -3026,7 +3038,7 @@ _copyAlterOwnerStmt(const AlterOwnerStmt *from) COPY_NODE_FIELD(relation); COPY_NODE_FIELD(object); COPY_NODE_FIELD(objarg); - COPY_STRING_FIELD(newowner); + COPY_NODE_FIELD(newowner); return newnode; } @@ -3411,7 +3423,7 @@ _copyCreateTableSpaceStmt(const CreateTableSpaceStmt *from) CreateTableSpaceStmt *newnode = makeNode(CreateTableSpaceStmt); COPY_STRING_FIELD(tablespacename); - COPY_STRING_FIELD(owner); + COPY_NODE_FIELD(owner); COPY_STRING_FIELD(location); COPY_NODE_FIELD(options); @@ -3548,7 +3560,7 @@ _copyCreateUserMappingStmt(const CreateUserMappingStmt *from) { CreateUserMappingStmt *newnode = makeNode(CreateUserMappingStmt); - COPY_STRING_FIELD(username); + COPY_NODE_FIELD(user); COPY_STRING_FIELD(servername); COPY_NODE_FIELD(options); @@ -3560,7 +3572,7 @@ _copyAlterUserMappingStmt(const AlterUserMappingStmt *from) { AlterUserMappingStmt *newnode = makeNode(AlterUserMappingStmt); - COPY_STRING_FIELD(username); + COPY_NODE_FIELD(user); COPY_STRING_FIELD(servername); COPY_NODE_FIELD(options); @@ -3572,7 +3584,7 @@ _copyDropUserMappingStmt(const DropUserMappingStmt *from) { DropUserMappingStmt *newnode = makeNode(DropUserMappingStmt); - COPY_STRING_FIELD(username); + COPY_NODE_FIELD(user); COPY_STRING_FIELD(servername); COPY_SCALAR_FIELD(missing_ok); @@ -3685,7 +3697,7 @@ _copyAlterRoleStmt(const AlterRoleStmt *from) { AlterRoleStmt *newnode = makeNode(AlterRoleStmt); - COPY_STRING_FIELD(role); + COPY_NODE_FIELD(role); COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(action); @@ -3697,7 +3709,7 @@ _copyAlterRoleSetStmt(const AlterRoleSetStmt *from) { AlterRoleSetStmt *newnode = makeNode(AlterRoleSetStmt); - COPY_STRING_FIELD(role); + COPY_NODE_FIELD(role); COPY_STRING_FIELD(database); COPY_NODE_FIELD(setstmt); @@ -3758,7 +3770,7 @@ _copyCreateSchemaStmt(const CreateSchemaStmt *from) CreateSchemaStmt *newnode = makeNode(CreateSchemaStmt); COPY_STRING_FIELD(schemaname); - COPY_STRING_FIELD(authid); + COPY_NODE_FIELD(authrole); COPY_NODE_FIELD(schemaElts); COPY_SCALAR_FIELD(if_not_exists); @@ -3843,7 +3855,7 @@ _copyReassignOwnedStmt(const ReassignOwnedStmt *from) ReassignOwnedStmt *newnode = makeNode(ReassignOwnedStmt); COPY_NODE_FIELD(roles); - COPY_STRING_FIELD(newrole); + COPY_NODE_FIELD(newrole); return newnode; } @@ -4729,6 +4741,9 @@ copyObject(const void *from) case T_XmlSerialize: retval = _copyXmlSerialize(from); break; + case T_RoleSpec: + retval = _copyRoleSpec(from); + break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from)); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index d5db71d..42a7f53 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -971,6 +971,7 @@ _equalAlterTableCmd(const AlterTableCmd *a, const AlterTableCmd *b) { COMPARE_SCALAR_FIELD(subtype); COMPARE_STRING_FIELD(name); + COMPARE_NODE_FIELD(newowner); COMPARE_NODE_FIELD(def); COMPARE_SCALAR_FIELD(behavior); COMPARE_SCALAR_FIELD(missing_ok); @@ -1009,7 +1010,7 @@ _equalGrantStmt(const GrantStmt *a, const GrantStmt *b) static bool _equalPrivGrantee(const PrivGrantee *a, const PrivGrantee *b) { - COMPARE_STRING_FIELD(rolname); + COMPARE_NODE_FIELD(role); return true; } @@ -1039,7 +1040,7 @@ _equalGrantRoleStmt(const GrantRoleStmt *a, const GrantRoleStmt *b) COMPARE_NODE_FIELD(grantee_roles); COMPARE_SCALAR_FIELD(is_grant); COMPARE_SCALAR_FIELD(admin_opt); - COMPARE_STRING_FIELD(grantor); + COMPARE_NODE_FIELD(grantor); COMPARE_SCALAR_FIELD(behavior); return true; @@ -1292,7 +1293,7 @@ _equalAlterOwnerStmt(const AlterOwnerStmt *a, const AlterOwnerStmt *b) COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(object); COMPARE_NODE_FIELD(objarg); - COMPARE_STRING_FIELD(newowner); + COMPARE_NODE_FIELD(newowner); return true; } @@ -1614,7 +1615,7 @@ static bool _equalCreateTableSpaceStmt(const CreateTableSpaceStmt *a, const CreateTableSpaceStmt *b) { COMPARE_STRING_FIELD(tablespacename); - COMPARE_STRING_FIELD(owner); + COMPARE_NODE_FIELD(owner); COMPARE_STRING_FIELD(location); COMPARE_NODE_FIELD(options); @@ -1731,7 +1732,7 @@ _equalAlterForeignServerStmt(const AlterForeignServerStmt *a, const AlterForeign static bool _equalCreateUserMappingStmt(const CreateUserMappingStmt *a, const CreateUserMappingStmt *b) { - COMPARE_STRING_FIELD(username); + COMPARE_NODE_FIELD(user); COMPARE_STRING_FIELD(servername); COMPARE_NODE_FIELD(options); @@ -1741,7 +1742,7 @@ _equalCreateUserMappingStmt(const CreateUserMappingStmt *a, const CreateUserMapp static bool _equalAlterUserMappingStmt(const AlterUserMappingStmt *a, const AlterUserMappingStmt *b) { - COMPARE_STRING_FIELD(username); + COMPARE_NODE_FIELD(user); COMPARE_STRING_FIELD(servername); COMPARE_NODE_FIELD(options); @@ -1751,7 +1752,7 @@ _equalAlterUserMappingStmt(const AlterUserMappingStmt *a, const AlterUserMapping static bool _equalDropUserMappingStmt(const DropUserMappingStmt *a, const DropUserMappingStmt *b) { - COMPARE_STRING_FIELD(username); + COMPARE_NODE_FIELD(user); COMPARE_STRING_FIELD(servername); COMPARE_SCALAR_FIELD(missing_ok); @@ -1849,7 +1850,7 @@ _equalCreateRoleStmt(const CreateRoleStmt *a, const CreateRoleStmt *b) static bool _equalAlterRoleStmt(const AlterRoleStmt *a, const AlterRoleStmt *b) { - COMPARE_STRING_FIELD(role); + COMPARE_NODE_FIELD(role); COMPARE_NODE_FIELD(options); COMPARE_SCALAR_FIELD(action); @@ -1859,7 +1860,7 @@ _equalAlterRoleStmt(const AlterRoleStmt *a, const AlterRoleStmt *b) static bool _equalAlterRoleSetStmt(const AlterRoleSetStmt *a, const AlterRoleSetStmt *b) { - COMPARE_STRING_FIELD(role); + COMPARE_NODE_FIELD(role); COMPARE_STRING_FIELD(database); COMPARE_NODE_FIELD(setstmt); @@ -1910,7 +1911,7 @@ static bool _equalCreateSchemaStmt(const CreateSchemaStmt *a, const CreateSchemaStmt *b) { COMPARE_STRING_FIELD(schemaname); - COMPARE_STRING_FIELD(authid); + COMPARE_NODE_FIELD(authrole); COMPARE_NODE_FIELD(schemaElts); COMPARE_SCALAR_FIELD(if_not_exists); @@ -1981,7 +1982,7 @@ static bool _equalReassignOwnedStmt(const ReassignOwnedStmt *a, const ReassignOwnedStmt *b) { COMPARE_NODE_FIELD(roles); - COMPARE_STRING_FIELD(newrole); + COMPARE_NODE_FIELD(newrole); return true; } @@ -2453,6 +2454,15 @@ _equalXmlSerialize(const XmlSerialize *a, const XmlSerialize *b) return true; } +static bool +_equalRoleSpec(const RoleSpec *a, const RoleSpec *b) +{ + COMPARE_SCALAR_FIELD(roltype); + COMPARE_STRING_FIELD(str); + + return true; +} + /* * Stuff from pg_list.h */ @@ -3163,6 +3173,9 @@ equal(const void *a, const void *b) case T_XmlSerialize: retval = _equalXmlSerialize(a, b); break; + case T_RoleSpec: + retval = _equalRoleSpec(a, b); + break; default: elog(ERROR, "unrecognized node type: %d", diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index bd180e7..4d9e374 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -192,6 +192,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); int ival; char *str; const char *keyword; + RoleSpec *rolespec; char chr; bool boolean; @@ -291,7 +292,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <str> opt_type %type <str> foreign_server_version opt_foreign_server_version -%type <str> auth_ident +%type <rolespec> auth_ident %type <str> opt_in_database %type <str> OptSchemaName @@ -474,7 +475,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <ival> Iconst SignedIconst %type <str> Sconst comment_text notify_payload -%type <str> RoleId opt_granted_by opt_boolean_or_string +%type <rolespec> RoleId opt_granted_by +%type <str> opt_boolean_or_string %type <list> var_list %type <str> ColId ColLabel var_name type_function_name param_name %type <str> NonReservedWord NonReservedWord_or_Sconst @@ -494,7 +496,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <list> constraints_set_list %type <boolean> constraints_set_mode -%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner +%type <str> OptTableSpace OptConsTableSpace +%type <rolespec> OptTableSpaceOwner %type <ival> opt_check_option %type <str> opt_provider security_label @@ -864,8 +867,14 @@ CreateRoleStmt: CREATE ROLE RoleId opt_with OptRoleList { CreateRoleStmt *n = makeNode(CreateRoleStmt); + RoleSpec *rolspc = $3; + if (rolspc->roltype != ROLESPEC_CSTRING) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("role name should not be a keyword nor reserved name."), + parser_errposition(@3))); n->stmt_type = ROLESTMT_ROLE; - n->role = $3; + n->role = rolspc->str; n->options = $5; $$ = (Node *)n; } @@ -1021,8 +1030,14 @@ CreateUserStmt: CREATE USER RoleId opt_with OptRoleList { CreateRoleStmt *n = makeNode(CreateRoleStmt); + RoleSpec *rolspc = $3; + if (rolspc->roltype != ROLESPEC_CSTRING) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("role name should not be a keyword nor reserved name."), + parser_errposition(@3))); n->stmt_type = ROLESTMT_USER; - n->role = $3; + n->role = rolspc->str; n->options = $5; $$ = (Node *)n; } @@ -1164,8 +1179,14 @@ CreateGroupStmt: CREATE GROUP_P RoleId opt_with OptRoleList { CreateRoleStmt *n = makeNode(CreateRoleStmt); + RoleSpec *rolspc = $3; + if (rolspc->roltype != ROLESPEC_CSTRING) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("role name should not be a keyword nor reserved name."), + parser_errposition(@3))); n->stmt_type = ROLESTMT_GROUP; - n->role = $3; + n->role = rolspc->str; n->options = $5; $$ = (Node *)n; } @@ -1231,11 +1252,8 @@ CreateSchemaStmt: { CreateSchemaStmt *n = makeNode(CreateSchemaStmt); /* One can omit the schema name or the authorization id. */ - if ($3 != NULL) - n->schemaname = $3; - else - n->schemaname = $5; - n->authid = $5; + n->schemaname = $3; + n->authrole = $5; n->schemaElts = $6; n->if_not_exists = false; $$ = (Node *)n; @@ -1245,7 +1263,7 @@ CreateSchemaStmt: CreateSchemaStmt *n = makeNode(CreateSchemaStmt); /* ...but not both */ n->schemaname = $3; - n->authid = NULL; + n->authrole = NULL; n->schemaElts = $4; n->if_not_exists = false; $$ = (Node *)n; @@ -1254,11 +1272,8 @@ CreateSchemaStmt: { CreateSchemaStmt *n = makeNode(CreateSchemaStmt); /* One can omit the schema name or the authorization id. */ - if ($6 != NULL) - n->schemaname = $6; - else - n->schemaname = $8; - n->authid = $8; + n->schemaname = $6; + n->authrole = $8; if ($9 != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -1273,7 +1288,7 @@ CreateSchemaStmt: CreateSchemaStmt *n = makeNode(CreateSchemaStmt); /* ...but not both */ n->schemaname = $6; - n->authid = NULL; + n->authrole = NULL; if ($7 != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -2263,7 +2278,7 @@ alter_table_cmd: { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ChangeOwner; - n->name = $3; + n->newowner = $3; $$ = (Node *)n; } /* ALTER TABLE <name> SET TABLESPACE <tablespacename> */ @@ -3727,7 +3742,7 @@ CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst } ; -OptTableSpaceOwner: OWNER name { $$ = $2; } +OptTableSpaceOwner: OWNER RoleId { $$ = $2; } | /*EMPTY */ { $$ = NULL; } ; @@ -4449,7 +4464,7 @@ import_qualification: CreateUserMappingStmt: CREATE USER MAPPING FOR auth_ident SERVER name create_generic_options { CreateUserMappingStmt *n = makeNode(CreateUserMappingStmt); - n->username = $5; + n->user = $5; n->servername = $7; n->options = $8; $$ = (Node *) n; @@ -4458,9 +4473,19 @@ CreateUserMappingStmt: CREATE USER MAPPING FOR auth_ident SERVER name create_gen /* User mapping authorization identifier */ auth_ident: - CURRENT_USER { $$ = "current_user"; } - | USER { $$ = "current_user"; } - | RoleId { $$ = (strcmp($1, "public") == 0) ? NULL : $1; } + RoleId + { $$ = $1; } + /* + * The keyword USER won't be appear in other syntxes so it is + * processed here, not at RoleId. + */ + | USER + { + RoleSpec *n = makeNode(RoleSpec); + n->roltype = ROLESPEC_CURRENT_USER; + n->str = pstrdup($1); + $$ = n; + } ; /***************************************************************************** @@ -4473,7 +4498,7 @@ auth_ident: DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name { DropUserMappingStmt *n = makeNode(DropUserMappingStmt); - n->username = $5; + n->user = $5; n->servername = $7; n->missing_ok = false; $$ = (Node *) n; @@ -4481,7 +4506,7 @@ DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name | DROP USER MAPPING IF_P EXISTS FOR auth_ident SERVER name { DropUserMappingStmt *n = makeNode(DropUserMappingStmt); - n->username = $7; + n->user = $7; n->servername = $9; n->missing_ok = true; $$ = (Node *) n; @@ -4498,7 +4523,7 @@ DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name AlterUserMappingStmt: ALTER USER MAPPING FOR auth_ident SERVER name alter_generic_options { AlterUserMappingStmt *n = makeNode(AlterUserMappingStmt); - n->username = $5; + n->user = $5; n->servername = $7; n->options = $8; $$ = (Node *) n; @@ -5403,7 +5428,7 @@ DropOwnedStmt: ; ReassignOwnedStmt: - REASSIGN OWNED BY role_list TO name + REASSIGN OWNED BY role_list TO RoleId { ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt); n->roles = $4; @@ -6221,21 +6246,27 @@ grantee_list: grantee: RoleId { PrivGrantee *n = makeNode(PrivGrantee); - /* This hack lets us avoid reserving PUBLIC as a keyword*/ - if (strcmp($1, "public") == 0) - n->rolname = NULL; - else - n->rolname = $1; + RoleSpec *rolspc = $1; + if (rolspc->roltype == ROLESPEC_NONE) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s cannot be used as grantee name", + rolspc->str))); + n->role = rolspc; $$ = (Node *)n; } | GROUP_P RoleId + /* Treat GROUP PUBLIC as a synonym for PUBLIC */ { PrivGrantee *n = makeNode(PrivGrantee); - /* Treat GROUP PUBLIC as a synonym for PUBLIC */ - if (strcmp($2, "public") == 0) - n->rolname = NULL; - else - n->rolname = $2; + RoleSpec *rolspc = $2; + + if (rolspc->roltype == ROLESPEC_NONE) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s cannot be used as grantee name", + rolspc->str))); + n->role = rolspc; $$ = (Node *)n; } ; @@ -7340,9 +7371,19 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name | ALTER GROUP_P RoleId RENAME TO RoleId { RenameStmt *n = makeNode(RenameStmt); + RoleSpec *nold = $3; + RoleSpec *nnew = $6; + if (nold->roltype != ROLESPEC_CSTRING || + nnew->roltype != ROLESPEC_CSTRING) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("role name should not be a keyword nor reserved name."), + parser_errposition( + nold->roltype != ROLESPEC_CSTRING ? + @3 : @6))); n->renameType = OBJECT_ROLE; - n->subname = $3; - n->newname = $6; + n->subname = nold->str; + n->newname = nnew->str; n->missing_ok = false; $$ = (Node *)n; } @@ -7640,18 +7681,38 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name | ALTER ROLE RoleId RENAME TO RoleId { RenameStmt *n = makeNode(RenameStmt); + RoleSpec *nold = $3; + RoleSpec *nnew = $6; + if (nold->roltype != ROLESPEC_CSTRING || + nnew->roltype != ROLESPEC_CSTRING) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("role name should not be a keyword nor reserved name."), + parser_errposition( + nold->roltype != ROLESPEC_CSTRING ? + @3 : @6))); n->renameType = OBJECT_ROLE; - n->subname = $3; - n->newname = $6; + n->subname = nold->str; + n->newname = nnew->str; n->missing_ok = false; $$ = (Node *)n; } | ALTER USER RoleId RENAME TO RoleId { RenameStmt *n = makeNode(RenameStmt); + RoleSpec *nold = $3; + RoleSpec *nnew = $6; + if (nold->roltype != ROLESPEC_CSTRING || + nnew->roltype != ROLESPEC_CSTRING) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("role name should not be a keyword nor reserved name."), + parser_errposition( + nold->roltype != ROLESPEC_CSTRING ? + @3 : @6))); n->renameType = OBJECT_ROLE; - n->subname = $3; - n->newname = $6; + n->subname = nold->str; + n->newname = nnew->str; n->missing_ok = false; $$ = (Node *)n; } @@ -10716,7 +10777,7 @@ opt_float: '(' Iconst ')' if ($2 < 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("precision for type float must be at least 1 bit"), + errmsg("recision for type float must be at least 1 bit"), parser_errposition(@2))); else if ($2 <= 24) $$ = SystemTypeName("float4"); @@ -12946,12 +13007,45 @@ AexprConst: Iconst Iconst: ICONST { $$ = $1; }; Sconst: SCONST { $$ = $1; }; -RoleId: NonReservedWord { $$ = $1; }; +RoleId: NonReservedWord + { + /* + * The name "public" and "none" are decided not to be + * keywords. They cannot be used as identifier by any + * means as the result. + */ + RoleSpec *n = makeNode(RoleSpec); + char *w = pstrdup($1); + if (strcmp(w, "public") == 0) + n->roltype = ROLESPEC_PUBLIC; + else if (strcmp(w, "none") == 0) + n->roltype = ROLESPEC_NONE; + else + n->roltype = ROLESPEC_CSTRING; + n->str = w; + $$ = n; + } + | CURRENT_USER + { + RoleSpec *n = makeNode(RoleSpec); + n->roltype = ROLESPEC_CURRENT_USER; + n->str = pstrdup($1); + $$ = n; + } + | SESSION_USER + { + RoleSpec *n = makeNode(RoleSpec); + n->roltype = ROLESPEC_SESSION_USER; + n->str = pstrdup($1); + $$ = n; + } + ; + role_list: RoleId - { $$ = list_make1(makeString($1)); } + { $$ = list_make1($1); } | role_list ',' RoleId - { $$ = lappend($1, makeString($3)); } + { $$ = lappend($1, $3); } ; SignedIconst: Iconst { $$ = $1; } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 7c1939f..1edc112 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -90,7 +90,7 @@ typedef struct { const char *stmtType; /* "CREATE SCHEMA" or "ALTER SCHEMA" */ char *schemaname; /* name of schema */ - char *authid; /* owner of schema */ + RoleSpec *authrole; /* owner of schema */ List *sequences; /* CREATE SEQUENCE items */ List *tables; /* CREATE TABLE items */ List *views; /* CREATE VIEW items */ @@ -2687,7 +2687,7 @@ transformCreateSchemaStmt(CreateSchemaStmt *stmt) cxt.stmtType = "CREATE SCHEMA"; cxt.schemaname = stmt->schemaname; - cxt.authid = stmt->authid; + cxt.authrole = stmt->authrole; cxt.sequences = NIL; cxt.tables = NIL; cxt.views = NIL; diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index dc6eb2c..4a1110e 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -5133,3 +5133,37 @@ get_role_oid_or_public(const char *rolname) return get_role_oid(rolname, false); } + +Oid +get_rolespec_oid(const RoleSpec *rolname, bool missing_ok) +{ + Oid oid; + + switch (rolname->roltype) + { + case ROLESPEC_CSTRING: + oid = get_role_oid(rolname->str, missing_ok); + break; + case ROLESPEC_CURRENT_USER: + oid = GetUserId(); + break; + case ROLESPEC_SESSION_USER: + oid = GetSessionUserId(); + break; + + /* special roles which should not exist */ + case ROLESPEC_PUBLIC: + case ROLESPEC_NONE: + if (!missing_ok) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("role \"%s\" does not exist", rolname->str))); + oid = InvalidOid; + break; + + default: + elog(ERROR, "Unexpected nameid for role: %d", rolname->roltype); + } + + return oid; +} diff --git a/src/include/commands/user.h b/src/include/commands/user.h index d766851..e83afab 100644 --- a/src/include/commands/user.h +++ b/src/include/commands/user.h @@ -30,6 +30,6 @@ extern void GrantRole(GrantRoleStmt *stmt); extern Oid RenameRole(const char *oldname, const char *newname); extern void DropOwnedObjects(DropOwnedStmt *stmt); extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt); -extern List *roleNamesToIds(List *memberNames); +extern List *roleSpecsToIds(List *memberNames); #endif /* USER_H */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index bc71fea..fdb217d 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -413,6 +413,7 @@ typedef enum NodeTag T_XmlSerialize, T_WithClause, T_CommonTableExpr, + T_RoleSpec, /* * TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h) diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 3e4f815..02d4c88 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -278,6 +278,29 @@ typedef struct CollateClause } CollateClause; /* + * RoleSpec - Stroes role name or id of some special values. + * + * "public" and "none" are the special role which cannot be used as role name + * from historical reasons. + */ +typedef enum RoleSpecTypes +{ + ROLESPEC_CSTRING, /* role name is stored in str */ + ROLESPEC_CURRENT_USER, /* role spec is CURRENT_USER */ + ROLESPEC_SESSION_USER, /* role spec is SESSION_USER */ + ROLESPEC_PUBLIC, /* role name is "public", a special value */ + ROLESPEC_NONE /* role name is "none", a special value and this + * is simply unusable at all. */ +} RoleSpecTypes; + +typedef struct RoleSpec +{ + NodeTag type; + RoleSpecTypes roltype; /* Type of this rolespec */ + char *str; /* Will be filled only for ROLESPEC_CSTRING */ +} RoleSpec; + +/* * FuncCall - a function or aggregate invocation * * agg_order (if not NIL) indicates we saw 'foo(... ORDER BY ...)', or if @@ -1254,7 +1277,7 @@ typedef struct CreateSchemaStmt { NodeTag type; char *schemaname; /* the name of the schema to create */ - char *authid; /* the owner of the created schema */ + RoleSpec *authrole; /* the owner of the created schema */ List *schemaElts; /* schema components (list of parsenodes) */ bool if_not_exists; /* just do nothing if schema already exists? */ } CreateSchemaStmt; @@ -1353,7 +1376,8 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ NodeTag type; AlterTableType subtype; /* Type of table alteration to apply */ char *name; /* column, constraint, or trigger to act on, - * or new owner or tablespace */ + * or tablespace */ + RoleSpec *newowner; /* new owner could be special values */ Node *def; /* definition of new column, index, * constraint, or parent table */ DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */ @@ -1433,7 +1457,7 @@ typedef struct GrantStmt typedef struct PrivGrantee { NodeTag type; - char *rolname; /* if NULL then PUBLIC */ + RoleSpec *role; /* if NULL then PUBLIC */ } PrivGrantee; /* @@ -1478,7 +1502,7 @@ typedef struct GrantRoleStmt List *grantee_roles; /* list of member roles to add/delete */ bool is_grant; /* true = GRANT, false = REVOKE */ bool admin_opt; /* with admin option */ - char *grantor; /* set grantor to other than current role */ + RoleSpec *grantor; /* set grantor to other than current role */ DropBehavior behavior; /* drop behavior (for REVOKE) */ } GrantRoleStmt; @@ -1690,7 +1714,7 @@ typedef struct CreateTableSpaceStmt { NodeTag type; char *tablespacename; - char *owner; + RoleSpec *owner; char *location; List *options; } CreateTableSpaceStmt; @@ -1816,7 +1840,7 @@ typedef struct CreateForeignTableStmt typedef struct CreateUserMappingStmt { NodeTag type; - char *username; /* username or PUBLIC/CURRENT_USER */ + RoleSpec *user; /* user role */ char *servername; /* server name */ List *options; /* generic options to server */ } CreateUserMappingStmt; @@ -1824,7 +1848,7 @@ typedef struct CreateUserMappingStmt typedef struct AlterUserMappingStmt { NodeTag type; - char *username; /* username or PUBLIC/CURRENT_USER */ + RoleSpec *user; /* user role */ char *servername; /* server name */ List *options; /* generic options to server */ } AlterUserMappingStmt; @@ -1832,7 +1856,7 @@ typedef struct AlterUserMappingStmt typedef struct DropUserMappingStmt { NodeTag type; - char *username; /* username or PUBLIC/CURRENT_USER */ + RoleSpec *user; /* user role */ char *servername; /* server name */ bool missing_ok; /* ignore missing mappings */ } DropUserMappingStmt; @@ -1982,7 +2006,7 @@ typedef struct CreateRoleStmt typedef struct AlterRoleStmt { NodeTag type; - char *role; /* role name */ + RoleSpec *role; /* role */ List *options; /* List of DefElem nodes */ int action; /* +1 = add members, -1 = drop members */ } AlterRoleStmt; @@ -1990,7 +2014,7 @@ typedef struct AlterRoleStmt typedef struct AlterRoleSetStmt { NodeTag type; - char *role; /* role name */ + RoleSpec *role; /* role */ char *database; /* database name, or NULL */ VariableSetStmt *setstmt; /* SET or RESET subcommand */ } AlterRoleSetStmt; @@ -2365,7 +2389,7 @@ typedef struct AlterOwnerStmt RangeVar *relation; /* in case it's a table */ List *object; /* in case it's some other object */ List *objarg; /* argument types, if applicable */ - char *newowner; /* the new owner */ + RoleSpec *newowner; /* the new owner */ } AlterOwnerStmt; @@ -2813,7 +2837,7 @@ typedef struct ReassignOwnedStmt { NodeTag type; List *roles; - char *newrole; + RoleSpec *newrole; } ReassignOwnedStmt; /* diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index a8e3164..2863183 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -229,7 +229,7 @@ extern bool is_admin_of_role(Oid member, Oid role); extern void check_is_member_of_role(Oid member, Oid role); extern Oid get_role_oid(const char *rolname, bool missing_ok); extern Oid get_role_oid_or_public(const char *rolname); - +extern Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok); extern void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions); -- 2.1.0.GIT
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers