#lexer #sql-parser #sql-query #sql #parser #ansi

no-std sqlparser-queryscript

支持 ANSI SQL:2011 的可扩展 SQL 词法分析和解析器

3 个版本 (破坏性更新)

0.32.0 2023 年 3 月 9 日
0.31.0 2023 年 3 月 2 日
0.30.0 2023 年 2 月 9 日

24#sql-parser

每月 26 次下载
用于 queryscript

Apache-2.0

720KB
17K SLoC

注意:这是一个 sqlparser-rs 项目的分支,其中包含针对 QueryScript 的特定更改。根据 这些说明 进行分支和发布。

Rust 的可扩展 SQL 词法分析和解析器

License Version Build Status Coverage Status Gitter Chat

这个包包含一个符合 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 节点的 SerializeDeserialize 添加 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]

用户

此解析器目前正在以下查询引擎中使用:DataFusionLocustDBBallistaGlueSQLOpteryx

如果您的项目正在使用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 testcargo fmtcargo clippy通过,您在提交PR之前可能需要在本地运行这三个命令。

如果您无法提交补丁,请随时提交一个问题。请尽量包括

  • 您希望支持或修复的语法的一些代表性示例;
  • 如果该语法是 SQL:2016 的一部分,相关的语法部分,以及
  • 一些最流行且支持该功能的数据库的文档链接。

如果您需要支持某个功能,您可能需要自行实现。作为维护者,我们的目标是促进各种贡献者提供的各种功能的集成,但我们自己并不提供实现,因为我们没有这样的资源。

许可协议

本存储库中的所有代码均基于Apache 软件许可证 2.0授权。

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交给作品包含的贡献,将按照上述许可协议进行授权,不附加任何额外条款或条件。

依赖项

~47–500KB
~11K SLoC