3 个版本 (破坏性更新)
0.32.0 | 2023 年 3 月 9 日 |
---|---|
0.31.0 | 2023 年 3 月 2 日 |
0.30.0 | 2023 年 2 月 9 日 |
24 在 #sql-parser
每月 26 次下载
用于 queryscript
720KB
17K SLoC
注意:这是一个 sqlparser-rs 项目的分支,其中包含针对 QueryScript 的特定更改。根据 这些说明 进行分支和发布。
Rust 的可扩展 SQL 词法分析和解析器
这个包包含一个符合 ANSI/ISO SQL 标准和其他方言的 SQL 词法分析和解析器。该包被用作 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")], 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
。
语法 vs 语义
这个包仅提供语法解析器,并试图避免应用任何 SQL 语义,即使在使用特定数据库的特定 Dialect
时也接受特定数据库会拒绝的查询。例如,这个包接受 CREATE TABLE(x int, x int)
,尽管大多数 SQL 引擎会由于重复的列名 x
而拒绝此语句。
由于方言和实现之间的差异很大,这个包避免进行语义分析。如果您想进行语义分析,请随意使用此项目作为基础。
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。
如果您的项目正在使用sqlparser-rs,请随时提交PR以将其添加到此列表。
设计
核心表达式解析器使用Pratt解析器设计,这是一种自顶向下的运算符优先级(TDOP)解析器,而周围的SQL语句解析器是一个传统的、手工编写的递归下降解析器。Eli Bendersky有一个关于TDOP解析器的优秀教程,如果您想了解更多关于该技术,可以参考。
我们喜欢这种设计模式而不是解析器生成器,原因如下:
- 代码易于编写,可以简洁而优雅
- 性能通常优于解析器生成器生成的代码
- 与手写代码相比,调试更加容易
- 与使用解析器生成器相比,扩展和创建方言特定扩展要容易得多
支持自定义SQL方言
这是一个正在进行中的工作,但我们有一些关于编写自定义SQL解析器的笔记。
贡献
我们非常欢迎贡献!然而,我们维护此软件包的带宽相当有限。
提交的PR如果添加了对SQL标准中某个功能的支持或修复了某个功能中的错误,或者对流行的RDBMS(如Microsoft SQL Server或PostgreSQL)中的某个功能进行修复,经过简要审查后可能会被接受。
当前维护者不计划在目前对API进行任何重大更改。因此,提出重大重构的PR不太可能被接受。
请记住,尽管我们希望以合理的时间审查PR,但可能需要一些时间。为了加快进程,请确保PR通过了所有CI检查,并包括展示您的代码按预期工作的测试(以避免回归)。请记住测试错误路径。
没有测试的PR将不会被审查或合并。由于CI确保cargo test
、cargo fmt
和cargo clippy
通过,您在提交PR之前可能需要在本地运行这三个命令。
如果您无法提交补丁,请随时提交一个问题。请尽量包括
- 您希望支持或修复的语法的一些代表性示例;
- 如果该语法是 SQL:2016 的一部分,相关的语法部分,以及
- 一些最流行且支持该功能的数据库的文档链接。
如果您需要支持某个功能,您可能需要自行实现。作为维护者,我们的目标是促进各种贡献者提供的各种功能的集成,但我们自己并不提供实现,因为我们没有这样的资源。
许可协议
本存储库中的所有代码均基于Apache 软件许可证 2.0授权。
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交给作品包含的贡献,将按照上述许可协议进行授权,不附加任何额外条款或条件。
依赖项
~47–500KB
~11K SLoC