I encountered a problem which makes me suspect Postgres deletes rows from dependent tables (ON DELETE CASCADE) only after it already deleted the original row.
I have these tables:
CREATE TABLE IF NOT EXISTS function (
id UUID PRIMARY KEY,
level VARCHAR(4) NOT NULL CHECK (level IN ('ORG', 'DEP', 'GRP', 'SESS')),
name VARCHAR(64) NOT NULL UNIQUE,
type VARCHAR(15) NOT NULL CHECK (type IN ('SYSTEM', 'SYS-AUTO-ASSIGN', 'CUSTOM'))
);
CREATE TABLE IF NOT EXISTS function_inclusion (
super_function UUID REFERENCES function (id) ON DELETE CASCADE,
sub_function UUID REFERENCES function (id) ON DELETE CASCADE,
UNIQUE (super_function, sub_function)
);
I created a trigger (before delete) on the function_inclusion table:
CREATE OR REPLACE FUNCTION trg_function_inclusion_del_bef()
RETURNS trigger AS
$func$
DECLARE
function_type VARCHAR(15);
BEGIN
SELECT type INTO function_type FROM function WHERE id = OLD.super_function;
RAISE NOTICE 'function_type: %', function_type;
-- do stuff based on the function_type of the super_function
CASE
WHEN function_type = 'SYSTEM' OR function_type = 'SYS-AUTO-ASSIGN' THEN
-- (do stuff)
WHEN function_type = 'CUSTOM' THEN
-- (do stuff)
ELSE RAISE EXCEPTION 'The function % doesn''t have a correct type', OLD.super_function;
END CASE;
RETURN OLD;
END
$func$
LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS function_inclusion_delete_before ON function_inclusion CASCADE;
CREATE TRIGGER function_inclusion_delete_before
BEFORE DELETE ON function_inclusion
FOR EACH ROW
EXECUTE PROCEDURE trg_function_inclusion_del_bef();
Let's say I have 2 functions and a function_inclusion:
INSERT INTO function (id, level, name, type)
VALUES ('abcf3dbc-9433-4b73-b9c1-f00745dc1175', 'DEP', 'custom-function-1', 'CUSTOM');
INSERT INTO function (id, level, name, type)
VALUES ('360bde13-7953-49ed-a923-793b2d828d7e', 'DEP', 'custom-function-2', 'CUSTOM');
INSERT INTO function_inclusion (super_function, sub_function)
VALUES ('abcf3dbc-9433-4b73-b9c1-f00745dc1175', '360bde13-7953-49ed-a923-793b2d828d7e');
When I delete the super_function:
DELETE FROM function WHERE id = 'abcf3dbc-9433-4b73-b9c1-f00745dc1175';
I get this error:
NOTICE: function_type: <NULL>
Query 1 ERROR: ERROR: The function abcf3dbc-9433-4b73-b9c1-f00745dc1175 doesn't have a correct type
CONTEXT: PL/pgSQL function trg_function_inclusion_del_bef() line 13 at RAISE
SQL statement "DELETE FROM ONLY "public"."function_inclusion" WHERE $1 OPERATOR(pg_catalog.=) "super_function""
So it seems like the function has already been deleted and I cannot access it anymore from my trigger on function_inclusion.
I tried to find more information about 'ON DELETE CASCADE', but everywhere I read it only says that 'the referencing rows are automatically deleted', no mention of which get deleted first, the referencing rows or the referenced row.
Does postgres first delete the original (referenced) row before it deletes rows in dependent (referencing) tables? And if so, how can I implement the same thing without having to store redundant data in my function_inclusion table?