2021SC@SDUSC
目录
方法CommandProcessorFactory.get
好消息是这个方法并不长,坏消息是这个方法调用了另一个方法……这方法是直接把参数传下去了
我们经过几层调用调用到了一个叫getForHiveCommandInternal
的方法。不过同时也要记住下面还有一种可能有意义的返回方式
方法getForHiveCommandInternal
我们集中关注这个find
方法
方法HiveCommand.find
这里前半部分是各种特殊情况,注释里也有很多的解释了。不过基于之前CommandProcessorFactory.get
在你各种返回null
的时候仍能做出有意义的返回,所有返回null
的都要考虑一下……
我们接下来的一个分支可以再着重看一下
COMMANDS
是一个集合,这个集合的内容来自一个枚举类
相当于是定义了一些指令,然后先检查我们的这个token化的命令的第一个token属不属于这个给定的指令集合,如果属于的话,后续通过valueOf
获取这个指令usedOnlyForTesting
这个属性。看名字就知道是干啥用的了,指明这个指令是否只用于测试。如果findOnlyForTesting
——也就是我们传入的,指明执行这个指令时是否是测试状态的boolean量——如果和这个操作的usedOnlyForTesting
是否一致。只有一致才返回这个操作的枚举量。
枚举类来定义这种常量应该有考虑吧,比如非硬编码、可扩展性强?
总得看下来,这个find
方法返回了我们的指令的第一个token所指向的指令类型。如果不属于这里规定的那些指令的话就会返回null
。有一点也让我很在意:这里规定的那些指令中没有SELECT
?如果一层一层往回看的话,SELECT
开头的指令就会CommandProcessorFactory.get
的返回就会滑向我之前说猜测的“另一种有意义”的走向了。
ps:后来我发现这个枚举上面有一行注释
看来这里规定的指令都是“非SQL”语句,至少能明显看出来是数据仓库不常用的指令(毕竟数据仓库的主力是SELECT)
指令安全性检查
下面那个是检测特殊指令的,我们主要看上面。上面那个HiveConf.ConfVars.HIVE_SECURITY_COMMAND_WHITELIST
,这个有一段非常漫长的调用,总的来说返回的内容是这个defaultVal
的内容
也就是说这是一个安全指令的名单啦,最上面那段是在确认这个命令是白名单中的安全指令
最终switch
这里就很明显了,根据HiveCommand.find
检查到的这条命令所属类型,返回不同的CommandProcessor
。那些不同的Processor都是实现了CommandProcessor
这个接口
那么DriverFactory.newDriver?
这个方法调用到了这里
而这里面的HIVE_QUERY_REEXECUTION_ENABLED
,defaultVar
为true
。但是呢Driver
和ReExecDriver
,从名字来看,后者是“重新执行”的意思,不免让我猜测后者是否依赖于前者。于是我去查看ReExecDriver
的run
方法。
这是因为我提前粗略地阅读了下一步的代码,CommandProcessorFactory.get
这个方法的返回量被传入下一个方法后执行了run(cmd)
这个方法,这个方法是一个接口的方法,被Driver
和ReExecDriver
两个类实现。而且这个run
方法还被计时了,显然对应了执行hql语句后命令行返回的执行时长,run
就是核心方法,值得关注。而且这也说明这两个类间的联系。
run(cmd)
也经过了一些调用,最后是这个
这里我就发现了一个很有趣的事情:各种return
的值,都是来自于一个叫做coreDriver
的类变量的方法,而这个类变量恰恰又是个Driver
类对象。闭环了同学们!而且这个Driver
也执行过一个compileAndRespond
的方法(这是从run(cmd)
到run()
中间做的事情),传入参数就是我们得命令。我们可以确定Driver
才是核心,分析的目标应该是Driver
,这也为我们再下一步的分析指明了方向
总结
看似是确定了CommandProcessorFactory.get
的返回值情况,但是我最后发现这个分析恰好十分关键,为下一个方法——processLocalCmd
——的核心内容铺平了道路,明确了分析方向,可喜可贺。