/* 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 */
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);
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 */
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.
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),
case OBJECT_TSPARSER:
case OBJECT_TSTEMPLATE:
case OBJECT_TYPE:
+ case OBJECT_USER_MAPPING:
case OBJECT_VIEW:
return true;
}
OBJECT_TSPARSER,
OBJECT_TSTEMPLATE,
OBJECT_TYPE,
+ OBJECT_USER_MAPPING,
OBJECT_VIEW
} ObjectType;
NOTICE: test_event_trigger: ddl_command_end REVOKE
drop table event_trigger_fire1;
NOTICE: test_event_trigger: ddl_command_end DROP TABLE
+create foreign data wrapper useless;
+NOTICE: test_event_trigger: ddl_command_end CREATE FOREIGN DATA WRAPPER
+create server useless_server foreign data wrapper useless;
+NOTICE: test_event_trigger: ddl_command_end CREATE SERVER
+create user mapping for regression_bob server useless_server;
+NOTICE: test_event_trigger: ddl_command_end CREATE USER MAPPING
-- alter owner to non-superuser should fail
alter event trigger regress_event_trigger owner to regression_bob;
ERROR: permission denied to change owner of event trigger "regress_event_trigger"
-- should fail, doesn't exist any more
drop event trigger regress_event_trigger;
ERROR: event trigger "regress_event_trigger" does not exist
--- should fail, regression_bob owns regress_event_trigger2/3
+-- should fail, regression_bob owns some objects
drop role regression_bob;
ERROR: role "regression_bob" cannot be dropped because some objects depend on it
DETAIL: owner of event trigger regress_event_trigger3
+owner of user mapping for regression_bob on server useless_server
-- cleanup before next test
-- these are all OK; the second one should emit a NOTICE
drop event trigger if exists regress_event_trigger2;
CREATE FUNCTION addr_nsp.trig() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN END; $$;
CREATE TRIGGER t BEFORE INSERT ON addr_nsp.gentable FOR EACH ROW EXECUTE PROCEDURE addr_nsp.trig();
CREATE POLICY genpol ON addr_nsp.gentable;
+CREATE SERVER "integer" FOREIGN DATA WRAPPER addr_fdw;
+CREATE USER MAPPING FOR regtest_addr_user SERVER "integer";
-- test some error cases
SELECT pg_get_object_address('stone', '{}', '{}');
ERROR: unrecognized object type "stone"
BEGIN
FOR objtype IN VALUES ('toast table'), ('index column'), ('sequence column'),
('toast table column'), ('view column'), ('materialized view column'),
- ('operator of access method'), ('function of access method'),
- ('user mapping')
+ ('operator of access method'), ('function of access method')
LOOP
BEGIN
PERFORM pg_get_object_address(objtype, '{one}', '{}');
WARNING: error for materialized view column: unsupported object type "materialized view column"
WARNING: error for operator of access method: unsupported object type "operator of access method"
WARNING: error for function of access method: unsupported object type "function of access method"
-WARNING: error for user mapping: unsupported object type "user mapping"
DO $$
DECLARE
objtype text;
('operator'), ('operator class'), ('operator family'), ('rule'), ('trigger'),
('text search parser'), ('text search dictionary'),
('text search template'), ('text search configuration'),
- ('policy')
+ ('policy'), ('user mapping')
LOOP
FOR names IN VALUES ('{eins}'), ('{addr_nsp, zwei}'), ('{eins, zwei, drei}')
LOOP
WARNING: error for policy,{addr_nsp,zwei},{integer}: relation "addr_nsp" does not exist
WARNING: error for policy,{eins,zwei,drei},{}: schema "eins" does not exist
WARNING: error for policy,{eins,zwei,drei},{integer}: schema "eins" does not exist
+WARNING: error for user mapping,{eins},{}: argument list length must be exactly 1
+WARNING: error for user mapping,{eins},{integer}: user mapping for user "eins" in server "integer" does not exist
+WARNING: error for user mapping,{addr_nsp,zwei},{}: argument list length must be exactly 1
+WARNING: error for user mapping,{addr_nsp,zwei},{integer}: user mapping for user "addr_nsp" in server "integer" does not exist
+WARNING: error for user mapping,{eins,zwei,drei},{}: argument list length must be exactly 1
+WARNING: error for user mapping,{eins,zwei,drei},{integer}: user mapping for user "eins" in server "integer" does not exist
-- these object types cannot be qualified names
SELECT pg_get_object_address('language', '{one}', '{}');
ERROR: language "one" does not exist
-- tablespace
('foreign-data wrapper', '{addr_fdw}', '{}'),
('server', '{addr_fserv}', '{}'),
- -- user mapping
+ ('user mapping', '{regtest_addr_user}', '{integer}'),
-- extension
-- event trigger
('policy', '{addr_nsp, gentable, genpol}', '{}')
foreign table | addr_nsp | genftable | addr_nsp.genftable | t
role | | regtest_addr_user | regtest_addr_user | t
server | | addr_fserv | addr_fserv | t
+ user mapping | | | regtest_addr_user on server integer | t
foreign-data wrapper | | addr_fdw | addr_fdw | t
default value | | | for addr_nsp.gentable.b | t
cast | | | (bigint AS integer) | t
text search parser | addr_nsp | addr_ts_prs | addr_nsp.addr_ts_prs | t
text search configuration | addr_nsp | addr_ts_conf | addr_nsp.addr_ts_conf | t
text search template | addr_nsp | addr_ts_temp | addr_nsp.addr_ts_temp | t
-(35 rows)
+(36 rows)
---
--- Cleanup resources
comment on table event_trigger_fire1 is 'here is a comment';
revoke all on table event_trigger_fire1 from public;
drop table event_trigger_fire1;
+create foreign data wrapper useless;
+create server useless_server foreign data wrapper useless;
+create user mapping for regression_bob server useless_server;
-- alter owner to non-superuser should fail
alter event trigger regress_event_trigger owner to regression_bob;
-- should fail, doesn't exist any more
drop event trigger regress_event_trigger;
--- should fail, regression_bob owns regress_event_trigger2/3
+-- should fail, regression_bob owns some objects
drop role regression_bob;
-- cleanup before next test
CREATE FUNCTION addr_nsp.trig() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN END; $$;
CREATE TRIGGER t BEFORE INSERT ON addr_nsp.gentable FOR EACH ROW EXECUTE PROCEDURE addr_nsp.trig();
CREATE POLICY genpol ON addr_nsp.gentable;
+CREATE SERVER "integer" FOREIGN DATA WRAPPER addr_fdw;
+CREATE USER MAPPING FOR regtest_addr_user SERVER "integer";
-- test some error cases
SELECT pg_get_object_address('stone', '{}', '{}');
BEGIN
FOR objtype IN VALUES ('toast table'), ('index column'), ('sequence column'),
('toast table column'), ('view column'), ('materialized view column'),
- ('operator of access method'), ('function of access method'),
- ('user mapping')
+ ('operator of access method'), ('function of access method')
LOOP
BEGIN
PERFORM pg_get_object_address(objtype, '{one}', '{}');
('operator'), ('operator class'), ('operator family'), ('rule'), ('trigger'),
('text search parser'), ('text search dictionary'),
('text search template'), ('text search configuration'),
- ('policy')
+ ('policy'), ('user mapping')
LOOP
FOR names IN VALUES ('{eins}'), ('{addr_nsp, zwei}'), ('{eins, zwei, drei}')
LOOP
-- tablespace
('foreign-data wrapper', '{addr_fdw}', '{}'),
('server', '{addr_fserv}', '{}'),
- -- user mapping
+ ('user mapping', '{regtest_addr_user}', '{integer}'),
-- extension
-- event trigger
('policy', '{addr_nsp, gentable, genpol}', '{}')