feat(stammbaum): add V54 migration for family network
Adds persons.family_member flag and person_relationships table with ON DELETE CASCADE on both FKs, no_self_rel check, unique_rel composite, indexes on both person columns, and partial unique index for symmetric SIBLING_OF pairs (LEAST/GREATEST trick). Refs #358. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
-- Family network: marks a Person as a tree node and stores typed relationships
|
||||||
|
-- between two persons. The tree page (/stammbaum) only shows persons with
|
||||||
|
-- family_member = TRUE. Symmetric types (SPOUSE_OF, SIBLING_OF) are stored once;
|
||||||
|
-- the partial unique index keeps SIBLING_OF pairs from being duplicated in the
|
||||||
|
-- reverse direction.
|
||||||
|
|
||||||
|
ALTER TABLE persons
|
||||||
|
ADD COLUMN family_member BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
|
||||||
|
CREATE TABLE person_relationships (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
person_id UUID NOT NULL REFERENCES persons(id) ON DELETE CASCADE,
|
||||||
|
related_person_id UUID NOT NULL REFERENCES persons(id) ON DELETE CASCADE,
|
||||||
|
relation_type VARCHAR(30) NOT NULL,
|
||||||
|
from_year INTEGER,
|
||||||
|
to_year INTEGER,
|
||||||
|
notes VARCHAR(2000),
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
CONSTRAINT no_self_rel CHECK (person_id <> related_person_id),
|
||||||
|
CONSTRAINT unique_rel UNIQUE (person_id, related_person_id, relation_type)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_person_rel_person_id ON person_relationships(person_id);
|
||||||
|
CREATE INDEX idx_person_rel_related_person_id ON person_relationships(related_person_id);
|
||||||
|
|
||||||
|
-- Symmetric SIBLING_OF: enforce only one row per unordered pair.
|
||||||
|
CREATE UNIQUE INDEX unique_sibling_pair ON person_relationships (
|
||||||
|
LEAST(person_id, related_person_id),
|
||||||
|
GREATEST(person_id, related_person_id)
|
||||||
|
) WHERE relation_type = 'SIBLING_OF';
|
||||||
Reference in New Issue
Block a user