📄 database.cs
字号:
/*
* Database.cs
*
* Copyright (c) 2001, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This package is based on HypersonicSQL, originally developed by Thomas Mueller.
*
* C# port by Mark Tutt
*
*/
namespace SharpHSQL
{
using System;
using System.Collections;
/**
* Database class declaration
* <P>Database is the root class for HSQL Database Engine database.
* This class should not be used directly by the application,
* instead the jdbc* classes should be used.
*
* @version 1.0.0.1
*/
class Database
{
private string sName;
private Access aAccess;
private ArrayList tTable;
private DatabaseInformation dInfo;
private Log lLog;
private bool bReadOnly;
private bool bShutdown;
private Hashtable hAlias;
private bool bIgnoreCase;
private bool bReferentialIntegrity;
private ArrayList cChannel;
/**
* Constructor declaration
*
*
* @param name
*/
public Database(string name)
{
if (Trace.TRACE)
{
Trace.trace();
}
sName = name;
tTable = new ArrayList();
aAccess = new Access();
cChannel = new ArrayList();
hAlias = new Hashtable();
bReferentialIntegrity = true;
// Library.register(hAlias);
dInfo = new DatabaseInformation(this, tTable, aAccess);
bool newdatabase = false;
Channel sys = new Channel(this, new User(null, null, true, null),
true, false, 0);
registerChannel(sys);
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 \"org.hsqldb.Library\"", Access.ALL);
}
/**
* Method declaration
*
*
* @return
*/
public string getName()
{
return sName;
}
/**
* Method declaration
*
*
* @return
*/
public bool isShutdown()
{
return bShutdown;
}
/**
* Method declaration
*
*
* @param username
* @param password
*
* @return
*
* @throws Exception
*/
public Channel connect(string username,
string password)
{
User user = aAccess.getUser(username.ToUpper(),
password.ToUpper());
int size = cChannel.Count, id = size;
for (int i = 0; i < size; i++)
{
if (cChannel[i] == null)
{
id = i;
break;
}
}
Channel c = new Channel(this, user, true, bReadOnly, id);
if (lLog != null)
{
lLog.write(c,
"CONNECT USER " + username + " PASSWORD \"" + password
+ "\"");
}
registerChannel(c);
return c;
}
/**
* Method declaration
*
*
* @param channel
*/
public void registerChannel(Channel channel)
{
int size = cChannel.Count;
int id = channel.getId();
if (id >= size)
{
cChannel.Add(channel);
}
cChannel.RemoveAt(id);
cChannel.Insert(id,channel);
}
/**
* Method declaration
*
*
* @param user
* @param password
* @param statement
*
* @return
*/
public byte[] execute(string user, string password, string statement)
{
Result r = null;
try
{
Channel channel = connect(user, password);
r = execute(statement, channel);
execute("DISCONNECT", channel);
}
catch (Exception e)
{
r = new Result(e.Message);
}
try
{
return r.getBytes();
}
catch (Exception e)
{
return new byte[0];
}
}
/**
* Method declaration
*
*
* @param statement
* @param channel
*
* @return
*/
public 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();
bool 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("ALTER"))
{
rResult=p.processAlter();
}
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("DISCONNECT"))
{
rResult = processDisconnect(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);
script = true;
}
else if (sToken.Equals("ROLLBACK"))
{
rResult = processRollback(c, channel);
script = true;
}
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(channel, c.getPart(begin, end));
}
}
}
catch (Exception e)
{
rResult = new Result(Trace.getMessage(e) + " in statement ["
+ statement + "]");
}
return rResult;
}
/**
* Method declaration
*
*/
public void setReadOnly()
{
bReadOnly = true;
}
/**
* Method declaration
*
*
* @return
*/
public ArrayList getTables()
{
return tTable;
}
/**
* Method declaration
*
*
* @param ref
*/
public void setReferentialIntegrity(bool refint)
{
bReferentialIntegrity = refint;
}
/**
* Method declaration
*
*
* @return
*/
public bool isReferentialIntegrity()
{
return bReferentialIntegrity;
}
/**
* Method declaration
*
*
* @return
*/
public Hashtable getAlias()
{
return hAlias;
}
/**
* Method declaration
*
*
* @param s
*
* @return
*/
public string getAlias(string s)
{
object o = hAlias[s];
if (o == null)
{
return s;
}
return (string) o;
}
/**
* Method declaration
*
*
* @return
*/
public Log getLog()
{
return lLog;
}
/**
* Method declaration
*
*
* @param name
* @param channel
*
* @return
*
* @throws Exception
*/
public Table getTable(string name, Channel channel)
{
Table t = null;
for (int i = 0; i < tTable.Count; i++)
{
t = (Table) tTable[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;
}
/**
* Method declaration
*
*
* @param drop
* @param insert
* @param cached
* @param channel
*
* @return
*
* @throws Exception
*/
public Result getScript(bool drop, bool insert, bool cached,
Channel channel)
{
return dInfo.getScript(drop, insert, cached, channel);
}
/**
* Method declaration
*
*
* @param t
*
* @throws Exception
*/
public void linkTable(Table t)
{
string name = t.getName();
for (int i = 0; i < tTable.Count; i++)
{
Table o = (Table) tTable[i];
if (o.getName().Equals(name))
{
throw Trace.error(Trace.TABLE_ALREADY_EXISTS, name);
}
}
tTable.Add(t);
}
/**
* Method declaration
*
*
* @return
*/
public bool isIgnoreCase()
{
return bIgnoreCase;
}
/**
* Method declaration
*
*
* @param c
* @param channel
*
* @return
*
* @throws Exception
*/
private Result processScript(Tokenizer c,
Channel channel)
{
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);
}
}
/**
* Method declaration
*
*
* @param c
* @param channel
*
* @return
*
* @throws Exception
*/
private Result processCreate(Tokenizer c,
Channel channel)
{
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();
bool 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.Add(name, sToken);
}
else
{
bool 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();
}
/**
* Method declaration
*
*
* @param c
* @param t
*
* @return
*
* @throws Exception
*/
private int[] processColumnList(Tokenizer c,
Table t)
{
ArrayList v = new ArrayList();
c.getThis("(");
while (true)
{
v.Add(c.getstring());
string sToken = c.getstring();
if (sToken.Equals(")"))
{
break;
}
if (!sToken.Equals(","))
{
throw Trace.error(Trace.UNEXPECTED_TOKEN, sToken);
}
}
int s = v.Count;
int[] col = new int[s];
for (int i = 0; i < s; i++)
{
col[i] = t.getColumnNr((string) v[i]);
}
return col;
}
/**
* Method declaration
*
*
* @param channel
* @param t
* @param col
* @param name
* @param unique
*
* @throws Exception
*/
private void createIndex(Channel channel, Table t, int[] col,
string name,
bool unique)
{
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);
}
}
/**
* Method declaration
*
*
* @param c
* @param channel
* @param name
* @param t
*
* @throws Exception
*/
private void addForeignKeyOn(Tokenizer c, Channel channel, string name,
Table t)
{
int[] col = processColumnList(c, t);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -