版权声明:本文为博主原创文章,未经博主容许不得转载。java
手动码字不易,请你们尊重劳动成果,谢谢git
做者:http://blog.csdn.net/wang_wbqgithub
Spark SQL之因此能支持如此强大的表达式系统,是由于其包含了一套字符串解析并生成表达式树的模块。正则表达式
在Spark 2.0以前,Spark SQL使用Scala Parser功能去解析SQL表达式,其解析类为org.apache.spark.sql.catalyst.SqlParser
。sql
对于没用使用过Scala Parser的人来说,这个类基本上就能够称为天书了。其中用到的几个基本符号:apache
~ 链接符,并将左右侧匹配结果保留
~> 链接符,仅保留右侧匹配结果,左侧将丢弃
<~ 链接符,仅保留左侧匹配结果,右侧将丢弃。该链接符优先级低于 ~ 和 ~>
^^ 其左侧为词法表达式,右侧为一个函数
例如: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/79794897maven
在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插件生成的表达式树: