Day8 druid sql 解析器

druid sql 解析器

今天来研究下druid的sql解析器。

解析器组成部分

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

Parse

词法分析(Lexer)

当拿到一条形如 select id, name from user 的 SQL 语句后,首先需要解析出每个独立的单词,select,id,name,from,user。这一部分,称为词法分析,也叫作 Lexer。

语法分析

语法分析的职责就是明确一个语句的语义,表达的是什么意思,它不仅需要知道每个单词,而且要知道这些单词组合在一起后,表达了什么含义。

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

AST 是 Parser 的产物,语句经过词法分析,语法分析后,它的结构需要以一种计算机能读懂的方式表达出来,最常用的就是抽象语法树。
树的概念很接近于一个语句结构的表示,一个语句,我们经常会对它这样看待:它由哪些部分组成?其中一个组成部分又有哪些部分组成?例如一条 select 语句,它由 select 列表、where 子句、排序字段、分组字段等组成,而 select 列表则由一个或多个 select 项组成,where 子句又由一个或者多个 where条件组成。

Visitor

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

关系图

在这里插入图片描述

测试用例

  public void test_0() throws Exception {
        String sql = "SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;";
// 新建 MySQL Parser
        MySqlStatementParser parser = new MySqlStatementParser(sql);
         // 使用Parser解析生成AST,这里SQLStatement就是AST
        List<SQLStatement> statementList = parser.parseStatementList();
        SQLStatement statemen = statementList.get(0);
//        print(statementList);

        Assert.assertEquals(1, statementList.size());
 // 使用visitor来访问AST
        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
        statemen.accept(visitor);
   // 从visitor中拿出你所关注的信息     
//        System.out.println("Tables : " + visitor.getTables());
//        System.out.println("fields : " + visitor.getColumns());
//        System.out.println("coditions : " + visitor.getConditions());
//        System.out.println("orderBy : " + visitor.getOrderByColumns());
        
        Assert.assertEquals(1, visitor.getTables().size());
        Assert.assertEquals(2, visitor.getColumns().size());
        Assert.assertEquals(0, visitor.getConditions().size());

        Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("mytable")));

        Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "last_name")));
        Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "first_name")));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值