Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2d689ba

Browse files
committed
Improve handling of dropped objects in pg_event_trigger_ddl_commands()
An object found as dropped when digging into the list of objects returned by pg_event_trigger_ddl_commands() could cause a cache lookup error, as the calls grabbing for the object address and the type name would fail if the object was missing. Those lookup errors could be seen with combinations of ALTER TABLE sub-commands involving identity columns. The lookup logic is changed in this code path to get a behavior similar to any other SQL-callable function by ignoring objects that are not found, taking advantage of 2a10fdc. The back-branches are not changed, as they require this commit that is too invasive for stable branches. While on it, add test cases to exercise event triggers with identity columns, and stress more cases with the event ddl_command_end for relations. Author: Sven Klemm, Aleksander Alekseev, Michael Paquier Discussion: https://postgr.es/m/CAMCrgp2R1cEXU53iYKtW6yVEp2_yKUz+z=3-CTrYpPP+xryRtg@mail.gmail.com
1 parent dbab0c0 commit 2d689ba

File tree

3 files changed

+91
-7
lines changed

3 files changed

+91
-7
lines changed

src/backend/commands/event_trigger.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -1936,8 +1936,19 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
19361936
else if (cmd->type == SCT_AlterTSConfig)
19371937
addr = cmd->d.atscfg.address;
19381938

1939-
type = getObjectTypeDescription(&addr, false);
1940-
identity = getObjectIdentity(&addr, false);
1939+
/*
1940+
* If an object was dropped in the same command we may end
1941+
* up in a situation where we generated a message but can
1942+
* no longer look for the object information, so skip it
1943+
* rather than failing. This can happen for example with
1944+
* some subcommand combinations of ALTER TABLE.
1945+
*/
1946+
identity = getObjectIdentity(&addr, true);
1947+
if (identity == NULL)
1948+
continue;
1949+
1950+
/* The type can never be NULL. */
1951+
type = getObjectTypeDescription(&addr, true);
19411952

19421953
/*
19431954
* Obtain schema name, if any ("pg_temp" if a temp

src/test/regress/expected/event_trigger.out

+54-3
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ SELECT * FROM dropped_objects WHERE type = 'schema';
366366
DROP ROLE regress_evt_user;
367367
DROP EVENT TRIGGER regress_event_trigger_drop_objects;
368368
DROP EVENT TRIGGER undroppable;
369+
-- Event triggers on relations.
369370
CREATE OR REPLACE FUNCTION event_trigger_report_dropped()
370371
RETURNS event_trigger
371372
LANGUAGE plpgsql
@@ -384,41 +385,90 @@ BEGIN
384385
END; $$;
385386
CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop
386387
EXECUTE PROCEDURE event_trigger_report_dropped();
388+
CREATE OR REPLACE FUNCTION event_trigger_report_end()
389+
RETURNS event_trigger
390+
LANGUAGE plpgsql
391+
AS $$
392+
DECLARE r RECORD;
393+
BEGIN
394+
FOR r IN SELECT * FROM pg_event_trigger_ddl_commands()
395+
LOOP
396+
RAISE NOTICE 'END: command_tag=% type=% identity=%',
397+
r.command_tag, r.object_type, r.object_identity;
398+
END LOOP;
399+
END; $$;
400+
CREATE EVENT TRIGGER regress_event_trigger_report_end ON ddl_command_end
401+
EXECUTE PROCEDURE event_trigger_report_end();
387402
CREATE SCHEMA evttrig
388-
CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two')
403+
CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two', col_c SERIAL)
389404
CREATE INDEX one_idx ON one (col_b)
390-
CREATE TABLE two (col_c INTEGER CHECK (col_c > 0) REFERENCES one DEFAULT 42);
405+
CREATE TABLE two (col_c INTEGER CHECK (col_c > 0) REFERENCES one DEFAULT 42)
406+
CREATE TABLE id (col_d int NOT NULL GENERATED ALWAYS AS IDENTITY);
407+
NOTICE: END: command_tag=CREATE SCHEMA type=schema identity=evttrig
408+
NOTICE: END: command_tag=CREATE SEQUENCE type=sequence identity=evttrig.one_col_a_seq
409+
NOTICE: END: command_tag=CREATE SEQUENCE type=sequence identity=evttrig.one_col_c_seq
410+
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.one
411+
NOTICE: END: command_tag=CREATE INDEX type=index identity=evttrig.one_pkey
412+
NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.one_col_a_seq
413+
NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.one_col_c_seq
414+
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.two
415+
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.two
416+
NOTICE: END: command_tag=CREATE SEQUENCE type=sequence identity=evttrig.id_col_d_seq
417+
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.id
418+
NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.id_col_d_seq
419+
NOTICE: END: command_tag=CREATE INDEX type=index identity=evttrig.one_idx
391420
-- Partitioned tables with a partitioned index
392421
CREATE TABLE evttrig.parted (
393422
id int PRIMARY KEY)
394423
PARTITION BY RANGE (id);
424+
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.parted
425+
NOTICE: END: command_tag=CREATE INDEX type=index identity=evttrig.parted_pkey
395426
CREATE TABLE evttrig.part_1_10 PARTITION OF evttrig.parted (id)
396427
FOR VALUES FROM (1) TO (10);
428+
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.part_1_10
397429
CREATE TABLE evttrig.part_10_20 PARTITION OF evttrig.parted (id)
398430
FOR VALUES FROM (10) TO (20) PARTITION BY RANGE (id);
431+
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.part_10_20
399432
CREATE TABLE evttrig.part_10_15 PARTITION OF evttrig.part_10_20 (id)
400433
FOR VALUES FROM (10) TO (15);
434+
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.part_10_15
401435
CREATE TABLE evttrig.part_15_20 PARTITION OF evttrig.part_10_20 (id)
402436
FOR VALUES FROM (15) TO (20);
437+
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.part_15_20
403438
ALTER TABLE evttrig.two DROP COLUMN col_c;
404439
NOTICE: NORMAL: orig=t normal=f istemp=f type=table column identity=evttrig.two.col_c name={evttrig,two,col_c} args={}
405440
NOTICE: NORMAL: orig=f normal=t istemp=f type=table constraint identity=two_col_c_check on evttrig.two name={evttrig,two,two_col_c_check} args={}
441+
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.two
406442
ALTER TABLE evttrig.one ALTER COLUMN col_b DROP DEFAULT;
407443
NOTICE: NORMAL: orig=t normal=f istemp=f type=default value identity=for evttrig.one.col_b name={evttrig,one,col_b} args={}
444+
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.one
408445
ALTER TABLE evttrig.one DROP CONSTRAINT one_pkey;
409446
NOTICE: NORMAL: orig=t normal=f istemp=f type=table constraint identity=one_pkey on evttrig.one name={evttrig,one,one_pkey} args={}
447+
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.one
448+
ALTER TABLE evttrig.one DROP COLUMN col_c;
449+
NOTICE: NORMAL: orig=t normal=f istemp=f type=table column identity=evttrig.one.col_c name={evttrig,one,col_c} args={}
450+
NOTICE: NORMAL: orig=f normal=t istemp=f type=default value identity=for evttrig.one.col_c name={evttrig,one,col_c} args={}
451+
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.one
452+
ALTER TABLE evttrig.id ALTER COLUMN col_d SET DATA TYPE bigint;
453+
NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.id_col_d_seq
454+
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.id
455+
ALTER TABLE evttrig.id ALTER COLUMN col_d DROP IDENTITY,
456+
ALTER COLUMN col_d SET DATA TYPE int;
457+
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.id
410458
DROP INDEX evttrig.one_idx;
411459
NOTICE: NORMAL: orig=t normal=f istemp=f type=index identity=evttrig.one_idx name={evttrig,one_idx} args={}
412460
DROP SCHEMA evttrig CASCADE;
413-
NOTICE: drop cascades to 3 other objects
461+
NOTICE: drop cascades to 4 other objects
414462
DETAIL: drop cascades to table evttrig.one
415463
drop cascades to table evttrig.two
464+
drop cascades to table evttrig.id
416465
drop cascades to table evttrig.parted
417466
NOTICE: NORMAL: orig=t normal=f istemp=f type=schema identity=evttrig name={evttrig} args={}
418467
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.one name={evttrig,one} args={}
419468
NOTICE: NORMAL: orig=f normal=t istemp=f type=sequence identity=evttrig.one_col_a_seq name={evttrig,one_col_a_seq} args={}
420469
NOTICE: NORMAL: orig=f normal=t istemp=f type=default value identity=for evttrig.one.col_a name={evttrig,one,col_a} args={}
421470
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.two name={evttrig,two} args={}
471+
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.id name={evttrig,id} args={}
422472
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.parted name={evttrig,parted} args={}
423473
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_1_10 name={evttrig,part_1_10} args={}
424474
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_10_20 name={evttrig,part_10_20} args={}
@@ -427,6 +477,7 @@ NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_15_20
427477
DROP TABLE a_temp_tbl;
428478
NOTICE: NORMAL: orig=t normal=f istemp=t type=table identity=pg_temp.a_temp_tbl name={pg_temp,a_temp_tbl} args={}
429479
DROP EVENT TRIGGER regress_event_trigger_report_dropped;
480+
DROP EVENT TRIGGER regress_event_trigger_report_end;
430481
-- only allowed from within an event trigger function, should fail
431482
select pg_event_trigger_table_rewrite_oid();
432483
ERROR: pg_event_trigger_table_rewrite_oid() can only be called in a table_rewrite event trigger function

src/test/regress/sql/event_trigger.sql

+24-2
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ DROP ROLE regress_evt_user;
273273
DROP EVENT TRIGGER regress_event_trigger_drop_objects;
274274
DROP EVENT TRIGGER undroppable;
275275

276+
-- Event triggers on relations.
276277
CREATE OR REPLACE FUNCTION event_trigger_report_dropped()
277278
RETURNS event_trigger
278279
LANGUAGE plpgsql
@@ -291,10 +292,26 @@ BEGIN
291292
END; $$;
292293
CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop
293294
EXECUTE PROCEDURE event_trigger_report_dropped();
295+
CREATE OR REPLACE FUNCTION event_trigger_report_end()
296+
RETURNS event_trigger
297+
LANGUAGE plpgsql
298+
AS $$
299+
DECLARE r RECORD;
300+
BEGIN
301+
FOR r IN SELECT * FROM pg_event_trigger_ddl_commands()
302+
LOOP
303+
RAISE NOTICE 'END: command_tag=% type=% identity=%',
304+
r.command_tag, r.object_type, r.object_identity;
305+
END LOOP;
306+
END; $$;
307+
CREATE EVENT TRIGGER regress_event_trigger_report_end ON ddl_command_end
308+
EXECUTE PROCEDURE event_trigger_report_end();
309+
294310
CREATE SCHEMA evttrig
295-
CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two')
311+
CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two', col_c SERIAL)
296312
CREATE INDEX one_idx ON one (col_b)
297-
CREATE TABLE two (col_c INTEGER CHECK (col_c > 0) REFERENCES one DEFAULT 42);
313+
CREATE TABLE two (col_c INTEGER CHECK (col_c > 0) REFERENCES one DEFAULT 42)
314+
CREATE TABLE id (col_d int NOT NULL GENERATED ALWAYS AS IDENTITY);
298315

299316
-- Partitioned tables with a partitioned index
300317
CREATE TABLE evttrig.parted (
@@ -312,11 +329,16 @@ CREATE TABLE evttrig.part_15_20 PARTITION OF evttrig.part_10_20 (id)
312329
ALTER TABLE evttrig.two DROP COLUMN col_c;
313330
ALTER TABLE evttrig.one ALTER COLUMN col_b DROP DEFAULT;
314331
ALTER TABLE evttrig.one DROP CONSTRAINT one_pkey;
332+
ALTER TABLE evttrig.one DROP COLUMN col_c;
333+
ALTER TABLE evttrig.id ALTER COLUMN col_d SET DATA TYPE bigint;
334+
ALTER TABLE evttrig.id ALTER COLUMN col_d DROP IDENTITY,
335+
ALTER COLUMN col_d SET DATA TYPE int;
315336
DROP INDEX evttrig.one_idx;
316337
DROP SCHEMA evttrig CASCADE;
317338
DROP TABLE a_temp_tbl;
318339

319340
DROP EVENT TRIGGER regress_event_trigger_report_dropped;
341+
DROP EVENT TRIGGER regress_event_trigger_report_end;
320342

321343
-- only allowed from within an event trigger function, should fail
322344
select pg_event_trigger_table_rewrite_oid();

0 commit comments

Comments
 (0)