• Druid SQL 解析器概览


    概览

    Druid 的官方 wiki 对 SQL 解析器部分的讲解内容并不多,但虽然不多,也有利于完全没接触过 Druid 的人对 SQL 解析器有个初步的印象。

    说到解析器,脑海里便很容易浮现 parser 这个单词,然后便很容易联想到计算机科学中理论性比较强的学科------编译原理。想必很多人都知道(即使不知道,应该也耳濡目染)能够手写编译器的人并不多,并且这类人呢,理论知识和工程能力都比较强。在缺乏人力的条件下,大多数时候实现一个编译器,往往是选择采用一些工具,比如说 ANTLR,只需要描述好语法规则,这个工具就能生成对应的编译器。

    不过,Druid 的 SQL 解析器是手写的,官方宣称性能是 ANTLR 这类工具的10倍以上。

    解析器组成部分

    在 Druid 的 SQL 解析器中,有三个重要的组成部分,它们分别是:

    • Parser

      • 词法分析

      • 语法分析

    • AST(Abstract Syntax Tree,抽象语法树)

    • Visitor

    这三者的关系如下图所示:

    Parser 由两部分组成,词法分析和语法分析。
    当拿到一条形如 select id, name from user 的 SQL 语句后,首先需要解析出每个独立的单词,select,id,name,from,user。这一部分,称为词法分析,也叫作 Lexer。
    通过词法分析后,便要进行语法分析了。
    经常能听到很多人在调侃自己英文水平很一般时会说:26个字母我都知道,但是一组合在一起我就不知道是什么意思了。这说明他掌握了词法分析的技能,却没有掌握语法分析的技能。
    那么对于 SQL 解析器来说呢,它不仅需要知道每个单词,而且要知道这些单词组合在一起后,表达了什么含义。语法分析的职责就是明确一个语句的语义,表达的是什意思。
    自然语言和形式语言的一个重要区别是,自然语言的一个语句,可能有多重含义,而形式语言的一个语句,只能有一个语义;形式语言的语法是人为规定的,有了一定的语法规则,语法解析器就能根据语法规则,解析出一个语句的一个唯一含义。

    AST 是 Parser 的产物,语句经过词法分析,语法分析后,它的结构需要以一种计算机能读懂的方式表达出来,最常用的就是抽象语法树。
    树的概念很接近于一个语句结构的表示,一个语句,我们经常会对它这样看待:它由哪些部分组成?其中一个组成部分又有哪些部分组成?例如一条 select 语句,它由 select 列表、where 子句、排序字段、分组字段等组成,而 select 列表则由一个或多个 select 项组成,where 子句又由一个或者多个 where条件组成。
    在我们人类的思维中,这种组成结构就是一个总分的逻辑结构,用树来表达,最合适不过。并且对于计算机来说,它显然比人类更擅长处理“树”。

    AST 仅仅是语义的表示,但如何对这个语义进行表达,便需要去访问这棵 AST,看它到底表达什么含义。通常遍历语法树,使用 VISITOR 模式去遍历,从根节点开始遍历,一直到最后一个叶子节点,在遍历的过程中,便不断地收集信息到一个上下文中,整个遍历过程完成后,对这棵树所表达的语法含义,已经被保存到上下文了。有时候一次遍历还不够,需要二次遍历。遍历的方式,广度优先的遍历方式是最常见的。

    快速上手

    使用 Druid SQL Parser 来解析 SQL 语句,一般需要进行以下几个步骤:

    1. 新建一个 Parser

    2. 使用 Parser 解析 SQL,生成 AST

    3. 使用 Visitor 访问 AST

    如下代码所示:

    package io.beansoft.demo;
    
    import com.alibaba.druid.sql.ast.SQLStatement;
    import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
    import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
    import com.alibaba.druid.sql.parser.SQLStatementParser;
    
    /**
     *
     *
     * @author beanlam
     * @date 2017年1月10日 下午11:06:26
     * @version 1.0
     *
     */
    public class ParserMain {
    
        public static void main(String[] args) {
            String sql = "select id,name from user";
    
            // 新建 MySQL Parser
            SQLStatementParser parser = new MySqlStatementParser(sql);
    
            // 使用Parser解析生成AST,这里SQLStatement就是AST
            SQLStatement statement = parser.parseStatement();
    
            // 使用visitor来访问AST
            MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
            statement.accept(visitor);
                    
            // 从visitor中拿出你所关注的信息        
            System.out.println(visitor.getColumns());
        }
    }

    以上代码运行后控制台的输出为

    [user.id, user.name]

    当然,不使用 Visitor,直接操作 AST 也可以得到 SQL 语句的信息,在 Druid 现有内置的 Visitor 不能满足需求时,可以自己去实现 Visitor,对于用 Visitor 无法解析到的信息,可以直接访问 AST 去获取。

  • 相关阅读:
    iphone开发 使用TouchJSON框架 解析JSON
    iphone开发UIScrollView控件详解
    iPhone UIAlertView属性及使用方法
    vim文本编辑器使用大全 命令的解读
    iphone开发软件Xcode3.2.6破解免证书真机开发调试方案
    Objectivec语言 字符串类NSMutableString用法
    iphone开发 如何在NSMutableDictionary中放入基本数据类型
    找了很久,终于让我找到了,登陆界面登陆按钮随着输入法键盘的弹出而动态改变
    微软安全指南中心:Windows 2000
    在网络中安装、配置和使用SUS服务
  • 原文地址:https://www.cnblogs.com/qiumingcheng/p/7121419.html
Copyright © 2020-2023  润新知