⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 database.cs

📁 C#数据库中间层处理,支持主流数据库,如sql、oracle等
💻 CS
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -