本章主要介绍一下XML数据库中sql语言解析的问题。
现在解析sql基本是使用了类似后缀表达式的解析方法,具体如下:
比如有一个sql语言是这样的:a>1 && b <2
如果我们现在将它转换成具体sql动作如下,则会变成下面的样子:
a 1 > b 2 < &&.
->与后缀表达式很相近,主要区别在于&&的判断上。
算法如下:
首先规定如下:
1.定义一个栈P用来存放运算符。且&&的运算符优先级别低于>,<运算符。
2.只有当&& 或者 ||入栈P的情况下,才根据优先级,将运算符推出栈,
3.反之则继续进栈。
当前解析结果 当前栈
1.a 放入解析结果中 a null
2.>,放入栈中 a >
3.1 放入解析结果中 a 1 >
4.&&优先级低,将>推出 a 1 > &&
5.b放入解析结果中 a 1 > b &&
6.<,由于&&优先级低,<入站 a 1 > b 2 < &&
7.所有运算符出栈。
最后:
a 1 > b 2 < &&
实际上,代码会生成一个action list,来保存之前的解析结果。
action list如下:
action1 a1>
action2 b2<
action3 action1&&action2
关键代码如下:
for(;i<queryList.length;i++) {
char c = queryList[i];
if(c == MARK_LEFT_BRACES) {
operationList.add(String.valueOf(c));
continue;
}
if(c == MARK_RIGHT_BRACES){
for(int k = operationList.size() - 1;k >= 0;k--) {
String d = operationList.get(k);
if(!d.equals(OPERATION_LEFT_BRACES)) {
nodeList.add(d);
operationList.remove(d);
} else {
operationList.remove(d);
break;
}
}
if(record != 0) {
nodeList.add(String.valueOf(queryList, i - record, record));
record = 0;
}
continue;
}
if((c == OPERATION_AND.charAt(0) && queryList[i+1] == OPERATION_AND.charAt(1))
||(c == OPERATION_OR.charAt(0) && queryList[i+1] == OPERATION_OR.charAt(1))
||(c == OPERATION_LESS_THAN_OR_EQUAL.charAt(0) && queryList[i+1] == OPERATION_LESS_THAN_OR_EQUAL.charAt(1))
||(c == OPERATION_MORE_THAN_OR_EQUAL.charAt(0) && queryList[i+1] == OPERATION_MORE_THAN_OR_EQUAL.charAt(1))
||(c == OPERATION_EQUAL.charAt(0) && queryList[i+1] == OPERATION_EQUAL.charAt(1))
||(c == OPERATION_NOT_EQUAL.charAt(0) && queryList[i+1] == OPERATION_NOT_EQUAL.charAt(1))) {
String operation = String.valueOf(queryList, i, 2);
int operationNewPri = mPriorityMap.get(operation);
if(operationList.size() > 0) {
String top = operationList.get(operationList.size() - 1);
int operationOldPri = mPriorityMap.get(top);
if((operationNewPri < operationOldPri)
|| (top.equals(OPERATION_LEFT_BRACES))) {
operationList.add(operation);
} else {
operationList.remove(top);
nodeList.add(top);
operationList.add(operation);
}
} else {
operationList.add(operation);
}
if(record != 0) {
nodeList.add(String.valueOf(queryList, i - record, record));
record = 0;
}
i++;
continue;
}
if(c == MARK_MORE_THAN || c == MARK_LESS_THAN) {
String operation = String.valueOf(c);
operationList.add(operation);
if(record != 0) {
nodeList.add(String.valueOf(queryList, i - record, record));
record = 0;
}
continue;
}
if(c == MARK_DOUBLE_QUOTATION) {
int j = i + 1;
for(;j < queryList.length;j++) {
if(queryList[j] == MARK_DOUBLE_QUOTATION){
break;
}
}
String node = String.valueOf(queryList,i,j - i + 1);
nodeList.add(node);
i = j;
if(record != 0) {
nodeList.add(String.valueOf(queryList, i - record, record));
record = 0;
}
continue;
}
if(c >= MARK_NUMBER_0 && c <= MARK_NUMBER_9) {
int j = i + 1;
for(;j < queryList.length;j++) {
if((queryList[j] < MARK_NUMBER_0 || queryList[j] > MARK_NUMBER_9)&&
queryList[j] != MARK_SPOT){
break;
}
}
String node = String.valueOf(queryList,i,j - i);
nodeList.add(node);
record = 0;
i = j - 1;
continue;
}
if(c == OPERATION_LIKE.charAt(0)
&& queryList[i+1] == OPERATION_LIKE.charAt(1)
&& queryList[i+2] == OPERATION_LIKE.charAt(2)
&& queryList[i+3] == OPERATION_LIKE.charAt(3)) {
int position1 = 0;
int position2 = 0;
//This maybe LIKE operation,
//but we should take care this condition LIKE = 5 && name LIKE 'abc%'
for(int j = i + 4;j < queryList.length; j++) {
if(queryList[j] == MARK_SPACE) {
continue;
}
else if(queryList[j] != MARK_SINGLE_QUOTATION) {
break;
}else {
position1 = j;
int k = j + 1;
for(;k < queryList.length;k++) {
if(queryList[k] == MARK_SINGLE_QUOTATION) {
position2 = k;
break;
}
}
String operation = OPERATION_LIKE;
int operationNewPri = mPriorityMap.get(operation);
if(operationList.size() > 0) {
String top = operationList.get(operationList.size() - 1);
int operationOldPri = mPriorityMap.get(top);
if((operationNewPri < operationOldPri)
|| (top.equals(OPERATION_LEFT_BRACES))) {
operationList.add(operation);
} else {
operationList.remove(top);
nodeList.add(top);
operationList.add(operation);
}
} else {
operationList.add(operation);
}
if(record != 0) {
nodeList.add(String.valueOf(queryList, i - record, record));
record = 0;
}
i = i + 4;
break;
}
}
}
record++;
}
if(record != 0) {
nodeList.add(String.valueOf(queryList, i - record, record));
}
//last out
if(operationList.size() != 0) {
for(int k = operationList.size() - 1;k >= 0;k--) {
String d = operationList.get(k);
nodeList.add(d);
}
}