Spark SQL表达式解析器-Scala Parser与Antlr4

Spark SQL表达式解析器-Scala Parser与Antlr4

版权声明:本文为博主原创文章,未经博主允许不得转载。

手动码字不易,请大家尊重劳动成果,谢谢

作者:http://blog.csdn.net/wang_wbq

Spark SQL之所以能支持如此强大的表达式系统,是因为其包含了一套字符串解析并生成表达式树的模块。

Scala Parser

在Spark 2.0之前,Spark SQL使用Scala Parser功能去解析SQL表达式,其解析类为org.apache.spark.sql.catalyst.SqlParser

对于没用使用过Scala Parser的人来讲,这个类基本上就可以称为天书了。其中用到的几个基本符号:


~ 连接符,并将左右侧匹配结果保留
~> 连接符,仅保留右侧匹配结果,左侧将丢弃
<~ 连接符,仅保留左侧匹配结果,右侧将丢弃。该连接符优先级低于 ~ 和 ~>
^^ 其左侧为词法表达式,右侧为一个函数
   例如:p1 ~ p2 ^^ { case a ~ b => a + b }
   这个表达式可以把p1和p2匹配出的结果分别赋值给a和b,
   注意:此处的前后两个 ~ 不是同一个函数; ^^ 左右匹配结果的数量必须一致
? 和正则表达式中一样,表示可有可无
*  和正则表达式中一样,表示可以有零个或多个
*(sep: => Parser[(U, U) => U])  表示this (sep this)*
   例如:andExpression * (OR ^^^ { (e1: Expression, e2: Expression) => Or(e1, e2) })
   上面表达式的意思就是:
   andExpression (OR andExpression)*
   将*展开就是:
   andExpression OR andExpression OR andExpression ...
   一个andExpression后面跟上一堆可重复的 OR andExpression
+  和正则表达式中一样,表示可以至少有一个      
^^^ 如果其左侧匹配成功,则丢弃左边,返回右侧运算结果

Scala Parser原理简介
https://blog.csdn.net/wang_wbq/article/details/79794897

Antlr 4

在Spark 2.0之后,Spark SQL使用Antlr 4来解析SQL表达式,其解析描述文件路径为spark源码根路径\sql\catalyst\src\main\antlr4\org\apache\spark\sql\catalyst\parser\SqlBase.g4

但是只有描述文件是不能解析表达式的,需要先将其变换成代码。

在spark-catalyst的pom文件里,我们可以看到它引入了antlr4的maven插件:

      <plugin>
        <groupId>org.antlr</groupId>
        <artifactId>antlr4-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>antlr4</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <visitor>true</visitor>
          <sourceDirectory>../catalyst/src/main/antlr4</sourceDirectory>
        </configuration>
      </plugin>

其中<goal>antlr4</goal>会在<phase>generate-sources</phase>生命周期内执行描述文件的解析,并且在target\generated-sources\antlr4下生成表达式解析的java文件:

这里写图片描述

Antlr 4是一个非常优秀的词法语法分析工具,借助它你可以实现很多自定义表达式解析,甚至可以做一个简单的编译器。Antlr 4使用了Visitor模式和Listener模式来帮助使用者对解析好的表达式进行处理。

Visitor模式即Antlr 4已经将表达式按照你给的规则解析成为一个语法树。然后把语法树的根节点交给你,你去决定该往哪走。

Listener模式即Antlr 4已经将表达式按照你给的规则解析成为一个语法树。然后自己执行深度优先遍历,然后在遍历到每个节点的时候给你发送事件。

我之前学习Antlr 4的时候写过一个表达式解析器,可以通过这个链接来查看。这个程序可以解析一个自定义模式的表达式,然后生成Spark SQL可用的表达式。具体实例可以参考代码中的测试用例部分。

如果你使用Spark 2.0之后的版本,你可以下载Antlr 4的IDEA插件来测试SqlBase.g4文件,其中singleStatement为整个SQL语句的解析器,singleExpression为单个表达式的解析器,我在平常工作中测试singleExpression居多,在写代码前先用插件测试下这个表达式的合法性,然后再写到代码里运行,这样可以大大增加代码的运行成功率。

以下是我使用singleExpression对表达式进行解析的结果,右侧为Antlr 4插件生成的表达式树:

这里写图片描述

posted @ 2018-03-23 23:08  海角Q  阅读(730)  评论(0编辑  收藏  举报