Some times ago I created a PostgreSQL user named user1 (PostgreSQL 9.4.9).

I want to drop this user. So I first revoke all permissions on tables, sequences, functions, default privileges and ownership too:

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;

However it seems that one object remains linked to this user in 2 databases:

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

It even seems to be a function:

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

But I can not determine which object is owned or related to user1.

If I pg_dump -s db1 | grep user1 I get no result! Could it be a global object?

How can I identify the missing object?

share|improve this question
up vote 0 down vote accepted

Answer to question asked

To look for the function and its owner in the error message:

SELECT oid::regproc AS function
     , pg_get_function_identity_arguments(oid) AS in_params
     , pg_get_userbyid(proowner) AS owner
FROM   pg_proc
WHERE  proname = 'text'
AND    pg_get_function_identity_arguments(oid) = 'boolean';

Related:

Actual problem

But if you closely, the error message says:

DETAIL: privileges for function text(boolean)

It's not about ownership but about privileges.

The manual for DROP ROLE:

Before dropping the role, you must drop all the objects it owns (or reassign their ownership) and revoke any privileges the role has been granted on other objects.

And for ALTER DEFAULT PRIVILEGES:

If you wish to drop a role for which the default privileges have been altered, it is necessary to reverse the changes in its default privileges or use DROP OWNED BY to get rid of the default privileges entry for the role.

It also looks like you only executed REASSIGN OWNED in one DB, but the manual instructs:

Because REASSIGN OWNED does not affect objects within other databases, it is usually necessary to execute this command in each database that contains objects owned by a role that is to be removed.

Bold emphasis mine.

And you restricted your commands with IN SCHEMA public. Drop that clause to target the whole DB. But don't bother, there is a ...

Simple solution using DROP OWNED

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

All the role's objects changed ownership to postgres with the first command and are safe now. The wording of DROP OWNED is a bit misleading, since it also gets rid of all privileges and default privileges. The manual for DROP OWNED:

DROP OWNED drops all the objects within the current database that are owned by one of the specified roles. Any privileges granted to the given roles on objects in the current database and on shared objects (databases, tablespaces) will also be revoked.

Repeat in all relevant DBs, then you can move in for the kill:

DROP ROLE user1;
share|improve this answer
    
I did not specify it in my question but yes, I have executed the commands in each database (db1 and db2). Regarding DROP OWNED command, well, I do not want to drop objects owned by user1, just want to reassign or remove grants for this user... – Nicolas Payart Nov 15 '16 at 20:39
    
@NicolasPayart: I updated my answer with a detailed explanation. – Erwin Brandstetter Nov 16 '16 at 5:46
    
DROP OWNED BY after a REASSIGN OWNED BY (to prevent dropping any object) did the job. This is a convenient way indeed! Thanks. – Nicolas Payart Nov 16 '16 at 14:12

The query below lists objects with owners. For all privileges we actually need more.

--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
share|improve this answer
    
I still do not find the missing object with this. – Nicolas Payart Nov 15 '16 at 23:05
    
@NicolasPayart: Are you executing the query in the right database? – Erwin Brandstetter Nov 16 '16 at 4:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.