为什么使用@tablename起别名产生的sql语句不能用_antlr语法增强使用

看这篇之前,对antlr没有了解的可以自行百度。

用过antlr语法解析的都会遇到需要写listener和 visitor的时候,看我之前写过的这篇

松仁普:antlr解析语法树的使用​zhuanlan.zhihu.com

如果有一套DSL语言让你不用写很多listener和visitor你会用吗?

举个例子:你在查找一个SQL中的表名的时候:

select * from A join B on A.xx = B.xx where A.yy = yy

用listener可以轻松搞定,但是需要写一大段代码。

如果提供了一个工具类 ComplexQuery,调用方法 query("tableName")就返回了你想要的,你觉得是不是很好用。 这里"tableName"不是随意的字符串,而是q4语法文件中定义的节点。

这里我们用facebook的开源项目presto中的sql.q4文件为例,因为大而全,这个东西自己写会累死,而且考虑不周全。

姑且认为它是个sql完全体了,目前的大大小小sql它都能语法推导。

我们举一个简单的栗子,客官看下面这段SQL:

select  

此时有个需求给到了你,“取出表B_t中的b,c字段”,很多童鞋看到这里,可能想到了用正则,但是正则匹配难度会比较大,本人正则比较菜,这里不过多讨论了。

如果了解过antlr,写过listener、visitor程序也觉得该需求好实现,相比于正则肯定是简单容易的多。

如果不信,我们需求再变态点,正则规则会越来越复杂。

比如说,我们这里的SQL还是比较简单的,现在加上where条件.

select  

我随便举得这个栗子,不要在意sql不好看,这里我如果要取的 b,c字段是来自子查询中要有限制条件“e=0 且 不能 有 g=1 ” 的。 显然我们肉眼可见这里是无解的。

但是你用正则怎么写呢? 如果你能写出来,可以留言评论,我会再升级个变态3.0,总归能让你写的发狂。。

1e44888c21c1f5a278e222ac7ac86bbd.png

这里举这种栗子是为了引出下面的基于listener和visitor代码之上的DSL查找器。

主体代码就是三行

ComplexQuery 

说明:

dsl 的值是下面插件第二行输入框的内容 “querySpecification:not( tableName:text(A_t)) d”

sql 的值是 第一行输入的内容 ,即SQL本尊

set 返回时一个ParseTree集合 ,即语法树节点集合

3ac8fc40d9e193a112388804e1f25819.gif

以上插件本质上就是上面三行代码实现的,这里为了直观看到效果,所以开发了IDEA的插件,方便直观看到节点选择跟随DSL的变化。还是比较实用的哈,觉得我这段不错的可以在github给star哦。(写文章真心不容易呀)

antlr_query的git地址:

prs1022/antlr_query​github.com
8f63b0fcce0d38c36a7ed4568bd01289.png

antlr语法高亮插件的git地址:

prs1022/a_antlr_plugin​github.com
8f63b0fcce0d38c36a7ed4568bd01289.png

如果不想下载插件源码,直接安装这个插件,这里我发个百度云下载链接:

链接:https://pan.baidu.com/s/1E_Sg7NyScdzhJZkxNhAdLg

提取码:vux4

6e6a007e97d704508b0f1fb733f15bbd.gif

目前支持的查找指令如下:

  1. :is() 为以is之前查询的节点为根、按照括号内的查询语句进行后续查找 查找结果不为空时保留:is之前的筛选到的节点
  2. > 为相邻子节点查找
  3. :not()__ 与 :is() 相反
  4. :text(reg)__ 为节点 文本内容的匹配筛选 可以应用正则匹配
  5. 空格 为全部子孙节点的查找
  6. * 为任意节点都可以匹配的一个占位符
  7. + 相邻后继节点
  8. ~ 所有后继兄弟节点

eq(index) 根据下标获取还未实现
工作学习中有特殊需要可以自行添加,需要改下g4文件添加新语法支持

写在最后:

该项目不是我一人所开发,主要贡献者是前同事项目经理,也是我导师,还有很多待完善的地方。在此也对我导师表示感谢。

当初为什么要做这件事呢? 因为日常开发中写了太多listener和visitor,而熟悉的人也知道很多代码都是为了查找节点。

js中获取一个dom节点的API是这样的“getDocumentById(xxxx)” ,而用过jquery的都知道(当然现在jquery也不流行了),jquery中提供了丰富的选择器API,类似 $(‘p’)获取<p>元素,复杂点$("div#intro .head") 获取 id="intro" 的 <div> 元素中的所有 class="head" 的元素。

此时,大佬PM就想到antlr解析的语法树也是节点树,可以类比jquery的实现思路,我们也定义一套DSL语言,基于antlr语法文件之上的一套语法文件,这样可以帮开发人员省略大量listener,visitor查找节点的代码。

想到就去做,无奈当时的我听了是一脸懵逼,不过这个idea我是赞同的,只是实现起来由于我不理解没能完成。后面PM写了主体代码我才理解。时隔一年,我将它整理一下写成文章,放到github上也算开源了,供有识之士一起学习研究。感兴趣一起讨论的可以联系我。

e4b0c427f4c2bd2ef6ead14eddfb14ba.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值