| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- -- ============================================================================
- -- AI 研判 · 补齐约束与索引(insight_agent_tables.sql 的补丁)
- --
- -- 背景:agent_insight_session / agent_insight_message 两张表的**列**已按
- -- insight_agent_tables.sql 建好(含 NOT NULL 与主键),但建表时未带上
- -- 约束与索引:
- -- · 缺 uk_aim_session_seq UNIQUE (session_id, seq)
- -- · 缺 fk_aim_session FOREIGN KEY ... ON DELETE CASCADE
- -- · 缺 idx_ais_case_list / idx_ais_ctx_hash / idx_aim_output
- -- 原因是那些约束写在 CREATE TABLE 语句**内部**,而
- -- CREATE TABLE IF NOT EXISTS 对「表已存在」的情况整句跳过,
- -- 不会补建内部约束 —— 只补建了语句外的 CREATE INDEX IF NOT EXISTS。
- --
- -- 本脚本幂等:约束先 DROP IF EXISTS 再 ADD,索引用 IF NOT EXISTS。
- -- 重复执行结果一致。
- --
- -- 执行库:PostgreSQL(master)
- -- ============================================================================
- -- 加约束需要 ACCESS EXCLUSIVE 锁:设个超时,避免在后端有长事务时无限等待
- SET lock_timeout = '5s';
- -- ============================================================
- -- 1) seq 会话内唯一
- -- 与 UPDATE ... RETURNING last_seq 的行级锁形成双保险:
- -- 行锁防并发、唯一约束防「万一锁失效」时静默写入重号。
- -- ============================================================
- ALTER TABLE agent_insight_message DROP CONSTRAINT IF EXISTS uk_aim_session_seq;
- ALTER TABLE agent_insight_message
- ADD CONSTRAINT uk_aim_session_seq UNIQUE (session_id, seq);
- -- ============================================================
- -- 2) 会话删除级联删消息
- -- 否则删会话会留下孤儿消息,越权/脏数据都从这里来。
- -- ============================================================
- ALTER TABLE agent_insight_message DROP CONSTRAINT IF EXISTS fk_aim_session;
- ALTER TABLE agent_insight_message
- ADD CONSTRAINT fk_aim_session FOREIGN KEY (session_id)
- REFERENCES agent_insight_session (id) ON DELETE CASCADE;
- -- ============================================================
- -- 3) 历史列表
- -- WHERE case_id=? AND biz_type=? ORDER BY pinned DESC, last_message_at DESC
- -- ============================================================
- CREATE INDEX IF NOT EXISTS idx_ais_case_list
- ON agent_insight_session (case_id, biz_type, last_message_at DESC);
- -- ============================================================
- -- 4) 同条件复用 / 去重提示:WHERE case_id=? AND context_hash=?
- -- ============================================================
- CREATE INDEX IF NOT EXISTS idx_ais_ctx_hash
- ON agent_insight_session (case_id, context_hash);
- -- ============================================================
- -- 5) 线索聚合(部分索引)
- -- 绝大多数消息没有结构化产物,全量索引是浪费。
- -- ============================================================
- CREATE INDEX IF NOT EXISTS idx_aim_output
- ON agent_insight_message (case_id, create_at DESC)
- WHERE output_json IS NOT NULL;
- -- ============================================================
- -- 6) 场景默认值对齐(旧库列默认值仍是 CALL_CONTINUOUS)
- -- 仅改 DEFAULT,不动存量数据:存量行按原场景语义保留,
- -- 新场景查询一律显式带 biz_type,不依赖默认值。
- -- ============================================================
- ALTER TABLE agent_insight_session
- ALTER COLUMN biz_type SET DEFAULT 'GRAPH_RELATION';
- -- ============================================================
- -- 7) 表 / 列注释(与 insight_agent_tables.sql 保持一致,便于运维直读)
- -- ============================================================
- COMMENT ON TABLE agent_insight_session IS 'AI研判会话(独立存储,不复用通用对话表)';
- COMMENT ON COLUMN agent_insight_session.case_id IS '案件ID:案件级硬隔离边界,所有查询强制携带';
- COMMENT ON COLUMN agent_insight_session.biz_type IS '研判场景:本期恒 GRAPH_RELATION(对象关系分析),为将来同表扩场景预留';
- COMMENT ON COLUMN agent_insight_session.scope IS '分析范围:BATCH=当前图谱整体,PAIR=单个节点/关系(预留)';
- COMMENT ON COLUMN agent_insight_session.context IS '查询条件+图谱快照(节点/关系),动态系统提示词的数据源';
- COMMENT ON COLUMN agent_insight_session.context_hash IS 'context 的 sha256,用于同条件复用与去重提示';
- COMMENT ON COLUMN agent_insight_session.sys_prompt IS '会话内实际使用的完整系统提示词,仅运维/追溯读,不通过接口下发';
- COMMENT ON COLUMN agent_insight_session.last_seq IS '会话内消息序号水位,消息 seq 由它原子分配';
- COMMENT ON COLUMN agent_insight_session.status IS 'ACTIVE | STREAMING(流式进行中,用于并发抢占)| ARCHIVED';
- COMMENT ON TABLE agent_insight_message IS 'AI研判消息(独立存储;case_id 冗余自会话表,用于强制归属过滤)';
- COMMENT ON COLUMN agent_insight_message.seq IS '会话内单调序号,分页排序列(勿用 create_at/id 排序)';
- COMMENT ON COLUMN agent_insight_message.case_id IS '冗余自会话表:保证消息查询永远可带 case_id 过滤';
- COMMENT ON COLUMN agent_insight_message.message_type IS 'chat | first_round(首轮自动分析) | followup';
- COMMENT ON COLUMN agent_insight_message.output_json IS '```insight 围栏解析后的结构化产物,仅首轮 assistant 消息有值';
- COMMENT ON COLUMN agent_insight_message.status IS 'DONE | INTERRUPTED(用户中止/异常时保留已生成正文)';
|