基于 Trino/Presto 的AST,使用Antlr扩展其他SQL方言
对于 Trino/Presto 的parser模块的基本梳理,可以参考这篇,这里以 sparkSQL为例,大家如果还想扩展其他方言是同理的
前言
(官方博客)
扩展流程
主要是基于 core/trino-parser 模块进行扩展
- 引入词法文件g4,这里以SparkSQL为例
- 编译生成词法分析器
SparkSQLlexer
,语法分析器SparkSQLparser
,和SparkSQLBaseVisitor
- 新增
SparkSQLAstBuilder
,构建 Node - 修改
SqlParser
的入口,可以选择SparkSQL
- 新增语法
Node
,添加到AstVisitor
中 - 在对应方言的
AstBuilder
中构建它 - 在
SqlFormatter
/ExpressionFormatter
中添加它的组装逻辑 单测
(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里获得