mirror of
https://github.com/postgres/postgres.git
synced 2025-11-13 16:22:44 +03:00
Support user mappings in get_object_address
Since commit 72dd233d3e we were trying to obtain object addressing
information in sql_drop event triggers, but that caused failures when
the drops involved user mappings. This addition enables that to work
again. Naturally, pg_get_object_address can work with these objects
now, too.
I toyed with the idea of removing DropUserMappingStmt as a node and
using DropStmt instead in the DropUserMappingStmt grammar production,
but that didn't go very well: for one thing the messages thrown by the
specific code are specialized (you get "server not found" if you specify
the wrong server, instead of a generic "user mapping for ... not found"
which you'd get it we were to merge this with RemoveObjects --- unless
we added even more special cases). For another thing, it would require
to pass RoleSpec nodes through the objname/objargs representation used
by RemoveObjects, which works in isolation, but gets messy when
pg_get_object_address is involved. So I dropped this part for now.
Reviewed by Stephen Frost.
This commit is contained in:
@@ -520,7 +520,7 @@ ObjectTypeMap[] =
|
||||
/* OCLASS_FOREIGN_SERVER */
|
||||
{ "server", OBJECT_FOREIGN_SERVER },
|
||||
/* OCLASS_USER_MAPPING */
|
||||
{ "user mapping", -1 }, /* unmapped */
|
||||
{ "user mapping", OBJECT_USER_MAPPING },
|
||||
/* OCLASS_DEFACL */
|
||||
{ "default acl", -1 }, /* unmapped */
|
||||
/* OCLASS_EXTENSION */
|
||||
@@ -555,6 +555,8 @@ static ObjectAddress get_object_address_type(ObjectType objtype,
|
||||
List *objname, bool missing_ok);
|
||||
static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
|
||||
List *objargs, bool missing_ok);
|
||||
static ObjectAddress get_object_address_usermapping(List *objname,
|
||||
List *objargs, bool missing_ok);
|
||||
static const ObjectPropertyType *get_object_property_data(Oid class_id);
|
||||
|
||||
static void getRelationDescription(StringInfo buffer, Oid relid);
|
||||
@@ -769,6 +771,10 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
|
||||
address.objectId = get_ts_config_oid(objname, missing_ok);
|
||||
address.objectSubId = 0;
|
||||
break;
|
||||
case OBJECT_USER_MAPPING:
|
||||
address = get_object_address_usermapping(objname, objargs,
|
||||
missing_ok);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
|
||||
/* placate compiler, in case it thinks elog might return */
|
||||
@@ -1372,6 +1378,75 @@ get_object_address_opcf(ObjectType objtype,
|
||||
return address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the ObjectAddress for a user mapping.
|
||||
*/
|
||||
static ObjectAddress
|
||||
get_object_address_usermapping(List *objname, List *objargs, bool missing_ok)
|
||||
{
|
||||
ObjectAddress address;
|
||||
Oid userid;
|
||||
char *username;
|
||||
char *servername;
|
||||
ForeignServer *server;
|
||||
HeapTuple tp;
|
||||
|
||||
ObjectAddressSet(address, UserMappingRelationId, InvalidOid);
|
||||
|
||||
/* fetch string names from input lists, for error messages */
|
||||
username = strVal(linitial(objname));
|
||||
servername = strVal(linitial(objargs));
|
||||
|
||||
/* look up pg_authid OID of mapped user; InvalidOid if PUBLIC */
|
||||
if (strcmp(username, "public") == 0)
|
||||
userid = InvalidOid;
|
||||
else
|
||||
{
|
||||
tp = SearchSysCache1(AUTHNAME,
|
||||
CStringGetDatum(username));
|
||||
if (!HeapTupleIsValid(tp))
|
||||
{
|
||||
if (!missing_ok)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("user mapping for user \"%s\" in server \"%s\" does not exist",
|
||||
username, servername)));
|
||||
return address;
|
||||
}
|
||||
userid = HeapTupleGetOid(tp);
|
||||
ReleaseSysCache(tp);
|
||||
}
|
||||
|
||||
/* Now look up the pg_user_mapping tuple */
|
||||
server = GetForeignServerByName(servername, true);
|
||||
if (!server)
|
||||
{
|
||||
if (!missing_ok)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("server \"%s\" does not exist", servername)));
|
||||
return address;
|
||||
}
|
||||
tp = SearchSysCache2(USERMAPPINGUSERSERVER,
|
||||
ObjectIdGetDatum(userid),
|
||||
ObjectIdGetDatum(server->serverid));
|
||||
if (!HeapTupleIsValid(tp))
|
||||
{
|
||||
if (!missing_ok)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("user mapping for user \"%s\" in server \"%s\" does not exist",
|
||||
username, servername)));
|
||||
return address;
|
||||
}
|
||||
|
||||
address.objectId = HeapTupleGetOid(tp);
|
||||
|
||||
ReleaseSysCache(tp);
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of TEXT into a List of string Values, as emitted by the
|
||||
* parser, which is what get_object_address uses as input.
|
||||
@@ -1523,6 +1598,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
|
||||
case OBJECT_OPCLASS:
|
||||
case OBJECT_OPFAMILY:
|
||||
case OBJECT_CAST:
|
||||
case OBJECT_USER_MAPPING:
|
||||
if (list_length(args) != 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
|
||||
@@ -1092,6 +1092,7 @@ EventTriggerSupportsObjectType(ObjectType obtype)
|
||||
case OBJECT_TSPARSER:
|
||||
case OBJECT_TSTEMPLATE:
|
||||
case OBJECT_TYPE:
|
||||
case OBJECT_USER_MAPPING:
|
||||
case OBJECT_VIEW:
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user