林氏物语.技术乱弹之hive源码之词法语法解析(MD版格式已乱 请查看docx版)
第一章 前言
我们知道 hive是一个基于hadoop上面提供了类sql的接口的组件,以方便熟悉sql的人使用hadoop,对大数据的处理。限于精力,本文只关注hive所提供的语法,它解析语法的过程,以及生成执行计划和优化这几个过程。
本文可以作为antlr实现的高级进阶教程,亦可以作为hive的源码分析教程,毕竟,语法词法解析,执行计划的生成优化以及执行也是hive的核心。这不是定位不清晰,而是我有这样的需求,既想了解antlr的具体使用,又想深入了解hive。
本文所用到的自绘的图尽量采用graphviz生成,考虑到他们放入word会失真,所以给提供了最原始的生成文件,你可以按照自己的需要生成各种格式,他们都存放在dot_file的目录下。
最后,本文随时会根据作者的喜好和发现而做调整,如果你觉得那些地方不妥,请来信指正或者指教:workspace.public@gmail.com
第二章 准备工作
分析对象:hive源代码,版本Revision 1522497
需要用到的工具: svn ant antlr-3.5-complete.jar,antlrworks-1.4.2.jar,eclipse。
注:在http://www.antlr3.org/download.html 可以下载antlr-3.5-complete.jar,antlrworks-1.4.2.jar.
hive中使用到的antlr是 v3.4版本的,使用v3.5没有问题,但请别使用v4.0的。
下载源代码,并编译
cd hive
ant clean package eclipse-files
最后一个是为了方便导入成eclipse项目,有些人是喜欢用eclipse查看源代码。
安装部署好分布式的hadoop,并安装好hive。可以跑例子...具体的可以参考网络上的教程,一搜一大把。
文中准备的是官方网的测试数据。所以你需要执行以下语句:
CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);
LOAD DATA LOCAL INPATH '../examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
LOAD DATA LOCAL INPATH '../examples/files/kv3.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-08');
注意:数据文件在本地的位置要根据你启动hive的不同而改变。
第三章 总体概览
第一节 hive官方架构图
摘自 hadoop 权威指南
第二节 流程处理图
这张图是从源代码中剥茧抽丝的出来的抽象,忽略掉了无关紧要的细节。
这张图描述了 hive从解析语句到执行的过程。 后续的内容会以为大纲详细展开。
第三节 具体框架图
(待完善)
第四章 语法分析
对一个已有的项目进行语法分析,首先是要找到语法分析文件,分析语法文件之间的关系,然后根据语法分析文件提供的接口,确定语法解析在这个体系中所处的位置。
在分析语法文件的时候,一般常用两种分析方法 静态分析和动态分析方法。静态分析方法常见是读语法文件, 或者使用可视化工具查看语法文件。动态分析方法是运行该解析程序,查看运行过程中语法识别的情况以及相关的具体语法树的构建过程以及抽象语法树构建过程(如果可能有抽象语法树的话)。
第一节 快速定位词法语法分析的位置的方法
搜索 .g的位置
find ./ -name "*.g"
会得到
./ql/src/java/org/apache/hadoop/hive/ql/parse/FromClauseParser.g
./ql/src/java/org/apache/hadoop/hive/ql/parse/SelectClauseParser.g
./ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g
./ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g
./ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g
./metastore/src/java/org/apache/hadoop/hive/metastore/parser/Filter.g
基本可以确定了 ql下面就是需要找到东西。
find . -name "*.java" |xargs grep "HiveLexer "
找到两处
./build/ql/gen/antlr/gen-java/org/apache/hadoop/hive/ql/parse/HiveLexer.java:public class HiveLexer extends Lexer {
./ql/src/java/org/apache/hadoop/hive/ql/parse/ParseDriver.java: public class HiveLexerX extends HiveLexer {
其中第一处是编译期构建的, 而另外一处是包装了该类。重点可以放到第二处。也即parseDriver类。
对parseDriver类做一个大致的分析,
包装了antlr的antlrStringStream 成为antlrnocasestream。消除了大小写敏感。
包装了词法解析器 HiveLexer,主要是包装了出错信息。
包装了抽象树节点,主要聚合了ASTNodeOrigin 以求能获得对象类型,名字,定义,别名,和定义。
其中parser方法是我们重点关注的,它调用词法解析和语法解析。
察看其所有的调用者的关系形成的路径,找到一条通向cli的包的clidriver类main方法,(可以通过eclipse的北调用关系反向查看)
clidriver.run() ->clidriver.executeDriver()->clidriver.processLine(string,boolean)->clidriver.processCmd()->clidriver.processloaclcmd()->driver.run->driver.runInternal()->driver.compile()->parserdriver.parse
而我们知道这也