Skip to content

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

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();
        }
    }

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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