Hello, thank you for the comment. > Looking at this a bit, I'm not sure completely replacing RoleId with a > node is the best idea; some of the users of that production in the > grammar are okay with accepting only normal strings as names, and don't > need all the CURRENT_USER etc stuff.
You're right. the productions don't need RoleSpec already uses char* for the role member in its *Stmt structs. I might have done a bit too much. Adding new nonterminal RoleId and using it makes a bit duplicate of check code for "public"/"none" and others but removes other redundant check for "!= CSTRING" from some production, CREATE ROLE/USER/GROUP, ALTER ROLE/USER/GROUP RENAME. RoleId in the patch still has rule components for CURRENT_USER, SESSION_USER, and CURRENT_ROLE. Without them, the parser prints an error ununderstandable to users. | =# alter role current_user rename to "PuBlic"; | ERROR: syntax error at or near "rename" | LINE 1: alter role current_user rename to "PuBlic"; | ^ With the components, the error message becomes like this. | =# alter role current_role rename to "PuBlic"; | ERROR: reserved word cannot be used | LINE 1: alter role current_role rename to "PuBlic"; | ^ > Maybe we need a new production, > say RoleSpec, and we modify the few productions that need the extra > flexibility? For instance we could have ALTER USER RoleSpec instead of > ALTER USER RoleId. But we would keep CREATE USER RoleId, because it > doesn't make any sense to accept CREATE USER CURRENT_USER. > I think that would lead to a less invasive patch also. > Am I making sense? I think I did what you expected. It was good as the code got simpler but the invasive-ness dosn't seem to be reduced.. What do you think about this? regards, -- Kyotaro Horiguchi NTT Open Source Software Center
>From d90b7e09968f32a5b543242469fb65e304df3318 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 v4 Added RoleId for the use in where CURRENT_USER-like sutff is not used. CREATE ROLE/USER/GROUP, ALTER ROLE/USER/GROUP RENAME are changed to use RoleId. --- 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 | 229 +++++++++++++++++++++++++------------ 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, 400 insertions(+), 205 deletions(-) diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 1e3888e..1c90626 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 78b54b4..1d8799b 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -679,7 +679,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 3b95552..2a8b2a0 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 a3aeabb..e2d8a9d 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 a44dbf4..6667313 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 66d5083..8b30a9a 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3481,7 +3481,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 */ @@ -9361,7 +9361,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 e098b9f..6f255a5 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 2210eed..aaf2c25 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 f1a24f5..7a13aa1 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2500,6 +2500,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) { @@ -2646,6 +2657,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); @@ -2690,7 +2702,7 @@ _copyPrivGrantee(const PrivGrantee *from) { PrivGrantee *newnode = makeNode(PrivGrantee); - COPY_STRING_FIELD(rolname); + COPY_NODE_FIELD(role); return newnode; } @@ -2726,7 +2738,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; @@ -3033,7 +3045,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; } @@ -3419,7 +3431,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); @@ -3556,7 +3568,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); @@ -3568,7 +3580,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); @@ -3580,7 +3592,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); @@ -3693,7 +3705,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); @@ -3705,7 +3717,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); @@ -3764,7 +3776,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); @@ -3849,7 +3861,7 @@ _copyReassignOwnedStmt(const ReassignOwnedStmt *from) ReassignOwnedStmt *newnode = makeNode(ReassignOwnedStmt); COPY_NODE_FIELD(roles); - COPY_STRING_FIELD(newrole); + COPY_NODE_FIELD(newrole); return newnode; } @@ -4735,6 +4747,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 6e8b308..ba6c7a9 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; } @@ -1615,7 +1616,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); @@ -1732,7 +1733,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); @@ -1742,7 +1743,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); @@ -1752,7 +1753,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); @@ -1850,7 +1851,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); @@ -1860,7 +1861,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); @@ -1909,7 +1910,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); @@ -1980,7 +1981,7 @@ static bool _equalReassignOwnedStmt(const ReassignOwnedStmt *a, const ReassignOwnedStmt *b) { COMPARE_NODE_FIELD(roles); - COMPARE_STRING_FIELD(newrole); + COMPARE_NODE_FIELD(newrole); return true; } @@ -2452,6 +2453,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 */ @@ -3162,6 +3172,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 36dac29..0e52669 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 @@ -473,8 +474,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <boolean> opt_varying opt_timezone opt_no_inherit %type <ival> Iconst SignedIconst -%type <str> Sconst comment_text notify_payload -%type <str> RoleId opt_granted_by opt_boolean_or_string +%type <str> Sconst comment_text notify_payload RoleId +%type <rolespec> RoleSpec 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 @@ -1036,7 +1039,7 @@ CreateUserStmt: *****************************************************************************/ AlterRoleStmt: - ALTER ROLE RoleId opt_with AlterOptRoleList + ALTER ROLE RoleSpec opt_with AlterOptRoleList { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; @@ -1052,7 +1055,7 @@ opt_in_database: ; AlterRoleSetStmt: - ALTER ROLE RoleId opt_in_database SetResetClause + ALTER ROLE RoleSpec opt_in_database SetResetClause { AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); n->role = $3; @@ -1078,7 +1081,7 @@ AlterRoleSetStmt: *****************************************************************************/ AlterUserStmt: - ALTER USER RoleId opt_with AlterOptRoleList + ALTER USER RoleSpec opt_with AlterOptRoleList { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; @@ -1090,7 +1093,7 @@ AlterUserStmt: AlterUserSetStmt: - ALTER USER RoleId SetResetClause + ALTER USER RoleSpec SetResetClause { AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); n->role = $3; @@ -1179,7 +1182,7 @@ CreateGroupStmt: *****************************************************************************/ AlterGroupStmt: - ALTER GROUP_P RoleId add_drop USER role_list + ALTER GROUP_P RoleSpec add_drop USER role_list { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; @@ -1227,15 +1230,12 @@ DropGroupStmt: *****************************************************************************/ CreateSchemaStmt: - CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList + CREATE SCHEMA OptSchemaName AUTHORIZATION RoleSpec OptSchemaEltList { 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,20 +1245,17 @@ 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; } - | CREATE SCHEMA IF_P NOT EXISTS OptSchemaName AUTHORIZATION RoleId OptSchemaEltList + | CREATE SCHEMA IF_P NOT EXISTS OptSchemaName AUTHORIZATION RoleSpec OptSchemaEltList { 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 +1270,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), @@ -2258,12 +2255,12 @@ alter_table_cmd: n->subtype = AT_DropOf; $$ = (Node *)n; } - /* ALTER TABLE <name> OWNER TO RoleId */ - | OWNER TO RoleId + /* ALTER TABLE <name> OWNER TO RoleSpec */ + | OWNER TO RoleSpec { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ChangeOwner; - n->name = $3; + n->newowner = $3; $$ = (Node *)n; } /* ALTER TABLE <name> SET TABLESPACE <tablespacename> */ @@ -3755,7 +3752,7 @@ CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst } ; -OptTableSpaceOwner: OWNER name { $$ = $2; } +OptTableSpaceOwner: OWNER RoleSpec { $$ = $2; } | /*EMPTY */ { $$ = NULL; } ; @@ -4477,7 +4474,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; @@ -4486,9 +4483,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; } + RoleSpec + { $$ = $1; } + /* + * The keyword USER won't be appear in other syntxes so it is + * processed here, not at RoleSpec. + */ + | USER + { + RoleSpec *n = makeNode(RoleSpec); + n->roltype = ROLESPEC_CURRENT_USER; + n->str = pstrdup($1); + $$ = n; + } ; /***************************************************************************** @@ -4501,7 +4508,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; @@ -4509,7 +4516,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; @@ -4526,7 +4533,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; @@ -5431,7 +5438,7 @@ DropOwnedStmt: ; ReassignOwnedStmt: - REASSIGN OWNED BY role_list TO name + REASSIGN OWNED BY role_list TO RoleSpec { ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt); n->roles = $4; @@ -6347,24 +6354,30 @@ grantee_list: | grantee_list ',' grantee { $$ = lappend($1, $3); } ; -grantee: RoleId +grantee: RoleSpec { 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 + | GROUP_P RoleSpec + /* 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; } ; @@ -6437,7 +6450,7 @@ opt_grant_admin_option: WITH ADMIN OPTION { $$ = TRUE; } | /*EMPTY*/ { $$ = FALSE; } ; -opt_granted_by: GRANTED BY RoleId { $$ = $3; } +opt_granted_by: GRANTED BY RoleSpec { $$ = $3; } | /*EMPTY*/ { $$ = NULL; } ; @@ -8101,7 +8114,7 @@ AlterObjectSchemaStmt: * *****************************************************************************/ -AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId +AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_AGGREGATE; @@ -8110,7 +8123,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $7; $$ = (Node *)n; } - | ALTER COLLATION any_name OWNER TO RoleId + | ALTER COLLATION any_name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_COLLATION; @@ -8118,7 +8131,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER CONVERSION_P any_name OWNER TO RoleId + | ALTER CONVERSION_P any_name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_CONVERSION; @@ -8126,7 +8139,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER DATABASE database_name OWNER TO RoleId + | ALTER DATABASE database_name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_DATABASE; @@ -8134,7 +8147,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER DOMAIN_P any_name OWNER TO RoleId + | ALTER DOMAIN_P any_name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_DOMAIN; @@ -8142,7 +8155,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER FUNCTION function_with_argtypes OWNER TO RoleId + | ALTER FUNCTION function_with_argtypes OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_FUNCTION; @@ -8151,7 +8164,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER opt_procedural LANGUAGE name OWNER TO RoleId + | ALTER opt_procedural LANGUAGE name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_LANGUAGE; @@ -8159,7 +8172,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $7; $$ = (Node *)n; } - | ALTER LARGE_P OBJECT_P NumericOnly OWNER TO RoleId + | ALTER LARGE_P OBJECT_P NumericOnly OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_LARGEOBJECT; @@ -8167,7 +8180,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $7; $$ = (Node *)n; } - | ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleId + | ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_OPERATOR; @@ -8176,7 +8189,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $7; $$ = (Node *)n; } - | ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleId + | ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_OPCLASS; @@ -8185,7 +8198,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $9; $$ = (Node *)n; } - | ALTER OPERATOR FAMILY any_name USING access_method OWNER TO RoleId + | ALTER OPERATOR FAMILY any_name USING access_method OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_OPFAMILY; @@ -8194,7 +8207,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $9; $$ = (Node *)n; } - | ALTER SCHEMA name OWNER TO RoleId + | ALTER SCHEMA name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_SCHEMA; @@ -8202,7 +8215,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER TYPE_P any_name OWNER TO RoleId + | ALTER TYPE_P any_name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_TYPE; @@ -8210,7 +8223,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER TABLESPACE name OWNER TO RoleId + | ALTER TABLESPACE name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_TABLESPACE; @@ -8218,7 +8231,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO RoleId + | ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_TSDICTIONARY; @@ -8226,7 +8239,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $8; $$ = (Node *)n; } - | ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO RoleId + | ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_TSCONFIGURATION; @@ -8234,7 +8247,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $8; $$ = (Node *)n; } - | ALTER FOREIGN DATA_P WRAPPER name OWNER TO RoleId + | ALTER FOREIGN DATA_P WRAPPER name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_FDW; @@ -8242,7 +8255,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $8; $$ = (Node *)n; } - | ALTER SERVER name OWNER TO RoleId + | ALTER SERVER name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_FOREIGN_SERVER; @@ -8250,7 +8263,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $6; $$ = (Node *)n; } - | ALTER EVENT TRIGGER name OWNER TO RoleId + | ALTER EVENT TRIGGER name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_EVENT_TRIGGER; @@ -13080,12 +13093,84 @@ AexprConst: Iconst Iconst: ICONST { $$ = $1; }; Sconst: SCONST { $$ = $1; }; -RoleId: NonReservedWord { $$ = $1; }; +RoleId: NonReservedWord + { + if (strcmp($1, "public") == 0 || + strcmp($1, "none") == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("reserved word cannot be used"), + parser_errposition(@1))); + $$ = $1; + } + | CURRENT_USER + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("reserved word cannot be used"), + parser_errposition(@1))); + } + | SESSION_USER + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("reserved word cannot be used"), + parser_errposition(@1))); + } + | CURRENT_ROLE + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("reserved word cannot be used"), + parser_errposition(@1))); + } + ; +RoleSpec: 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; + } + | CURRENT_ROLE + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("reserved word cannot be used"), + parser_errposition(@1))); + } + ; -role_list: RoleId - { $$ = list_make1(makeString($1)); } - | role_list ',' RoleId - { $$ = lappend($1, makeString($3)); } + +role_list: RoleSpec + { $$ = list_make1($1); } + | role_list ',' RoleSpec + { $$ = lappend($1, $3); } ; SignedIconst: Iconst { $$ = $1; } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 3ccdbb7..6021e43 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 */ @@ -2712,7 +2712,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 411d779..4f4716b 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 97ef0fc..38469ef 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 b1dfa85..8def76c 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 @@ -1256,7 +1279,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; @@ -1355,7 +1378,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 */ @@ -1435,7 +1459,7 @@ typedef struct GrantStmt typedef struct PrivGrantee { NodeTag type; - char *rolname; /* if NULL then PUBLIC */ + RoleSpec *role; /* if NULL then PUBLIC */ } PrivGrantee; /* @@ -1480,7 +1504,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; @@ -1692,7 +1716,7 @@ typedef struct CreateTableSpaceStmt { NodeTag type; char *tablespacename; - char *owner; + RoleSpec *owner; char *location; List *options; } CreateTableSpaceStmt; @@ -1818,7 +1842,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; @@ -1826,7 +1850,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; @@ -1834,7 +1858,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; @@ -1984,7 +2008,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; @@ -1992,7 +2016,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; @@ -2367,7 +2391,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; @@ -2823,7 +2847,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 ab0df6c..1ef5e41 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