From 890192e99af5db1d15d5bb73f3f1044faa1d2758 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Wed, 11 Mar 2015 17:01:13 -0300 Subject: Support user mappings in get_object_address Since commit 72dd233d3ef 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. --- src/backend/catalog/objectaddress.c | 78 ++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) (limited to 'src/backend/catalog') diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 541912bac5..67c14020e5 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -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), -- cgit v1.2.1