2个不稳定版本
0.43.1 | 2024年2月1日 |
---|---|
0.41.0 | 2024年1月24日 |
1011 在 数据库接口 中
1MB
21K SLoC
Rust的可扩展SQL词法分析和解析器
此crate包含符合ANSI/ISO SQL标准和其它方言的SQL词法分析和解析器。此crate被用作SQL查询引擎、特定供应商的解析器和各种SQL分析的基础。
示例
解析一个简单的SELECT
语句
use sqlparser::dialect::GenericDialect;
use 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 dialect = GenericDialect {}; // or AnsiDialect, or your own dialect ...
let ast = Parser::parse_sql(&dialect, sql).unwrap();
println!("AST: {:?}", ast);
输出如下
AST: [Query(Query { ctes: [], body: Select(Select { distinct: false, projection: [UnnamedExpr(Identifier("a")), UnnamedExpr(Identifier("b")), UnnamedExpr(Value(Long(123))), UnnamedExpr(Function(Function { name: ObjectName(["myfunc"]), args: [Identifier("b")], filter: None, over: None, distinct: false }))], from: [TableWithJoins { relation: Table { name: ObjectName(["table_1"]), alias: None, args: [], with_hints: [] }, joins: [] }], selection: Some(BinaryOp { left: BinaryOp { left: Identifier("a"), op: Gt, right: Identifier("b") }, op: And, right: BinaryOp { left: Identifier("b"), op: Lt, right: Value(Long(100)) } }), group_by: [], having: None }), order_by: [OrderByExpr { expr: Identifier("a"), asc: Some(false) }, OrderByExpr { expr: Identifier("b"), asc: None }], limit: None, offset: None, fetch: None })]
功能
以下可选的crate功能可用:
serde
:通过为所有AST节点实现Serialize
和Deserialize
添加Serde支持。visitor
:添加了一个能够递归遍历AST树的Visitor
。
语法与语义
此crate仅提供语法解析器,并尽量不应用任何SQL语义,接受特定数据库会拒绝的查询,即使在使用该数据库特定的Dialect
的情况下。例如,CREATE TABLE(x int, x int)
被此crate接受,尽管大多数SQL引擎会由于重复的列名x
而拒绝此语句。
此crate避免语义分析,因为不同方言和实现之间的差异很大。如果您想进行语义分析,请随时使用此项目作为基础。
保留语法往返
此crate允许用户恢复原始SQL文本(移除注释,标准化空白和关键字大小写),这对于分析和操作SQL的工具很有用。
这意味着除了注释、空白和关键字的大小写外,以下对于所有SQL都应成立:
// Parse SQL
let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
// The original SQL text can be generated from the AST
assert_eq!(ast[0].to_string(), sql);
在此crate中,仍有少数情况,其中看似具有相似语义的不同SQL使用相同的AST表示。我们欢迎PR来修复此类问题并在AST中区分不同的语法。
SQL兼容性
SQL 首次在 1987 年被标准化,并且自那时起,标准就定期进行了修订。大多数修订都为语言添加了显著的新特性,因此没有数据库声称支持所有功能。这个解析器目前支持 SQL-92 的大部分语法,以及一些新版本的特定语法,这些语法已被明确要求,还包括一些 MSSQL、PostgreSQL 和其他方言的特定语法。在可能的情况下,使用在线 SQL:2016 语法来指导接受哪些语法。
不幸的是,说明具体的合规性是非常困难的。没有公开可用的测试套件可以自动评估合规性,手动进行将耗尽项目的有限资源。尽管如此,我们最终有兴趣支持完整的 SQL 方言,我们正在缓慢地构建自己的测试套件。
如果您正在评估该项目是否适合您的需求,您可能需要通过实验来验证它是否支持您需要的 SQL 子集。请报告您发现的任何不受支持的查询。这样做有助于我们优先支持实际使用的标准部分。请注意,如果您迫切需要支持某个特性,您可能需要自己编写实现。有关详细信息,请参阅贡献部分。
命令行
此软件包包含一个 CLI 程序,可以解析文件并将结果作为 JSON 输出。
$ cargo run --features json_example --example cli FILENAME.sql [--dialectname]
用户
此解析器目前正在被DataFusion查询引擎、LocustDB、Ballista、GlueSQL、Opteryx、PRQL、Qrlew 和 JumpWire 等项目使用。
如果您的项目正在使用 sqlparser-rs,请随意将其添加到此列表中。
设计
核心表达式解析器使用的是Pratt 解析器设计,这是一个自顶向下的操作符优先(TDOP)解析器,而周围的 SQL 语句解析器则是一个传统的、手写的递归下降解析器。Eli Bendersky 有一个关于 TDOP 解析器的教程,如果您想了解更多关于这项技术的信息。
我们之所以喜欢这种设计模式,是因为
- 代码简单易写,可以简洁而优雅
- 性能通常比由解析器生成器的代码更好
- 使用手写代码进行调试更容易
- 与使用解析器生成器相比,扩展和创建特定方言的扩展更容易
支持自定义 SQL 方言
这是一个正在进行中的工作,但我们有一些关于编写自定义 SQL 解析器的笔记。
贡献
鼓励贡献!然而,维护此软件包的带宽是有限的。请仔细阅读以下部分。
新语法
最常用的 PR 添加了对 SQL 标准中或流行的 RDBMS(如 Microsoft SQL Server 或 PostgreSQL)中功能的支持或修复,这些 PR 可能会在简短审查后被接受。任何特定方言的 SQL 功能都应该由相关的 Dialect
和 GenericDialect
解析。
主要 API 变更
当前维护者不计划对此crate的API进行任何重大更改。提出重大重构的PR不太可能被接受。
测试
虽然我们希望以合理的时间及时审查PR,但可能需要一周或更长时间。为了加快流程,请确保PR通过所有CI检查,并包含测试以证明您的代码按预期工作(并避免回归)。请记住还要测试错误路径。
没有测试的PR将不会被审查或合并。由于CI确保cargo test
、cargo fmt
和cargo clippy
通过,您在提交PR之前可能需要在本地运行所有三个命令。
提交问题
如果您无法提交补丁,请随时提交问题。请尽量包含
- 一些代表性的示例,您希望支持或修复的语法;
- 如果是SQL:2016的一部分,请提供相关的SQL语法SQL语法;以及
- 一些流行数据库中支持该特性的文档链接。
不幸的是,如果您需要支持某个功能,您可能需要自己实现它,或者提交一个描述得当的ticket,以便社区的其他成员可以这样做。作为维护者,我们的目标是促进从各种贡献者那里整合各种功能,但我们不提供实现,因为我们没有资源。
许可
此存储库中的所有代码均根据Apache软件许可协议2.0进行许可。
除非您明确表示 otherwise,否则您提交的任何有意包含在作品中的贡献,根据Apache-2.0许可的定义,应按上述方式许可,不得添加任何额外的条款或条件。
依赖项
~46–600KB
~13K SLoC