📄 parser.java
字号:
/*
* Parser.java
*/
package org.hsql;
import java.util.*;
import java.sql.*;
class Parser {
private Database dDatabase;
private Tokenizer tTokenizer;
private Channel cChannel;
private String sTable;
private String sToken;
private Object oData;
private int iType;
private int iToken;
Parser(Database db,Tokenizer t,Channel channel) {
dDatabase=db;
tTokenizer=t;
cChannel=channel;
}
Result processSelect() throws SQLException {
Select select=parseSelect();
if(select.sIntoTable==null) {
return select.getResult(cChannel.getMaxRows());
} else {
Result r=select.getResult(0);
Table t=new Table(dDatabase,true,select.sIntoTable,false);
t.addColumns(r);
t.createPrimaryKey();
// SELECT .. INTO can't fail because of violation of primary key
t.insert(r,cChannel);
dDatabase.linkTable(t);
int i=r.getSize();
r=new Result();
r.iUpdateCount=i;
return r;
}
}
Result processCall() throws SQLException {
Expression e=parseExpression();
e.resolve(null);
int type=e.getDataType();
Object o=e.getValue();
Result r=new Result(1);
r.iType[0]=type;
r.sLabel[0]="";
r.sName[0]="";
Object row[]=new Object[1];
row[0]=o;
r.add(row);
return r;
}
Result processUpdate() throws SQLException {
String token=tTokenizer.getString();
cChannel.checkReadWrite();
cChannel.check(token,Access.UPDATE);
Table table=dDatabase.getTable(token,cChannel);
TableFilter filter=new TableFilter(table,null,false);
tTokenizer.getThis("SET");
Vector vColumn=new Vector();
Vector eColumn=new Vector();
int len=0;
token=null;
do {
len++;
int i=table.getColumnNr(tTokenizer.getString());
vColumn.addElement(new Integer(i));
tTokenizer.getThis("=");
Expression e=parseExpression();
e.resolve(filter);
eColumn.addElement(e);
token=tTokenizer.getString();
} while(token.equals(","));
Expression eCondition=null;
if(token.equals("WHERE")) {
eCondition=parseExpression();
eCondition.resolve(filter);
filter.setCondition(eCondition);
} else {
tTokenizer.back();
}
// do the update
int col[]=new int[len];
Expression exp[]=new Expression[len];
int type[]=new int[len];
for(int i=0;i<len;i++) {
col[i]=((Integer)vColumn.elementAt(i)).intValue();
exp[i]=(Expression)eColumn.elementAt(i);
type[i]=table.getType(col[i]);
}
int count=0;
if(filter.findFirst()) {
Result del=new Result(); // don't need column count and so on
Result ins=new Result();
int size=table.getColumnCount();
do {
if(eCondition==null || eCondition.test()) {
Object nd[]=filter.oCurrentData;
del.add(nd);
Object ni[]=table.getNewRow();
for(int i=0;i<size;i++) {
ni[i]=nd[i];
}
for(int i=0;i<len;i++) {
ni[col[i]]=exp[i].getValue(type[i]);
}
ins.add(ni);
}
} while(filter.next());
cChannel.beginNestedTransaction();
try {
Record nd=del.rRoot;
while(nd!=null) {
table.deleteNoCheck(nd.data,cChannel);
nd=nd.next;
}
Record ni=ins.rRoot;
while(ni!=null) {
table.insertNoCheck(ni.data,cChannel);
ni=ni.next;
count++;
}
table.checkUpdate(col,del,ins);
cChannel.endNestedTransaction(false);
} catch(SQLException e) {
// update failed (violation of primary key / referential integrity)
cChannel.endNestedTransaction(true);
throw e;
}
}
Result r=new Result();
r.iUpdateCount=count;
return r;
}
Result processDelete() throws SQLException {
tTokenizer.getThis("FROM");
String token=tTokenizer.getString();
cChannel.checkReadWrite();
cChannel.check(token,Access.DELETE);
Table table=dDatabase.getTable(token,cChannel);
TableFilter filter=new TableFilter(table,null,false);
token=tTokenizer.getString();
Expression eCondition=null;
if(token.equals("WHERE")) {
eCondition=parseExpression();
eCondition.resolve(filter);
filter.setCondition(eCondition);
} else {
tTokenizer.back();
}
int count=0;
if(filter.findFirst()) {
Result del=new Result(); // don't need column count and so on
do {
if(eCondition==null || eCondition.test()) {
del.add(filter.oCurrentData);
}
} while(filter.next());
Record n=del.rRoot;
while(n!=null) {
table.delete(n.data,cChannel);
count++;
n=n.next;
}
}
Result r=new Result();
r.iUpdateCount=count;
return r;
}
Result processInsert() throws SQLException {
tTokenizer.getThis("INTO");
String token=tTokenizer.getString();
cChannel.checkReadWrite();
cChannel.check(token,Access.INSERT);
Table t=dDatabase.getTable(token,cChannel);
token=tTokenizer.getString();
Vector vcolumns=null;
if(token.equals("(")) {
vcolumns=new Vector();
int i=0;
while(true) {
vcolumns.addElement(tTokenizer.getString());
i++;
token=tTokenizer.getString();
if(token.equals(")")) {
break;
}
if(!token.equals(",")) {
throw Trace.error(Trace.UNEXPECTED_TOKEN,token);
}
}
token=tTokenizer.getString();
}
int count=0;
int len;
if(vcolumns==null) {
len=t.getColumnCount();
} else {
len=vcolumns.size();
}
if(token.equals("VALUES")) {
tTokenizer.getThis("(");
Object row[]=t.getNewRow();
int i=0;
while(true) {
int column;
if(vcolumns==null) {
column=i;
if(i>len) {
throw Trace.error(Trace.COLUMN_COUNT_DOES_NOT_MATCH);
}
} else {
column=t.getColumnNr((String)vcolumns.elementAt(i));
}
row[column]=getValue(t.getType(column));
i++;
token=tTokenizer.getString();
if(token.equals(")")) {
break;
}
if(!token.equals(",")) {
throw Trace.error(Trace.UNEXPECTED_TOKEN,token);
}
}
t.insert(row,cChannel);
count=1;
} else if(token.equals("SELECT")) {
Result result=processSelect();
Record r=result.rRoot;
Trace.check(len==result.getColumnCount(),
Trace.COLUMN_COUNT_DOES_NOT_MATCH);
int col[]=new int[len];
int type[]=new int[len];
for(int i=0;i<len;i++) {
int j;
if(vcolumns==null) {
j=i;
} else {
j=t.getColumnNr((String)vcolumns.elementAt(i));
}
col[i]=j;
type[i]=t.getType(j);
}
cChannel.beginNestedTransaction();
try {
while(r!=null) {
Object row[]=t.getNewRow();
for(int i=0;i<len;i++) {
row[col[i]]=Column.convertObject(r.data[i],type[i]);
}
t.insert(row,cChannel);
count++;
r=r.next;
}
cChannel.endNestedTransaction(false);
} catch(SQLException e) {
// insert failed (violation of primary key)
cChannel.endNestedTransaction(true);
throw e;
}
} else {
throw Trace.error(Trace.UNEXPECTED_TOKEN,token);
}
Result r=new Result();
r.iUpdateCount=count;
return r;
}
private Select parseSelect() throws SQLException {
Select select=new Select();
String token=tTokenizer.getString();
if(token.equals("DISTINCT")) {
select.bDistinct=true;
} else {
tTokenizer.back();
}
// parse column list
Vector vcolumn=new Vector();
do {
Expression e=parseExpression();
token=tTokenizer.getString();
if(token.equals("AS")) {
e.setAlias(tTokenizer.getName());
token=tTokenizer.getString();
} else if(tTokenizer.wasName()) {
e.setAlias(token);
token=tTokenizer.getString();
}
vcolumn.addElement(e);
} while(token.equals(","));
if(token.equals("INTO")) {
select.sIntoTable=tTokenizer.getString();
token=tTokenizer.getString();
}
if(!token.equals("FROM")) {
throw Trace.error(Trace.UNEXPECTED_TOKEN,token);
}
Expression condition=null;
// parse table list
Vector vfilter=new Vector();
vfilter.addElement(parseTableFilter(false));
while(true) {
token=tTokenizer.getString();
if(token.equals("LEFT")) {
token=tTokenizer.getString();
if(token.equals("OUTER")) {
token=tTokenizer.getString();
}
Trace.check(token.equals("JOIN"),Trace.UNEXPECTED_TOKEN,token);
vfilter.addElement(parseTableFilter(true));
tTokenizer.getThis("ON");
condition=addCondition(condition,parseExpression());
} else if(token.equals("INNER")) {
tTokenizer.getThis("JOIN");
vfilter.addElement(parseTableFilter(false));
tTokenizer.getThis("ON");
condition=addCondition(condition,parseExpression());
} else if(token.equals(",")) {
vfilter.addElement(parseTableFilter(false));
} else {
break;
}
}
tTokenizer.back();
int len=vfilter.size();
TableFilter filter[]=new TableFilter[len];
for(int i=0;i<len;i++) {
filter[i]=(TableFilter)vfilter.elementAt(i);
}
select.tFilter=filter;
// expand [table.]* columns
len=vcolumn.size();
for(int i=0;i<len;i++) {
Expression e=(Expression)(vcolumn.elementAt(i));
if(e.getType()==Expression.ASTERIX) {
int current=i;
Table table=null;
String n=e.getTableName();
for(int t=0;t<filter.length;t++) {
TableFilter f=filter[t];
e.resolve(f);
if(n!=null && !n.equals(f.getName())) {
continue;
}
table=f.getTable();
int col=table.getColumnCount();
for(int c=0;c<col;c++) {
Expression ins=new Expression(f.getName(),table.getColumnName(c));
vcolumn.insertElementAt(ins,current++);
// now there is one element more to parse
len++;
}
}
Trace.check(table!=null,Trace.TABLE_NOT_FOUND,n);
// minus the asterix element
len--;
vcolumn.removeElementAt(current);
}
}
select.iResultLen=len;
// where
token=tTokenizer.getString();
if(token.equals("WHERE")) {
condition=addCondition(condition,parseExpression());
token=tTokenizer.getString();
}
select.eCondition=condition;
if(token.equals("GROUP")) {
tTokenizer.getThis("BY");
len=0;
do {
vcolumn.addElement(parseExpression());
token=tTokenizer.getString();
len++;
} while(token.equals(","));
select.iGroupLen=len;
}
if(token.equals("ORDER")) {
tTokenizer.getThis("BY");
len=0;
do {
Expression e=parseExpression();
if(e.getType()==Expression.VALUE) {
// order by 1,2,3
if(e.getDataType()==Column.INTEGER) {
int i=((Integer)e.getValue()).intValue();
e=(Expression)vcolumn.elementAt(i-1);
}
} else if(e.getType()==Expression.COLUMN && e.getTableName()==null) {
// this could be an alias column
String s=e.getColumnName();
for(int i=0;i<vcolumn.size();i++) {
Expression ec=(Expression)vcolumn.elementAt(i);
if(s.equals(ec.getAlias())) {
e=ec;
break;
}
}
}
token=tTokenizer.getString();
if(token.equals("DESC")) {
e.setDescending();
token=tTokenizer.getString();
} else if(token.equals("ASC")) {
token=tTokenizer.getString();
}
vcolumn.addElement(e);
len++;
} while(token.equals(","));
select.iOrderLen=len;
}
len=vcolumn.size();
select.eColumn=new Expression[len];
for(int i=0;i<len;i++) {
select.eColumn[i]=(Expression)vcolumn.elementAt(i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -