summaryrefslogtreecommitdiff
path: root/src/backend/catalog
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2015-03-11 17:01:13 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2015-03-11 17:04:27 -0300
commit890192e99af5db1d15d5bb73f3f1044faa1d2758 (patch)
treefdb3529d0e3df5ad4ace15df1f594ca4598c8758 /src/backend/catalog
parent1ce7a57ca6e8c5212fa2ab3bf31d56c74d5b5b8f (diff)
downloadpostgresql-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.c78
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),