Druid SQL解析原理分析(二)

概览

续上篇文章后,继续分析Drui的SQL解析原理,如果没有看上篇文章,可以先浏览下上篇文章:Druid SQL解析原理分析(一),有利于概念的连续性,更容易理解。
由于SQL解析流程过于庞大复制,本篇文章只分析访问者访问AST的主要流程。

流程分析
SQLObject 对象

SQLObject对象是Druid体系中的顶层接口,用于描述所有SQL有关的对象,比如:ASTSQLObject的一个继承类。对应访问者模式中的Element,用于接收一个访问者对象(Visitor 的具体实现类)。

访问者遍历AST语法树
  1. 使用如下方式遍历AST树
sqlStatement.accept(sqlCustomedVisitor);

2.跟踪accept方法里面后发现,accept方法是SQLObjectImpl里面的一个final方法,无法被子类重写,最后进入到了accept0方法,该方法是一个抽象的方法,子类必须重写,这里就使用到了模板方法的设计模式。
image
3.到一个实现类MySqlUpdateStatement里面去跟踪accept0的具体实现,发现这里会调用visitor.visit(this)方法,把对象自己传进去。visitor同时实现了visitor.visit(MySqlUpdateStatement mySqlUpdateStatement)方法,此时就会进入到visitor的实现里面去。
image
4. visitor访问完自身节点后,然后再去访问子节点,就如MySqlUpdateStatement实例一样。

            this.acceptChild(visitor, this.tableSource);
            this.acceptChild(visitor, this.items);
            this.acceptChild(visitor, this.where);
            this.acceptChild(visitor, this.orderBy);
            this.acceptChild(visitor, this.limit);

然后子节点又是一个SQLObject对象,再次调用accept方法,所以又回到了步骤2,以此类推,遍历完整个AST树。
image
4. 如果我们需要自定义visitor,那么必须实现 SQLASTVisitor接口,该接口是抽象访问者,定义访问者的行为规范。SQLASTVisitorAdapter类已经帮我们实现了SQLASTVisitor,所以需要自定义visitor时,可以选择继承SQLASTVisitorAdapter,然后重写特定接口即可。比如:需要通过自定义visitor获取SQL的limit RowCount数量,可以以如下方式定义visitor,当使用该visitor遍历AST树时,如果遍历到SQLLimit节点,就会调用该重写方法。

    // 自定义访问者
    class SQLCustomedVisitor extends SQLASTVisitorAdapter {

        protected boolean hasLimit = false;

        @Override
        public boolean visit(SQLLimit x) {
            System.out.println(x.getRowCount());
            hasLimit = true;
            return false;
        }

        public boolean isHasLimit() {
            return hasLimit;
        }
    }

posted on 2021-08-26 18:45  bigstrong_code  阅读(1452)  评论(0编辑  收藏  举报

导航