-- 007_fix_canonical_order.sql -- 정사 경로 순서 계산 로직 수정 -- 기존 트리거 삭제 DROP TRIGGER IF EXISTS trigger_update_canonical_order ON memo_nodes; DROP FUNCTION IF EXISTS update_canonical_order(); -- 정사 경로 순서를 올바르게 계산하는 함수 CREATE OR REPLACE FUNCTION update_canonical_order() RETURNS TRIGGER AS $$ BEGIN -- 정사로 설정될 때 IF NEW.is_canonical = TRUE AND (OLD.is_canonical IS NULL OR OLD.is_canonical = FALSE) THEN -- 같은 부모를 가진 다른 형제 노드들의 정사 상태 해제 (분기점에서 하나만 선택) IF NEW.parent_id IS NOT NULL THEN UPDATE memo_nodes SET is_canonical = FALSE, canonical_order = NULL, story_path = NULL WHERE tree_id = NEW.tree_id AND parent_id = NEW.parent_id AND id != NEW.id AND is_canonical = TRUE; END IF; -- 정사 경로 업데이트 NEW.story_path = COALESCE(NEW.path, ''); -- 순서는 별도 함수에서 일괄 계산 PERFORM recalculate_canonical_orders(NEW.tree_id); END IF; -- 정사에서 제외될 때 IF NEW.is_canonical = FALSE AND OLD.is_canonical = TRUE THEN NEW.canonical_order = NULL; NEW.story_path = NULL; -- 순서 재계산 PERFORM recalculate_canonical_orders(NEW.tree_id); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- 트리별 정사 경로 순서를 DFS로 재계산하는 함수 CREATE OR REPLACE FUNCTION recalculate_canonical_orders(tree_uuid UUID) RETURNS VOID AS $$ DECLARE current_order INTEGER := 1; BEGIN -- 모든 정사 노드의 순서를 NULL로 초기화 UPDATE memo_nodes SET canonical_order = NULL WHERE tree_id = tree_uuid AND is_canonical = TRUE; -- DFS로 순서 할당 (재귀 CTE 사용) WITH RECURSIVE canonical_path AS ( -- 루트 노드들 (정사인 것만) SELECT id, parent_id, title, 1 as order_num, ARRAY[id] as path FROM memo_nodes WHERE tree_id = tree_uuid AND parent_id IS NULL AND is_canonical = TRUE UNION ALL -- 자식 노드들 (정사인 것만) SELECT n.id, n.parent_id, n.title, cp.order_num + 1 as order_num, cp.path || n.id FROM memo_nodes n INNER JOIN canonical_path cp ON n.parent_id = cp.id WHERE n.tree_id = tree_uuid AND n.is_canonical = TRUE ) UPDATE memo_nodes SET canonical_order = cp.order_num FROM canonical_path cp WHERE memo_nodes.id = cp.id; END; $$ LANGUAGE plpgsql; -- 트리거 다시 생성 CREATE TRIGGER trigger_update_canonical_order AFTER UPDATE ON memo_nodes FOR EACH ROW EXECUTE FUNCTION update_canonical_order(); -- 기존 데이터의 순서 재계산 DO $$ DECLARE tree_rec RECORD; BEGIN FOR tree_rec IN SELECT DISTINCT tree_id FROM memo_nodes WHERE is_canonical = TRUE LOOP PERFORM recalculate_canonical_orders(tree_rec.tree_id); END LOOP; END $$;