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

no-std illumex-sqlparser

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

8 个版本 (4 个重大更改)

0.39.0 2023 年 10 月 29 日
0.38.4 2023 年 10 月 23 日
0.28.1 2022 年 12 月 6 日
0.27.1 2022 年 11 月 29 日
0.26.1 2022 年 10 月 30 日

#10 in #query-parser

Download history 47/week @ 2024-04-01

每月 62 次下载

Apache-2.0

1MB
19K SLoC

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")], 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 })]

功能

以下可选 软件包功能 可用

  • serde: 通过实现所有 AST 节点的 SerializeDeserialize 为 Serde 添加支持。
  • visitor: 添加一个能够递归遍历 AST 树的 Visitor

语法与语义

此软件包仅提供语法解析器,并尽量不应用任何 SQL 语义,即使使用特定数据库的特定 Dialect,也接受特定数据库会拒绝的查询。例如,CREATE TABLE(x int, x int) 被此软件包接受,尽管大多数 SQL 引擎会因为重复的列名 x 而拒绝此语句。

由于方言和实现之间差异很大,此软件包避免语义分析。如果您想进行语义分析,请随意将此项目作为基础。

SQL 兼容性

SQL 首次于 1987 年标准化,此后该标准的修订版定期发布。大多数修订版都添加了语言的重要新功能,因此没有数据库声称支持该语言的全部功能。此解析器目前支持大多数 SQL-92 语法,以及一些已明确请求的新版本语法,以及一些 MSSQL、PostgreSQL 和其他特定方言的语法。尽可能使用 在线 SQL:2016 语法 指导接受哪些语法。

不幸的是,关于合规性的具体说明很困难。没有公开可用的测试套件可以自动评估合规性,手动进行会消耗项目有限的资源。尽管如此,我们最终仍希望支持完整的SQL方言,并且我们正在逐渐构建自己的测试套件。

如果您正在评估该项目是否适合您的需求,您可能需要通过实验来验证它是否支持您所需的SQL子集。请就您发现的任何不受支持的查询提交问题。这样做有助于我们优先支持实际使用的标准部分。请注意,如果您迫切需要支持某个功能,您可能需要自己编写实现。请参阅贡献部分以获取详细信息。

命令行

此crate包含一个CLI程序,可以解析文件并将结果以JSON格式输出。

$ cargo run --features json_example --example cli FILENAME.sql [--dialectname]

用户

此解析器目前正在以下查询引擎中使用:DataFusion(https://github.com/apache/arrow-datafusion)、LocustDB(https://github.com/cswinter/LocustDB)、Ballista(https://github.com/apache/arrow-ballista)、GlueSQL(https://github.com/gluesql/gluesql)、Opteryx(https://github.com/mabel-dev/opteryx)和JumpWire(https://github.com/extragoodlabs/jumpwire)。

如果您正在使用sqlparser-rs,请随时提交PR将其添加到此列表。

设计

核心表达式解析器采用Pratt解析器设计,这是一种自顶向下的运算符优先(TDOP)解析器,而周围的SQL语句解析器是一个传统的、手工编写的递归下降解析器。Eli Bendersky有一个很好的TDOP解析器教程,如果您想了解更多关于这种技术,请参阅。

我们更喜欢这种设计模式而不是解析器生成器,以下是一些原因:

  • 代码简单易写,可以简洁优雅。
  • 性能通常优于解析器生成器生成的代码。
  • 使用手工代码进行调试要容易得多。
  • 与使用解析器生成器相比,扩展和创建特定方言的扩展要容易得多。

支持自定义SQL方言

这是一个正在进行中的工作,但我们有一些关于编写自定义SQL解析器的笔记。

贡献

我们非常欢迎贡献!然而,我们维护此crate的带宽有限。请仔细阅读以下部分。

新语法

最常接受的PR是添加对SQL标准或流行的RDBMS(如Microsoft SQL Server或PostgreSQL)中的功能的支持或修复一个功能中的错误。任何特定方言的SQL功能都应该由相关的Dialect以及GenericDialect解析。

重大API更改

当前维护者不计划对此crate的API进行任何重大更改。不打算接受的PR是提议进行重大重构的。

测试

虽然我们希望尽快审查PR,但可能需要一周或更长时间。为了加快进程,请确保PR通过了所有CI检查,并包括测试以证明您的代码按预期工作(并避免回归)。请记住还要测试错误路径。

没有测试的PR将不会被审查或合并。由于CI确保了cargo testcargo fmtcargo clippy都通过,你应该在提交PR之前本地运行这三个命令。

提交问题

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

  • 你希望支持或修复的语法的代表性示例;
  • 如果该语法是SQL:2016的一部分,则相关SQL语法的部分;以及
  • 支持该特性的几个最受欢迎的数据库的文档链接。

不幸的是,如果你需要支持某个特性,你可能需要自己实现它,或者提交一个描述足够好的ticket,以便社区的其他成员可以这样做。作为维护者,我们的目标是促进从各种贡献者那里集成各种特性,但不是我们自己提供实现,因为我们没有这样的资源。

许可

此存储库中的所有代码均根据Apache Software License 2.0授权。

除非你明确声明,否则根据Apache-2.0许可定义的,任何有意提交以包含在你工作的贡献,都应按上述方式授权,不附加任何额外条款或条件。

依赖关系

~46–710KB
~16K SLoC