查找链接到PostgreSQL角色的对象


12

有时,我创建了一个名为user1(PostgreSQL 9.4.9)的PostgreSQL用户。

我要删除此用户。因此,我也首先撤销了对表,序列,函数,默认特权和所有权的所有权限:

ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON SEQUENCES FROM user1;
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON TABLES FROM user1;
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM user1;

REVOKE ALL ON ALL SEQUENCES IN SCHEMA public FROM user1;
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM user1;
REVOKE ALL ON ALL FUNCTIONS IN SCHEMA public FROM user1;

REASSIGN OWNED BY user1 TO postgres;

但是,似乎在两个数据库中一个对象仍然链接到该用户:

postgres=# DROP ROLE user1;
ERROR:  role "user1" cannot be dropped because some objects depend on it
DETAIL:  1 object in database db1
1 object in database db2

它甚至似乎是一个函数:

postgres=# \c db1
You are now connected to database "db1" as user "postgres".
db1=# DROP ROLE user1;
ERROR:  role "user1" cannot be dropped because some objects depend on it
DETAIL:  privileges for function text(boolean)
1 object in database db2

但是我无法确定哪个对象是user1的所有者或与之有关。

如果我pg_dump -s db1 | grep user1没有结果!可以成为全局对象吗?

如何识别丢失的物体?

我已经在每个数据库(db1和db2)中执行了命令。我不想删除拥有的对象user1,只想重新分配或删除此用户的授权。

Answers:


11

回答问题的答案

要在错误消息及其所有者中查找功能,请执行以下操作:

SELECT oid::regprocedure AS function
     , pg_get_userbyid(proowner) AS owner
FROM   pg_proc
WHERE  oid = 'text(boolean)'::regprocedure;

有关:

实际问题

错误消息显示:

详细信息:函数文本的特权(布尔)

这与所有权无关,而与特权有关。

手册DROP ROLE

在删除角色之前,必须删除其拥有的所有对象(或重新分配其所有权),并撤消已在其他对象上授予该角色的所有特权

对于ALTER DEFAULT PRIVILEGES

如果要删除已更改了默认特权的角色,则必须撤消其默认特权的更改,或者使用DROP OWNEDBY 摆脱该角色的默认特权条目

看起来您只REASSIGN OWNED在一个数据库中执行,但该手册指示:

因为REASSIGN OWNED它不影响其他数据库中的对象,所以通常必须包含要删除的角色所拥有的对象的每个数据库执行此命令

大胆强调我的。

并且您使用限制了命令IN SCHEMA public。删除该子句以定位整个数据库。但不要打扰,有一个...

简单的解决方案 DROP OWNED

REASSIGN OWNED BY user1 TO postgres;
DROP OWNED BY user1;

所有角色的对象都将所有权更改为postgres第一个命令,并且现在可以安全使用。的措词DROP OWNED有点误导,因为它也摆脱了所有特权和默认特权。手册DROP OWNED

DROP OWNED删除当前数据库中由指定角色之一拥有的所有对象。在当前数据库中的对象和共享对象(数据库,表空间)上授予给定角色的任何特权也将被撤销。

在所有相关的数据库中重复操作,然后您可以执行以下操作:

DROP ROLE user1;

6

下面的查询列出了具有所有者的对象。对于所有特权,我们实际上需要更多。

--r = ordinary table, i = index, S = sequence, v = view, m = materialized view, c = composite type, t = TOAST table, f = foreign table
SELECT 
    n.nspname AS schema_name,
    c.relname AS rel_name,
    c.relkind AS rel_kind,
    pg_get_userbyid(c.relowner) AS owner_name
  FROM pg_class c
  JOIN pg_namespace n ON n.oid = c.relnamespace

UNION ALL

-- functions (or procedures)
SELECT
    n.nspname AS schema_name,
    p.proname,
    'p',
    pg_get_userbyid(p.proowner)
  FROM pg_proc p
  JOIN pg_namespace n ON n.oid = p.pronamespace

我仍然找不到与此丢失的对象。
Nicolas Payart '16

@NicolasPayart:您是否在正确的数据库中执行查询?
Erwin Brandstetter

1

您需要首先连接到数据库。在你的情况下

\c db1

\c db2

然后尝试再次运行REVOKE ALL PRIVILEGES和REASSIGN OWNED / DROP OWNED语句。


1
嘿,谢谢你的第一个答案。但是,在发布之前,请考虑一下这会对现有答案有什么影响,并在答案中也进行描述。
dezso
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.