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

无需std wing-sqlparser

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

1个不稳定版本

0.13.1-alpha.02022年1月7日

#1456 in 数据库接口

Apache-2.0

350KB
8K SLoC

这是sqlparser的分支

由于网络原因,我不得不在Crates.io上发布以解决问题。

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

License Version Build Status Coverage Status Gitter Chat

此项目的目标是构建一个能够解析符合ANSI/ISO SQL标准的SQL的词法分析和解析器,同时使其易于支持自定义方言,以便此crate可以作为特定供应商解析器的基石。

此解析器目前正在DataFusion查询引擎、LocustDBBallistaGlueSQL中使用。

示例

解析简单的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 testcargo fmtcargo clippy,因此在你提交PR之前,你可能会想要在本地运行这三个命令。

如果你无法提交补丁,请随时提出一个问题。请尽量包括以下内容:

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

请注意,虽然我们努力快速解决bug和审查PR,但我们不保证对功能请求作出回应。如果你需要支持某个功能,你可能需要自己实现它。作为维护者,我们的目标是促进各种贡献者各种功能的整合,而不是我们自己提供实现,因为我们没有这样的资源。

依赖关系

~47–500KB
~11K SLoC