📄 table.java
字号:
/* Copyrights and Licenses * * This product includes Hypersonic SQL. * Originally developed by Thomas Mueller and the Hypersonic SQL Group. * * Copyright (c) 1995-2000 by the Hypersonic SQL 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. * - All advertising materials mentioning features or use of this software must display the * following acknowledgment: "This product includes Hypersonic SQL." * - Products derived from this software may not be called "Hypersonic SQL" nor may * "Hypersonic SQL" appear in their names without prior written permission of the * Hypersonic SQL Group. * - Redistributions of any form whatsoever must retain the following acknowledgment: "This * product includes Hypersonic SQL." * This software is provided "as is" and any expressed 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 Hypersonic SQL Group or its 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 any 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 software consists of voluntary contributions made by many individuals on behalf of the * Hypersonic SQL Group. * * * For work added by the HSQL Development Group: * * Copyright (c) 2001-2002, 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, including earlier * license statements (above) and comply with all above license conditions. * * 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, including earlier * license statements (above) and comply with all above license conditions. * * 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 HSQL DEVELOPMENT GROUP, HSQLDB.ORG, * 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. */package org.hsqldb;import org.hsqldb.lib.ArrayUtil;import org.hsqldb.lib.StringUtil;import java.sql.SQLException;import java.sql.Types;import java.util.Vector;import java.util.Hashtable;// fredt@users 20020405 - patch 1.7.0 by fredt - quoted identifiers// for sql standard quoted identifiers for column and table names and aliases// applied to different places// fredt@users 20020225 - patch 1.7.0 - restructuring// some methods moved from Database.java, some rewritten// changes to several methods// fredt@users 20020225 - patch 1.7.0 - CASCADING DELETES// fredt@users 20020225 - patch 1.7.0 - named constraints// boucherb@users 20020225 - patch 1.7.0 - multi-column primary keys// fredt@users 20020221 - patch 513005 by sqlbob@users (RMP)// tony_lai@users 20020820 - patch 595099 by tlai@users - user defined PK name// tony_lai@users 20020820 - patch 595172 by tlai@users - drop constraint fix/** * Holds the data structures and methods for creation of a database table. * * * @version 1.7.0 */class Table { // types of table static final int SYSTEM_TABLE = 0; static final int TEMP_TABLE = 1; static final int MEMORY_TABLE = 2; static final int CACHED_TABLE = 3; static final int TEMP_TEXT_TABLE = 4; static final int TEXT_TABLE = 5; static final int VIEW = 6; // name of the column added to tables without primary key static final String DEFAULT_PK = ""; // main properties private Vector vColumn; // columns in table private Vector vIndex; // vIndex(0) is the primary key index private int[] iPrimaryKey; // column numbers for primary key private int iIndexCount; // size of vIndex private int iIdentityColumn; // -1 means no such row private int iIdentityId; // next value of identity column Vector vConstraint; // constrainst for the table Vector vTrigs[]; // array of trigger Vectors private int[] colTypes; // fredt - types of columns private boolean isSystem; private boolean isText; private boolean isView; // properties for subclasses protected int iColumnCount; // inclusive the hidden primary key protected int iVisibleColumns; // exclusive of hidden primary key protected Database dDatabase; protected Cache cCache; protected HsqlName tableName; // SQL name protected int tableType; protected Session ownerSession; // fredt - set for temp tables only protected boolean isReadOnly; protected boolean isTemp; protected boolean isCached; protected int indexType; // fredt - type of index used /** * Constructor declaration * * @param db * @param isTemp * @param name * @param cached * @param nameQuoted Description of the Parameter * @exception SQLException Description of the Exception */ Table(Database db, HsqlName name, int type, Session session) throws SQLException { dDatabase = db; if (type == SYSTEM_TABLE) { isTemp = true; } else if (type == TEMP_TABLE) { Trace.doAssert(session != null); isTemp = true; ownerSession = session; } else if (type == CACHED_TABLE) { cCache = db.logger.getCache(); if (cCache != null) { isCached = true; } else { type = MEMORY_TABLE; } } else if (type == TEMP_TEXT_TABLE) { Trace.doAssert(session != null); if (!db.logger.hasLog()) { throw Trace.error(Trace.DATABASE_IS_MEMORY_ONLY); } isTemp = true; isText = true; isReadOnly = true; isCached = true; ownerSession = session; } else if (type == TEXT_TABLE) { if (!db.logger.hasLog()) { throw Trace.error(Trace.DATABASE_IS_MEMORY_ONLY); } isText = true; isCached = true; } else if (type == VIEW) { isView = true; } if (isText) { indexType = Index.POINTER_INDEX; } else if (isCached) { indexType = Index.DISK_INDEX; } // type may have changed above for CACHED tables tableType = type; tableName = name; iPrimaryKey = null; iIdentityColumn = -1; vColumn = new Vector(); vIndex = new Vector(); vConstraint = new Vector(); vTrigs = new Vector[TriggerDef.numTrigs()]; for (int vi = 0; vi < TriggerDef.numTrigs(); vi++) { vTrigs[vi] = new Vector(); } } boolean equals(String other, Session c) { if (isTemp && c.getId() != ownerSession.getId()) { return false; } return (tableName.name.equals(other)); } boolean equals(String other) { return (tableName.name.equals(other)); } final boolean isText() { return isText; } final boolean isTemp() { return isTemp; } final boolean isView() { return isView; } final int getIndexType() { return indexType; } final boolean isDataReadOnly() { return isReadOnly; } void setDataReadOnly(boolean value) throws SQLException { isReadOnly = value; } Session getOwnerSession() { return ownerSession; } protected void setDataSource(String source, boolean isDesc, Session s) throws SQLException { // Same exception as setIndexRoots. throw (Trace.error(Trace.TABLE_NOT_FOUND)); } protected String getDataSource() throws SQLException { return null; } protected boolean isDescDataSource() throws SQLException { return (false); } /** * Method declaration * * @param c */ void addConstraint(Constraint c) { vConstraint.addElement(c); } /** * Method declaration * * @return */ Vector getConstraints() { return vConstraint; } /** * Get the index supporting a constraint that can be used as an index * of the given type and index column signature. * * @param col column list array * @param unique for the index * @return */ Index getConstraintIndexForColumns(int[] col, boolean unique) { Index currentIndex = getPrimaryIndex(); if (ArrayUtil.haveEquality(currentIndex.getColumns(), col, col.length, unique)) { return currentIndex; } for (int i = 0; i < vConstraint.size(); i++) { Constraint c = (Constraint) vConstraint.elementAt(i); currentIndex = c.getMainIndex(); if (ArrayUtil.haveEquality(currentIndex.getColumns(), col, col.length, unique)) { return currentIndex; } } return null; } /** * Method declaration * * @param from * @param type * @return */ int getNextConstraintIndex(int from, int type) { for (int i = from; i < vConstraint.size(); i++) { Constraint c = (Constraint) vConstraint.elementAt(i); if (c.getType() == type) { return i; } } return -1; } /** * Method declaration * * @param name * @param type * @throws SQLException */ void addColumn(String name, int type) throws SQLException { Column column = new Column(new HsqlName(name, false), true, type, 0, 0, false, false, null); addColumn(column); }// fredt@users 20020220 - patch 475199 - duplicate column /** * Performs the table level checks and adds a column to the table at the * DDL level. * * @param column new column to add * @throws SQLException when table level checks fail */ void addColumn(Column column) throws SQLException { if (searchColumn(column.columnName.name) >= 0) { throw Trace.error(Trace.COLUMN_ALREADY_EXISTS); } if (column.isIdentity()) { Trace.check(column.getType() == Types.INTEGER, Trace.WRONG_DATA_TYPE, column.columnName.name); Trace.check(iIdentityColumn == -1, Trace.SECOND_PRIMARY_KEY, column.columnName.name); iIdentityColumn = iColumnCount; } Trace.doAssert(iPrimaryKey == null, "Table.addColumn"); vColumn.addElement(column); iColumnCount++; } /** * Method declaration * * @param result * @throws SQLException */ void addColumns(Result result) throws SQLException { for (int i = 0; i < result.getColumnCount(); i++) { Column column = new Column( new HsqlName(result.sLabel[i], result.isLabelQuoted[i]), true, result.colType[i], result.colSize[i], result.colScale[i], false, false, null); addColumn(column); } } /** * Method declaration * * @return */ HsqlName getName() { return tableName; } /** * Changes table name. Used by 'alter table rename to' * * @param name * @param isquoted * @throws SQLException */ void setName(String name, boolean isquoted) { tableName.rename(name, isquoted); if (HsqlName.isReservedName(getPrimaryIndex().getName().name)) { getPrimaryIndex().getName().rename("SYS_PK", name, isquoted); } } /** * Method declaration * * @return */ int getInternalColumnCount() { // todo: this is a temporary solution; // the the hidden column is not really required return iColumnCount; } protected Table duplicate() throws SQLException { Table t = (new Table(dDatabase, tableName, tableType, ownerSession)); return t; } /** * Match two columns arrays for length and type of coluns * * @param col column array from this Table * @param other the other Table object * @param othercol column array from the other Table * @throws SQLException if there is a mismatch */ void checkColumnsMatch(int[] col, Table other, int[] othercol) throws SQLException { if (col.length != othercol.length) { throw Trace.error(Trace.COLUMN_COUNT_DOES_NOT_MATCH); } for (int i = 0; i < col.length; i++) { // integrity check - should not throw in normal operation if (col[i] >= iColumnCount || othercol[i] >= other.iColumnCount) { throw Trace.error(Trace.COLUMN_COUNT_DOES_NOT_MATCH); } if (getColumn(col[i]).getType() != other.getColumn(othercol[i]).getType()) { throw Trace.error(Trace.COLUMN_TYPE_MISMATCH); } } }// fredt@users 20020405 - patch 1.7.0 by fredt - DROP and CREATE INDEX bug /** * DROP INDEX and CREATE INDEX on non empty tables both recreate the table * and the data to reflect the new indexing structure. The new structure * should be reflected in the DDL script, otherwise if a * SHUTDOWN IMMEDIATE occures, the following will happen:<br> * If the table is cached, the index roots will be different from what * is specified in SET INDEX ROOTS. <br> * If the table is memory, the old index will be used until the script * reaches drop index etc. and data is recreated again.<b> * * The fix avoids scripting the row insert and delete ops. * * Constraints that need removing are removed outside this (fredt@users) * @param withoutindex * @param newcolumn * @param colindex * @param adjust -1 or 0 or +1 * @return * @throws SQLException */ Table moveDefinition(String withoutindex, Column newcolumn, int colindex, int adjust) throws SQLException { Table tn = duplicate(); for (int i = 0; i < iVisibleColumns + 1; i++) { if (i == colindex) { if (adjust > 0) { tn.addColumn(newcolumn); } else if (adjust < 0) { continue; } } if (i == iVisibleColumns) { break; } tn.addColumn(getColumn(i)); } // treat it the same as new table creation and // take account of the a hidden column int[] primarykey = (iPrimaryKey[0] == iVisibleColumns) ? null : iPrimaryKey; if (primarykey != null) { int[] newpk = ArrayUtil.toAdjustedColumnArray(primarykey, colindex, adjust); // fredt - we don't drop pk column // in future we can drop signle column pk wih no fk reference if (primarykey.length != newpk.length) { throw Trace.error(Trace.DROP_PRIMARY_KEY); } else { primarykey = newpk; } }// tony_lai@users - 20020820 - patch 595099 - primary key names tn.createPrimaryKey(getIndex(0).getName(), primarykey); tn.vConstraint = vConstraint; for (int i = 1; i < getIndexCount(); i++) { Index idx = getIndex(i); if (withoutindex != null && idx.getName().name.equals(withoutindex)) { continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -