dbx 的 Doris 与 SelectDB SQL 函数辅助:从函数目录生成到补全、签名提示与语义建模
【免费下载链接】dbx20 MB lightweight cross-platform database client for 90+ databases, including MySQL, PostgreSQL, SQLite, Redis, MongoDB, DuckDB, SQL Server, and Dameng. Built-in AI, MCP Server, CLI, desktop and Docker. | 轻量级跨平台数据库管理工具,支持 MySQL、PostgreSQL、SQLite、Redis、MongoDB、达梦等 90+ 数据库,提供桌面端、Docker、CLI、内置 AI 助手和 MCP Server。项目地址: https://gitcode.com/gh_mirrors/dbx7/dbx
导读
本文围绕 dbx 桌面端(apps/desktop)内置的Doris 与 SelectDB SQL 函数辅助功能展开:它如何从 Apache Doris 官方文档站点自动提取 496 个 SQL 函数的目录与签名,如何把这些目录注入 SQL 编辑器的函数补全、签名提示(Signature Help)和语义分析,以及如何让 SelectDB、StarRocks 等 Doris 兼容系连接复用同一套辅助能力。读完本文,你将理解该功能的完整数据链路(生成脚本 → 生成产物 → 运行时消费),并掌握如何自行重新生成、验证与排查这套函数目录。
该功能的官方说明位于 apps/desktop/src/lib/sql/doris/README.md,本文以其为主体,结合仓库源码与测试用例展开深入讲解。
功能概览:Doris 系连接的 SQL 辅助能力
Doris(Apache Doris)与 SelectDB 是两款高度 MySQL 兼容的 OLAP 数据库。dbx 在为这类连接提供 SQL 编辑体验时,不能简单套用 MySQL 的函数库——Doris 拥有大量自有函数(BITMAP_UNION_COUNT、HLL_UNION_AGG、EXPLODE_SPLIT、PERCENTILE_APPROX、DATE_TRUNC等),这些函数在 MySQL 中并不存在。
为此,dbx 在 apps/desktop/src/lib/sql/doris/ 目录下维护了一套完整的 Doris 函数辅助体系,包含三个层次:
| 文件 | 角色 |
|---|---|
| README.md | 功能说明与再生成指引(本文主体) |
| functions.generated.json | 生成产物:496 个函数的目录、签名与文档链接 |
| functions.ts | 运行时消费层:把 JSON 目录解析为补全/提示用的数据结构 |
从源码结构看,该目录的职责非常单一:目录数据全部来自生成脚本,运行时只做解析与注入,不维护任何手写的函数清单(仅有一个针对JSON_EXTRACT_STRING的兼容性补丁,见下文)。
目录来源:Apache Doris 官方 SQL 手册
README 明确说明,函数目录派生自 Apache Doris 2.1 与 3.x 版本的 SQL 手册("The function catalogue is derived from the Apache Doris 2.1 and 3.x SQL manuals")。
这一点在生成产物中有直接证据:functions.generated.json 的根级元数据记录了:
{ "source": "https://github.com/apache/doris-website", "revision": "b28541fb0fc91425ab97c8324af5abd0f72d1ef0", "license": "Apache-2.0" }也就是说,目录数据来自 Apache 官方文档仓库 [apache/doris-website](Apache License 2.0),并精确记录到生成时的 Git 提交(revision),保证目录可追溯、可复现。
再生成流程:从 doris-website 检出重建目录
README 给出了再生成命令:
node scripts/generate-doris-functions.mjs /path/to/doris-website其中/path/to/doris-website是本地 Apachedoris-website仓库检出路径。该脚本位于 scripts/generate-doris-functions.mjs,其完整处理流水线如下:
- 输入校验:从
process.argv[2]读取 docs 根目录,缺失时直接报错退出(Usage: node scripts/generate-doris-functions.mjs /path/to/doris-website)。 - 记录修订号:通过
git -C <docsRoot> rev-parse HEAD获取 doris-website 检出的当前提交,写入产物revision字段。 - 递归收集 Markdown 文档:递归扫描
versioned_docs/version-2.1/sql-manual/sql-functions与versioned_docs/version-3.x/sql-manual/sql-functions下所有.md文件。 - 解析 frontmatter 与签名:读取每个文档的 YAML frontmatter 提取函数名(
title,转为大写);过滤掉 draft、OVERVIEW页面以及combinators/目录下的内容;再从## Syntax章节中提取代码块与行内代码,用括号配对算法截取完整的函数调用签名。 - 归类与拼接文档链接:以相对路径生成
category(如scalar-functions/numeric-functions)与官方文档 URL(https://doris.apache.org/docs/<version>/sql-manual/sql-functions/<path>/)。 - 合并 2.1 与 3.x 两版:以 3.x 为主表,按函数名合并 2.1 的定义,生成
documentedIn覆盖标记;仅存在于 2.1 的函数也保留(标记为["2.1"])。 - 排序输出:按函数名(en 排序)写入
apps/desktop/src/lib/sql/doris/functions.generated.json,并打印生成统计。
当前产物规模与覆盖标记
对当前仓库中的生成产物做统计(见 functions.generated.json):
- 函数总数:496 个;
documentedIn分布:466 个函数同时被 2.1 与 3.x 手册记录,24 个仅见于 3.x,6 个仅见于 2.1;- 函数类别分布(
category字段):日期时间函数 90、字符串函数 72、数值函数 42、聚合函数 48、数组函数 48、位图函数 27、JSON 函数 30、IP 函数 23、空间函数 20、加密摘要函数 15、表函数 11、表值函数 14、窗口函数 10,以及位运算、条件、HLL、Map、Quantile、Struct、System 等其他类别。
关于documentedIn字段的语义,README 特意强调了一处易误解点:
documentedInrecords documentation coverage, not a minimum server version: the 3.x manuals also contain functions added after 3.0.
即:documentedIn表示该函数在哪些版本的官方手册中“有文档记录”,并不表示函数的最低服务器版本要求——3.x 手册同样收录了 3.0 之后新增的函数。因此在阅读产物时,不能把["3.x"]误读为“需要 Doris 3.x 才能用”,它只说明官方文档已覆盖。
运行时消费:从 JSON 目录到补全与签名提示
生成产物不能直接用于补全,需要经过 functions.ts 的解析层。其关键逻辑:
- 类型定义:
DorisFunctionDefinition接口包含name、category、signatures、docs、documentedIn五个字段,与生成产物的函数条目一一对应。 splitParameters:按逗号拆分参数,同时追踪( )、< >、[ ]三层括号深度,深度为 0 时才在逗号处切分——这保证MAP<STRING,INT>、ARRAY<INT>这类泛型类型不会被误拆。parameterName:从<占位符>中提取参数名,清理成合法的标识符(空格转_,剔除非法字符),空则回退为argN;例如签名ABS(<x>)得到参数名x。parametersFor:取第一条含(的签名,提取括号内参数列表,过滤...,最终产出补全占位符所需的参数名数组。- 导出三个运行时数据结构:
DORIS_FUNCTION_DEFINITIONS:完整定义数组;DORIS_FUNCTION_SIGNATURES:Map<函数名, 参数名数组>,供补全插入与签名提示使用;DORIS_FUNCTION_DOCS:Map<函数名, "分类 · 文档链接">,供补全项的描述展示。
兼容性补丁:JSON_EXTRACT_STRING
functions.ts 中还内置了一个手工兼容性补丁:
const compatibilityOverrides: DorisFunctionDefinition[] = [ { name: "JSON_EXTRACT_STRING", category: "JSON", signatures: ["JSON_EXTRACT_STRING(json_string, path)"], docs: "Extracts a string value from a JSON string by path.", documentedIn: ["Apache Doris JSON function compatibility"], }, ];该函数以"Apache Doris JSON 函数兼容性"的名义补充进目录,且仅在目录中不存在同名函数时追加(if (!DORIS_FUNCTION_DEFINITIONS.some(...))),避免与自动生成的定义冲突。这一设计体现了"自动生成 + 少量手工兜底"的双轨策略。
接入 SQL 编辑器:补全注册、描述与签名帮助
函数目录最终注入 SQL 补全系统。核心入口是 apps/desktop/src/lib/sql/sqlCompletion.ts:
import { DORIS_FUNCTION_DOCS, DORIS_FUNCTION_SIGNATURES } from "@/lib/sql/doris/functions"; ... const DATABASE_FUNCTION_SIGNATURES: Partial<Record<DatabaseType, Map<string, string[]>>> = { ... doris: DORIS_FUNCTION_SIGNATURES, starrocks: DORIS_FUNCTION_SIGNATURES, };从源码可以看出:
- doris 与 starrocks 两种数据库类型共用同一套 Doris 函数签名表;
- 同文件中还定义了
DORIS_FUNCTION_DESCRIPTIONS = new Map(DORIS_FUNCTION_DOCS),把"分类 · 文档链接"作为补全项的说明文字(description)展示给用户,鼠标悬停即可看到函数所属分类与官方文档地址。
补全项的插入形式
Doris 函数的补全项以函数补全项(type: "function")形式提供,apply内容包含完整调用前缀,例如BITMAP_UNION_COUNT(。其参数占位符由DORIS_FUNCTION_SIGNATURES中的参数名数组生成,用户在补全后可直接 Tab 跳转填写参数。
签名帮助(Signature Help)
补全之外,getSqlFunctionSignatureHelp使用同一份签名数据提供函数签名帮助:当光标位于BITMAP_UNION_COUNT(括号内时,编辑器会弹出该函数的形式参数说明。其覆盖范围同样包括 Doris/StarRocks/SelectDB。
连接路由:SelectDB 与 StarRocks 如何共享 Doris 辅助
README 中有一句关键说明:"SelectDB connections use the Doris capability family throughjdbcDialect.ts."(SelectDB 连接通过jdbcDialect.ts复用 Doris 能力族)。
在 apps/desktop/src/lib/database/jdbcDialect.ts 中有对应实现:
if (profile === "doris" || profile === "selectdb") return "doris";即:当连接的驱动 profile 为doris或selectdb时,其有效数据库类型(effectiveDatabaseType)被归并为doris,从而自动获得完整的 Doris 函数补全、语义方言与各类数据库能力。这一归并逻辑被测试 apps/desktop/src/lib/tests/sql/dorisCompletion.spec.ts 显式验证:
it.each(["doris", "selectdb"])("routes the %s profile to Doris assistance", (driver_profile) => { expect(effectiveDatabaseTypeForConnection({ db_type: "mysql", driver_profile })).toBe("doris"); });注意db_type为mysql、driver_profile为selectdb的连接,其辅助能力仍路由到 Doris——这正是"MySQL 兼容协议、Doris 能力族"这一设计意图的体现。
Doris 语义方言:标识符、注释与 LATERAL VIEW
除函数补全外,Doris 在 SQL 语义层也有独立方言。在 apps/desktop/src/lib/sql/semantic/dialect.ts 中:
doris: { id: "doris", identifierQuotes: [ { open: "`", close: "`" }, { open: '"', close: '"' }, ], supportsAsForTableAlias: true, projectionAliasVisibility: { where: false, groupBy: true, having: true, orderBy: true }, normalizeIdentifier: defaultNormalize, quoteIdentifier: (identifier) => quoteWith(identifier, "`"), qualifierRole: roleForMysqlLikeQualifier, },该适配器定义了 Doris 的:
- 标识符引用方式:反引号
`与双引号均可用,默认以反引号包裹; - 投影别名可见性:
WHERE中不可用别名,GROUP BY/HAVING/ORDER BY中可用——与 MySQL 系行为一致; - 限定符角色解析:复用 MySQL 风格(catalog 维度按
schema处理)。
在方言选择上,dialect.ts 中有两条关键规则:
sqlReferenceAnalysisDialectFor:databaseType为doris或starrocks时返回"doris",不回退到 MySQL;sqlSemanticDialectFor:即使编辑器传入的 dialect 是"mysql"(Doris 连接在 CodeMirror 层走 MySQL 回退方言),databaseType为doris/starrocks时仍强制选用 doris 适配器——源码注释明确说明这是为了不让 mysql 方言掩盖 Doris 的LATERAL VIEW建模等能力。
Doris 语法的一个显著特征是#行注释。测试用例验证了这一点(见 dorisCompletion.spec.ts):
it("treats # as a line comment for Doris", () => { const tokens = tokenizeSqlSemantic("SELECT 1 # trailing note\nFROM t", "doris"); expect(tokens).toContainEqual(expect.objectContaining({ kind: "comment", text: "# trailing note" })); });LATERAL VIEW 的表函数建模
Doris 使用LATERAL VIEW explode(...)将数组/Map 展开为多行。dbx 的语义模型把每个LATERAL VIEW的输出建模为"表函数行源"(kind: "table_function"),并支持链式 LATERAL VIEW(多个视图依次展开)以及LATERAL VIEW OUTER形式:
it("models chained LATERAL VIEW outputs as local columns", () => { const sql = "SELECT e, part FROM events t LATERAL VIEW explode(t.tags) a AS e LATERAL VIEW explode_split(t.name, ',') b AS part"; const model = buildSqlSemanticModel(sql, sql.indexOf("e,") + 1, { databaseType: "doris", dialect: "doris" }); expect(model.rowSources).toEqual(expect.arrayContaining([...])); });这意味着在编辑器中,explode/explode_split展开出的列(如e、part)会被识别为当前行的局部列,参与后续补全与解析。
测试验证:Doris 辅助功能的质量保障
Doris 辅助功能有专门的测试套件 apps/desktop/src/lib/tests/sql/dorisCompletion.spec.ts,覆盖以下关键场景:
| 测试点 | 验证内容 |
|---|---|
| profile 路由 | doris、selectdbprofile 均路由到 Doris 辅助 |
| 函数补全与签名帮助 | BITMAP_UNION_COUNT、HLL_UNION_AGG、ARRAY_MAP、JSON_EXTRACT_STRING、DATE_TRUNC、PERCENTILE_APPROX、EXPLODE_SPLIT均产出可插入的补全项与签名帮助 |
| 排序优先级 | 匹配的列名排在函数前缀匹配之前(bitmap_value优先于BITMAP_UNION_COUNT) |
| 方言保持 | databaseType: "doris"时解析方言为 doris 而非 mysql |
| 链式 LATERAL VIEW | 多个LATERAL VIEW的输出建模为局部列 |
| 编辑器方言形态 | 编辑器传入 mysql 回退方言时,doris 适配器不被掩盖 |
#注释 | Doris 下#被识别为行注释 |
LATERAL VIEW OUTER | 与普通形式同等建模 |
此外,databaseFeatureSupport.ts 中driverProfile === "doris" || driverProfile === "selectdb" || driverProfile === "starrocks"的判定,以及 dorisCatalogCapability.spec.ts 中"catalog 能力"的测试,进一步表明 Doris 系连接在整个客户端(对象浏览器、用户管理、数据迁移等)中均按统一能力族处理。
实战:如何更新与验证 Doris 函数目录
如果你想在本地同步最新的 Doris 官方函数文档,操作步骤如下:
准备 doris-website 检出:克隆 Apache
doris-website仓库并切换到包含versioned_docs/version-2.1与versioned_docs/version-3.x的版本分支(注意该仓库采用版本化文档目录结构)。执行生成脚本:
node scripts/generate-doris-functions.mjs /path/to/doris-website检查输出:脚本会打印
Generated <N> Doris functions from <revision>,并将结果写入 apps/desktop/src/lib/sql/doris/functions.generated.json。验证集成:运行 Doris 辅助测试套件,确认补全、签名帮助与语义建模行为未回归:
pnpm vitest run apps/desktop/src/lib/__tests__/sql/dorisCompletion.spec.ts核对元数据:确认产物的
source、revision、license字段与所用 doris-website 检出一致,保证目录可追溯。
小结
dbx 的 Doris 与 SelectDB SQL 函数辅助,是一条"官方文档 → 生成脚本 → JSON 产物 → 运行时补全/语义"的完整数据链路:
- 数据可信:目录派生自 Apache Doris 2.1/3.x 官方 SQL 手册(Apache License 2.0),并记录源仓库 revision;
- 自动可再生成:一条命令即可从 scripts/generate-doris-functions.mjs 重建 496 个函数的目录;
- 语义清晰:
documentedIn只表示文档覆盖范围而非最低版本要求; - 能力复用:SelectDB、StarRocks 通过 jdbcDialect.ts 路由到同一套 Doris 能力族;
- 质量有保障:dorisCompletion.spec.ts 覆盖了补全、签名帮助、方言选择与 LATERAL VIEW 建模等关键行为。
如果你正在使用 Doris、SelectDB 或 StarRocks 连接编写 SQL,本套辅助能让BITMAP_UNION_COUNT、HLL_UNION_AGG、EXPLODE_SPLIT等 Doris 专有函数获得与主流数据库一致的补全与提示体验。
【免费下载链接】dbx20 MB lightweight cross-platform database client for 90+ databases, including MySQL, PostgreSQL, SQLite, Redis, MongoDB, DuckDB, SQL Server, and Dameng. Built-in AI, MCP Server, CLI, desktop and Docker. | 轻量级跨平台数据库管理工具,支持 MySQL、PostgreSQL、SQLite、Redis、MongoDB、达梦等 90+ 数据库,提供桌面端、Docker、CLI、内置 AI 助手和 MCP Server。项目地址: https://gitcode.com/gh_mirrors/dbx7/dbx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考