-- GWAS/QTL/MAS 闭环(对应规格 §8.22)5 张新表。 -- 全部幂等,可在已有 dev 库上重复执行。create_all 只建新表,本脚本显式补齐兜底。 -- 2026-08-04 -- ============ bre_gwas_result:GWAS 批次元数据 ============ CREATE TABLE IF NOT EXISTS bre_gwas_result ( id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, dataset_id integer REFERENCES bre_genotyping_dataset(id) ON DELETE CASCADE, trait_id integer REFERENCES bre_trait(id) ON DELETE CASCADE, trait_code varchar(64), method varchar(16), n_individuals integer, n_markers integer, m_after_maf integer, maf_min numeric, n_pc integer, sig_level numeric, threshold_bonf numeric, n_sig_bonf integer, n_sig_fdr integer, n_qtl integer, data_version varchar(32), input_hash varchar(64), engine_version varchar(32), remark varchar(512), created_time timestamp with time zone NOT NULL DEFAULT now(), updated_time timestamp with time zone, is_deleted boolean NOT NULL DEFAULT false, deleted_time timestamp with time zone, created_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, uuid varchar(64) NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_gwas_result_uuid ON bre_gwas_result (uuid); CREATE INDEX IF NOT EXISTS ix_bre_gwas_result_created_deleted ON bre_gwas_result (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_gwas_result_dataset_id ON bre_gwas_result (dataset_id); CREATE INDEX IF NOT EXISTS ix_bre_gwas_result_trait_id ON bre_gwas_result (trait_id); CREATE INDEX IF NOT EXISTS ix_bre_gwas_result_created_id ON bre_gwas_result (created_id); -- ============ bre_gwas_snp:逐标记关联结果 ============ CREATE TABLE IF NOT EXISTS bre_gwas_snp ( id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, gwas_result_id integer NOT NULL REFERENCES bre_gwas_result(id) ON DELETE CASCADE, marker_id integer REFERENCES bre_marker(id) ON DELETE SET NULL, marker_name varchar(64), chromosome varchar(16), position integer, maf numeric, effect numeric, se numeric, t_value numeric, p_value numeric, neg_log10p numeric, q_value numeric, sig_bonf boolean, sig_fdr boolean, created_time timestamp with time zone NOT NULL DEFAULT now(), updated_time timestamp with time zone, is_deleted boolean NOT NULL DEFAULT false, deleted_time timestamp with time zone, created_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, uuid varchar(64) NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_gwas_snp_uuid ON bre_gwas_snp (uuid); CREATE INDEX IF NOT EXISTS ix_bre_gwas_snp_created_deleted ON bre_gwas_snp (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_gwas_snp_gwas_result_id ON bre_gwas_snp (gwas_result_id); CREATE INDEX IF NOT EXISTS ix_bre_gwas_snp_marker_id ON bre_gwas_snp (marker_id); CREATE INDEX IF NOT EXISTS ix_bre_gwas_snp_created_id ON bre_gwas_snp (created_id); -- ============ bre_qtl:QTL 区间(known 人工 / gwas 自动) ============ CREATE TABLE IF NOT EXISTS bre_qtl ( id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, trait_id integer REFERENCES bre_trait(id) ON DELETE CASCADE, chromosome varchar(16), start_bp integer, end_bp integer, peak_marker_id integer REFERENCES bre_marker(id) ON DELETE SET NULL, peak_marker_name varchar(64), peak_p numeric, n_markers integer, effect numeric, source varchar(8) DEFAULT 'known', gwas_result_id integer REFERENCES bre_gwas_result(id) ON DELETE CASCADE, remark varchar(512), created_time timestamp with time zone NOT NULL DEFAULT now(), updated_time timestamp with time zone, is_deleted boolean NOT NULL DEFAULT false, deleted_time timestamp with time zone, created_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, uuid varchar(64) NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_qtl_uuid ON bre_qtl (uuid); CREATE INDEX IF NOT EXISTS ix_bre_qtl_created_deleted ON bre_qtl (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_qtl_trait_id ON bre_qtl (trait_id); CREATE INDEX IF NOT EXISTS ix_bre_qtl_peak_marker_id ON bre_qtl (peak_marker_id); CREATE INDEX IF NOT EXISTS ix_bre_qtl_created_id ON bre_qtl (created_id); -- ============ bre_mas_panel:MAS 标记辅助选择面板 ============ CREATE TABLE IF NOT EXISTS bre_mas_panel ( id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, panel_name varchar(128), trait_id integer REFERENCES bre_trait(id) ON DELETE CASCADE, n_markers integer, remark varchar(512), created_time timestamp with time zone NOT NULL DEFAULT now(), updated_time timestamp with time zone, is_deleted boolean NOT NULL DEFAULT false, deleted_time timestamp with time zone, created_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, uuid varchar(64) NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_mas_panel_uuid ON bre_mas_panel (uuid); CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_created_deleted ON bre_mas_panel (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_trait_id ON bre_mas_panel (trait_id); CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_created_id ON bre_mas_panel (created_id); -- ============ bre_mas_panel_marker:面板标记(唯一 panel+marker) ============ CREATE TABLE IF NOT EXISTS bre_mas_panel_marker ( id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, panel_id integer NOT NULL REFERENCES bre_mas_panel(id) ON DELETE CASCADE, marker_id integer REFERENCES bre_marker(id) ON DELETE SET NULL, favorable_dose integer, effect numeric, direction varchar(8) DEFAULT 'high', created_time timestamp with time zone NOT NULL DEFAULT now(), updated_time timestamp with time zone, is_deleted boolean NOT NULL DEFAULT false, deleted_time timestamp with time zone, created_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL, uuid varchar(64) NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_uuid ON bre_mas_panel_marker (uuid); CREATE UNIQUE INDEX IF NOT EXISTS uq_bre_mas_panel_marker_panel_marker ON bre_mas_panel_marker (panel_id, marker_id); CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_created_deleted ON bre_mas_panel_marker (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_panel_id ON bre_mas_panel_marker (panel_id); CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_marker_id ON bre_mas_panel_marker (marker_id); CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_created_id ON bre_mas_panel_marker (created_id);