Files
AgentLab/backend/tests
ThearchyHelios ee7b8b2f97 剖析与探查的方言修正(C1)和没有真库时的方言验证(C2)
为什么:剖析是全站唯一主动查业务库的地方,以前只在守卫放行和字符串片段两层上测过,从没在真库上跑过。
本机四个容器(PG 16、MySQL 8.4、MariaDB 11、Oracle Free 23)实测,旧的 IN 列表写法在 PostgreSQL 上整数子列
对文字主键直接报 operator does not exist: character varying = integer,关系一条都核对不了。

C1 方言修正:
- IN 列表的字面量按被指向列的类型族写(key_literals):父列文字写 '12',父列数字只收整数写法的值,父列是时间、
  对不上的不拼并在备注里写「两端类型不同」;子表是 CHAR(n) 时去掉补齐的尾随空格。
- 列类型改存按方言编译的完整写法(VARCHAR2(20 CHAR)、NUMBER(10, 0)、ENUM('a','b')、TIMESTAMP WITH TIME ZONE),
  编译不了退回 str()。SQLAlchemy 把 Oracle 的 VARCHAR2 反射成通用 VARCHAR(容器实测),照数据字典写成 VARCHAR2。
  ENUM / SET 另记 enum_values;Oracle 小写带引号的表和列记 quote_name;各索引(含主键)的首列记进
  index_first_columns(下一波取值观察判断能不能对大表发窗口查询)。新探查的快照哈希会变,旧运行封存的不受影响。
- catalog._type_family 认 ENUM / SET 是文字、INTERVAL 不是数字,去掉引号里的取值再认;新增 column_family
  (有 enum_values 的是文字,PostgreSQL 枚举编译出来只有类型名);is_date_column 不再把 ENUM('date') 认成日期列。
- 码值候选:ENUM / SET 不看列名直接算候选,ENUM 列定义里这次没出现的取值也写进码值(含义待填);VARCHAR2(20 CHAR)
  的长度按 20 算;CHAR 码值去尾随空格;MySQL 上写明按排序规则分组、比较(可能不分大小写)。
- 统计信息估出的行数不超过整表统计上限时再跑一次有上限的计数确认,统计过期的大表不再被当成小表做整表统计。
- 日期列的最小值、最大值只看 0001-01-02 到 9999-12-31 之间的值,零日期、占位日期、PG 的 ±infinity 不计入,
  照实写「另有 N 个无效日期未计入」,日期范围里带 invalid 个数(界面显示)。
- 新增取值观察用的方言方法 date_literal / day_trunc / sample_from,以及按日行数、时间窗口里的取值分布、块采样三类
  查询的拼法(窗口上端截在 9999-12-31 之前,不让 infinity 多出一天)。
- 说明文字不再说「抽样」:大表看的是「按存储顺序取前 N 行」;设置项「抽样键值数」改叫「核对键值数」。

C2 验证:
- tests/test_profile_dialect_golden.py:五种方言 × 全部剖析和观察查询的完整 SQL 钉在 tests/fixtures/dialect/,
  sqlglot 逐条解析、过只读守卫,再用 qualify + annotate_types 核对 IN 两边类型族一致(附旧写法的对照)。
- scripts/dialect-it.sh(不进 CI):本机起四个容器,建虚构夹具(保留字列、Oracle 小写带引号的表、CHAR 码值、
  MySQL ENUM、零日期 / infinity / 占位日期、做旧的统计信息、超上限的大表、带索引的日期列),用 AgentLab 自己的
  探查和剖析代码跑全部查询,断言零报错、结论和手算一致。四种库都通过;MariaDB 插入时自己更新行数估算,统计信息
  做不旧,照实打印。把 IN 列表改回旧写法回跑,PG 上照样报出上面那条错误。跑完删容器、留镜像。
2026-10-16 10:25:28 +08:00
..
目录修改提案的依据改存成目录项单独的字段 reason(界面上叫「确认时的依据」,最多 500 字,超了截成 499 字加「…」),不再拼进备注:拼进 note 之后,带依据保存的关联关系再剖析时测量的说法换不了新、和覆盖率那一栏对不上;改了值的关联关系旧依据叠在新依据后面、越存越长;值不变、保存即确认的项撤销审阅回到推断后「依据:使用者说……」还挂着,看起来像使用者确认过一条推断项。去留:值改了(关联关系也一样)换成这次的依据,没写就去掉旧的;值不变的确认换成这次的,不叠;单项确认、驳回留着,撤销审阅去掉;整份提交改了值的、状态改回推断的、双盲复算改写的去掉;剖析刷新关联关系的测量只动备注。校验认 reason(文字、最多 500 字),起草、剖析的合并不碰人工确认的项,导出导入时已确认、已驳回的项连依据一起带,推断、有确证的项不带。表助手背景里已有的依据写成「以前确认时的依据:……」,系统提示词和 propose_changes 的说明写清那不是这次对话里使用者说的话、引用时写「以前确认时的依据写着:……」,遮罩列的项不给。表详情里依据和说明分开写:表级的项在值下面另起一行,列的一格、关联关系另一个悬停图标(读屏念「确认时的依据:……」),状态弹层里也写,驳回的项只在弹层里写;check-catalog-loop 的假服务端照服务端记下依据,补依据和说明分开、弹层、驳回项的检查;README 表助手一行写上依据另存
2026-10-14 15:38:15 +08:00
目录修改提案的依据改存成目录项单独的字段 reason(界面上叫「确认时的依据」,最多 500 字,超了截成 499 字加「…」),不再拼进备注:拼进 note 之后,带依据保存的关联关系再剖析时测量的说法换不了新、和覆盖率那一栏对不上;改了值的关联关系旧依据叠在新依据后面、越存越长;值不变、保存即确认的项撤销审阅回到推断后「依据:使用者说……」还挂着,看起来像使用者确认过一条推断项。去留:值改了(关联关系也一样)换成这次的依据,没写就去掉旧的;值不变的确认换成这次的,不叠;单项确认、驳回留着,撤销审阅去掉;整份提交改了值的、状态改回推断的、双盲复算改写的去掉;剖析刷新关联关系的测量只动备注。校验认 reason(文字、最多 500 字),起草、剖析的合并不碰人工确认的项,导出导入时已确认、已驳回的项连依据一起带,推断、有确证的项不带。表助手背景里已有的依据写成「以前确认时的依据:……」,系统提示词和 propose_changes 的说明写清那不是这次对话里使用者说的话、引用时写「以前确认时的依据写着:……」,遮罩列的项不给。表详情里依据和说明分开写:表级的项在值下面另起一行,列的一格、关联关系另一个悬停图标(读屏念「确认时的依据:……」),状态弹层里也写,驳回的项只在弹层里写;check-catalog-loop 的假服务端照服务端记下依据,补依据和说明分开、弹层、驳回项的检查;README 表助手一行写上依据另存
2026-10-14 15:38:15 +08:00
目录修改提案的依据改存成目录项单独的字段 reason(界面上叫「确认时的依据」,最多 500 字,超了截成 499 字加「…」),不再拼进备注:拼进 note 之后,带依据保存的关联关系再剖析时测量的说法换不了新、和覆盖率那一栏对不上;改了值的关联关系旧依据叠在新依据后面、越存越长;值不变、保存即确认的项撤销审阅回到推断后「依据:使用者说……」还挂着,看起来像使用者确认过一条推断项。去留:值改了(关联关系也一样)换成这次的依据,没写就去掉旧的;值不变的确认换成这次的,不叠;单项确认、驳回留着,撤销审阅去掉;整份提交改了值的、状态改回推断的、双盲复算改写的去掉;剖析刷新关联关系的测量只动备注。校验认 reason(文字、最多 500 字),起草、剖析的合并不碰人工确认的项,导出导入时已确认、已驳回的项连依据一起带,推断、有确证的项不带。表助手背景里已有的依据写成「以前确认时的依据:……」,系统提示词和 propose_changes 的说明写清那不是这次对话里使用者说的话、引用时写「以前确认时的依据写着:……」,遮罩列的项不给。表详情里依据和说明分开写:表级的项在值下面另起一行,列的一格、关联关系另一个悬停图标(读屏念「确认时的依据:……」),状态弹层里也写,驳回的项只在弹层里写;check-catalog-loop 的假服务端照服务端记下依据,补依据和说明分开、弹层、驳回项的检查;README 表助手一行写上依据另存
2026-10-14 15:38:15 +08:00