CREATE TABLE crash_signatures ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), repository_id UUID NOT NULL REFERENCES repositories(id), fingerprint TEXT NOT NULL, sample_trace TEXT, first_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), occurrence_count INT NOT NULL DEFAULT 1, UNIQUE (repository_id, fingerprint) ); CREATE INDEX idx_crash_signatures_repo ON crash_signatures (repository_id); CREATE INDEX idx_crash_signatures_last_seen ON crash_signatures (last_seen_at DESC); CREATE TABLE crash_groups ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), crash_signature_id UUID NOT NULL UNIQUE REFERENCES crash_signatures(id), repository_id UUID NOT NULL REFERENCES repositories(id), title TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'open', forgejo_issue_id INT, forgejo_issue_url TEXT, first_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_crash_groups_repo ON crash_groups (repository_id); CREATE INDEX idx_crash_groups_status ON crash_groups (status); CREATE INDEX idx_crash_groups_sig ON crash_groups (crash_signature_id); ALTER TABLE artifacts ADD COLUMN signature_id UUID REFERENCES crash_signatures(id); ALTER TABLE artifacts ADD COLUMN fingerprint TEXT; CREATE INDEX idx_artifacts_signature ON artifacts (signature_id); CREATE INDEX idx_artifacts_fingerprint ON artifacts (fingerprint); -- Full-text search support ALTER TABLE artifacts ADD COLUMN search_vector tsvector; CREATE INDEX idx_artifacts_search ON artifacts USING GIN (search_vector); CREATE OR REPLACE FUNCTION artifacts_search_update() RETURNS trigger AS $$ BEGIN NEW.search_vector := setweight(to_tsvector('english', COALESCE(NEW.crash_message, '')), 'A') || setweight(to_tsvector('english', COALESCE(NEW.stack_trace, '')), 'B') || setweight(to_tsvector('english', COALESCE(NEW.type, '')), 'C'); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER artifacts_search_trigger BEFORE INSERT OR UPDATE ON artifacts FOR EACH ROW EXECUTE FUNCTION artifacts_search_update();