Catalyst揭秘 Day3 sqlParser解析

Catalyst揭秘 Day3

sqlParser解析

今天我们会进入catalyst引擎的第一个模块sqlparser,它是catalyst的前置模块。

树形结构

从昨天的介绍我们可以看到sqlParser会返回一个logicalPlan,它是TreeNode的子类。
Snip20160723_126

TreeNode,作为一个树形抽象类,SQL语法的解析的时候,所有的元素都是TreeNode,可能是叶子节点,也可能是树枝节点,可能有0个或多个子节点,其方法都是对树的操作。

通过SQLParser,会把我们的sql语句变成一颗树,针对这个树,我们有一系列的数据类型,并且运用一系列的规则,对这个树进行解析、优化。所以第一个问题,就是怎么生成这个树,这个就是SQLParser的价值。

解析入口

sqlparse完成的步骤就是怎么把一个sql变成树状结构。

我们进入源码,从sql方法开始,会调用parseSql方法。
Snip20160723_127

其最终是会调用ParserDialect的parse方法。
Snip20160723_130

再进一步,会调用AbstractSparkSQLParser的parse方法来实现,这个方法非常的关键,使用的是个模板模式。
Snip20160723_131

这里面会用到lexical词法解析。

首先我们看到,在构造时,会使用反射的方式来找到所有保留的关键字。
Snip20160723_132

并在词法解析器初始化时,会进行添加。
Snip20160723_133

AbstractSparkSQLParser的parse方法是关键,我们来详细解析一下。
这里有三个关键部分,phrase方法,start方法和Scanner对象。
Snip20160723_134

解析方法1:循环遍历

首先看一下phrase方法,这是一个总控方法,会构造一个解析器,内部这是个循环器,循环读取字符串中的数据,进行解析生成短语。注意下,方法核心就是调用一句p(in),其中p是start方法,而in是Scanner对象。

Snip20160723_136

解析方法2:分词

再看下Scanner对象,其主要作用是对字符串进行分词,其中核心是whitespace和token方法。
Success封装了我们当前的解析结果和没有解析的结果,对分词功能来说,未解析部分是我们需要的。
Snip20160723_138

whitespace中定义了对于分割词的规则。
Snip20160723_139

token中定义了合法字符的校验。
Snip20160723_140

这里的表达是比较复杂,我们简单看一下。

关键字都会被定义为Keyword类型,这里有两个隐式转换。

首先是对Keyword进行转换,会对字符进行格式化normalize。
Snip20160723_141

下面是更关键,会对输入字符进行隐式转换,构建Parser,默认是于输入字符进行==等式判断。
Snip20160723_142

acceptIf方法内部会调用输入对象而first方法进行判断,并返回Success或Failure对象。
Snip20160723_143

解析方法3:生成语法树

最后让我们看下start方法,这个方法就是对分词的结果进行匹配,并生成TreeNode。

Snip20160723_144

这里使用到了非常强大的模式匹配,将select语句的各个部分解析出来,并形成了一个logicalPlan。

Snip20160723_145

至此,sqlParse的过程完成。总而而言,对输入字符会进行两轮处理,第一轮是通过Scanner进行分词处理,第二轮是根据语法规则,将各个语句部分生成TreeNode。

小结

整个Spark中,有几个数据结构,RDD、broadcast、accumulator,各个子框架都需要用RDD来存储数据。

我们传递了两个观点:
1.无论是哪个子框架,最终肯定是被rdd来存储的,一般只不过是在构建时会使用一个新的数据结构,比如sparksql是用树的方式来构建。
2.上面的算法调度执行引擎等一般都是依赖spark core,并加入自己基于这个数据结构领域框架需要的特色。

欲知后事如何,且听下回分解!

DT大数据每天晚上20:00YY频道现场授课频道68917580

posted @ 2016-07-23 13:02  哎哟慰  阅读(895)  评论(0编辑  收藏  举报