BUG #16177: pg_event_trigger_ddl_commands() returns empty set for ddl_command_start and "drop table"

Started by PG Bug reporting formover 6 years ago5 messagesbugs
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 16177
Logged by: Andrei Pozolotin
Email address: andrei.pozolotin@gmail.com
PostgreSQL version: 11.6
Operating system: linux
Description:

1. use case is to delete rows with oid references to the table before "drop
table"

2. one way to do that is with event_trigger, see code snippet below

3. the problem is that:
pg_event_trigger_ddl_commands() returns empty set for ddl_command_start and
"drop table"

4. this issue was already mentioned before:
https://postgrespro.com/list/thread-id/2394772

5. sample code:

CREATE OR REPLACE FUNCTION pglogical_assign_repset()
RETURNS event_trigger AS $$
DECLARE obj record;
BEGIN
RAISE NOTICE 'pglogical assign: % %', tg_event, tg_tag;
FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands()
LOOP
IF obj.object_type = 'table' THEN
IF obj.schema_name = 'public' THEN
IF tg_tag IN ('CREATE TABLE') THEN
PERFORM
pglogical.replication_set_add_table('default', obj.objid);
END IF;
IF tg_tag IN ('DROP TABLE') THEN
PERFORM
pglogical.replication_set_remove_table('default', obj.objid);
END IF;
END IF;
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;
---
DROP EVENT TRIGGER IF EXISTS
pglogical_assign_repset_create;
CREATE EVENT TRIGGER
pglogical_assign_repset_create
ON ddl_command_end
WHEN TAG IN ('CREATE TABLE')
EXECUTE FUNCTION pglogical_assign_repset();
---
DROP EVENT TRIGGER IF EXISTS
pglogical_assign_repset_delete;
CREATE EVENT TRIGGER
pglogical_assign_repset_delete
ON ddl_command_start
WHEN TAG IN ('DROP TABLE')
EXECUTE FUNCTION pglogical_assign_repset();
---

#2Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: PG Bug reporting form (#1)
Re: BUG #16177: pg_event_trigger_ddl_commands() returns empty set for ddl_command_start and "drop table"

On 2019-Dec-22, PG Bug reporting form wrote:

1. use case is to delete rows with oid references to the table before "drop
table"

I think you could achieve that with an event trigger on event sql_drop.
IIRC that event trigger is run for the objects before the drops are
actually executed.

ddl_command_start is pretty useless, because it doesn't have much info
abot the command being run; I'm sure that
pg_event_trigger_ddl_commands() would always return empty there.
The function would return non-empty only during ddl_command_end, but
that's no useful to you because the drops will already have run.

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#3Andrei Pozolotin
andrei.pozolotin@gmail.com
In reply to: Alvaro Herrera (#2)
Re: BUG #16177: pg_event_trigger_ddl_commands() returns empty set for ddl_command_start and "drop table"

Alvaro, hi:

1. thank you for the idea, I have just tried that

2. I could not make it work, since "sql_drop" event
happens **after** the "drop table" has already being attempted
and failed due to table oid dependencies

3. you may find it curious that I was in fact trying to improve on the
following trigger function:
https://github.com/2ndQuadrant/pglogical#automatic-assignment-of-replication-sets-for-new-tables
to make it work for "drop table" as well

4. my current workaround is to move trigger logic for "create
table"/"drop table"
outside of postgre into the app layer, essentially doing via execute()
intercept:
* replicate_ddl_command("create table; replication_set_add_table();")
* replicate_ddl_command("replication_set_remove_table(); drop table;")

5. nonetheless, can you suggest any other way to make "event_trigger"
work for this scenario:
https://github.com/2ndQuadrant/pglogical#automatic-assignment-of-replication-sets-for-new-tables
?

Thanks,

Andrei.

Show quoted text

On 2019-12-23 08:36, Alvaro Herrera wrote:

On 2019-Dec-22, PG Bug reporting form wrote:

1. use case is to delete rows with oid references to the table before
"drop
table"

I think you could achieve that with an event trigger on event sql_drop.
IIRC that event trigger is run for the objects before the drops are
actually executed.

ddl_command_start is pretty useless, because it doesn't have much info
abot the command being run; I'm sure that
pg_event_trigger_ddl_commands() would always return empty there.
The function would return non-empty only during ddl_command_end, but
that's no useful to you because the drops will already have run.

#4Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Andrei Pozolotin (#3)
Re: BUG #16177: pg_event_trigger_ddl_commands() returns empty set for ddl_command_start and "drop table"

Hello,

On 2019-Dec-23, Andrei Pozolotin wrote:

1. thank you for the idea, I have just tried that

2. I could not make it work, since "sql_drop" event
happens **after** the "drop table" has already being attempted
and failed due to table oid dependencies

Well, that's really disappointing, but now that you say it, I remember
that yes we had to save all table info prior to firing the trigger
because it (the trigger) would run after the drop. I think there was a
restriction that forced us to do things that way, but TBH I don't
remember clearly.

3. you may find it curious that I was in fact trying to improve on the
following trigger function:
https://github.com/2ndQuadrant/pglogical#automatic-assignment-of-replication-sets-for-new-tables
to make it work for "drop table" as well

That makes sense.

4. my current workaround is to move trigger logic for "create table"/"drop
table"
outside of postgre into the app layer, essentially doing via execute()
intercept:
* replicate_ddl_command("create table; replication_set_add_table();")
* replicate_ddl_command("replication_set_remove_table(); drop table;")

That seems a decent workaround, if suboptimal.

5. nonetheless, can you suggest any other way to make "event_trigger" work
for this scenario:
https://github.com/2ndQuadrant/pglogical#automatic-assignment-of-replication-sets-for-new-tables
?

I wonder if it's possible for pglogical to register pg_depend entries to
the replication set, so that the repset membership is dropped alongside
the table.

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#5Andrei Pozolotin
andrei.pozolotin@gmail.com
In reply to: Alvaro Herrera (#4)
Re: BUG #16177: pg_event_trigger_ddl_commands() returns empty set for ddl_command_start and "drop table"

Alvaro:

great, I posted your idea with pglogical:
https://github.com/2ndQuadrant/pglogical/issues/234

Andrei.

On 2019-12-24 10:18, Alvaro Herrera wrote:

Show quoted text

I wonder if it's possible for pglogical to register pg_depend entries
to
the replication set, so that the repset membership is dropped alongside
the table.