【免费下载链接】polyglot
Rust/Wasm-powered SQL transpiler for more than 30 SQL dialects
Polyglot 是一个基于 Rust/Wasm 的 SQL 转译器(SQL transpiler),可在 30+ 种 SQL 方言之间互相转换,比如把 MySQL 的IFNULL转成 PostgreSQL 的COALESCE。它最硬核的地方,是背后那套覆盖数十万级用例的测试体系:从 sqlglot 自动提取的 fixture、6 层转译测试矩阵、known-failures 白名单机制,到三个 cargo-fuzz 模糊测试目标,共同保证"100% 通过"不是口号,而是可复现的工程实践。
用例从哪里来:一条命令提取 sqlglot 整个测试集
很多人以为测试用例是手写出来的,Polyglot 的做法更聪明:用脚本直接从 sqlglot 的 Python 测试文件里"挖"用例。
提取脚本 tools/sqlglot-extract/extract-tests.py 会解析 sqlglot 源码的 AST,把其中的validate_identity()、validate_all()、self.validate()等调用全部转换成 JSON fixture,落到 crates/polyglot-sql/tests/ 目录下。配合 Makefile 里固定版本的 sqlglot(SQLGLOT_REF := v30.14.0),整个流程就是一条命令:
make extract-all-fixtures它还会顺带把 ClickHouse 官方测试仓库里 sparse checkout 出来的 stateless 测试,转成 crates/polyglot-sql/tests/custom_fixtures/ 下的方言 fixture。这意味着上游 sqlglot 每新增一条用例,Polyglot 几乎零成本地"继承"了它。
6 层 fixture 测试矩阵:identity、dialect、transpile、pretty、parser、custom
提取出来的用例并不是堆在一起跑的,crates/polyglot-sql/tests/common/test_runner.rs 把校验逻辑拆成了 6 种测试类型,每种类型对应一个独立的集成测试文件:
| 测试层 | 测试目标 | 入口文件 |
|---|---|---|
| Identity(恒等回环) | 解析后重新生成,输出必须与原 SQL 完全一致 | sqlglot_identity.rs |
| Dialect Identity | 指定方言下解析+方言变换+生成,校验方言特性 | sqlglot_dialect_identity.rs |
| Transpilation(跨方言转译) | 源方言 → 目标方言,输出必须等于预期 | sqlglot_transpilation.rs |
| Pretty(格式化) | pretty-print 输出逐字符比对 | sqlglot_pretty.rs |
| Parser(含错误路径) | 正常解析 + 应当报错的用例必须报错 | sqlglot_parser.rs |
| Custom Dialect | 自动发现custom_fixtures/下所有方言目录 | custom_dialect_tests.rs |
几个细节很能说明工程质量:
transpile_test()会先扫描预期输出里的换行符(还要跳过字符串字面量和注释),自动决定走 pretty 还是紧凑生成,避免"格式差异"造成的假失败;- 针对 T-SQL 的布尔值语义、ClickHouse 的小写关键字等方言特殊行为,测试运行器内置了精确的适配逻辑;
- 深嵌套 SQL 用例会专门开 16MB 栈的独立线程跑(见 analyze_failures.rs),防止栈溢出污染其他用例。
"100% 通过"的秘密:known-failures 白名单机制
如果 14 万条用例有一条挂掉就红,那测试体系迟早变成"狼来了"。Polyglot 的答案是 crates/polyglot-sql/tests/common/known_failures.rs 里的TestResults追踪器:
- 每条失败用例先查白名单:白名单里的失败被标记为 "Known failure",不阻塞整体结果;
- 白名单必须"逐条"登记:不允许按方言整包跳过,每条都要写明 issue 编号、语义差异原因和验证方式(例如 #479 记录了 BigQuery
NUMERIC精度收窄到 DuckDB 的行为差异,并说明已在真实 DuckDB 1.5.5 里执行验证); - 自动发现"新通过"用例:如果某个 known failure 哪天通过了,结果里会输出
New passes,提醒开发者把它从白名单里摘掉——白名单只会越用越小; - 新失败自动分类:
categorize_error()把 Mismatch、Unexpected token、Tokenization error 等归入不同类别并输出统计表,定位问题一眼到位。
这套机制让"100% 通过"有了严格定义:除逐条登记、逐条验证、且都有 issue 追踪的已知差异外,其余用例全部通过。
方言矩阵 + 回归套件:把"修好的 bug"钉死在测试里
除了 fixture,crates/polyglot-sql/tests/dialect_matrix.rs 对 7 个核心方言(Generic、PostgreSQL、MySQL、BigQuery、Snowflake、DuckDB、TSQL)做全排列——42 个方言对——每个方向都验证函数名、语法形态的转换是否正确。
tests/目录下还有大量以"具体 bug"命名的回归文件,命名即文档:
- tsql_regression.rs、fabric_tpch_regression.rs:T-SQL 与 Fabric(含 TPC-H 完整负载)
- clickhouse_regression.rs:ClickHouse 解析回归
- deep_nesting_regression.rs:深嵌套表达式的栈安全
- transform_regression.rs:AST 变换迭代正确性
每个历史 bug 都有对应的"钉子",防止二次回归。
Fuzzing 实战:三个目标守住"永不 panic"底线
确定性测试能覆盖"想得到的输入",fuzzing 负责覆盖"想不到的输入"。crates/polyglot-sql/fuzz/ 下用cargo-fuzz定义了三个目标:
| Fuzz 目标 | 输入 | 校验什么 |
|---|---|---|
| fuzz_parser.rs | 任意字节串(合法 UTF-8 时) | 6 种方言下解析器永不 panic,非法输入只允许返回错误 |
| fuzz_roundtrip.rs | 同上 | parse → generate → 再 parse 的完整回环不崩溃 |
| fuzz_transpile.rs | arbitrary派生结构(SQL + 随机源/目标方言) | 随机方言对之间的转译调用永不 panic |
这三个目标的选择非常克制且有针对性:fuzzing 的目标不是"找到更多功能差异",而是守住内存安全与栈安全这条底线——SQL 解析器处理的是不可信外部输入,"任何输入都不能 panic"是对外部 API(WASM SDK、FFI、Python 绑定)最重要的承诺。
一键验证:Makefile 里的完整测试流水线
整个体系通过 Makefile 收口成几条常用命令,本地和 CI 用同一套配方:
make test-rust # 快速跑 sqlglot 兼容测试 make test-rust-verify # 本地全量验证:单测 + 全部 fixture + FFI make test-rust-ci-core # CI 核心套件 make test-rust-ci-feature-gates # 逐一验证 Cargo feature 组合(30+ 种开关) make validate # 提交前完整校验值得一提的是test-rust-ci-feature-gates:Polyglot 的每个方言、每项能力(transpile、builder、semantic、openlineage…)都是独立 Cargo feature,这条目标会把几十种 feature 组合逐一cargo check,防止 feature 统一性掩盖依赖问题。
给新手的三条可复用的经验
- 用例可以"继承",但必须固定基准版本——把上游项目的测试集作为基准,并 pin 住版本(
SQLGLOT_REF := v30.14.0),差异才可追溯; - 失败要"白名单化 + 逐条登记 + 可自动发现修复","100% 通过"才有工程意义;
- fuzzing 目标要小而准:不追求覆盖率数字,而是锁定"永不 panic"这类可证伪的底线承诺。
想进一步阅读:crates/polyglot-sql/tests/ 全部集成测试、crates/polyglot-sql/fuzz/ 模糊测试目标、tools/sqlglot-compare/known-differences.json 差异豁免配置,以及 crates/polyglot-sql/README.md 中的能力说明。
【免费下载链接】polyglot
Rust/Wasm-powered SQL transpiler for more than 30 SQL dialects
相关推荐
SQL转译幕后揭秘:Polyglot如何把MySQL语法无损翻译成PostgreSQL
SQL转译幕后揭秘:Polyglot如何把MySQL语法无损翻译成PostgreSQL Polyglot 是一个用 Rust 实现的高性能 SQL 转译器(SQ
SocketRocket Autobahn测试:300+用例通过实战
SocketRocket Autobahn测试:300+用例通过实战 WebSocket协议实现的兼容性验证一直是移动开发中的隐形痛点。当你还在为不同服务器环境
网络通信Mermaid CLI Agent 测试体系全解析:从测试计划到 100% 通过率的实践验证
Mermaid CLI Agent 测试体系全解析:从测试计划到 100% 通过率的实践验证 导读 TEST.md https://link.gitcode.c
人工智能AI AgentAI 技能/插件CLI工具调用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考