1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-11 10:01:57 +03:00

Allow CURRENT/SESSION_USER to be used in certain commands

Commands such as ALTER USER, ALTER GROUP, ALTER ROLE, GRANT, and the
various ALTER OBJECT / OWNER TO, as well as ad-hoc clauses related to
roles such as the AUTHORIZATION clause of CREATE SCHEMA, the FOR clause
of CREATE USER MAPPING, and the FOR ROLE clause of ALTER DEFAULT
PRIVILEGES can now take the keywords CURRENT_USER and SESSION_USER as
user specifiers in place of an explicit user name.

This commit also fixes some quite ugly handling of special standards-
mandated syntax in CREATE USER MAPPING, which in particular would fail
to work in presence of a role named "current_user".

The special role specifiers PUBLIC and NONE also have more consistent
handling now.

Also take the opportunity to add location tracking to user specifiers.

Authors: Kyotaro Horiguchi.  Heavily reworked by Álvaro Herrera.
Reviewed by: Rushabh Lathia, Adam Brightwell, Marti Raudsepp.
This commit is contained in:
Alvaro Herrera
2015-03-09 15:41:54 -03:00
parent fa83f80945
commit 31eae6028e
52 changed files with 2000 additions and 347 deletions

View File

@ -421,22 +421,25 @@ ExecuteGrantStmt(GrantStmt *stmt)
istmt.behavior = stmt->behavior;
/*
* Convert the PrivGrantee list into an Oid list. Note that at this point
* we insert an ACL_ID_PUBLIC into the list if an empty role name is
* detected (which is what the grammar uses if PUBLIC is found), so
* downstream there shouldn't be any additional work needed to support
* this case.
* Convert the RoleSpec list into an Oid list. Note that at this point
* we insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
* there shouldn't be any additional work needed to support this case.
*/
foreach(cell, stmt->grantees)
{
PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
RoleSpec *grantee = (RoleSpec *) lfirst(cell);
Oid grantee_uid;
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));
switch (grantee->roletype)
{
case ROLESPEC_PUBLIC:
grantee_uid = ACL_ID_PUBLIC;
break;
default:
grantee_uid = get_rolespec_oid((Node *) grantee, false);
break;
}
istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
}
/*
@ -904,22 +907,25 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
iacls.behavior = action->behavior;
/*
* Convert the PrivGrantee list into an Oid list. Note that at this point
* we insert an ACL_ID_PUBLIC into the list if an empty role name is
* detected (which is what the grammar uses if PUBLIC is found), so
* downstream there shouldn't be any additional work needed to support
* this case.
* Convert the RoleSpec list into an Oid list. Note that at this point
* we insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
* there shouldn't be any additional work needed to support this case.
*/
foreach(cell, action->grantees)
{
PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
RoleSpec *grantee = (RoleSpec *) lfirst(cell);
Oid grantee_uid;
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));
switch (grantee->roletype)
{
case ROLESPEC_PUBLIC:
grantee_uid = ACL_ID_PUBLIC;
break;
default:
grantee_uid = get_rolespec_oid((Node *) grantee, false);
break;
}
iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
}
/*

View File

@ -699,7 +699,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
ObjectAddress
ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
{
Oid newowner = get_role_oid(stmt->newowner, false);
Oid newowner = get_rolespec_oid(stmt->newowner, false);
switch (stmt->objectType)
{

View File

@ -1371,7 +1371,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);

View File

@ -197,24 +197,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.
*
@ -1156,10 +1138,14 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
ObjectAddress referenced;
ForeignServer *srv;
ForeignDataWrapper *fdw;
RoleSpec *role = (RoleSpec *) stmt->user;
rel = heap_open(UserMappingRelationId, RowExclusiveLock);
useId = GetUserOidFromMapping(stmt->username, false);
if (role->roletype == ROLESPEC_PUBLIC)
useId = ACL_ID_PUBLIC;
else
useId = get_rolespec_oid(stmt->user, false);
/* Check that the server exists. */
srv = GetForeignServerByName(stmt->servername, false);
@ -1252,10 +1238,15 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
Oid umId;
ForeignServer *srv;
ObjectAddress address;
RoleSpec *role = (RoleSpec *) stmt->user;
rel = heap_open(UserMappingRelationId, RowExclusiveLock);
useId = GetUserOidFromMapping(stmt->username, false);
if (role->roletype == ROLESPEC_PUBLIC)
useId = ACL_ID_PUBLIC;
else
useId = get_rolespec_oid(stmt->user, false);
srv = GetForeignServerByName(stmt->servername, false);
umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
@ -1338,20 +1329,27 @@ RemoveUserMapping(DropUserMappingStmt *stmt)
Oid useId;
Oid umId;
ForeignServer *srv;
RoleSpec *role = (RoleSpec *) stmt->user;
useId = GetUserOidFromMapping(stmt->username, stmt->missing_ok);
srv = GetForeignServerByName(stmt->servername, true);
if (stmt->username && !OidIsValid(useId))
if (role->roletype == ROLESPEC_PUBLIC)
useId = ACL_ID_PUBLIC;
else
{
/*
* 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",
role->rolename);
return InvalidOid;
}
}
srv = GetForeignServerByName(stmt->servername, true);
if (!srv)
{
if (!stmt->missing_ok)

View File

@ -129,13 +129,7 @@ parse_policy_command(const char *cmd_name)
/*
* policy_role_list_to_array
* helper function to convert a list of role names in to an array of
* role ids.
*
* Note: If PUBLIC is provided as a role name, then ACL_ID_PUBLIC is
* used as the role id.
*
* roles - the list of role names to convert.
* helper function to convert a list of RoleSpecs to an array of role ids.
*/
static ArrayType *
policy_role_list_to_array(List *roles)
@ -162,25 +156,25 @@ policy_role_list_to_array(List *roles)
foreach(cell, roles)
{
Oid roleid = get_role_oid_or_public(strVal(lfirst(cell)));
RoleSpec *spec = lfirst(cell);
/*
* PUBLIC covers all roles, so it only makes sense alone.
*/
if (roleid == ACL_ID_PUBLIC)
if (spec->roletype == ROLESPEC_PUBLIC)
{
if (num_roles != 1)
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("ignoring roles specified other than public"),
errhint("All roles are members of the public role.")));
temp_array[0] = ObjectIdGetDatum(roleid);
temp_array[0] = ObjectIdGetDatum(ACL_ID_PUBLIC);
num_roles = 1;
break;
}
else
temp_array[i++] = ObjectIdGetDatum(roleid);
temp_array[i++] =
ObjectIdGetDatum(get_rolespec_oid((Node *) spec, false));
}
role_ids = construct_array(temp_array, num_roles, OIDOID, sizeof(Oid), true,

View File

@ -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,7 @@ 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;
Oid namespaceId;
OverrideSearchPath *overridePath;
List *parsetree_list;
@ -58,11 +58,24 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
/*
* Who is supposed to own the new schema?
*/
if (authId)
owner_uid = get_role_oid(authId, false);
if (stmt->authrole)
owner_uid = get_rolespec_oid(stmt->authrole, false);
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))
elog(ERROR, "cache lookup failed for role %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

View File

@ -3507,7 +3507,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 */
@ -9388,7 +9388,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 &&

View File

@ -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();

View File

@ -49,10 +49,10 @@ extern bool Password_encryption;
check_password_hook_type check_password_hook = NULL;
static void AddRoleMems(const char *rolename, Oid roleid,
List *memberNames, List *memberIds,
List *memberSpecs, List *memberIds,
Oid grantorId, bool admin_opt);
static void DelRoleMems(const char *rolename, Oid roleid,
List *memberNames, List *memberIds,
List *memberSpecs, List *memberIds,
bool admin_opt);
@ -443,10 +443,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 */
@ -478,7 +478,9 @@ AlterRole(AlterRoleStmt *stmt)
TupleDesc pg_authid_dsc;
HeapTuple tuple,
new_tuple;
Form_pg_authid authform;
ListCell *option;
char *rolename = NULL;
char *password = NULL; /* user password */
bool encrypt_password = Password_encryption; /* encrypt password? */
char encrypted_password[MD5_PASSWD_LEN + 1];
@ -647,33 +649,30 @@ 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))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", stmt->role)));
tuple = get_rolespec_tuple(stmt->role);
authform = (Form_pg_authid) GETSTRUCT(tuple);
rolename = pstrdup(NameStr(authform->rolname));
roleid = HeapTupleGetOid(tuple);
/*
* To mess with a superuser you gotta be superuser; else you need
* createrole, or just want to change your own password
*/
if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper || issuper >= 0)
if (authform->rolsuper || issuper >= 0)
{
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter superusers")));
}
else if (((Form_pg_authid) GETSTRUCT(tuple))->rolreplication || isreplication >= 0)
else if (authform->rolreplication || isreplication >= 0)
{
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter replication users")));
}
else if (((Form_pg_authid) GETSTRUCT(tuple))->rolbypassrls || bypassrls >= 0)
else if (authform->rolbypassrls || bypassrls >= 0)
{
if (!superuser())
ereport(ERROR,
@ -718,11 +717,11 @@ 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
@ -784,7 +783,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] =
@ -831,12 +830,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);
/*
@ -860,13 +859,7 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
if (stmt->role)
{
roletuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));
if (!HeapTupleIsValid(roletuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", stmt->role)));
roletuple = get_rolespec_tuple(stmt->role);
roleid = HeapTupleGetOid(roletuple);
/*
@ -955,7 +948,8 @@ DropRole(DropRoleStmt *stmt)
foreach(item, stmt->roles)
{
const char *role = strVal(lfirst(item));
RoleSpec *rolspec = lfirst(item);
char *role;
HeapTuple tuple,
tmp_tuple;
ScanKeyData scankey;
@ -964,6 +958,12 @@ DropRole(DropRoleStmt *stmt)
SysScanDesc sscan;
Oid roleid;
if (rolspec->roletype != ROLESPEC_CSTRING)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot use special role specifier in \"%s\"", "DROP ROLE")));
role = rolspec->rolename;
tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
if (!HeapTupleIsValid(tuple))
{
@ -1233,11 +1233,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);
@ -1286,7 +1286,7 @@ GrantRole(GrantRoleStmt *stmt)
void
DropOwnedObjects(DropOwnedStmt *stmt)
{
List *role_ids = roleNamesToIds(stmt->roles);
List *role_ids = roleSpecsToIds(stmt->roles);
ListCell *cell;
/* Check privileges */
@ -1312,7 +1312,7 @@ DropOwnedObjects(DropOwnedStmt *stmt)
void
ReassignOwnedObjects(ReassignOwnedStmt *stmt)
{
List *role_ids = roleNamesToIds(stmt->roles);
List *role_ids = roleSpecsToIds(stmt->roles);
ListCell *cell;
Oid newrole;
@ -1328,7 +1328,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,
@ -1340,22 +1340,24 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
}
/*
* roleNamesToIds
* roleSpecsToIds
*
* Given a list of role names (as String nodes), generate a list of role OIDs
* in the same order.
* Given a list of RoleSpecs, generate a list of role OIDs in the same order.
*
* ROLESPEC_PUBLIC is not allowed.
*/
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);
Node *rolespec = (Node *) lfirst(l);
Oid roleid;
roleid = get_rolespec_oid(rolespec, false);
result = lappend_oid(result, roleid);
}
return result;
@ -1366,7 +1368,7 @@ roleNamesToIds(List *memberNames)
*
* rolename: name of role to add to (used only for error messages)
* roleid: OID of role to add to
* memberNames: list of names of roles to add (used only for error messages)
* memberSpecs: list of RoleSpec of roles to add (used only for error messages)
* memberIds: OIDs of roles to add
* grantorId: who is granting the membership
* admin_opt: granting admin option?
@ -1375,15 +1377,15 @@ roleNamesToIds(List *memberNames)
*/
static void
AddRoleMems(const char *rolename, Oid roleid,
List *memberNames, List *memberIds,
List *memberSpecs, List *memberIds,
Oid grantorId, bool admin_opt)
{
Relation pg_authmem_rel;
TupleDesc pg_authmem_dsc;
ListCell *nameitem;
ListCell *specitem;
ListCell *iditem;
Assert(list_length(memberNames) == list_length(memberIds));
Assert(list_length(memberSpecs) == list_length(memberIds));
/* Skip permission check if nothing to do */
if (!memberIds)
@ -1428,9 +1430,9 @@ AddRoleMems(const char *rolename, Oid roleid,
pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
forboth(nameitem, memberNames, iditem, memberIds)
forboth(specitem, memberSpecs, iditem, memberIds)
{
const char *membername = strVal(lfirst(nameitem));
RoleSpec *memberRole = lfirst(specitem);
Oid memberid = lfirst_oid(iditem);
HeapTuple authmem_tuple;
HeapTuple tuple;
@ -1449,7 +1451,7 @@ AddRoleMems(const char *rolename, Oid roleid,
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
(errmsg("role \"%s\" is a member of role \"%s\"",
rolename, membername))));
rolename, get_rolespec_name((Node *) memberRole)))));
/*
* Check if entry for this role/member already exists; if so, give
@ -1464,7 +1466,7 @@ AddRoleMems(const char *rolename, Oid roleid,
{
ereport(NOTICE,
(errmsg("role \"%s\" is already a member of role \"%s\"",
membername, rolename)));
get_rolespec_name((Node *) memberRole), rolename)));
ReleaseSysCache(authmem_tuple);
continue;
}
@ -1513,7 +1515,7 @@ AddRoleMems(const char *rolename, Oid roleid,
*
* rolename: name of role to del from (used only for error messages)
* roleid: OID of role to del from
* memberNames: list of names of roles to del (used only for error messages)
* memberSpecs: list of RoleSpec of roles to del (used only for error messages)
* memberIds: OIDs of roles to del
* admin_opt: remove admin option only?
*
@ -1521,15 +1523,15 @@ AddRoleMems(const char *rolename, Oid roleid,
*/
static void
DelRoleMems(const char *rolename, Oid roleid,
List *memberNames, List *memberIds,
List *memberSpecs, List *memberIds,
bool admin_opt)
{
Relation pg_authmem_rel;
TupleDesc pg_authmem_dsc;
ListCell *nameitem;
ListCell *specitem;
ListCell *iditem;
Assert(list_length(memberNames) == list_length(memberIds));
Assert(list_length(memberSpecs) == list_length(memberIds));
/* Skip permission check if nothing to do */
if (!memberIds)
@ -1559,9 +1561,9 @@ DelRoleMems(const char *rolename, Oid roleid,
pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
forboth(nameitem, memberNames, iditem, memberIds)
forboth(specitem, memberSpecs, iditem, memberIds)
{
const char *membername = strVal(lfirst(nameitem));
RoleSpec *memberRole = lfirst(specitem);
Oid memberid = lfirst_oid(iditem);
HeapTuple authmem_tuple;
@ -1575,7 +1577,7 @@ DelRoleMems(const char *rolename, Oid roleid,
{
ereport(WARNING,
(errmsg("role \"%s\" is not a member of role \"%s\"",
membername, rolename)));
get_rolespec_name((Node *) memberRole), rolename)));
continue;
}

View File

@ -2504,6 +2504,18 @@ _copyXmlSerialize(const XmlSerialize *from)
return newnode;
}
static RoleSpec *
_copyRoleSpec(const RoleSpec *from)
{
RoleSpec *newnode = makeNode(RoleSpec);
COPY_SCALAR_FIELD(roletype);
COPY_STRING_FIELD(rolename);
COPY_LOCATION_FIELD(location);
return newnode;
}
static Query *
_copyQuery(const Query *from)
{
@ -2650,6 +2662,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);
@ -2689,16 +2702,6 @@ _copyGrantStmt(const GrantStmt *from)
return newnode;
}
static PrivGrantee *
_copyPrivGrantee(const PrivGrantee *from)
{
PrivGrantee *newnode = makeNode(PrivGrantee);
COPY_STRING_FIELD(rolname);
return newnode;
}
static FuncWithArgs *
_copyFuncWithArgs(const FuncWithArgs *from)
{
@ -2730,7 +2733,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;
@ -3038,7 +3041,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;
}
@ -3424,7 +3427,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);
@ -3561,7 +3564,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);
@ -3573,7 +3576,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);
@ -3585,7 +3588,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);
@ -3698,7 +3701,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);
@ -3710,7 +3713,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);
@ -3769,7 +3772,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);
@ -3854,7 +3857,7 @@ _copyReassignOwnedStmt(const ReassignOwnedStmt *from)
ReassignOwnedStmt *newnode = makeNode(ReassignOwnedStmt);
COPY_NODE_FIELD(roles);
COPY_STRING_FIELD(newrole);
COPY_NODE_FIELD(newrole);
return newnode;
}
@ -4728,9 +4731,6 @@ copyObject(const void *from)
case T_CommonTableExpr:
retval = _copyCommonTableExpr(from);
break;
case T_PrivGrantee:
retval = _copyPrivGrantee(from);
break;
case T_FuncWithArgs:
retval = _copyFuncWithArgs(from);
break;
@ -4740,6 +4740,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));

View File

@ -973,6 +973,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);
@ -1008,14 +1009,6 @@ _equalGrantStmt(const GrantStmt *a, const GrantStmt *b)
return true;
}
static bool
_equalPrivGrantee(const PrivGrantee *a, const PrivGrantee *b)
{
COMPARE_STRING_FIELD(rolname);
return true;
}
static bool
_equalFuncWithArgs(const FuncWithArgs *a, const FuncWithArgs *b)
{
@ -1041,7 +1034,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;
@ -1295,7 +1288,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;
}
@ -1618,7 +1611,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);
@ -1735,7 +1728,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);
@ -1745,7 +1738,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);
@ -1755,7 +1748,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);
@ -1853,7 +1846,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);
@ -1863,7 +1856,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);
@ -1912,7 +1905,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);
@ -1983,7 +1976,7 @@ static bool
_equalReassignOwnedStmt(const ReassignOwnedStmt *a, const ReassignOwnedStmt *b)
{
COMPARE_NODE_FIELD(roles);
COMPARE_STRING_FIELD(newrole);
COMPARE_NODE_FIELD(newrole);
return true;
}
@ -2455,6 +2448,16 @@ _equalXmlSerialize(const XmlSerialize *a, const XmlSerialize *b)
return true;
}
static bool
_equalRoleSpec(const RoleSpec *a, const RoleSpec *b)
{
COMPARE_SCALAR_FIELD(roletype);
COMPARE_STRING_FIELD(rolename);
COMPARE_LOCATION_FIELD(location);
return true;
}
/*
* Stuff from pg_list.h
*/
@ -3153,9 +3156,6 @@ equal(const void *a, const void *b)
case T_CommonTableExpr:
retval = _equalCommonTableExpr(a, b);
break;
case T_PrivGrantee:
retval = _equalPrivGrantee(a, b);
break;
case T_FuncWithArgs:
retval = _equalFuncWithArgs(a, b);
break;
@ -3165,6 +3165,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",

View File

@ -143,6 +143,7 @@ static Node *makeBitStringConst(char *str, int location);
static Node *makeNullAConst(int location);
static Node *makeAConst(Value *v, int location);
static Node *makeBoolAConst(bool state, int location);
static Node *makeRoleSpec(RoleSpecType type, int location);
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
static List *check_func_name(List *names, core_yyscan_t yyscanner);
static List *check_indirection(List *indirection, core_yyscan_t yyscanner);
@ -291,7 +292,6 @@ 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 <str> opt_in_database
%type <str> OptSchemaName
@ -474,12 +474,13 @@ 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 <str> RoleId 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
%type <str> createdb_opt_name
%type <node> var_value zone_value
%type <node> auth_ident RoleSpec opt_granted_by
%type <keyword> unreserved_keyword type_func_name_keyword
%type <keyword> col_name_keyword reserved_keyword
@ -494,7 +495,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 <node> OptTableSpaceOwner
%type <ival> opt_check_option
%type <str> opt_provider security_label
@ -1037,7 +1039,7 @@ CreateUserStmt:
*****************************************************************************/
AlterRoleStmt:
ALTER ROLE RoleId opt_with AlterOptRoleList
ALTER ROLE RoleSpec opt_with AlterOptRoleList
{
AlterRoleStmt *n = makeNode(AlterRoleStmt);
n->role = $3;
@ -1053,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;
@ -1079,7 +1081,7 @@ AlterRoleSetStmt:
*****************************************************************************/
AlterUserStmt:
ALTER USER RoleId opt_with AlterOptRoleList
ALTER USER RoleSpec opt_with AlterOptRoleList
{
AlterRoleStmt *n = makeNode(AlterRoleStmt);
n->role = $3;
@ -1091,7 +1093,7 @@ AlterUserStmt:
AlterUserSetStmt:
ALTER USER RoleId SetResetClause
ALTER USER RoleSpec SetResetClause
{
AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
n->role = $3;
@ -1180,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;
@ -1228,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;
@ -1246,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;
/* schema name can be omitted here, too */
n->schemaname = $6;
n->authrole = $8;
if ($9 != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@ -1272,9 +1268,9 @@ CreateSchemaStmt:
| CREATE SCHEMA IF_P NOT EXISTS ColId OptSchemaEltList
{
CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
/* ...but not both */
/* ...but not here */
n->schemaname = $6;
n->authid = NULL;
n->authrole = NULL;
if ($7 != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@ -2259,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> */
@ -3756,7 +3752,7 @@ CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst
}
;
OptTableSpaceOwner: OWNER name { $$ = $2; }
OptTableSpaceOwner: OWNER RoleSpec { $$ = $2; }
| /*EMPTY */ { $$ = NULL; }
;
@ -4478,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,10 +4482,8 @@ 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; }
auth_ident: RoleSpec { $$ = $1; }
| USER { $$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1); }
;
/*****************************************************************************
@ -4502,7 +4496,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;
@ -4510,7 +4504,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;
@ -4527,7 +4521,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;
@ -4612,7 +4606,7 @@ RowSecurityOptionalWithCheck:
RowSecurityDefaultToRole:
TO role_list { $$ = $2; }
| /* EMPTY */ { $$ = list_make1(makeString("public")); }
| /* EMPTY */ { $$ = list_make1(makeRoleSpec(ROLESPEC_PUBLIC, -1)); }
;
RowSecurityOptionalToRole:
@ -5432,7 +5426,7 @@ DropOwnedStmt:
;
ReassignOwnedStmt:
REASSIGN OWNED BY role_list TO name
REASSIGN OWNED BY role_list TO RoleSpec
{
ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt);
n->roles = $4;
@ -6348,26 +6342,9 @@ grantee_list:
| grantee_list ',' grantee { $$ = lappend($1, $3); }
;
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;
$$ = (Node *)n;
}
| GROUP_P RoleId
{
PrivGrantee *n = makeNode(PrivGrantee);
/* Treat GROUP PUBLIC as a synonym for PUBLIC */
if (strcmp($2, "public") == 0)
n->rolname = NULL;
else
n->rolname = $2;
$$ = (Node *)n;
}
grantee:
RoleSpec { $$ = $1; }
| GROUP_P RoleSpec { $$ = $2; }
;
@ -6438,7 +6415,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; }
;
@ -8104,7 +8081,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;
@ -8113,7 +8090,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;
@ -8121,7 +8098,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;
@ -8129,7 +8106,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;
@ -8137,7 +8114,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;
@ -8145,7 +8122,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;
@ -8154,7 +8131,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;
@ -8162,7 +8139,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;
@ -8170,7 +8147,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;
@ -8179,7 +8156,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;
@ -8188,7 +8165,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;
@ -8197,7 +8174,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;
@ -8205,7 +8182,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;
@ -8213,7 +8190,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;
@ -8221,7 +8198,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;
@ -8229,7 +8206,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;
@ -8237,7 +8214,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;
@ -8245,7 +8222,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;
@ -8253,7 +8230,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;
@ -13113,19 +13090,86 @@ AexprConst: Iconst
Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; };
RoleId: NonReservedWord { $$ = $1; };
role_list: RoleId
{ $$ = list_make1(makeString($1)); }
| role_list ',' RoleId
{ $$ = lappend($1, makeString($3)); }
;
SignedIconst: Iconst { $$ = $1; }
| '+' Iconst { $$ = + $2; }
| '-' Iconst { $$ = - $2; }
;
/* Role specifications */
RoleId: RoleSpec
{
RoleSpec *spc = (RoleSpec *) $1;
switch (spc->roletype)
{
case ROLESPEC_CSTRING:
$$ = spc->rolename;
break;
case ROLESPEC_PUBLIC:
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("role name \"%s\" is reserved",
"public"),
parser_errposition(@1)));
case ROLESPEC_SESSION_USER:
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("%s cannot be used as a role name",
"SESSION_USER"),
parser_errposition(@1)));
case ROLESPEC_CURRENT_USER:
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("%s cannot be used as a role name",
"CURRENT_USER"),
parser_errposition(@1)));
}
}
;
RoleSpec: NonReservedWord
{
/*
* "public" and "none" are not keywords, but they must
* be treated specially here.
*/
RoleSpec *n;
if (strcmp($1, "public") == 0)
{
n = (RoleSpec *) makeRoleSpec(ROLESPEC_PUBLIC, @1);
n->roletype = ROLESPEC_PUBLIC;
}
else if (strcmp($1, "none") == 0)
{
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("role name \"%s\" is reserved",
"none"),
parser_errposition(@1)));
}
else
{
n = (RoleSpec *) makeRoleSpec(ROLESPEC_CSTRING, @1);
n->rolename = pstrdup($1);
}
$$ = (Node *) n;
}
| CURRENT_USER
{
$$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1);
}
| SESSION_USER
{
$$ = makeRoleSpec(ROLESPEC_SESSION_USER, @1);
}
;
role_list: RoleSpec
{ $$ = list_make1($1); }
| role_list ',' RoleSpec
{ $$ = lappend($1, $3); }
;
/*
* Name classification hierarchy.
*
@ -13812,6 +13856,20 @@ makeBoolAConst(bool state, int location)
return makeTypeCast((Node *)n, SystemTypeName("bool"), -1);
}
/* makeRoleSpec
* Create a RoleSpec with the given type
*/
static Node *
makeRoleSpec(RoleSpecType type, int location)
{
RoleSpec *spec = makeNode(RoleSpec);
spec->roletype = type;
spec->location = location;
return (Node *) spec;
}
/* check_qualified_name --- check the result of qualified_name production
*
* It's easiest to let the grammar production for qualified_name allow

View File

@ -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 */
@ -2723,7 +2723,7 @@ transformCreateSchemaStmt(CreateSchemaStmt *stmt)
cxt.stmtType = "CREATE SCHEMA";
cxt.schemaname = stmt->schemaname;
cxt.authid = stmt->authid;
cxt.authrole = (RoleSpec *) stmt->authrole;
cxt.sequences = NIL;
cxt.tables = NIL;
cxt.views = NIL;

View File

@ -5105,7 +5105,7 @@ select_best_grantor(Oid roleId, AclMode privileges,
/*
* get_role_oid - Given a role name, look up the role's OID.
*
* If missing_ok is false, throw an error if tablespace name not found. If
* If missing_ok is false, throw an error if role name not found. If
* true, just return InvalidOid.
*/
Oid
@ -5133,3 +5133,117 @@ get_role_oid_or_public(const char *rolname)
return get_role_oid(rolname, false);
}
/*
* Given a RoleSpec node, return the OID it corresponds to. If missing_ok is
* true, return InvalidOid if the role does not exist.
*
* PUBLIC is always disallowed here. Routines wanting to handle the PUBLIC
* case must check the case separately.
*/
Oid
get_rolespec_oid(const Node *node, bool missing_ok)
{
RoleSpec *role;
Oid oid;
if (!IsA(node, RoleSpec))
elog(ERROR, "invalid node type %d", node->type);
role = (RoleSpec *) node;
switch (role->roletype)
{
case ROLESPEC_CSTRING:
Assert(role->rolename);
oid = get_role_oid(role->rolename, missing_ok);
break;
case ROLESPEC_CURRENT_USER:
oid = GetUserId();
break;
case ROLESPEC_SESSION_USER:
oid = GetSessionUserId();
break;
case ROLESPEC_PUBLIC:
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", "public")));
oid = InvalidOid; /* make compiler happy */
break;
default:
elog(ERROR, "unexpected role type %d", role->roletype);
}
return oid;
}
/*
* Given a RoleSpec node, return the pg_authid HeapTuple it corresponds to.
* Caller must ReleaseSysCache when done with the result tuple.
*/
HeapTuple
get_rolespec_tuple(const Node *node)
{
RoleSpec *role;
HeapTuple tuple;
role = (RoleSpec *) node;
if (!IsA(node, RoleSpec))
elog(ERROR, "invalid node type %d", node->type);
switch (role->roletype)
{
case ROLESPEC_CSTRING:
Assert(role->rolename);
tuple = SearchSysCache1(AUTHNAME, CStringGetDatum(role->rolename));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", role->rolename)));
break;
case ROLESPEC_CURRENT_USER:
tuple = SearchSysCache1(AUTHOID, GetUserId());
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for role %u", GetUserId());
break;
case ROLESPEC_SESSION_USER:
tuple = SearchSysCache1(AUTHOID, GetSessionUserId());
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for role %u", GetSessionUserId());
break;
case ROLESPEC_PUBLIC:
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role \"%s\" does not exist", "public")));
tuple = NULL; /* make compiler happy */
default:
elog(ERROR, "unexpected role type %d", role->roletype);
}
return tuple;
}
/*
* Given a RoleSpec, returns a palloc'ed copy of the corresponding role's name.
*/
char *
get_rolespec_name(const Node *node)
{
HeapTuple tp;
Form_pg_authid authForm;
char *rolename;
tp = get_rolespec_tuple(node);
authForm = (Form_pg_authid) GETSTRUCT(tp);
rolename = pstrdup(NameStr(authForm->rolname));
ReleaseSysCache(tp);
return rolename;
}