分类: Java
2014-10-22 23:00:49
上篇在Session.java中
本来服务器端完全不知道客户端想要做什么事情,是要查询某个表的数据,还是更新哪条记录,还是要创建一个表,经过parser对象的处理之后,服务器端就能明白客户端到底要做什么了。
今天,我们就来深入看parser这个对象,是怎么做的。
在compileStatement之前,其实先调用了reset(String sql) ,有什么作用呢?基本上就是要通知各部门准备,下一个要编译的sql变成这个,该复位的复位。——因为每一个Session对象中有一个parser对象,而不是来一个sql,new一个parser。
在ParserDDL.java中,reset如下
点击(此处)折叠或打开
[不过这里个人感觉,只是调用super.reset(sql)的话,好像没有必要写个方法哦]
在ParserDDL的父类ParserDQL.java,reset如下:
点击(此处)折叠或打开
这里做了一个清除工作(复归没有编译的状态)
在ParserDQL的父类ParserBase.java中,reset如下:
点击(此处)折叠或打开
scanner.reset
点击(此处)折叠或打开
token.reset
点击(此处)折叠或打开
哎呀,终于把该复位的都复位了。为什么不直接new 一个parser对象呢?从以上也可以看到,要操作的字段也挺多,我的理解,如果new的成本比逐一复位成本要高吧。
裤子都脱了不能只看reset就完事了啊,真正的实质还没开始呢,下面就进入compile
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
这里主体工作在scanNext:
点击(此处)折叠或打开
currentPosition == limit, limit就是指字符串的长度,表明当前位置已到最后,则当然是结束了。而scanSeparator(),则是忽略掉空格制表符等分隔符号。
所以该函数的本质内容在scanToken。
scanToken的全文内容就不在此贴了,相当长。这里我挑一些代表性的代码,贴出来:
点击(此处)折叠或打开
这种类型,就是一个字符,代表一个token的处理过程,设置token的类型,以及字符串,然后将扫描位置往后移动。
点击(此处)折叠或打开
这代表来另一种类型,本身单独一个字符,能作为一个token,但是如果后面跟着某些特定的字符时,又是另外的Token
点击(此处)折叠或打开
以某些字母开头,可能会是关键字,又可能是一个普通的标识符,如bit是一种数据类型,但bxxxx,则是一个标识符。
在处理了所有特殊的地方之后,做为标识符读取。
Scanner.java文件行数有2500多行,功能就是将字符串分成一个个的Token(Token流)。之所以这么“庞大”,是由HSQLDB支持的SQL功能决定的:功能性包括支持的sql语句、关键字的数量、数据类型的数量,这个在scanner里需要一一区分出来。
这个过程是编译的第一步叫:词法分析。
本篇先到这里,本文主要分析了编译的准备工作,以及SQL语句词法分析过程。
[相关源码文件]
Session.java
ParserCommand.java[及其父类:ParserDDL.java、ParserDML.java、ParserDQL.java、ParserBase.java]
Scanner.java