📄 database.java
字号:
/*
* Database.java
*/
package org.hsql;
import java.sql.*;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Database is the root class for Hypersonic SQL database.
* This class should not be used directly by the application,
* instead the jdbc* classes should be used.
*/
class Database {
private String sName;
private Access aAccess;
private Vector tTable;
private DatabaseInformation dInfo;
private Log lLog;
private boolean bReadOnly;
private boolean bShutdown;
private Hashtable hAlias;
private boolean bIgnoreCase;
private boolean bReferentialIntegrity;
Database(String name) throws SQLException {
if(Trace.TRACE) Trace.trace();
sName=name;
tTable=new Vector();
aAccess=new Access();
hAlias=new Hashtable();
bReferentialIntegrity=true;
Library.register(hAlias);
dInfo=new DatabaseInformation(this,tTable,aAccess);
boolean newdatabase=false;
Channel sys=new Channel(this,new User(null,null,true,null),true,false);
if(name.equals(".")) {
newdatabase=true;
} else {
lLog=new Log(this,sys,name);
newdatabase=lLog.open();
}
if(newdatabase) {
execute("CREATE USER SA PASSWORD \"\" ADMIN",sys);
}
aAccess.grant("PUBLIC","CLASS \"java.lang.Math\"",Access.ALL);
aAccess.grant("PUBLIC","CLASS \"org.hsql.Library\"",Access.ALL);
}
String getName() {
return sName;
}
boolean isShutdown() {
return bShutdown;
}
synchronized Channel connect(String username,String password)
throws SQLException {
User user=aAccess.getUser(username.toUpperCase(),password.toUpperCase());
return new Channel(this,user,true,bReadOnly);
}
byte[] execute(String user,String password,String statement) {
Result r=null;
try {
Channel channel=connect(user,password);
r=execute(statement,channel);
} catch(Exception e) {
r=new Result(e.getMessage());
}
try {
return r.getBytes();
} catch(Exception e) {
return new byte[0];
}
}
synchronized Result execute(String statement,Channel channel) {
if(Trace.TRACE) Trace.trace(statement);
Tokenizer c=new Tokenizer(statement);
Parser p=new Parser(this,c,channel);
Result rResult=new Result();
try {
if(lLog!=null && lLog.cCache!=null) {
lLog.cCache.cleanUp();
}
if(Trace.ASSERT) Trace.assert(!channel.isNestedTransaction());
Trace.check(channel!=null,Trace.ACCESS_IS_DENIED);
Trace.check(!bShutdown,Trace.DATABASE_IS_SHUTDOWN);
while(true) {
int begin=c.getPosition();
boolean script=false;
String sToken=c.getString();
if(sToken.equals("")) {
break;
} else if(sToken.equals("SELECT")) {
rResult=p.processSelect();
} else if(sToken.equals("INSERT")) {
rResult=p.processInsert();
} else if(sToken.equals("UPDATE")) {
rResult=p.processUpdate();
} else if(sToken.equals("DELETE")) {
rResult=p.processDelete();
} else if(sToken.equals("CREATE")) {
rResult=processCreate(c,channel);
script=true;
} else if(sToken.equals("DROP")) {
rResult=processDrop(c,channel);
script=true;
} else if(sToken.equals("GRANT")) {
rResult=processGrantOrRevoke(c,channel,true);
script=true;
} else if(sToken.equals("REVOKE")) {
rResult=processGrantOrRevoke(c,channel,false);
script=true;
} else if(sToken.equals("CONNECT")) {
rResult=processConnect(c,channel);
} else if(sToken.equals("SET")) {
rResult=processSet(c,channel);
script=true;
} else if(sToken.equals("SCRIPT")) {
rResult=processScript(c,channel);
} else if(sToken.equals("COMMIT")) {
rResult=processCommit(c,channel);
} else if(sToken.equals("ROLLBACK")) {
rResult=processRollback(c,channel);
} else if(sToken.equals("SHUTDOWN")) {
rResult=processShutdown(c,channel);
} else if(sToken.equals("CHECKPOINT")) {
rResult=processCheckpoint(channel);
} else if(sToken.equals("CALL")) {
rResult=p.processCall();
} else if(sToken.equals(";")) {
// ignore
} else {
throw Trace.error(Trace.UNEXPECTED_TOKEN,sToken);
}
if(script && lLog!=null) {
int end=c.getPosition();
lLog.write(c.getPart(begin,end));
}
}
} catch(SQLException e) {
// e.printStackTrace();
rResult=new Result(Trace.getMessage(e)+" in statement ["+statement+"]");
} catch(Exception e) {
e.printStackTrace();
String s=Trace.getMessage(Trace.GENERAL_ERROR)+" "+e;
rResult=new Result(s+" in statement ["+statement+"]");
}
return rResult;
}
void setReadOnly() {
bReadOnly=true;
}
Vector getTables() {
return tTable;
}
void setReferentialIntegrity(boolean ref) {
bReferentialIntegrity=ref;
}
boolean isReferentialIntegrity() {
return bReferentialIntegrity;
}
Hashtable getAlias() {
return hAlias;
}
String getAlias(String s) {
Object o=hAlias.get(s);
if(o==null) {
return s;
}
return (String)o;
}
Log getLog() {
return lLog;
}
Table getTable(String name,Channel channel) throws SQLException {
Table t=null;
for(int i=0;i<tTable.size();i++) {
t=(Table)tTable.elementAt(i);
if(t.getName().equals(name)) {
return t;
}
}
t=dInfo.getSystemTable(name,channel);
if(t==null) {
throw Trace.error(Trace.TABLE_NOT_FOUND,name);
}
return t;
}
Result getScript(boolean drop,boolean insert,boolean cached,Channel channel)
throws SQLException {
return dInfo.getScript(drop,insert,cached,channel);
}
void linkTable(Table t) throws SQLException {
String name=t.getName();
for(int i=0;i<tTable.size();i++) {
Table o=(Table)tTable.elementAt(i);
if(o.getName().equals(name)) {
throw Trace.error(Trace.TABLE_ALREADY_EXISTS,name);
}
}
tTable.addElement(t);
}
boolean isIgnoreCase() {
return bIgnoreCase;
}
private Result processScript(Tokenizer c,Channel channel)
throws SQLException {
String sToken=c.getString();
if(c.wasValue()) {
sToken=(String)c.getAsValue();
Log.scriptToFile(this,sToken,true,channel);
return new Result();
} else {
c.back();
// try to script all: drop, insert; but no positions for cached tables
return getScript(true,true,false,channel);
}
}
private Result processCreate(Tokenizer c,Channel channel)
throws SQLException {
channel.checkReadWrite();
channel.checkAdmin();
String sToken=c.getString();
if(sToken.equals("TABLE")) {
processCreateTable(c,channel,false);
} else if(sToken.equals("MEMORY")) {
c.getThis("TABLE");
processCreateTable(c,channel,false);
} else if(sToken.equals("CACHED")) {
c.getThis("TABLE");
processCreateTable(c,channel,true);
} else if(sToken.equals("USER")) {
String u=c.getStringToken();
c.getThis("PASSWORD");
String p=c.getStringToken();
boolean admin;
if(c.getString().equals("ADMIN")) {
admin=true;
} else {
admin=false;
}
aAccess.createUser(u,p,admin);
} else if(sToken.equals("ALIAS")) {
String name=c.getString();
sToken=c.getString();
Trace.check(sToken.equals("FOR"),Trace.UNEXPECTED_TOKEN,sToken);
sToken=c.getString();
hAlias.put(name,sToken);
} else {
boolean unique=false;
if(sToken.equals("UNIQUE")) {
unique=true;
sToken=c.getString();
}
if(!sToken.equals("INDEX")) {
throw Trace.error(Trace.UNEXPECTED_TOKEN,sToken);
}
String name=c.getName();
c.getThis("ON");
Table t=getTable(c.getString(),channel);
addIndexOn(c,channel,name,t,unique);
}
return new Result();
}
private int[] processColumnList(Tokenizer c,Table t) throws SQLException {
Vector v=new Vector();
c.getThis("(");
while(true) {
v.addElement(c.getString());
String sToken=c.getString();
if(sToken.equals(")")) {
break;
}
if(!sToken.equals(",")) {
throw Trace.error(Trace.UNEXPECTED_TOKEN,sToken);
}
}
int s=v.size();
int col[]=new int[s];
for(int i=0;i<s;i++) {
col[i]=t.getColumnNr((String)v.elementAt(i));
}
return col;
}
private void createIndex(Channel channel,Table t,int col[],
String name,boolean unique) throws SQLException {
channel.commit();
if(t.isEmpty()) {
t.createIndex(col,name,unique);
} else {
Table tn=t.moveDefinition(null);
tn.createIndex(col,name,unique);
tn.moveData(t);
dropTable(t.getName());
linkTable(tn);
}
}
private void addForeignKeyOn(Tokenizer c,Channel channel,String name,Table t)
throws SQLException {
int col[]=processColumnList(c,t);
c.getThis("REFERENCES");
Table t2=getTable(c.getString(),channel);
int col2[]=processColumnList(c,t2);
if(t.getIndexForColumns(col)==null) {
createIndex(channel,t,col,"SYSTEM_FOREIGN_KEY_"+name,false);
}
if(t2.getIndexForColumns(col2)==null) {
createIndex(channel,t2,col2,"SYSTEM_REFERENCE_"+name,false);
}
t.addConstraint(new Constraint(Constraint.FOREIGN_KEY,t2,t,col2,col));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -