@@ -4501,12 +4501,12 @@ DROP FUNCTION f1;
4501
4501
subtest end
4502
4502
4503
4503
# ==============================================================================
4504
- # Test information_schema.triggers
4504
+ # Test information_schema.triggers and pg_catalog.pg_trigger
4505
4505
# ==============================================================================
4506
4506
4507
- subtest information_schema_triggers
4507
+ subtest trigger_introspection
4508
4508
4509
- # Create test tables and trigger functions
4509
+ # Create test tables and trigger functions.
4510
4510
statement ok
4511
4511
CREATE TABLE test_triggers (
4512
4512
id INT PRIMARY KEY,
@@ -4601,27 +4601,40 @@ CREATE FUNCTION trigger_func3() RETURNS TRIGGER AS $$
4601
4601
END;
4602
4602
$$ LANGUAGE PLpgSQL;
4603
4603
4604
- # TODO(sql-queries): Enable tests for statement-level triggers when supported.
4605
- # statement ok
4606
- # CREATE TRIGGER after_update_transition
4607
- # AFTER UPDATE ON test_triggers
4608
- # REFERENCING OLD TABLE AS old_data NEW TABLE AS new_data
4609
- # FOR EACH STATEMENT
4610
- # EXECUTE FUNCTION trigger_func3();
4611
-
4612
- # TODO(sql-queries): Enable tests for statement-level triggers when supported.
4613
- # query TTTTT colnames
4614
- # SELECT
4615
- # trigger_name,
4616
- # action_orientation,
4617
- # action_reference_old_table,
4618
- # action_reference_new_table,
4619
- # action_reference_old_row
4620
- # FROM information_schema.triggers
4621
- # WHERE trigger_name = 'after_update_transition';
4622
- # ----
4604
+ # TODO(#126362, #135655): Enable tests for statement-level triggers when supported.
4605
+ statement error statement-level triggers are not yet supported
4606
+ CREATE TRIGGER after_update_transition
4607
+ AFTER UPDATE ON test_triggers
4608
+ REFERENCING OLD TABLE AS old_data NEW TABLE AS new_data
4609
+ FOR EACH STATEMENT
4610
+ EXECUTE FUNCTION trigger_func3();
4611
+
4612
+ # TODO(#126362, #135655): Enable tests for statement-level triggers when supported.
4613
+ # The expected results are:
4623
4614
# trigger_name action_orientation action_reference_old_table action_reference_new_table action_reference_old_row
4624
4615
# after_update_transition STATEMENT old_data new_data NULL
4616
+ query TTTTT colnames
4617
+ SELECT
4618
+ trigger_name,
4619
+ action_orientation,
4620
+ action_reference_old_table,
4621
+ action_reference_new_table,
4622
+ action_reference_old_row
4623
+ FROM information_schema.triggers
4624
+ WHERE trigger_name = 'after_update_transition';
4625
+ ----
4626
+ trigger_name action_orientation action_reference_old_table action_reference_new_table action_reference_old_row
4627
+
4628
+ # TODO(#126362, #135655): Populate tgoldtable and tgnewtable.
4629
+ # The expected results are:
4630
+ # tgname tgoldtable tgnewtable
4631
+ # after_update_transition old_data new_data
4632
+ query TTT colnames
4633
+ SELECT tgname, tgoldtable, tgnewtable
4634
+ FROM pg_catalog.pg_trigger
4635
+ WHERE tgname = 'after_update_transition';
4636
+ ----
4637
+ tgname tgoldtable tgnewtable
4625
4638
4626
4639
# Test multiple event types (create a trigger for multiple events).
4627
4640
statement ok
@@ -4671,6 +4684,125 @@ trigger_schema trigger_count
4671
4684
other_schema 1
4672
4685
public 7
4673
4686
4687
+ # Create a trigger with arguments to test tgnargs and tgargs.
4688
+ statement ok
4689
+ CREATE TRIGGER trigger_with_args
4690
+ AFTER INSERT ON test_triggers
4691
+ FOR EACH ROW
4692
+ EXECUTE FUNCTION trigger_func1('arg1', 'arg2', 'test value with spaces');
4693
+
4694
+ # Test pg_catalog.pg_trigger.
4695
+ query TIBITTT colnames
4696
+ SELECT
4697
+ tgname,
4698
+ tgtype,
4699
+ tgfoid > 0 AS has_func_oid,
4700
+ tgnargs,
4701
+ tgenabled,
4702
+ tgoldtable,
4703
+ tgnewtable
4704
+ FROM pg_catalog.pg_trigger
4705
+ WHERE tgrelid = 'test_triggers'::regclass
4706
+ ORDER BY tgname;
4707
+ ----
4708
+ tgname tgtype has_func_oid tgnargs tgenabled tgoldtable tgnewtable
4709
+ after_delete_row 9 true 0 A NULL NULL
4710
+ after_insert_row 5 true 0 A NULL NULL
4711
+ before_update_row 19 true 0 A NULL NULL
4712
+ multi_event_trigger 31 true 0 A NULL NULL
4713
+ trigger_with_args 5 true 3 A NULL NULL
4714
+
4715
+ # Test INSTEAD OF triggers (not yet implemented)
4716
+ statement error pgcode 42809 "test_triggers" is a table\nDETAIL: Tables cannot have INSTEAD OF triggers.
4717
+ CREATE TRIGGER instead_of_trigger INSTEAD OF INSERT ON test_triggers
4718
+ FOR EACH ROW EXECUTE FUNCTION trigger_func1();
4719
+
4720
+ statement error pgcode 42809 "test_triggers" is a table\nDETAIL: Tables cannot have INSTEAD OF triggers.
4721
+ CREATE TRIGGER instead_of_update_trigger INSTEAD OF UPDATE ON test_triggers
4722
+ FOR EACH ROW EXECUTE FUNCTION trigger_func1();
4723
+
4724
+ statement error pgcode 42809 "test_triggers" is a table\nDETAIL: Tables cannot have INSTEAD OF triggers.
4725
+ CREATE TRIGGER instead_of_delete_trigger INSTEAD OF DELETE ON test_triggers
4726
+ FOR EACH ROW EXECUTE FUNCTION trigger_func1();
4727
+
4728
+ # Test TRUNCATE triggers (not yet implemented)
4729
+ statement error statement-level triggers are not yet supported
4730
+ CREATE TRIGGER truncate_trigger AFTER TRUNCATE ON test_triggers
4731
+ FOR EACH STATEMENT EXECUTE FUNCTION trigger_func1();
4732
+
4733
+ statement error statement-level triggers are not yet supported
4734
+ CREATE TRIGGER before_truncate_trigger BEFORE TRUNCATE ON test_triggers
4735
+ FOR EACH STATEMENT EXECUTE FUNCTION trigger_func1();
4736
+
4737
+ # Test tgtype bitmap calculation
4738
+ # Bit 0: FOR EACH ROW (1) or FOR EACH STATEMENT (0)
4739
+ # Bit 1: BEFORE (2) or AFTER (0)
4740
+ # Bits 2-4: INSERT (4), DELETE (8), UPDATE (16)
4741
+ # TODO(#126363, #135657): Add tests for INSTEAD OF and TRUNCATE triggers here when supported.
4742
+ query TBBBBBBB colnames
4743
+ SELECT
4744
+ tgname,
4745
+ (tgtype::INT & 1) > 0 AS is_row_level,
4746
+ (tgtype::INT & 2) > 0 AS is_before,
4747
+ (tgtype::INT & 4) > 0 AS has_insert,
4748
+ (tgtype::INT & 8) > 0 AS has_delete,
4749
+ (tgtype::INT & 16) > 0 AS has_update,
4750
+ (tgtype::INT & 32) > 0 AS has_instead,
4751
+ (tgtype::INT & 64) > 0 AS has_truncate
4752
+ FROM pg_catalog.pg_trigger
4753
+ WHERE tgrelid = 'test_triggers'::regclass
4754
+ ORDER BY tgname;
4755
+ ----
4756
+ tgname is_row_level is_before has_insert has_delete has_update has_instead has_truncate
4757
+ after_delete_row true false false true false false false
4758
+ after_insert_row true false true false false false false
4759
+ before_update_row true true false false true false false
4760
+ multi_event_trigger true true true true true false false
4761
+ trigger_with_args true false true false false false false
4762
+
4763
+ # Check trigger arguments and column attributes.
4764
+ # TODO(#135656): Populate the tgattr column.
4765
+ query TITT colnames
4766
+ SELECT
4767
+ tgname,
4768
+ tgnargs,
4769
+ encode(tgargs, 'escape') AS tgargs,
4770
+ tgattr
4771
+ FROM pg_catalog.pg_trigger
4772
+ WHERE tgrelid = 'test_triggers'::regclass
4773
+ ORDER BY tgname;
4774
+ ----
4775
+ tgname tgnargs tgargs tgattr
4776
+ after_delete_row 0 · ·
4777
+ after_insert_row 0 · ·
4778
+ before_update_row 0 · ·
4779
+ multi_event_trigger 0 · ·
4780
+ trigger_with_args 3 arg1\000arg2\000test value with spaces\000 ·
4781
+
4782
+ # Test trigger with WHEN condition.
4783
+ query TTT colnames
4784
+ SELECT
4785
+ tgname,
4786
+ tgqual,
4787
+ tgattr
4788
+ FROM pg_catalog.pg_trigger
4789
+ WHERE tgrelid = 'test_triggers'::regclass AND tgqual IS NOT NULL;
4790
+ ----
4791
+ tgname tgqual tgattr
4792
+ before_update_row ((new).value > 100) ·
4793
+
4794
+ # Test cross-schema trigger.
4795
+ query TTT colnames
4796
+ SELECT
4797
+ tgname,
4798
+ tgrelid::regclass::text AS table_name,
4799
+ tgfoid::regproc::text AS trigger_func_name
4800
+ FROM pg_catalog.pg_trigger
4801
+ WHERE tgrelid = 'other_schema.test_table'::regclass;
4802
+ ----
4803
+ tgname table_name trigger_func_name
4804
+ other_schema_trigger test_table trigger_func1
4805
+
4674
4806
# Clean up
4675
4807
statement ok
4676
4808
DROP TABLE test_triggers CASCADE;
0 commit comments