系列:用python+antlr解析hive sql获得数据血缘关系(四)

本文介绍了在使用Python和ANTLR解析Hive SQL获取数据血缘关系时遇到的分号和大小写问题。针对分号问题,作者选择修改HiveParser.g的语法规则,允许语句间用分号分隔。对于大小写问题,通过引入Hive源码中的ANTLRNoCaseStringStream进行输入内容的预处理,将所有内容转换为大写。文章详细阐述了解决方案并提供了代码修订过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标

系列第三篇里做了基本的AST遍历。

在深入做SQL中的表名列名提取前,还需要先解决第三篇里遗留的两个实用性问题,分号和大小写

分号问题

分号问题的表现是自动生成的HiveParser.java代码,只能解析单个的语句,对包含多个语句的sql文本会报错,甚至连单个语句结尾多一个分号都不行。例如这种

SELECT DISTINCT a1.c1 c2, a1.c3 c4, '' c5  FROM db2.tb2 a1 ;

还有这种

SELECT DISTINCT a1.c1 c2, a1.c3 c4, '' c5  FROM db2.tb2 a1 ;
SELECT c6  FROM tb3 ;

原因

引发这个问题的地方很好找,就在HiveParser.g里面,具体就在statement()方法对应的这条RULE上。

// starting rule
statement
	: explainStatement EOF
	| execStatement EOF
	;

这段天书的符号体系和正则表达式很像,简单翻译成人间语言的意思是,HiveParser接受的输入都是statement,一个statement可以是一个explainStatement 加上EOF组成,也可以是execStatement加上EOF组成。explainStatement和execStatement都是有具体类型的单个语句

这个体验不符合使用hive的经验啊,最常用提交Hive语句的方式是通过hive client,它肯定是能处理多个语句的。要往下解决这个分号问题,有两个明显的方向可选

  1. 扩大使用hive源码的范围
  2. 修改HiveParser.g里的语法规则

但要怎么选呢?笔者在Hive源码里上下翻找了一通,再结合Hive实际的使用情形后有了推断。

  • HiveParser.g 的语法规则只被藏在Hive执行引擎深处的代码调用,调用时的输入已经被裁剪约束到只包含单个语句
  • 最常用提交Hive语句的方式是要通过hive client,它还需要被翻译到或者thrift,或者jdbc协议上的调用。
  • Hive client能处理的脚本里,会存在一部分conf设置、运行参数替换这样,需要在执行hive sql前预处理的语句

有了以上几个推断,结论也很显然,处理血缘关系的需求并不需要完备的hive client处理能力,而且裁剪hive源码的工作量不太可控,所以要选择2 ,修改HiveParser.g里的语法规则

如果对1还有兴趣,可以从研究源码同目录下的ParseDriver.java类出发。

规则修订

现在的规则名为statement, 一个语句后面就是EOF结束,作为写过正则的笔者,很自然的想法是,如果能让statement这个rule匹配上多次,分号分隔一下,是不是可以?试验过程略去不说,成功的结果如下

// starting rule
statements
    : statement (SEMICOLON statement )* SEMICOLON* EOF
    ;
statement
    : explainStatement | execStatement
    ;

把原先statement里这个EOF去掉,两行并做一行

然后增加一个statments这个复数名字的rule,SEMICOLON是从HiveLexer.g里的定义找出的,表示分号的写法。在.g文件里的括号()表示括号内的内容作为一个整体判断,*
的作用和正则表达式里类似,表示前面的这个整体出现0到无限次,合起来后的效果就是,一段文本里可以有多个语句,语句之间是单个分号分隔,但最末尾的语句后的分号可以省略

验证输出

测试sql语句如下

SELECT DISTINCT a1.c1 AS c2,
 a1.c3 AS c4,
 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值