diff options
| author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2015-03-11 17:01:13 -0300 |
|---|---|---|
| committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2015-03-11 17:04:27 -0300 |
| commit | 890192e99af5db1d15d5bb73f3f1044faa1d2758 (patch) | |
| tree | fdb3529d0e3df5ad4ace15df1f594ca4598c8758 /src/backend/catalog | |
| parent | 1ce7a57ca6e8c5212fa2ab3bf31d56c74d5b5b8f (diff) | |
| download | postgresql-890192e99af5db1d15d5bb73f3f1044faa1d2758.tar.gz | |
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.
Diffstat (limited to 'src/backend/catalog')
| -rw-r--r-- | src/backend/catalog/objectaddress.c | 78 |
1 files changed, 77 insertions, 1 deletions
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 */ @@ -1373,6 +1379,75 @@ get_object_address_opcf(ObjectType objtype, } /* + * 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), |
