li7y/migrations/20240703122248_item_add_parent.up.sql
Simon Bruder 00d7647187
Switch to sqlx
While diesel has a native rust interface, writing more complex queries
is easier when you can just pass a SQL query string.
2024-07-19 00:05:26 +02:00

51 lines
1.1 KiB
PL/PgSQL

-- SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
ALTER TABLE items
ADD parent UUID REFERENCES items(id);
CREATE RECURSIVE VIEW item_tree (id, parents) AS (
SELECT id, ARRAY[]::UUID[] AS parents FROM items WHERE parent IS NULL
UNION
SELECT items.id, item_tree.parents || items.parent FROM items, item_tree WHERE items.parent = item_tree.id
);
CREATE FUNCTION check_item_cycle()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.parent IS NULL THEN
RETURN NEW;
END IF;
IF NEW.id = NEW.parent THEN
RAISE EXCEPTION 'Cycle detected';
END IF;
IF (WITH RECURSIVE cte AS (
SELECT id, parent
FROM items
WHERE id = NEW.parent
UNION
SELECT items.id, items.parent
FROM items, cte
WHERE items.id = cte.parent
)
SELECT 1
FROM cte
WHERE parent = NEW.id
LIMIT 1) THEN
RAISE EXCEPTION 'Cycle detected';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER prevent_item_cycle
BEFORE INSERT OR UPDATE ON items
FOR EACH ROW
EXECUTE FUNCTION check_item_cycle();