添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Repository files navigation

metasequoia-sql

metasequoia-sql 是一款注重性能的 SQL 语法的解析和分析器,适用于 SQL 的格式化、执行和分析场景,致力于打造性能最高的 Python 版 SQL 解析器。具有如下 3 个主要特性:

  • 词法解析器与语法解析器相互独立,支持插件开发
  • 使用单一状态机实现词法解析,避免大量正则表达式的复杂逻辑
  • 除包含并列关系的节点外(例如 ORDER BY 多个字段),抽象语法树为完全的、根据计算优先级嵌套的一元和二元表达式结构
  • metasequoia-sql 包含词法树解析( lexical 模块)、语法树解析( core 模块)和语法树分析( analyzer 模块)等主要功能。

    自 0.6.0 版本起,metasequoia-sql 的 public 方法 API 将尽可能支持向前兼容。

    pip install metasequoia-sql

    单纯的词法解析,可以应用于 SQL 语句格式化等场景。

    将 SQL 语句解析为一个词法节点的列表(demo_101),节点中包含对应的源代码( source 属性)以及节点标签( marks 属性)。

    from metasequoia_sql import FSMMachine
    amt_tree = FSMMachine.parse("SELECT column1, '2' FROM table_1")
    for node in amt_tree:
        print(node)

    对于有括号的 SQL 语句,会将括号生成一个 AMTParenthesis 类型节点,该节点包含一个 PARENTHESIS 标记,括号中的词法节点会被添加到括号节点的 children 属性中(demo_102)。

    from metasequoia_sql import FSMMachine
    amt_tree = FSMMachine.parse("SELECT column1, (column2 + 1) * 2 FROM table_1")
    for node in amt_tree:
        print(node)

    将 SQL 语句解析为一个抽象语法树,返回抽象语法树的根节点。

    词法解析支持一次性解析一个语句(demo_201):

    from metasequoia_sql import SQLParser
    statement = SQLParser.parse_select_statement("SELECT column1, '2' FROM table_1")
    print(statement)

    也支持一次性解析多个语句(demo_202):

    from metasequoia_sql import SQLParser
    statements = SQLParser.parse_statements("SELECT column1 FROM table_1; SELECT column2 FROM table_2")
    for statement in statements:
        print(statement)

    此外,也可以解析语句中的某个部分(demo_203):

    from metasequoia_sql import SQLParser
    expression = SQLParser.parse_logical_and_level_expression("(`column1` > 2) AND (`column2` > 1)")
    print(expression)

    应用样例:数据血缘分析

    通过基于语法解析器的数据血缘分析工具,可以实现对 SQL 语句的分析。例如:

    分析 INSERT 语句的数据血缘。数据血缘分析需要依赖元数据,所以需要根据你的数据源继承 CreateTableStatementGetter 类并提供给数据血缘分析器(demo_301):

    from metasequoia_sql import *
    from metasequoia_sql.analyzer import CreateTableStatementGetter
    from metasequoia_sql.analyzer.data_linage.table_lineage_analyzer import TableLineageAnalyzer
    table_lineage_analyzer = TableLineageAnalyzer(CreateTableStatementGetter(...))
    for statement in SQLParser.parse_statements("your sql file"):
        if isinstance(statement, ASTInsertSelectStatement):
            result = table_lineage_analyzer.get_insert_table_lineage(statement)

    插件样例:MyBatis 插件(暂未完善)

    通过重写了语法解析器和词法解析器的插件,可以实现对特殊 SQL 语法的解析。例如:

    对 MyBatis 语法进行解析(demo_302):

    from metasequoia_sql.plugins.mybaitis import SQLParserMyBatis
    statements = SQLParserMyBatis.parse_statements("SELECT column_1 FROM Shohin "
                                                   "WHERE #{column_2} > 500 "
                                                   "GROUP BY #{column_3}")
    for statement in statements:
        print(statement)

    工具样例:SQL on OTS(暂未发布)

    通过基于语法解析器的工具,可以实现一些实现 SQL 执行的工具。

  • 测试样本:4482 个脚本,共 19880057 字节(18.96 MB)的 SQL 语句。
  • 测试 Python环境:Python 3.10
  • 测试 CPU:Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
  • 单元测试当前不会自动检查):

    运行 scripts/test/test_main.py 脚本。如果有新增功能,也需要新增对应的单元测试。

    pylint 代码质量检查(在 Pull Request 时自动检查):

    pylint --max-line-length=120 metasequoia_sql

    单元测试覆盖率检查(当前不会自动检查):

    # 将 metasequoia-sql 文件夹添加到 PYTHONPATH,并在 metasequoia-sql 文件夹下执行
    coverage run .\scripts\tests\test_main.py
    coverage report  # 生成文字报告
    coverage html  # 生成 HTML 报告

    版本更新记录