分类: Java
2014-10-25 20:11:28
说完Scanner/Token的部分,我们再回头来看compilePart之前被我们忽略掉的100多行的代码。
点击(此处)折叠或打开
我们知道SQL,全称是Structured Query Language, 既然是语言,就满足一定的约定。比如陈述一件事情,一般是主谓宾。SQL也需要满足约定。比如这个SQL语句:
select id from t1;
这个约定就是 select xx from yy,其先后顺序不能颠倒(不能是from yy select xx——虽然看起来好像也能表达),有些内容不可被替换(from不能被换成join)。
在这里代码也是以这样的逻辑来处理的,就是如果出现了一个TokenA,那么接下来的Tokens就必须满足TokenA开始的句式。
我们以其中的Tokens.Select为例,进入到compileCursorSpecification方法中:
StatementQuery compileCursorSpecification(RangeGroup[] rangeGroups, int props, boolean isRoutine)
首先,我们看这个方法的签名,它的返回值是一个StatementQuery对象,而不是之前的Statement这个抽象类型了,这就表明了根据不同的SQL语句,实际上返回了不同的Statement的实现类。
点击(此处)折叠或打开
在这段代码中,被一句带过的
QueryExpression queryExpression = XreadQueryExpression();
这里有一个QueryExpression,就是一个查询表达式的意思。
一个表达式Expression,可以表达一个最基本的单元:如表式一个字段,一个数值,一个操作符;
一个表达式Expression:也可以由一个或多个子表达式组成,比如一个表达了“select col1 as c1, col2 from t1 where id=5”含义的QueryExpression ,下面这个图大概表示了QueryExpression是个什么内容:
(注:QuerySpecification继承QueryExpression)
1、通过XreadSelect方法,构建一个基本的QuerySpecification对象
2、循环调用XreadValueExpression,将列add到exprColumnList(QuerySpecification的属性/字段)
3、调用XreadFromClause,将读取的表,添加的rangeVariableList中
4、调用XreadBooleanValueExpression,将查询条件添加到queryCondtion中
当然,如果更复杂的语句,这个图无疑将是更复杂的。
总之,ParserDQL(以及其它ParserXXX) 调用scanner.scanNext,将SQL字符串先变成一个个token,然后再将token变成这样一棵逻辑树状的对象()。
回到前面,我们知道返回的可是一个Statement对象啊,
点击(此处)折叠或打开
在最后步骤,就new一个具体类型的Statement对象(StatementQuery, StatementCursor都继承自Statement)。
那么返回了Statement,有什么用?
比如对于一个查询语句来说(如StatementQuery),我们知道可以查询出一些数据啊;而对于一个指令语句(如StatementCommand)来说,我们知道可以增删改库里的数据。
那么Statement返回之后,HSQLDB里是怎么使用的?我们下篇再分析。
总结:
本文分析了HSQLDB从token到语法树的创建过程——也就是编译原理中的词法分析到语法分析的过程。
[相关源码文件]
ParserDQL.java(ParserXXX)