写点什么

神秘的 SQL AST 抽象语法树

作者:张磊
  • 2023-11-15
    广东
  • 本文字数:1670 字

    阅读完需:约 5 分钟

在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每个细节。比如,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现;而类似于 if-condition-then 这样的条件跳转语句,可以使用带有三个分支的节点来表示。

        和抽象语法树相对的是具体语法树(通常称作分析树)。一般的,在源代码的翻译和编译过程中,语法分析器创建出分析树,然后从分析树生成 AST。一旦 AST 被创建出来,在后续的处理过程中,比如语义分析阶段,会添加一些信息。

对应的 AST 示例:"AST":[ "Query(Query"{ "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"")" ], }"))" ], "from":[ "TableWithJoins"{ "relation":"Table"{ "name":"ObjectName("[ "table_1" ]")", "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)) } }")", }")", "order_by":[ "OrderByExpr"{ "expr":"Identifier(""a"")", "asc":"Some(false)" }, "OrderByExpr"{ "expr":"Identifier(""b"")", } ], }")"]
复制代码

 从上图可以看到 AST 将 SQL 语法完全结构化,元数据化的展示了出来。

那 AST 到底有什么用?

AST 的用途非常广泛,主要具有以下用途:

  1. SQL 解析:解析器通过将输入的 SQL 查询转换成 AST,检查 SQL 语法的正确性。在编译或解释 SQL 查询时,AST 是一个关键部分。

  2. 查询优化:优化器使用 SQL AST 对原始查询进行改写、优化,以获得更快的执行计划。例如:谓词下推、查询剪枝、索引选择等。

  3. 方言转换:与特定数据库兼容的 SQL 生成工具可以使用 SQL AST 进行多种方言的转换。例如:将 Oracle 数据库的 SQL 转换为 MySQL 数据库的 SQL。

  4. 检查约束和权限:通过分析 SQL AST,可以对查询进行约束和权限检查,以防止未授权访问、执行非法操作等。

  5. 静态代码分析:基于 SQL AST,开发者可以识别安全漏洞、编程错误以及风格不一致等问题。例如:常用的 Lint 工具。

  6. 自动补全与代码提示:在 IDE 或代码编辑器中,使用 SQL AST 的信息来为开发者提供智能提示、自动补全等功能,以提高代码编写效率。

  7. 代码重构与迁移:利用 AST,开发者可以更轻松地进行代码重构、迁移和优化,保留原始代码逻辑的同时进行修改。

  8. 语法高亮:代码编辑器可以通过 AST 进行语法高亮,根据代码的不同部分使用不同的颜色和样式,增强可读性。

  9. 查询自动生成与推理:在某些 AI 和 NLP 系统中,可以通过解析和生成 SQL AST,实现基于自然语言的查询自动生成与推理。

总的来说, SQL AST 作为源代码的抽象语法结构,在查询解析、优化、生成和分析等多个方面具有重要作用。基于 AST,开发者可以实现对 SQL 查询的更深入分析、更迅速的响应和更高效的操作。

那如何生成?

生成 SQL 语法树的工具类包很多,各种常见的数据库驱动高级驱动 SDK 中都有会各种版本的工具类去解析  SQL 生成 AST 

比如本文用到的  

Extensible SQL Lexer and Parser for Rust 

地址:  https://github.com/sqlparser-rs/sqlparser-rs

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();
复制代码


转自:https://wp.wtrzl.xyz/archives/65

发布于: 刚刚阅读数: 4
用户头像

张磊

关注

探索永无止境! 2010-01-17 加入

腾讯资深解决方案架构师

评论

发布
暂无评论
神秘的SQL AST抽象语法树_sql_张磊_InfoQ写作社区