用过hive的人都知道,可以通过在cli向hive传递参数,变量等,这里其实是通过下面两个类实现的。

org.apache.hadoop.hive.ql.processors.SetProcessor类
org.apache.hadoop.hive.ql.parse.VariableSubstitution类

其中SetProcessor类定义了对set 命令的处理,VariableSubstitution类负责把变量值进行转换。

VariableSubstitution用来实现在解析hive命令时把特殊字符进行转换,如果是以!开头的shell命令的话,直接在 CliDriver类的 processCmd方法中做转换

else if (cmd_trimmed.startsWith("!")) {String shell_cmd = cmd_trimmed.substring(1);shell_cmd = new VariableSubstitution().substitute(ss.getConf(), shell_cmd);

其他的命令会在具体的CommandProcessor 实现类中做转换。关于CommandProcessor 类这里简单说下,后面会相信分析:

CommandProcessor 的调用是在在CliDriver类的processLocalCmd 方法中发生的。

int processLocalCmd (String cmd, CommandProcessor proc, CliSessionState ss)

这里传入一个CommandProcessor 的实例,函数中会判断具体的实现类。如果实现类是Driver类(即执行的命令是sql),会调用Driver的run方法。

           if (proc instanceof Driver) {Driver qp = (Driver) proc;
.....ret = qp.run(cmd).getResponseCode();

如果是其他实现类(即执行的命令是set/add/compile等),会调用对应实现类(commandprocessor相关类)的run方法。

下面分析下VariableSubstitution的具体实现:

VariableSubstitution类有两个控制参数

hive.variable.substitute  控制是否打开Substitution功能,默认是true
hive.variable.substitute.depth ,控制可以匹配到几层,默认是40

主要有getSubstitute和substitute方法。

方法的调用顺序是

substitute----->getSubstitute

其中substitute 方法如下:

public String substitute ( HiveConf conf, String expr) {
if (conf.getBoolVar( ConfVars.HIVEVARIABLESUBSTITUTE)){ //判断hive.variable.substitute是否设置truel4j.debug( "Substitution is on: "+expr);} else {return expr;}if (expr == null) {return null;}Matcher match = varPat.matcher( "");String eval = expr;for(int s=0;s<conf.getIntVar( ConfVars.HIVEVARIABLESUBSTITUTEDEPTH); s++) {match.reset(eval);if (!match.find()) {    //判断输入的命令是否匹配"\\$\\{[^\\}\\$\u0020]+\\}",如果不匹配直接返回return eval;}String var = match.group();var = var.substring(2, var.length()-1); // remove ${ .. }String val = getSubstitute(conf, var);if (val == null) {l4j.debug("Interpolation result: " +eval);return eval; // return literal, no substitution found}// substituteeval = eval.substring(0, match.start())+val+eval.substring(match.end()); //完成替换}throw new IllegalStateException("Variable substitution depth too large: "+ conf.getIntVar(ConfVars.HIVEVARIABLESUBSTITUTEDEPTH) + " " + expr);}

其中getSubstitute会调用SetProcessor类,来解析命令。

比如,以hiveconf:开头的命令会经过如下的处理:

      if (var.startsWith( SetProcessor.HIVECONF_PREFIX)){val = conf.get(var.substring( SetProcessor.HIVECONF_PREFIX.length()));}

但是对于使用命名空间如hiveconf,system,env的,前缀则不可少,hivevar可以不需要前缀。

    if (val == null){if(var.startsWith( SetProcessor.HIVEVAR_PREFIX)){  //这里HIVEVAR_PREFIX的值是hivevar:val =  SessionState.get().getHiveVariables().get(var.substring( SetProcessor.HIVEVAR_PREFIX.length()));} else {val = SessionState.get().getHiveVariables().get(var);}}

这里有个例子:

set system:testdate=20140816;
select * from chinacache_log where dt >= '${system:testdate}'  limit 5;

1)第一个set命令在经过processLocalCmd 方法处理之后,传入substitute的expr是20140816 (取=号之后的数据)

因为不能匹配到正则,直接回返回。

String eval = expr;
.....if (!match.find()) { return eval;}

2)第2条sql

 select * from xxxx where f1>='${system:testdate}'

由Driver处理后,传入的expr是

select * from peter001 where f1>='${system:testdate}'

由match.group()匹配到${system:testdate},然后通过

var.substring(2, var.length()-1)

去除掉${},并调用getSubstitute获取设置的变量值,并最终生成一个有效的sql。

最终由

eval.substring(0, match.start())+val+eval.substring(match.end())

返回的值是

select * from peter001 where f1>='20140816'

完成了变量的替换。

转载于:https://blog.51cto.com/caiguangguang/1541758

hive变量传递的源码实现相关推荐

  1. react中context到底是如何传递的-源码分析

    react中使用context 基本要求就是 父组件中声明Parent.prototype.getChildContext 父组件中声明Parent.childContextType 子组件声明 Ch ...

  2. Flutter路由管理和页面参数的传递(源码分析)

    前言 上一篇 Flutter路由管理和页面参数的传递(获取&返回) 文章中我们讲述了这么用代码实现 Flutter 中页面参数的传递,这一篇我们用源码分析一下 Navigator 为什么可以进 ...

  3. hive 强转为string_String 源码浅析————终结篇

    写在前面 说说这几天看源码的感受吧,其实 jdk 中的源码设计是最值得进阶学习的地方.我们在对 api 较为熟悉之后,完全可以去尝试阅读一些 jdk 源码,打开 jdk 源码后,如果你英文能力稍微过得 ...

  4. 关于互斥锁,条件变量的内核源码解析

    一.解决问题和适用范围 主要是用来等待一个条件,这个条件可能需要另一个线程来满足这个条件.这个和我们平常适用的pthread_mutex_lock的最大不同在于后者保护的一般是一个代码段(也就是关键区 ...

  5. 二位数组的随机生成,遍历,求和,反转。和两个变量的^反转 源码

    import java.util.Random;/*** derf*/ public class Operate {public static void main(String[] args) {in ...

  6. Hive学习(一)窗口函数源码阅读

    Hive学习(一)窗口函数源码阅读 背景 窗口函数执行逻辑 代码流转图 源码阅读分析 PTFOperator PTFInvocation PTFPartition TableFunctionEvalu ...

  7. nginx源码分析之变量

    nginx中的变量在nginx中的使用非常的多,正因为变量的存在,使得nginx在配置上变得非常灵活. 我们知道,在nginx的配置文件中,配合变量,我们可以动态的得到我们想要的值.最常见的使用是,我 ...

  8. Hive源码阅读之路

    Hive源码阅读(1)阅读环境搭建 前言:让学习成为一种习惯 环境准备 Hive源码下载 Hive源码目录 hive三个最重要的组件: 其他组件 hive辅助组件 编译源码 配置Hive本地调试 配置 ...

  9. uboot源码——环境变量

    以下内容源于朱有鹏嵌入式课程的学习,如有侵权,请告知删除. 参考资料:http://www.cnblogs.com/biaohc/p/6398515.html. 一.uboot的环境变量基础 1.环境 ...

  10. HashMap、ConcurrentHashMap源码解读(JDK7/8)

    下载地址(已将图片传到云端,md文件方便浏览更改):https://download.csdn.net/download/hancoder/12318377 推荐视频地址: https://www.b ...

最新文章

  1. IIS初始化(预加载),解决第一次访问慢,程序池被回收问题
  2. go语言定义二维数组
  3. 光流 | 由粗到精的稠密光流算法
  4. zabbix监控搭建
  5. 5-(基础入门篇)学会刷Wi-Fi模块固件(刷LUA版本固件)
  6. pyecharts geo_pyechartstableau可视化分析案例+分析思路
  7. 延迟分析中的案例研究:锁定与同步
  8. 【机器学习】opencv-人脸识别
  9. torch学习笔记--tensor介绍2,对tensor的结构
  10. c语言加速度积分得到速度_自编微积分教材-第一章 微积分漫谈(1)
  11. 二维数组名作为实参或者形参
  12. 阿里巴巴证实全资收购协作软件平台 Teambition
  13. Xcode 4.2 中的Automatic Reference Counting (ARC)
  14. JAVA如何选中一行上移_js操作table中tr的顺序实现上移下移一行的效果
  15. xlsxwriter去掉网格线_(原创)xlsxwriter,python excel 写入数据\图表等操作_图表操作(二)...
  16. 《现代信息检索导论》课程梳理
  17. 天线的极化与圆极化天线
  18. 用python画小仓鼠代码,用python画小仓鼠教程
  19. 【计算机操作系统】新兴操作系统
  20. html 获取浏览器语言,js之获取浏览器语言

热门文章

  1. KVM 介绍(2):CPU 和内存虚拟化
  2. Camera 初始化(Open)一(FrameWork - Hal)
  3. freeswitch的dialplan中condition变量
  4. Linux虚拟文件系统之文件打开(sys_open())
  5. android AES对称加密算法使用实例
  6. 上传附件点击事件_支持高拍仪扫描凭证附件的出纳记账软件
  7. Bellman-ford算法、SPFA算法、SPFA判断负环(附例题)
  8. 同余方程-NOIP2012TGD2T1
  9. 51nod1433--简单数学
  10. baum welch java_Baum Welch估计HMM参数实例