-- should fail, return type mismatch create event trigger regress_event_trigger on ddl_command_start
execute procedure pg_backend_pid();
-- OK create function test_event_trigger() returns event_trigger as $$
BEGIN
RAISE NOTICE 'test_event_trigger: % %', tg_event, tg_tag;
END
$$ language plpgsql;
-- should fail, can't call it as a plain function SELECT test_event_trigger();
-- should fail, event triggers cannot have declared arguments create function test_event_trigger_arg(name text)
returns event_trigger as $$ BEGIN RETURN1; END $$ language plpgsql;
-- should fail, SQL functions cannot be event triggers create function test_event_trigger_sql() returns event_trigger as $$ SELECT1 $$ language sql;
-- should fail, no elephant_bootstrap entry point create event trigger regress_event_trigger on elephant_bootstrap
execute procedure test_event_trigger();
-- OK create event trigger regress_event_trigger on ddl_command_start
execute procedure test_event_trigger();
-- OK create event trigger regress_event_trigger_end on ddl_command_end
execute function test_event_trigger();
-- should fail, food is not a valid filter variable create event trigger regress_event_trigger2 on ddl_command_start when food in ('sandwich')
execute procedure test_event_trigger();
-- should fail, sandwich is not a valid command tag create event trigger regress_event_trigger2 on ddl_command_start when tag in ('sandwich')
execute procedure test_event_trigger();
-- should fail, create skunkcabbage is not a valid command tag create event trigger regress_event_trigger2 on ddl_command_start when tag in ('create table', 'create skunkcabbage')
execute procedure test_event_trigger();
-- should fail, can't have event triggers on event triggers create event trigger regress_event_trigger2 on ddl_command_start when tag in ('DROP EVENT TRIGGER')
execute procedure test_event_trigger();
-- should fail, can't have event triggers on global objects create event trigger regress_event_trigger2 on ddl_command_start when tag in ('CREATE ROLE')
execute procedure test_event_trigger();
-- should fail, can't have event triggers on global objects create event trigger regress_event_trigger2 on ddl_command_start when tag in ('CREATE DATABASE')
execute procedure test_event_trigger();
-- should fail, can't have event triggers on global objects create event trigger regress_event_trigger2 on ddl_command_start when tag in ('CREATE TABLESPACE')
execute procedure test_event_trigger();
-- should fail, can't have same filter variable twice create event trigger regress_event_trigger2 on ddl_command_start when tag in ('create table') and tag in ('CREATE FUNCTION')
execute procedure test_event_trigger();
-- should fail, can't have arguments create event trigger regress_event_trigger2 on ddl_command_start
execute procedure test_event_trigger('argument not allowed');
-- OK create event trigger regress_event_trigger2 on ddl_command_start when tag in ('create table', 'CREATE FUNCTION')
execute procedure test_event_trigger();
-- OK
comment on event trigger regress_event_trigger is'test comment';
-- drop as non-superuser should fail create role regress_evt_user; set role regress_evt_user; create event trigger regress_event_trigger_noperms on ddl_command_start
execute procedure test_event_trigger();
reset role;
-- test enabling and disabling alter event trigger regress_event_trigger disable; -- fires _trigger2 and _trigger_end should fire, but not _trigger createtable event_trigger_fire1 (a int); alter event trigger regress_event_trigger enable; set session_replication_role = replica; -- fires nothing createtable event_trigger_fire2 (a int); alter event trigger regress_event_trigger enable replica; -- fires only _trigger createtable event_trigger_fire3 (a int); alter event trigger regress_event_trigger enable always; -- fires only _trigger createtable event_trigger_fire4 (a int);
reset session_replication_role; -- fires all three createtable event_trigger_fire5 (a int); -- non-top-level command create function f1() returns int
language plpgsql as $$
begin createtable event_trigger_fire6 (a int); return0;
end $$; select f1(); -- non-top-level command createprocedure p1()
language plpgsql as $$
begin createtable event_trigger_fire7 (a int);
end $$; call p1();
-- clean up alter event trigger regress_event_trigger disable; droptable event_trigger_fire2, event_trigger_fire3, event_trigger_fire4, event_trigger_fire5, event_trigger_fire6, event_trigger_fire7; drop routine f1(), p1();
-- regress_event_trigger_end should fire on these commands grantallontable event_trigger_fire1 to public;
comment ontable event_trigger_fire1 is'here is a comment'; revokeallontable event_trigger_fire1 from public; droptable event_trigger_fire1; createforeign data wrapper useless; create server useless_server foreign data wrapper useless; create user mapping for regress_evt_user server useless_server; alterdefault privileges for role regress_evt_user revokedeleteon tables from regress_evt_user;
-- alter owner to non-superuser should fail alter event trigger regress_event_trigger owner to regress_evt_user;
-- alter owner to superuser should work alter role regress_evt_user superuser; alter event trigger regress_event_trigger owner to regress_evt_user;
-- should fail, name collision alter event trigger regress_event_trigger renameto regress_event_trigger2;
-- OK alter event trigger regress_event_trigger renameto regress_event_trigger3;
-- should fail, doesn't exist any more drop event trigger regress_event_trigger;
-- should fail, regress_evt_user owns some objects drop role regress_evt_user;
-- cleanup before next test -- these are all OK; the second one should emit a NOTICE drop event triggerifexists regress_event_trigger2; drop event triggerifexists regress_event_trigger2; drop event trigger regress_event_trigger3; drop event trigger regress_event_trigger_end;
-- test support for dropped objects CREATESCHEMA schema_one authorization regress_evt_user; CREATESCHEMA schema_two authorization regress_evt_user; CREATESCHEMA audit_tbls authorization regress_evt_user; CREATE TEMP TABLE a_temp_tbl (); SET SESSION AUTHORIZATION regress_evt_user;
-- This tests errors raised within event triggers; the one in audit_tbls -- uses 2nd-level recursive invocation via test_evtrig_dropped_objects(). CREATEORREPLACE FUNCTION undroppable() RETURNS event_trigger
LANGUAGE plpgsql AS $$ DECLARE
obj record;
BEGIN
PERFORM 1FROM pg_tables WHERE tablename = 'undroppable_objs'; IFNOT FOUND THEN
RAISE NOTICE 'table undroppable_objs not found, skipping'; RETURN;
END IF; FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects() JOIN
undroppable_objs USING (object_type, object_identity) LOOP
RAISE EXCEPTION 'object % of type % cannot be dropped',
obj.object_identity, obj.object_type;
END LOOP;
END;
$$;
CREATE EVENT TRIGGER undroppable ON sql_drop
EXECUTE PROCEDURE undroppable();
CREATEORREPLACE FUNCTION test_evtrig_dropped_objects() RETURNS event_trigger
LANGUAGE plpgsql AS $$ DECLARE
obj record;
BEGIN FOR obj INSELECT * FROM pg_event_trigger_dropped_objects() LOOP IF obj.object_type = 'table'THEN
EXECUTE format('DROP TABLE IF EXISTS audit_tbls.%I',
format('%s_%s', obj.schema_name, obj.object_name));
END IF;
-- exclude TOAST objects because they have unstable names SELECT * FROM dropped_objects WHERE schema_name ISNULLOR schema_name <> 'pg_toast';
DROP OWNED BY regress_evt_user; SELECT * FROM dropped_objects WHERE object_type = 'schema';
DROP ROLE regress_evt_user;
DROP EVENT TRIGGER regress_event_trigger_drop_objects; DROP EVENT TRIGGER undroppable;
-- Event triggers on relations. CREATEORREPLACE FUNCTION event_trigger_report_dropped()
RETURNS event_trigger
LANGUAGE plpgsql AS $$ DECLARE r record;
BEGIN FOR r INSELECT * from pg_event_trigger_dropped_objects() LOOP IFNOT r.normal ANDNOT r.original THEN CONTINUE;
END IF;
RAISE NOTICE 'NORMAL: orig=% normal=% istemp=% type=% identity=% schema=% name=% addr=% args=%',
r.original, r.normal, r.is_temporary, r.object_type,
r.object_identity, r.schema_name, r.object_name,
r.address_names, r.address_args;
END LOOP;
END; $$; CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop
EXECUTE PROCEDURE event_trigger_report_dropped(); CREATEORREPLACE FUNCTION event_trigger_report_end()
RETURNS event_trigger
LANGUAGE plpgsql AS $$ DECLARE r RECORD;
BEGIN FOR r INSELECT * FROM pg_event_trigger_ddl_commands() LOOP
RAISE NOTICE 'END: command_tag=% type=% identity=%',
r.command_tag, r.object_type, r.object_identity;
END LOOP;
END; $$; CREATE EVENT TRIGGER regress_event_trigger_report_end ON ddl_command_end
EXECUTE PROCEDURE event_trigger_report_end();
CREATESCHEMA evttrig CREATETABLE one (col_a SERIAL PRIMARYKEY, col_b text DEFAULT'forty two', col_c SERIAL) CREATEINDEX one_idx ON one (col_b) CREATETABLE two (col_c INTEGERCHECK (col_c > 0) REFERENCES one DEFAULT42) CREATETABLE id (col_d intNOTNULL GENERATED ALWAYS AS IDENTITY);
-- Partitioned tables with a partitioned index CREATETABLE evttrig.parted (
id intPRIMARYKEY)
PARTITION BY RANGE (id); CREATETABLE evttrig.part_1_10 PARTITION OF evttrig.parted (id) FORVALUESFROM (1) TO (10); CREATETABLE evttrig.part_10_20 PARTITION OF evttrig.parted (id) FORVALUESFROM (10) TO (20) PARTITION BY RANGE (id); CREATETABLE evttrig.part_10_15 PARTITION OF evttrig.part_10_20 (id) FORVALUESFROM (10) TO (15); CREATETABLE evttrig.part_15_20 PARTITION OF evttrig.part_10_20 (id) FORVALUESFROM (15) TO (20);
ALTERTABLE evttrig.two DROPCOLUMN col_c; ALTERTABLE evttrig.one ALTERCOLUMN col_b DROPDEFAULT; ALTERTABLE evttrig.one DROPCONSTRAINT one_pkey; ALTERTABLE evttrig.one DROPCOLUMN col_c; ALTERTABLE evttrig.id ALTERCOLUMN col_d SET DATA TYPE bigint; ALTERTABLE evttrig.id ALTERCOLUMN col_d DROP IDENTITY, ALTERCOLUMN col_d SET DATA TYPE int; DROPINDEX evttrig.one_idx; DROPSCHEMA evttrig CASCADE; DROPTABLE a_temp_tbl;
-- check unfiltered results, too CREATEORREPLACE FUNCTION event_trigger_report_dropped()
RETURNS event_trigger
LANGUAGE plpgsql AS $$ DECLARE r record;
BEGIN FOR r INSELECT * from pg_event_trigger_dropped_objects() LOOP
RAISE NOTICE 'DROP: orig=% normal=% istemp=% type=% identity=% schema=% name=% addr=% args=%',
r.original, r.normal, r.is_temporary, r.object_type,
r.object_identity, r.schema_name, r.object_name,
r.address_names, r.address_args;
END LOOP;
END; $$;
CREATE FUNCTION event_trigger_dummy_trigger()
RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN RETURN new;
END; $$;
CREATETABLE evtrg_nontemp_table (f1 intprimarykey, f2 intdefault42); CREATETRIGGER evtrg_nontemp_trig BEFOREINSERTON evtrg_nontemp_table
EXECUTE FUNCTION event_trigger_dummy_trigger(); CREATE POLICY evtrg_nontemp_pol ON evtrg_nontemp_table USING (f2 > 0); DROPTABLE evtrg_nontemp_table;
CREATE TEMP TABLE a_temp_tbl (f1 intprimarykey, f2 intdefault42); CREATETRIGGER a_temp_trig BEFOREINSERTON a_temp_tbl
EXECUTE FUNCTION event_trigger_dummy_trigger(); CREATE POLICY a_temp_pol ON a_temp_tbl USING (f2 > 0); DROPTABLE a_temp_tbl;
DROP FUNCTION event_trigger_dummy_trigger();
-- CREATE OPERATOR CLASS without FAMILY clause should report -- both CREATE OPERATOR FAMILY and CREATE OPERATOR CLASS CREATE OPERATOR CLASS evttrigopclass FOR TYPE intUSING btree AS STORAGE int;
DROP EVENT TRIGGER regress_event_trigger_report_dropped; DROP EVENT TRIGGER regress_event_trigger_report_end;
-- only allowed from within an event trigger function, should fail select pg_event_trigger_table_rewrite_oid();
-- test Table Rewrite Event Trigger CREATEORREPLACE FUNCTION test_evtrig_no_rewrite() RETURNS event_trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE EXCEPTION 'rewrites not allowed';
END;
$$;
create event trigger no_rewrite_allowed on table_rewrite
execute procedure test_evtrig_no_rewrite();
createtable rewriteme (id serial primarykey, foo float, bar timestamptz); insertinto rewriteme select x * 1.001from generate_series(1, 500) as t(x); altertable rewriteme altercolumn foo type numeric; altertable rewriteme addcolumn baz intdefault0;
-- test with more than one reason to rewrite a single table CREATEORREPLACE FUNCTION test_evtrig_no_rewrite() RETURNS event_trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE NOTICE 'Table ''%'' is being rewritten (reason = %)',
pg_event_trigger_table_rewrite_oid()::regclass,
pg_event_trigger_table_rewrite_reason();
END;
$$;
altertable rewriteme addcolumn onemore intdefault0, addcolumn another intdefault -1, altercolumn foo type numeric(10,4);
-- matview rewrite when changing access method CREATE MATERIALIZED VIEW heapmv USING heap ASSELECT1AS a; ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap2; DROP MATERIALIZED VIEW heapmv;
-- shouldn't trigger a table_rewrite event altertable rewriteme altercolumn foo type numeric(12,4);
begin; set timezone to'UTC'; altertable rewriteme altercolumn bar type timestamp; set timezone to'0'; altertable rewriteme altercolumn bar type timestamptz; set timezone to'Europe/London'; altertable rewriteme altercolumn bar type timestamp; -- does rewrite
rollback;
-- typed tables are rewritten when their type changes. Don't emit table -- name, because firing order is not stable. CREATEORREPLACE FUNCTION test_evtrig_no_rewrite() RETURNS event_trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE NOTICE 'Table is being rewritten (reason = %)',
pg_event_trigger_table_rewrite_reason();
END;
$$;
create type rewritetype as (a int); createtable rewritemetoo1 of rewritetype; createtable rewritemetoo2 of rewritetype; alter type rewritetype alter attribute a type text cascade;
-- but this doesn't work createtable rewritemetoo3 (a rewritetype); alter type rewritetype alter attribute a type varcharcascade;
droptable rewriteme; drop event trigger no_rewrite_allowed; drop function test_evtrig_no_rewrite();
-- Tests for REINDEX CREATEORREPLACE FUNCTION reindex_start_command()
RETURNS event_trigger AS $$
BEGIN
RAISE NOTICE 'REINDEX START: % %', tg_event, tg_tag;
END;
$$ LANGUAGE plpgsql; CREATE EVENT TRIGGER regress_reindex_start ON ddl_command_start WHEN TAG IN ('REINDEX')
EXECUTE PROCEDURE reindex_start_command(); CREATE FUNCTION reindex_end_command()
RETURNS event_trigger AS $$ DECLARE
obj record;
BEGIN FOR obj INSELECT * FROM pg_event_trigger_ddl_commands() LOOP
RAISE NOTICE 'REINDEX END: command_tag=% type=% identity=%',
obj.command_tag, obj.object_type, obj.object_identity;
END LOOP;
END;
$$ LANGUAGE plpgsql; CREATE EVENT TRIGGER regress_reindex_end ON ddl_command_end WHEN TAG IN ('REINDEX')
EXECUTE PROCEDURE reindex_end_command(); -- Extra event to force the use of a snapshot. CREATE FUNCTION reindex_end_command_snap() RETURNS EVENT_TRIGGER AS $$ BEGIN PERFORM 1; END $$ LANGUAGE plpgsql; CREATE EVENT TRIGGER regress_reindex_end_snap ON ddl_command_end
EXECUTE FUNCTION reindex_end_command_snap();
-- With simple relation CREATETABLE concur_reindex_tab (c1 int); CREATEINDEX concur_reindex_ind ON concur_reindex_tab (c1); -- Both start and end triggers enabled.
REINDEX INDEX concur_reindex_ind;
REINDEX TABLE concur_reindex_tab;
REINDEX INDEX CONCURRENTLY concur_reindex_ind;
REINDEX TABLE CONCURRENTLY concur_reindex_tab; -- with start trigger disabled. ALTER EVENT TRIGGER regress_reindex_start DISABLE;
REINDEX INDEX concur_reindex_ind;
REINDEX INDEX CONCURRENTLY concur_reindex_ind; -- without an index DROPINDEX concur_reindex_ind;
REINDEX TABLE concur_reindex_tab;
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
-- With a Schema CREATESCHEMA concur_reindex_schema; -- No indexes
REINDEX SCHEMA concur_reindex_schema;
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema; CREATETABLE concur_reindex_schema.tab (a int); CREATEINDEX ind ON concur_reindex_schema.tab (a); -- One index reported
REINDEX SCHEMA concur_reindex_schema;
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema; -- One table on schema but no indexes DROPINDEX concur_reindex_schema.ind;
REINDEX SCHEMA concur_reindex_schema;
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema; DROPSCHEMA concur_reindex_schema CASCADE;
-- With a partitioned table, and nothing else. CREATETABLE concur_reindex_part (id int) PARTITION BY RANGE (id);
REINDEX TABLE concur_reindex_part;
REINDEX TABLE CONCURRENTLY concur_reindex_part; -- Partition that would be reindexed, still nothing. CREATETABLE concur_reindex_child PARTITION OF concur_reindex_part FORVALUESFROM (0) TO (10);
REINDEX TABLE concur_reindex_part;
REINDEX TABLE CONCURRENTLY concur_reindex_part; -- Now add some indexes. CREATEINDEX concur_reindex_partidx ON concur_reindex_part (id);
REINDEX INDEX concur_reindex_partidx;
REINDEX INDEX CONCURRENTLY concur_reindex_partidx;
REINDEX TABLE concur_reindex_part;
REINDEX TABLE CONCURRENTLY concur_reindex_part; DROPTABLE concur_reindex_part;
-- Clean up DROP EVENT TRIGGER regress_reindex_start; DROP EVENT TRIGGER regress_reindex_end; DROP EVENT TRIGGER regress_reindex_end_snap; DROP FUNCTION reindex_end_command(); DROP FUNCTION reindex_end_command_snap(); DROP FUNCTION reindex_start_command(); DROPTABLE concur_reindex_tab;
-- test Row Security Event Trigger
RESET SESSION AUTHORIZATION; CREATETABLE event_trigger_test (a integer, b text);
CREATEORREPLACE FUNCTION start_command()
RETURNS event_trigger AS $$
BEGIN
RAISE NOTICE '% - ddl_command_start', tg_tag;
END;
$$ LANGUAGE plpgsql;
CREATEORREPLACE FUNCTION end_command()
RETURNS event_trigger AS $$
BEGIN
RAISE NOTICE '% - ddl_command_end', tg_tag;
END;
$$ LANGUAGE plpgsql;
CREATEORREPLACE FUNCTION drop_sql_command()
RETURNS event_trigger AS $$
BEGIN
RAISE NOTICE '% - sql_drop', tg_tag;
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER start_rls_command ON ddl_command_start WHEN TAG IN ('CREATE POLICY', 'ALTER POLICY', 'DROP POLICY') EXECUTE PROCEDURE start_command();
CREATE EVENT TRIGGER end_rls_command ON ddl_command_end WHEN TAG IN ('CREATE POLICY', 'ALTER POLICY', 'DROP POLICY') EXECUTE PROCEDURE end_command();
CREATE EVENT TRIGGER sql_drop_command ON sql_drop WHEN TAG IN ('DROP POLICY') EXECUTE PROCEDURE drop_sql_command();
CREATE POLICY p1 ON event_trigger_test USING (FALSE); ALTER POLICY p1 ON event_trigger_test USING (TRUE); ALTER POLICY p1 ON event_trigger_test RENAMETO p2; DROP POLICY p2 ON event_trigger_test;
-- Check the object addresses of all the event triggers. SELECT
e.evtname,
pg_describe_object('pg_event_trigger'::regclass, e.oid, 0) as descr,
b.type, b.object_names, b.object_args,
pg_identify_object(a.classid, a.objid, a.objsubid) as ident FROM pg_event_trigger as e,
LATERAL pg_identify_object_as_address('pg_event_trigger'::regclass, e.oid, 0) as b,
LATERAL pg_get_object_address(b.type, b.object_names, b.object_args) as a ORDERBY e.evtname;
DROP EVENT TRIGGER start_rls_command; DROP EVENT TRIGGER end_rls_command; DROP EVENT TRIGGER sql_drop_command;
-- Check the GUC for disabling event triggers CREATE FUNCTION test_event_trigger_guc() RETURNS event_trigger
LANGUAGE plpgsql AS $$ DECLARE
obj record;
BEGIN FOR obj INSELECT * FROM pg_event_trigger_dropped_objects() LOOP
RAISE NOTICE '% dropped %', tg_tag, obj.object_type;
END LOOP;
END;
$$; CREATE EVENT TRIGGER test_event_trigger_guc ON sql_drop WHEN TAG IN ('DROP POLICY') EXECUTE FUNCTION test_event_trigger_guc();
SET event_triggers = 'on'; CREATE POLICY pguc ON event_trigger_test USING (FALSE); DROP POLICY pguc ON event_trigger_test;
CREATE POLICY pguc ON event_trigger_test USING (FALSE); SET event_triggers = 'off'; DROP POLICY pguc ON event_trigger_test;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.