Skip to content

访问器编写难度能否降低 #5

@WuQuDeRen

Description

@WuQuDeRen
  1. druid中关于遍历AST的逻辑,访问器只需要编写访问哪块数据结构的代码即可,不直接负责接下来是否继续递归的逻辑(是由 SQLObject 子类负责,主要指 accept方法 的调用,这块逻辑算是重复逻辑,总不能每编写一种访问器就要再次重复编写这个递归逻辑吧,顶多访问器的visit方法返回布尔值来决定是否继续),降低了心智负担
public abstract class SQLObjectImpl implements SQLObject {
       public final void accept(SQLASTVisitor visitor) {
           if (visitor == null) {
               throw new IllegalArgumentException();
           }
           visitor.preVisit(this);
           // 由子类负责
           accept0(visitor);
           visitor.postVisit(this);
       }
}

 // 其中一个子类
public class SQLSelect extends SQLObjectImpl {
        protected void accept0(SQLASTVisitor visitor) {
              if (visitor.visit(this)) {
                 acceptChild(visitor, this.withSubQuery);
                 acceptChild(visitor, this.query);
                 acceptChild(visitor, this.restriction);
                 acceptChild(visitor, this.orderBy);
                 acceptChild(visitor, this.hints);
                 acceptChild(visitor, this.offset);
                 acceptChild(visitor, this.rowCount);
             }
             visitor.endVisit(this);
           }
   }
  //  我实现的访问器的时候,只需要 关注数据类型,不需要关注方法名(统一用visit)
  //  方法名+数据类型 已经语义明确的告知要访问那块数据类型,不需要在方法名中再重复说明了
  public interface SQLASTVisitor {
       boolean visit(SQLAllColumnExpr x);
       boolean visit(SQLBetweenExpr x);
       boolean visit(SQLBinaryOpExpr x);
       boolean visit(SQLCaseExpr x);
       boolean visit(SQLCaseExpr.Item x);
       boolean visit(SQLCaseStatement x);
  }
  1. 目前该解析器需要开发者自己在编写的访问器中处理递归逻辑转发,那就需要对数据结构很清晰,但对于刚接触该项目的人来说,很难了解这么清楚,就怕作者在时间长了之后也不一定记得住这么多数据结构类型

  2. 希望作者能将是否继续遍历语法树的逻辑迁移到 SqlExpression

  3. 额外说明下,我首次编写SqlParser.Net语法树访问器的尴尬点(下面自定义访问器的中VisitSqlSelectQueryExpression方法的代码注释)

    [Test]
    public void TestVisitor()
    {
        string sql = "select * from test where id = 1";
        SqlExpression sqlExpression = DbUtils.Parse(sql, DbType.Oracle);
        sqlExpression.Accept(new CustomVisitor());
    }
    
    // 自定义访问器
    public class CustomVisitor : BaseAstVisitor
    {
        // 我以为只要重写这个方法,就能访问到这里,结果并不是,然后我去看了 UnitTestAstVisitor的源码,才发现需要自己去编写 accept 的访问逻辑
        public override void VisitSqlSelectQueryExpression(SqlSelectQueryExpression sqlSelectQueryExpression)
        {
            Console.WriteLine();
        }
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions