Localizar objetos vinculados a uma função do PostgreSQL

12

Algumas vezes atrás eu criei um usuário do PostgreSQL chamado user1 (PostgreSQL 9.4.9).

Eu quero largar este usuário. Então, revogo todas as permissões em tabelas, seqüências, funções, privilégios padrão e propriedade também:

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;

No entanto, parece que um objeto permanece vinculado a esse usuário em 2 bancos de dados:

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

Parece até ser uma função:

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

Mas não consigo determinar qual objeto pertence ou está relacionado ao usuário1.

Se eu pg_dump -s db1 | grep user1não obtiver resultado! Poderia ser um objeto global?

Como posso identificar o objeto ausente?

Eu executei os comandos em cada banco de dados (db1 e db2). Não quero descartar objetos pertencentes a user1, apenas quero reatribuir ou remover concessões para esse usuário.

Nicolas Payart
fonte

Respostas:

11

Resposta à pergunta

Para procurar a função na mensagem de erro e seu proprietário:

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

Relacionado:

Problema real

A mensagem de erro diz:

DETALHE: privilégios para o texto da função (booleano)

Não se trata de propriedade, mas de privilégios .

O manual para DROP ROLE:

Antes de descartar a função, você deve descartar todos os objetos que possui (ou reatribuir sua propriedade) e revogar quaisquer privilégios que a função tenha sido concedida em outros objetos .

E para ALTER DEFAULT PRIVILEGES:

Se você deseja eliminar uma função para a qual os privilégios padrão foram alterados, é necessário reverter as alterações em seus privilégios padrão ou usar DROP OWNEDBY para se livrar da entrada de privilégios padrão para a função .

Também parece que você foi executado apenas REASSIGN OWNEDem um banco de dados, mas o manual instrui:

Como REASSIGN OWNEDnão afeta objetos em outros bancos de dados, geralmente é necessário executar este comando em cada banco de dados que contém objetos pertencentes a uma função que deve ser removida.

Negrito ênfase minha.

E você restringiu seus comandos com IN SCHEMA public. Solte essa cláusula para atingir todo o banco de dados. Mas não se preocupe, há um ...

Solução simples com DROP OWNED

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

Todos os objetos da função mudaram de propriedade para postgrescom o primeiro comando e estão seguros agora. A redação de DROP OWNEDé um pouco enganadora, pois também se livra de todos os privilégios e privilégios padrão. O manual para DROP OWNED:

DROP OWNEDdescarta todos os objetos no banco de dados atual que pertencem a uma das funções especificadas. Quaisquer privilégios concedidos às funções fornecidas em objetos no banco de dados atual e em objetos compartilhados (bancos de dados, espaços de tabela) também serão revogados.

Repita em todos os DBs relevantes e, em seguida, você pode se mudar para a matança:

DROP ROLE user1;
Erwin Brandstetter
fonte
6

A consulta abaixo lista objetos com proprietários. Para todos os privilégios, precisamos de mais.

--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
Sahap Asci
fonte
Ainda não encontro o objeto que falta com isso.
Nicolas Payart
@NicolasPayart: Você está executando a consulta no banco de dados correto?
Erwin Brandstetter
1

Você precisa primeiro se conectar ao banco de dados. No seu exemplo, isso seria

\c db1

e

\c db2

Em seguida, tente executar as instruções REVOKE ALL PRIVILEGES e REASSIGN OWNED / DROP OWNED novamente.

Samuel Anyaele
fonte
11
Ei, obrigado pela sua primeira resposta. No entanto, antes de postar, pense no que isso acrescenta às respostas existentes e descreva isso também.
Dezso