1个不稳定版本
0.13.1-alpha.0 | 2022年1月7日 |
---|
#1456 in 数据库接口
350KB
8K SLoC
这是sqlparser的分支
由于网络原因,我不得不在Crates.io上发布以解决问题。
Rust的可扩展SQL词法分析和解析器
此项目的目标是构建一个能够解析符合ANSI/ISO SQL标准的SQL的词法分析和解析器,同时使其易于支持自定义方言,以便此crate可以作为特定供应商解析器的基石。
此解析器目前正在DataFusion查询引擎、LocustDB、Ballista和GlueSQL中使用。
示例
解析简单的SELECT
语句
use wing_sqlparser::dialect::GenericDialect;
use wing_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 })]
命令行
解析文件并将结果以JSON格式输出
$ cargo run --features json_example --example cli FILENAME.sql [--dialectname]
SQL兼容性
SQL首次于1987年标准化,此后标准修订版定期发布。大多数修订版都为语言添加了重要的新功能,因此没有数据库声称支持该语言的所有功能。此解析器目前支持大多数SQL-92语法,以及一些明确请求的新版本语法,以及一些MSSQL、PostgreSQL和其他特定方言的语法。尽可能使用在线SQL:2016语法来指导接受哪些语法。
遗憾的是,关于兼容性的具体声明很困难。没有公开可用的测试套件可以自动评估兼容性,手动评估会耗尽项目的有限资源。尽管如此,我们有兴趣最终支持完整的SQL方言,并且我们正在逐渐构建自己的测试套件。
如果您正在评估此项目是否符合您的需求,您可能需要实验性地验证它是否支持您需要的SQL子集。请提交您发现的任何不支持查询的问题。这样做有助于我们优先支持实际使用的标准部分。请注意,如果您迫切需要支持某个功能,您可能需要自己编写实现。有关详细信息,请参阅贡献部分。
支持自定义SQL方言
这是一个正在进行的工程,但我们有一些关于编写自定义SQL解析器的笔记。
设计
核心表达式解析器使用Pratt解析器设计,它是一种自顶向下运算符优先(TDOP)解析器,而周围的SQL语句解析器是一个传统的、手工编写的递归下降解析器。Eli Bendersky有一个很好的TDOP解析器教程,如果你对这个技术感兴趣,可以了解更多。
我们更喜欢这种设计模式而不是解析器生成器,以下是一些原因:
- 代码简单易写,可以简洁优雅。
- 性能通常优于解析器生成器生成的代码。
- 与手写代码相比,调试要容易得多。
- 与使用解析器生成器相比,扩展和创建特定方言的扩展要容易得多。
贡献
我们非常鼓励贡献!
提交增加对SQL标准中某个功能或流行RDBMS(如Microsoft SQL Server或PostgreSQL)中某个功能的支持,或修复其bug的pull请求将会被接受,前提是经过简短的审查。对于特别大或侵入性的更改,考虑首先提出一个问题,尤其是如果你是第一次贡献者,以便你可以与维护者协调。CI将确保你的代码通过cargo test
、cargo fmt
和cargo clippy
,因此在你提交PR之前,你可能会想要在本地运行这三个命令。
如果你无法提交补丁,请随时提出一个问题。请尽量包括以下内容:
- 一些你希望支持或修复的语法的代表性示例;
- 如果该语法是SQL:2016的一部分,相关的SQL语法片段;
- 支持该功能的几个最流行数据库的文档链接。
请注意,虽然我们努力快速解决bug和审查PR,但我们不保证对功能请求作出回应。如果你需要支持某个功能,你可能需要自己实现它。作为维护者,我们的目标是促进各种贡献者各种功能的整合,而不是我们自己提供实现,因为我们没有这样的资源。
依赖关系
~47–500KB
~11K SLoC