Skip to content

feat: SQL 查询结果支持按来源分析补全字段注释 - #428

Merged
feigeCode merged 1 commit into
feigeCode:mainfrom
ekovovo:feat/sql-result-column-comments-lineage
Oct 20, 2026
Merged

feigeCode merged 1 commit into
feigeCode:mainfrom
ekovovo:feat/sql-result-column-comments-lineage

Conversation

@ekovovo

@ekovovo ekovovo commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

背景

「设置 - 列头显示字段注释」开关此前只对「表数据」页签生效:打开表能看到字段注释,
但通过「新建查询」执行 SQL 得到的结果列始终没有注释。

本次改动让该开关同时覆盖表数据与 SQL 查询结果,并通过 SQL 来源分析(column
lineage)把结果列可靠地映射回源表字段,重点解决 join、CTE、列别名、表达式/函数
等查询无法显示注释的问题。

实现思路

新增一个基于 sqlparser AST 的保守型来源分析模块,从 SELECT 语句推导每个结果列
对应的基表字段;执行查询后再按分析结果并发拉取相关表的列元数据,把注释贴回结果
列。无法唯一确定来源时宁可不显示,避免出现错误注释。

来源分析

  • 支持 join:限定列 u.id、db.table.col / schema.table.col;非限定列在所有
    候选表中唯一存在时才继承注释
  • 支持非递归 CTE:按定义顺序构建虚拟关系,并继续追踪到基表;CTE 名可覆盖同名基表
  • 支持 FROM 派生表:递归分析子查询并传递别名
  • 支持列别名:SELECT name AS label 仍映射回 name
  • 支持通配符:SELECT * / u.* 按源表列顺序展开
  • 支持单字段表达式/函数:UPPER(name)、SUM(amount)、COUNT(DISTINCT name) 等
    只引用一个源字段的表达式继承该字段注释
  • 多字段表达式(price * qty)、常量、多来源表达式不显示注释
  • 递归 CTE、UNION/EXCEPT/INTERSECT、SELECT * EXCLUDE、表函数等结构标记为
    「分析不完整」,退化为按列名唯一匹配的保守兜底

注释解析策略

  • 来源分析完整且展开列数与结果列数一致时,按列序直接映射注释
  • 分析不完整或列数不一致时,仅当列名在候选表中唯一匹配才显示
  • 任一涉及表的元数据读取失败时一律不显示,避免相同列名导致的错误映射

性能与时机

  • 仅在「列头显示字段注释」开关打开时执行 AST 分析与元数据查询,关闭时零额外开销
  • 多表列元数据通过 join_all 并发读取,单表失败不影响其它表
  • 结果集自带的列类型信息保持不变,仅补充注释字段
  • 开关打开前已打开的结果页签需刷新或重新执行查询后生效

主要改动

crates/db/src/result_column_lineage.rs(新增)

结果列来源分析模块:

  • ResultColumnLineage / ResultColumnSource / ColumnReference 公共数据结构
  • Analyzer 内部实现:作用域解析、CTE/派生表展开、通配符展开、表达式引用收集
  • analyze_sql_lineage 入口,解析失败或非 SELECT 语句返回 None

crates/db/src/lib.rs / crates/db/src/plugin.rs

  • 导出新模块
  • DatabasePlugin 新增默认方法 analyze_result_column_lineage,复用各插件已有的
    sql_dialect(),无需逐个数据库实现

crates/db_view/src/table_data/data_grid.rs

  • 新增 load_sql_result_column_comments:SQL 结果页签补全注释的入口
  • 新增 load_lineage_table_columns_on_runtime:并发获取多张基表的列元数据
  • 新增 resolve_result_column_comments / resolve_reference_comment /
    resolve_column_comments_by_name:按来源映射注释及保守兜底
  • load_data_with_sql 刷新路径同步支持注释补全,并保持 generation 校验防止过期回写
  • 清理上一轮遗留的 sql_result_needs_schema_meta 及其测试

crates/db_view/src/table_data/results_delegate.rs

  • 新增 set_column_comments:只更新列注释,保留结果集自带的列类型信息

crates/db_view/src/sql_result_tab.rs

  • 初始查询结果创建后调用 load_sql_result_column_comments

兼容性说明

  • 不改变现有 MySQL 二进制单元格纠偏的慢路径逻辑
  • 不改变结果集列类型识别与编辑能力
  • 所有数据库类型均适用,无数据库特定代码分支

测试

新增 16 个单元测试:

  • 来源分析(9 个):join 限定列、限定通配符、跨表歧义列、非递归 CTE、派生表、
    单字段函数、多字段表达式、UNION、递归 CTE
  • 注释解析(7 个):通配符按列序展开、唯一表匹配、歧义列不显示、多字段表达式
    不显示、单字段表达式继承、分析不完整时按列名兜底、元数据缺失时不显示

测试结果:

  • cargo test -p db --lib:1363 passed
  • cargo test -p db_view --lib:950 passed
  • cargo check -p db_view --tests:通过

手动验证建议

  1. 打开「列头显示字段注释」开关
  2. 分别执行以下查询,确认列头注释符合预期:
    • SELECT * FROM users
    • SELECT u.id, u.name AS user_name FROM users u
    • SELECT u.id, o.amount FROM users u JOIN orders o ON u.id = o.user_id
    • WITH recent AS (SELECT id, name FROM users) SELECT name FROM recent
    • SELECT t.n FROM (SELECT name AS n FROM users) t
    • SELECT UPPER(name) FROM users(应继承 name 注释)
    • SELECT price * qty FROM items(不应显示注释)
    • SELECT id FROM users u JOIN orders o ON u.id = o.user_id(歧义列不应显示注释)
  3. 关闭开关后重复执行,确认不再发起额外的表结构查询

@feigeCode
feigeCode merged commit 491692e into feigeCode:main Oct 20, 2026
8 checks passed
@feigeCode feigeCode mentioned this pull request Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants