用antlr实现将SQL转换成EQL(Ehcache Search Query)的语法解析器

来源:互联网 发布:office mac 安装教程 编辑:程序博客网 时间:2024/05/16 15:28

本文的目的

用ehcache实现对数据库的对象缓存,并且能够使用SQL直接从缓存中搜索已经缓存的对象。由于SQL语句与EQL(EhcacheSearch Query)在形式上完全不同,我们就需要将SQL翻译成对应的EQL。

这篇文章需要读者对antlr以及ehcache有个基本的了解,本文中不予详细讲述。相关的知识请移步至引用,那里将会提供相关链接与学习心得。

实现过程

废话不多说,其实我们要实现的的上述功能可以看做是一个伪内存数据库。但明显由于ehcahce的一些特性,它肯定不能完全实现真实的数据库功能,一个木桶能装多少水取决于,木桶边上最矮的那片木板长度。

翻看ehcache关于Search功能的那块官方文档,当前支持的一些组合函数如sum,max

,min,coun还有average。而支持的搜索数据类型也只有12种(居然还不支持byte[]类型),支持的搜索操作可以分为两个种类,一个是具有特色的key-value操作(听上去有点像NoSQL,其实就是一个hashmap,这种操作是速度最快的,也是最推荐的,因为其它的搜索操作都要遍历ehcache中所有对象对应的field),另一个是基本的数据库的搜索操作,如and,or,not,between,eq(就是'='操作,以下类似),ne('!='),lt('<'),gt('>'),le('<='),ge('>='),ilike('like')还有in('in').

综上所诉,我们就能搞清楚,我们写出来的这个伪内存数据库能做哪些事,以及对什么样的SQL提供支持了:

  1. 只能支持SELECT操作(这个好像是废话)。

  2. 不支持多表,嵌套的查询,union ,jion这样的操作就别想了。这个忘了说了,因为ehcache是根据对象来缓存的,就好像一个对象类型对应数据库里的一张表的,其实是可以通过其他方法实现对多表的查询的,可是要绕这个弯子,对于我来说太复杂了。

  3. 我们不能够搜索精确的字段,以及对字段操作如SELECTFEILD_1,FEILD_2+1 FROMTABLE_NAME (WHERE CLAUSE). 我们只能应对这样的SELECT* FROM TABLE_NAME (WHERE CLAUSE).跟第二条同样地原因,同样的也可以用其他方法绕过。但我们只考虑最简单的情况。

所以我们能够接受的SQL范式是:SELECT* FROM TABLE_NAME (WHERE CLAUSE) (ORDERBY).精简了就是:FROMTABLE_NAME (WHERE CLAUSE)(ORDERBY).如你所见,这就是我们根据ehcache的特性做出很多妥协后所能够支持的SQL了。


然后我们就要对比SQL与EQL的具体差别,实现用antlr编写SQL->EQL的解析器了。

我们假设有一张USER表,建表语句是:

createtable STUDENT (

idnumeric(19,0) not null,

namevarchar(20)

);

对应的缓存在ehcache的对象就是:

public class Student{

private long id;

private String name;


//getters and setters

}


那么假设有SQL语句:FROMSTUDENT WHERE ID > 10 OR NAME = 'Evan';

首先先要取出对应的字段的在ehcache中的Attribute:

ID:AttributeidAttrs=CacheManager.getEhcache(cacheName).getSearchAttribute(“id”);

NAME:AttributenameAttrs=CacheManager.getEhcache(cacheName).getSearchAttribute(“name”);

要做这些都要对ehcache进行配置的,具体的配置请移步官方网站查看。

所以对应的EQL就有:Criteriac =idAttrs.gt(new Long(10)).or(nameAttrs.eq(new String(“Evan”)));

是不是发现两者巨大的差别了,是的,最后的EQL完完全全是一个对象!仔细观察我们就会发现,从SQL到EQL我们最先得到的是对应字段的Attribute对象然后才进行的SQL拼凑。

所以对SQL的解析,应该是由内至外的。几乎是第一反应,我就想到了递归调用。

于是我就自己写了一段超长递归调用的用于将SQL解析成EQL的代码段,你可以在我提供的实例代码中找到。是的,我承认,这段代码很丑陋,大量的ifelse语句堆砌,而且容易出现深递归StackOverflow(有人拿我的代码,进行几百个OR和AND配凑成语句的解析测试)。还有很多其他的缺陷,如:不能有识别表达式Expression,要是加上这个功能的话,我估计得写死。还有,不好维护(除了我自己,谁也看不懂)。

所以antlr这个工具现在就派上用场了,我对antlr的理解就是:

  1. 简化了你解析语法的流程,提供解析的标准。

  2. 对于antlr做了什么,它其实就是把大的递归分解成一个个rule(里面是小的递归)。然后把ifelse转换成了switch语句(依靠词法分析器)。然后将解析语法和具体实现逻辑分离。所以有个基本的antlr解析流程lexer->parser->threeparser

说了那么多,现在上菜吧。示例下载地址:http://download.csdn.net/detail/taiyangyz/3688444

就我上传的例子,请阅读README文件,以及以下几点说明:

  1. 对于sql.g文件,我是模仿和学习自hibernate的hql.g,并对其做了适当的精简和修改。

  2. 对于sqlWalker.g文件,完全自主研发,因此bug肯定很多,希望各位同学多多指正。


后记


写到这,我可以嘘口气了。其实很想就很想写一篇文章了,可是每每提笔,就写不下去,原因很复杂,主要就是觉得没什么信心,也不想写那种毫无思考价值的文章。终于鼓起勇气写了这篇文章,可能这里还有很多错误或者不足,希望大家给予批评和指正,我的email:taiyangyz@gmail.com。

之后如果可以的话还想写写关于ehcachesearch 这块源代码的分析及缺陷优化。


引用

关于antlr:

本文中的antlr使用的是antlrv2,它的相关主页是:http://www.antlr2.org/

我为什么要使用antlrv2?

原因有几点:

  1. 我写的grammar文件,不管是lexar还是 parser异或是treeparser都模仿和学习来自hibernate的语法解析文件。这里提供相关的链接:https://github.com/hibernate/hibernate-core/tree/master/hibernate-core/src/main/antlr下的hql-sql.g,hql.g 和sql-gen.g 文件。

  2. antlrv2有中文手册而v3没有,看英文我头大。这里亦提供链接:http://www.antlr2.org/doc/antlr_2_7_5_ChineseVer.pdf

我对antlr的学习心得:

在学习antlr的过程中充满的失望和失败的挫折感,如果你直接去看antlr的中文手册并且没有一定的编译原理方面的知识,那你一定会死的很惨,因为里面的很多术语让你抓狂,如LL(k)文法,BNF规则,语义谓词,语法谓词等等。恰巧我是一个学物理出身的人,根本没见过这些东西,所以我的死相不是很好看。另外,中文网上的例子让人失望。要么是计算1+1,要么是计算1*1这样的例子,而且都是你抄我,我抄你的,根本毫无帮助。

如果你在学习中遇到上述困难,我建议你,先从简单的例子练起。练起的意思是你一定要自己手写,然后生成代码,做测试。千万别光盯着别人的代码看。这里提供一个国外的例子,这个例子不缺复杂度,能让你了解antlr中grammar各项语法规则,而且也具有简单易懂的特性,不至于看到官网上复杂的grammar文件让人抓狂。链接是:http://jnb.ociweb.com/jnb/jnbJun2008.html(请注意这是一个antlrv3的例子)

其实V2和 V3的差别不是很大,只要你会了其中的一个版本,基本上另一个版本也是手到擒来。这里有个讲述V2和V3差别的链接:http://www.antlr.org/wiki/pages/viewpage.action?pageId=719



关于ehcache

对于ehcache,它的官方主页是:http://ehcache.org/

对了,由于ehcahce好像是从2.4.0之后才支持搜索功能的,所以请务必下2.4.0+的版本,建议下载2.4.3。

关于ehcache的Search功能,这里有详细的官方文档:http://www.ehcache.org/documentation/user-guide/search

对于ehcache,我个人觉得,如果单纯拿来当工具用,学习还是小case的。但仔细翻看它的源代码就会觉得自己只站在人家的脚跟,虽然这个“脚跟”也不是很好看(至少search这块,我觉得还是有些缺陷的,如果有机会的话,我希望写另一篇文章关于改进这方面的缺陷)。


原创粉丝点击