尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

RisingWave SQL 解析器深度指南:从 sqlparser-rs 分支到 YAML 驱动的新增测试用例实战

发布时间:2026/9/25 9:53:12

资讯中心
01
ARTICLE

RisingWave SQL 解析器深度指南:从 sqlparser-rs 分支到 YAML 驱动的新增测试用例实战

RisingWave SQL 解析器深度指南:从 sqlparser-rs 分支到 YAML 驱动的新增测试用例实战
数据库流处理后端数据工程【免费下载链接】risingwaveEvent streaming platform for agentic AI. Continuously ingest, transform, and serve event streams in real time, at scale.项目地址https://gitcode.com/gh_mirrors/ri/risingwave点击查看免费下载RisingWave 内置了一个基于 Rust 编写的 SQL 解析器 craterisingwave_sqlparser它是知名开源项目 sqlparser-rs 的一个深度定制分支负责将用户提交的 SQL 文本解析为抽象语法树AST是前端Frontend执行计划生成流程的第一步。本文将以该 crate 的官方 README 为核心骨架结合仓库源码系统讲解解析器的整体架构、YAML 驱动的测试体系以及如何通过两个步骤快速为新增 SQL 语法注册测试用例。RisingWave 的 SQL 解析器定位与背景RisingWave 是流式事件处理平台用户通过 SQL 定义数据源Source、物化视图Materialized View和下游 Sink。这些 SQL 语句在进入查询规划与执行阶段之前必须先被转换成结构化的内部表示。承担这一职责的就是 src/sqlparser 目录下的risingwave_sqlparsercrate。根据 src/sqlparser/README.md 的说明该解析器是sqlparser-rs的一个 fork。sqlparser-rs 是一个纯 Rust 实现的 ANSI SQL:2011 词法分析器与解析器能直接将 SQL 字符串解析为 ASTRisingWave 在其基础上扩展了流处理场景特有的语法例如CREATE SOURCE、ALTER FRAGMENT ... SET BACKFILL_RATE_LIMIT、ALTER SOURCE ... CONNECTOR WITH (...)、WEBHOOK连接器等这些都能在 tests/testdata/alter.yaml 等测试文件中看到对应用例将底层解析引擎迁移到winnow解析组合子库见 src/sqlparser/Cargo.toml 中的winnow 1.0.1依赖建立了基于 YAML 快照文件的自动化测试体系用于锁定每条 SQL 的「格式化输出」与「错误信息」。从 crate 的文档注释src/sqlparser/src/lib.rs可以看到其核心能力描述提供 ANSI:SQL 2011 的词法分析与解析输出 AST并附带了最简单的使用示例。该 crate 在仓库内被命名为risingwave_sqlparser通过 workspace 管理版本号遵循 Apache-2.0 许可证。核心流程如何为解析器新增一个测试用例README 给出了最精炼的两步操作法这是理解整个测试体系的钥匙复制一个 YAML 测试条目在对应的 yaml 文件中复制一条现成的用例把其中的input改成你想要测试的 SQL 语句。重新生成期望输出运行./risedev update-parser-test让工具自动重新生成formatted_sql期望的格式化输出。这两步背后对应着一条完整的「快照测试」工作流下面结合源码逐层拆解。第一步理解 YAML 测试文件的结构测试数据存放在 src/sqlparser/tests/testdata 目录下每个文件对应一类 SQL 语法主题例如select.yamlSELECT 查询及投影、函数、字段访问、EXCEPT、LIMIT/FETCH等alter.yamlALTER 相关语句ALTER USER、ALTER SOURCE、ALTER FRAGMENT等create.yaml、drop.yaml、insert.yaml、set.yaml、show.yaml、union.yaml、as_of.yaml、match_recognize.yaml、lambda.yaml、copy.yaml、vacuum.yaml等 20 余个主题文件每个文件由若干条TestCase组成。测试用例的数据结构定义在 src/sqlparser/tests/parser_test.rspub struct TestCase { pub input: String, // 待解析的 SQL pub formatted_sql: OptionString, // 期望的格式化 SQL 输出成功用例 pub error_msg: OptionString, // 期望的解析错误信息失败用例 pub formatted_ast: OptionString, // 期望的 AST Debug 输出可选用于锁定 AST 形态 }以 tests/testdata/select.yaml 中的一条实际用例为例- input: SELECT * FROM generate_series(2::INT,10::INT,2::INT) formatted_sql: SELECT * FROM generate_series(CAST(2 AS INT), CAST(10 AS INT), CAST(2 AS INT)) formatted_ast: Query(Query { with: None, body: Select(...) })注意观察input中用户写的2::INT简写在formatted_sql中被规范化为CAST(2 AS INT)。这正是「格式化输出」的价值——它不仅验证 SQL 能被成功解析还验证解析器产出的 AST 在反向打印unparse时与预期完全一致从而锁定语法规范和规范化规则。失败的用例则记录error_msg例如- input: SELECT * FROM t LIMIT 1 FETCH FIRST ROWS ONLY error_msg: |- sql parser error: Cannot specify both LIMIT and FETCH LINE 1: SELECT * FROM t LIMIT 1 FETCH FIRST ROWS ONLY ^这类用例不仅断言「解析必须失败」还逐字符比对错误消息文本保证错误提示的稳定性。第二步运行./risedev update-parser-test重新生成期望输出在新增或修改input之后需要让期望输出与解析器的实际行为对齐。执行./risedev update-parser-test这个命令定义在 src/sqlparser/sqlparser_test.toml 中其本质是UPDATE_PARSER_TEST1 cargo test --test parser_test即设置环境变量UPDATE_PARSER_TEST1后运行集成测试。测试入口 src/sqlparser/tests/parser_test.rs 会遍历tests/testdata目录下的所有.yaml/.yml文件当检测到UPDATE_PARSER_TEST环境变量时走更新模式update_test_file否则走校验模式run_test_file。更新模式UPDATE_PARSER_TEST1做了什么update_test_fileparser_test.rs会对文件中每一条用例重新执行解析解析成功用当前解析器实际产出的formatted_sql以及可选的formatted_ast覆盖旧值error_msg置空解析失败用当前实际错误文本覆盖error_msgformatted_sql/formatted_ast置空文件头会重写为# This file is automatically generated by src/sqlparser/tests/parser_test.rs.的自动生成标记。同时会在终端用红/绿颜色打印发生变化的条目红色为旧值、绿色为新值方便你审查本次更新的差异。校验模式普通cargo test --test parser_test做了什么run_test_caseparser_test.rs则严格比对若用例声明了error_msg但解析成功报「Expected failure」若解析失败但实际错误文本与error_msg不一致报「Expected error message / Actual error message」差异若用例没有error_msg却缺少formatted_sql报「Illegal test case without given the formatted sql」成功用例会比对formatted_sql与format!({}, ast)是否一致Display实现负责 AST 反格式化若声明了formatted_ast还会比对format!({:?}, ast)。该测试使用libtest-mimic作为自定义测试驱动器harness false见 Cargo.toml每个 YAML 文件被包装成一个Trial因此可以像标准测试一样按文件过滤执行。新增测试用例的最佳实践结合上述机制为 RisingWave 解析器新增语法支持时推荐这样操作根据 SQL 所属语法主题选择最贴切的 YAML 文件SELECT 相关去select.yamlALTER 相关去alter.yamlDDL 去create.yaml/drop.yaml等复制一条结构最相似的同类型用例修改input为你的 SQL运行./risedev update-parser-test检查终端打印的绿/红差异是否符合预期对成功用例检查formatted_sql的规范化结果是否符合项目风格如::是否被规范为CAST、是否被规范为TO对应当报错的语法确认error_msg的定位符号^和错误文案是否准确重新运行普通测试确认全部通过cargo test --test parser_test解析器 API 的使用方式除测试体系外该 crate 对外暴露了简洁的解析入口。库方式Parser::parse_sql根据 src/sqlparser/src/lib.rs 的官方示例use risingwave_sqlparser::parser::Parser; let sql SELECT a, b, 123, myfunc(b) \ FROM table_1 \ WHERE a b AND b 100 \ ORDER BY a DESC, b; let ast Parser::parse_sql(sql).unwrap(); println!(AST: {:?}, ast);parse_sql返回语句Statement的Vec。返回的 AST 类型定义在 src/sqlparser/src/ast 目录下包含statement.rs、query.rs、data_type.rs、value.rs、operator.rs、ddl.rs等模块覆盖查询、DDL、数据类型、运算符等各类语法节点。命令行工具sqlparserbinCargo.toml 中声明了一个名为sqlparser的二进制入口src/sqlparser/src/bin/sqlparser.rs它从 stdin 读取一行 SQL 并打印 ASTecho SELECT 1; | cargo run --bin sqlparser示例程序tokenizer parserexamples/parse.rs 展示了更底层的用法——先通过Tokenizer将 SQL 切成 token 流再交给Parser生成 AST并利用 AST 的Display实现反打印use risingwave_sqlparser::parser::*; use risingwave_sqlparser::tokenizer::Tokenizer; let tokens Tokenizer::new(sql).tokenize_with_location().unwrap(); println!(tokens: {:?}, tokens); let ast Parser::parse_sql(sql).unwrap(); for stmt in ast { println!(unparse: {}, stmt); }这个例子也展示了「格式化 SQL」的来源formatted_sql正是通过format!({}, ast)得到的即 AST 的Display实现。底层实现winnow 驱动的解析引擎从源码结构看该解析器采用了两层解析架构词法层src/sqlparser/src/tokenizer.rs 负责把 SQL 文本切成 token标识符、关键字、字符串、数字、标点等提供tokenize_with_location()这类带位置信息的 API这正是错误消息中LINE 1: ... ^定位信息的来源语法层src/sqlparser/src/parser.rs约 6900 行基于 winnow 解析组合子实现通过alt、dispatch、repeat、separated_pair等组合子递归下降地构建 AST。关键的错误类型定义如下#[derive(Debug, Clone, PartialEq)] pub enum ParserError { TokenizerError(String), ParserError(String), }关键字表src/sqlparser/src/keywords.rs 定义了完整的 SQL 关键字集合含 RisingWave 扩展关键字v2 解析辅助模块src/sqlparser/src/parser_v2 提供dollar_quoted_string、keyword、literal_u64、single_quoted_string等常用解析原语。从 crate 文档看解析器覆盖 ANSI:SQL 2011 语法面结合测试文件如as_of.yaml、asof_join.yaml、match_recognize.yaml、lambda.yaml可以看出RisingWave 还在此基础上扩展了AS OF时间旅行语法、ASOF JOIN、MATCH_RECOGNIZE、lambda 表达式等面向流处理与高级分析场景的语法能力。错误消息统一以sql parser error: ...为前缀并附带行号与^定位。小结RisingWave 的 SQL 解析器是一个典型的「上游开源 深度定制」案例以 sqlparser-rs 为起点配合 winnow 解析框架实现了 ANSI SQL:2011 及其流处理扩展语法并用一套 YAML 快照测试体系将「新增语法」这件事简化为「改 input 跑一条命令」两个动作。无论你是想为 RisingWave 贡献新语法还是想理解 SQL 解析器测试的最佳工程实践都可以从 tests/testdata 下的用例与 tests/parser_test.rs 的测试驱动逻辑入手快速上手。赞分享数据库流处理后端数据工程【免费下载链接】risingwaveEvent streaming platform for agentic AI. Continuously ingest, transform, and serve event streams in real time, at scale.项目地址https://gitcode.com/gh_mirrors/ri/risingwave点击查看免费下载相关推荐SQL解析器Rust版sqlparser-rs完全指南SQL解析器Rust版sqlparser rs完全指南 项目介绍 sqlparser rs 是一个专为 Rust 编程语言设计的可扩展 SQL词法分析器和解析开发工具终极指南如何在PC上免费畅玩任天堂Switch游戏终极指南如何在PC上免费畅玩任天堂Switch游戏 想在电脑大屏幕上体验《塞尔达传说旷野之息》的壮丽世界或是与朋友联机畅玩《任天堂明星大乱斗》Ryuji数据库流处理后端数据工程RIOT OS RTC 外设驱动测试指南从测试用例到 alarm 中断机制深度解析RIOT OS RTC 外设驱动测试指南从测试用例到 alarm 中断机制深度解析 本篇技术指南以 RIOT OS 仓库中的 tests/periph/rtc物联网嵌入式操作系统实时系统上一篇UAssetGUI终极指南5分钟掌握虚幻引擎资源文件转换下一篇vscode-copilot-chat 调试日志全解析用 JSONL 会话日志定位 Agent 异常行为创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。