对于 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里获得
12 条评论
你的文章让我感受到了正能量,非常棒!http://www.yinuolcw.com
你的文章内容非常卖力,让人点赞。http://www.hntdqy.com
哈哈哈,写的太好了https://www.cscnn.com/
想想你的文章写的特别好https://www.ea55.com/
怎么收藏这篇文章?
不错不错,我喜欢看
叼茂SEO.bfbikes.com
博主好,我想问一下,如果我想按照博主的路径,通过trino的parser解析出hive,spark和trino语法到trino的ast,然后在这个基础上做后续的血缘之类的分析,是否有可行性
可以的,难点在于基于ast做后续的血缘分析,其实对于 hive, spark 和 trino 的语法,calcite 也能cover大部分,也可以直接通过 calcite 的 RelMetadataQuery 中的 api 获取血缘信息,你可以了解一下
谢谢博主!那这里的方案上1:扩展prsto.g4支持更多语法还是,2:直接用三份g4同时去解析呢。这两条路径看起来都可以,目前还在调研阶段
有利有弊,直接在一份g4上扩展只用写一个AstBuidler,前期实现快,问题是后期难维护不同的语法在一个g4里(当然可以使用antlr的import语法,但是仍然难以避免语法混杂)。使用三份g4就需要写三遍AstBuilder,前期实现慢,但是语法分开了,后期好维护,也方便同步官方的语法更新
谢谢 ,目前来看方法二应该好一些