皆非的万事屋

基于 Trino/Presto 的AST,使用Antlr扩展其他SQL方言

对于 Trino/Presto 的parser模块的基本梳理,可以参考这篇,这里以 sparkSQL为例,大家如果还想扩展其他方言是同理的

前言


官方博客

扩展流程

主要是基于 core/trino-parser 模块进行扩展

  1. 引入词法文件g4,这里以SparkSQL为例
  2. 编译生成词法分析器SparkSQLlexer,语法分析器SparkSQLparser,和SparkSQLBaseVisitor
  3. 新增SparkSQLAstBuilder,构建 Node
  4. 修改SqlParser的入口,可以选择 SparkSQL
  5. 新增语法Node,添加到AstVisitor
  6. 在对应方言的AstBuilder中构建它
  7. SqlFormatter/ExpressionFormatter中添加它的组装逻辑
  8. 单测
    (5~8步是重复操作)
    这里我以扩展SparkSQL里的一个Any_vaule函数为例
    大家可以根据更新的类文件更清晰看到改动点:demo地址

    public class AnyValue
         extends Expression
    {
     private final Expression expression;
    
     private final Boolean isIgnoreNulls;
    
     public AnyValue(Expression expression, Boolean isIgnoreNulls)
     {
         this(Optional.empty(), expression, isIgnoreNulls);
     }
    
     public AnyValue(NodeLocation location, Expression expression, Boolean isIgnoreNulls)
     {
         this(Optional.of(location), expression, isIgnoreNulls);
     }
    
     protected AnyValue(Optional<NodeLocation> location, Expression expression, Boolean isIgnoreNulls)
     {
         super(location);
         this.expression = expression;
         this.isIgnoreNulls = isIgnoreNulls;
     }
    
     public Expression getExpression()
     {
         return expression;
     }
    
     public Boolean getIsIgnoreNulls()
     {
         return isIgnoreNulls;
     }
    
     @Override
     protected <R, C> R accept(AstVisitor<R, C> visitor, C context)
     {
         return visitor.visitAnyValue(this, context);
     }
    
     @Override
     public List<? extends Node> getChildren()
     {
         ImmutableList.Builder<Node> nodes = ImmutableList.builder();
         nodes.add(expression);
         return nodes.build();
     }
    
     @Override
     public boolean equals(Object o)
     {
         if (this == o) {
             return true;
         }
         if (o == null || getClass() != o.getClass()) {
             return false;
         }
         AnyValue anyValue = (AnyValue) o;
         return Objects.equals(expression, anyValue.expression) && Objects.equals(isIgnoreNulls, anyValue.isIgnoreNulls);
     }
    
     @Override
     public int hashCode()
     {
         return Objects.hash(expression, isIgnoreNulls);
     }
    }

    Trino的Node设计的比较简单,需要重写的方法比较少,很适合新手选做入门AST起手练习。
    我修改了parsingOptions这个类,可以选择解析的方言,调用不同的解析器。

    debug看下类和结果:

更多的词法文件可以从antlr/gammer里获得

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »