incorrect pg_dump output due to not handling dropped roles correctly

From: Floris Van Nee <florisvannee(at)Optiver(dot)com>
To: "pgsql-bugs(at)lists(dot)postgresql(dot)org" <pgsql-bugs(at)lists(dot)postgresql(dot)org>
Cc: Ferdi Smit <FerdiSmit(at)Optiver(dot)com>
Subject: incorrect pg_dump output due to not handling dropped roles correctly
Date: 2019-11-15 09:01:23
Message-ID: 1573808483712.96817@Optiver.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

I noticed I wasn't able to apply my usual pg_dump schema output without errors anymore after I dropped some roles. After some digging, I found it has to do with Postgres not correctly updating the pg_init_privs table upon dropping roles. I can reproduce a similar scenario with the following steps (output from v13devel, but AFAIK all versions affected, I ran into the issue on v11.2):

postgres=# create role test;
CREATE ROLE
postgres=# alter default privileges in schema public grant all privileges on tables to test;
ALTER DEFAULT PRIVILEGES
postgres=# create extension pg_stat_statements;
CREATE EXTENSION
postgres=# select * from pg_catalog.pg_init_privs
where objoid=(select 'pg_stat_statements'::regclass);
objoid | classoid | objsubid | privtype | initprivs
--------+----------+----------+----------+-------------------------------------------------------------------------------
16409 | 1259 | 0 | e | {florisvannee=arwdDxt/florisvannee,test=arwdDxt/florisvannee,=r/florisvannee}
(1 row)

postgres=# drop owned by test;
DROP OWNED
postgres=# drop role test;
DROP ROLE
postgres=# select * from pg_catalog.pg_init_privs
where objoid=(select 'pg_stat_statements'::regclass);
objoid | classoid | objsubid | privtype | initprivs
--------+----------+----------+----------+--------------------------------------------------------------------------------
16409 | 1259 | 0 | e | {florisvannee=arwdDxt/florisvannee,16404=arwdDxt/florisvannee,=r/florisvannee}
(1 row)

If we do a pg_dump on this, there'll be a line like this in the output:

REVOKE ALL ON TABLE public.pg_stat_statements FROM "16404";

This fails when restoring, because there's no role '16404'.

Can I manually fix this by updating pg_init_privs catalog table? Eg. in the example, I could run something like?

update pg_catalog.pg_init_privs
set initprivs=(select array_agg(p) from unnest(initprivs) p where not (p::text like '16404%'))
where initprivs <> (select array_agg(p) from unnest(initprivs) p where not (p::text like '16404%'))
;

Dropping/recreating the extension seems to work too, but I'd like to avoid that if possible (that may be a solution for pg_stat_statements, but isn't necessarily possible for every extension).

I'm pretty sure I once ran into a similar issue before, when doing a pg_upgrade in-place from 10 to 11. I couldn't run pg_upgrade until - back then I fixed it by dropping/recreating the extension, but didn't know exactly what was causing it, so I didn't report it here. From glancing at the code, this seems to be following some similar code paths in dump/restore. Just so you know the impact may not be limited to manual pg_dump actions, but also potentially pg_upgrade if my memory is correct.

-Floris

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Thomas Butz 2019-11-15 09:03:48 Re: BUG #16095: Segfault while executing trigger
Previous Message Juan José Santamaría Flecha 2019-11-15 08:14:59 Re: BUG #16108: Colorization to the output of command-line has unproperly behaviors at Windows platform