Hi hackers,

While working on other projects, I found an issue $SUBJECT. Below describes the
exact problem, reproducer, and fix idea.

Problem
======
Unlogged tables cannot be included and excluded in a publication. When SET 
UNLOGGED
command is executed, validations are done in ATPrepChangePersistence() and the
backend raises an ERROR. However, rewrite-table event trigger can be fired after
the validation, and publication commands can be run at that time. Such commands
would bypass the validation thus unlogged tables could be in the 
pg_publication_rel.

Reproducer
=======
Below SQL commands could reproduce the inconsistency, unlogged table could be
excluded in the publication. Same thing can be said for the inclusion case.

```
postgres=# CREATE TABLE t (a int);
CREATE TABLE
postgres=# CREATE FUNCTION add_exclusion_during_rewrite()
RETURNS event_trigger
LANGUAGE plpgsql AS $$
BEGIN
    IF pg_event_trigger_table_rewrite_oid() = 'public.t'::regclass THEN
        EXECUTE
            'CREATE PUBLICATION p FOR ALL TABLES EXCEPT (TABLE public.t)';
    END IF;
END;
$$;
CREATE FUNCTION
postgres=# CREATE EVENT TRIGGER add_exclusion
    ON table_rewrite
    EXECUTE FUNCTION add_exclusion_during_rewrite();
CREATE EVENT TRIGGER
postgres=# ALTER TABLE t SET UNLOGGED;
ALTER TABLE
postgres=# SELECT c.relpersistence, pr.prexcept
FROM pg_class AS c
JOIN pg_publication_rel AS pr ON pr.prrelid = c.oid
WHERE c.oid = 'public.t'::regclass;
 relpersistence | prexcept
----------------+----------
 u              | t
(1 row)
```

Fix idea
=====
My primitive idea is to re-validate just after an event trigger is fired. 
Attached
Patch implemented the idea accordingly. How do you feel?

How do you feel?
Best regards,
Hayato Kuroda
FUJITSU LIMITED

Attachment: 0001-Recheck-table-persistence-after-table_rewrite-trigge.patch
Description: 0001-Recheck-table-persistence-after-table_rewrite-trigge.patch

Reply via email to