版權聲明:本文爲博主原創文章,未經博主容許不得轉載。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插件生成的表達式樹: