Find triggers that try prevent updating data in a certain column but prevent also certain legal updates - updates that write to a field a value that was in the field before the update.
Notes
Find row level BEFORE triggers that raise a warning or error but do not have any condition - in the function nor in the WHEN clause of the trigger.
Type
Problem detection (Each row in the result could represent a flaw in the design)
Add a condition to the WHEN clause of the trigger. For instance, if we want to prevent changing the registration time and the registrator, then the trigger should have the WHEN clause: WHEN (OLD.registration_time<>NEW.registration_time OR OLD.registrator_id<>NEW.registrator_id)
Data Source
INFORMATION_SCHEMA+system catalog
SQL Query
WITH Tr AS (SELECT
n.nspname AS trigger_schema,
t.tgname AS trigger_name,
em.text AS event_manipulation,
c.relname AS trigger_table,
np.nspname AS routine_schema,
p.proname AS routine_name,
p.prosrc AS routine_definition,
(SELECT DISTINCT action_condition FROM INFORMATION_SCHEMA.triggers AS it WHERE it.trigger_schema=n.nspname AND it.event_object_table=c.relname AND it.trigger_name=t.tgname) AS action_condition,
CASE t.tgtype::integer & 1
WHEN 1 THEN 'ROW'
ELSE 'STATEMENT'
END AS action_orientation,
CASE t.tgtype::integer & 66
WHEN 2 THEN 'BEFORE'
WHEN 64 THEN 'INSTEAD OF'
ELSE 'AFTER'
END AS action_timing
FROM pg_namespace n,
pg_class c,
pg_trigger t,
pg_proc p,
pg_namespace np,
( VALUES (4,'INSERT'), (8,'DELETE'), (16,'UPDATE'), (32,'TRUNCATE')) em(num, text)
WHERE n.oid = c.relnamespace
AND c.oid = t.tgrelid
AND t.tgfoid=p.oid
AND p.pronamespace=np.oid
AND (t.tgtype::integer & em.num) <> 0
AND NOT t.tgisinternal
AND NOT pg_is_other_temp_schema(n.oid))
SELECT trigger_schema, trigger_table, action_timing, event_manipulation, action_orientation, action_condition, routine_name, regexp_replace(routine_definition,'[\r\n]',' ','g') AS routine_definition
FROM Tr
WHERE action_orientation='ROW'
AND action_timing='BEFORE'
AND event_manipulation='UPDATE'
AND routine_definition~* '[[:space:]]+(WARNING|EXCEPTION)[[:space:]]+'
AND routine_definition!~* 'IF[[:space:]][^;]*[(OLD|NEW)[^;]*(OLD|NEW).*[[:space:]]+(WARNING|EXCEPTION)[[:space:]]+'
AND (action_condition !~*'(OLD|NEW).*(OLD|NEW)' OR action_condition IS NULL)
ORDER BY trigger_schema, trigger_table, routine_name;
Collections
This query belongs to the following collections:
Name
Description
Find problems automatically
Queries, that results point to problems in the database. Each query in the collection produces an initial assessment. However, a human reviewer has the final say as to whether there is a problem or not .
Categories
This query is classified under the following categories:
Name
Description
Triggers and rules
Queries of this category provide information about triggers and rules in a database.