📄 tableelementlist.java
字号:
/* Derby - Class org.apache.derby.impl.sql.compile.TableElementList Copyright 1997, 2005 The Apache Software Foundation or its licensors, as applicable. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */package org.apache.derby.impl.sql.compile;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.sql.compile.CompilerContext;import org.apache.derby.iapi.sql.compile.C_NodeTypes;import org.apache.derby.iapi.types.DataTypeDescriptor;import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.DataDictionary;import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;import org.apache.derby.iapi.sql.dictionary.TableDescriptor;import org.apache.derby.iapi.sql.depend.DependencyManager;import org.apache.derby.iapi.sql.depend.ProviderInfo;import org.apache.derby.iapi.sql.depend.ProviderList;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.impl.sql.execute.ColumnInfo;import org.apache.derby.impl.sql.execute.ConstraintInfo;import org.apache.derby.impl.sql.execute.ConstraintConstantAction;import org.apache.derby.impl.sql.execute.IndexConstantAction;import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;import org.apache.derby.catalog.UUID;import java.util.Hashtable;import java.util.Vector;/** * A TableElementList represents the list of columns and other table elements * such as constraints in a CREATE TABLE or ALTER TABLE statement. * * @author Jeff Lichtman */public class TableElementList extends QueryTreeNodeVector{ private int numColumns; private TableDescriptor td; /** * Add a TableElementNode to this TableElementList * * @param tableElement The TableElementNode to add to this list */ public void addTableElement(TableElementNode tableElement) { addElement(tableElement); if ((tableElement instanceof ColumnDefinitionNode) || tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN) { numColumns++; } } /** * Convert this object to a String. See comments in QueryTreeNode.java * for how this should be done for tree printing. * * @return This object as a String */ public String toString() { if (SanityManager.DEBUG) { StringBuffer buffer = new StringBuffer(""); for (int index = 0; index < size(); index++) { buffer.append(elementAt(index).toString()).append("\n"); } return buffer.toString(); } else { return ""; } } /** * Validate this TableElementList. This includes checking for * duplicate columns names, and checking that user types really exist. * * @param ddlStmt DDLStatementNode which contains this list * @param dd DataDictionary to use * @param td TableDescriptor for table, if existing table. * * @exception StandardException Thrown on error */ void validate(DDLStatementNode ddlStmt, DataDictionary dd, TableDescriptor td) throws StandardException { this.td = td; int numAutoCols = 0; int size = size(); Hashtable columnHT = new Hashtable(size + 2, (float) .999); Hashtable constraintHT = new Hashtable(size + 2, (float) .999); //all the primary key/unique key constraints for this table Vector constraintsVector = new Vector(); //special case for alter table (td is not null in case of alter table) if (td != null) { //In case of alter table, get the already existing primary key and unique //key constraints for this table. And then we will compare them with new //primary key/unique key constraint column lists. ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td); ConstraintDescriptor cd; if (cdl != null) //table does have some pre-existing constraints defined on it { for (int i=0; i<cdl.size();i++) { cd = cdl.elementAt(i); //if the constraint type is not primary key or unique key, ignore it. if (cd.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT || cd.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT) constraintsVector.addElement(cd); } } } int tableType = TableDescriptor.BASE_TABLE_TYPE; if (ddlStmt instanceof CreateTableNode) tableType = ((CreateTableNode)ddlStmt).tableType; for (int index = 0; index < size; index++) { TableElementNode tableElement = (TableElementNode) elementAt(index); if (tableElement instanceof ColumnDefinitionNode) { ColumnDefinitionNode cdn = (ColumnDefinitionNode) elementAt(index); if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE && (cdn.getDataTypeServices().getTypeId().isLongConcatableTypeId() || cdn.getDataTypeServices().getTypeId().isUserDefinedTypeId())) { throw StandardException.newException(SQLState.LANG_LONG_DATA_TYPE_NOT_ALLOWED, cdn.getColumnName()); } checkForDuplicateColumns(ddlStmt, columnHT, cdn.getColumnName()); cdn.checkUserType(td); cdn.bindAndValidateDefault(dd, td); cdn.validateAutoincrement(dd, td, tableType); if (tableElement instanceof ModifyColumnNode) { ModifyColumnNode mcdn = (ModifyColumnNode)cdn; mcdn.checkExistingConstraints(td); } else if (cdn.isAutoincrementColumn()) numAutoCols ++; } else if (tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN) { String colName = tableElement.getName(); if (td.getColumnDescriptor(colName) == null) { throw StandardException.newException( SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, colName, td.getQualifiedName()); } break; } /* The rest of this method deals with validating constraints */ if (! (tableElement.hasConstraint())) { continue; } ConstraintDefinitionNode cdn = (ConstraintDefinitionNode) tableElement; cdn.bind(ddlStmt, dd); //if constraint is primary key or unique key, add it to the vector if (cdn.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT || cdn.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT) { /* In case of create table, the vector can have only ConstraintDefinitionNode * elements. In case of alter table, it can have both ConstraintDefinitionNode * (for new constraints) and ConstraintDescriptor(for pre-existing constraints). */ Object destConstraint; String destName = null; String[] destColumnNames = null; for (int i=0; i<constraintsVector.size();i++) { destConstraint = constraintsVector.elementAt(i); if (destConstraint instanceof ConstraintDefinitionNode) { ConstraintDefinitionNode destCDN = (ConstraintDefinitionNode)destConstraint; destName = destCDN.getConstraintMoniker(); destColumnNames = destCDN.getColumnList().getColumnNames(); } else if (destConstraint instanceof ConstraintDescriptor) { //will come here only for pre-existing constraints in case of alter table ConstraintDescriptor destCD = (ConstraintDescriptor)destConstraint; destName = destCD.getConstraintName(); destColumnNames = destCD.getColumnDescriptors().getColumnNames(); } //check if there are multiple constraints with same set of columns if (columnsMatch(cdn.getColumnList().getColumnNames(), destColumnNames)) throw StandardException.newException(SQLState.LANG_MULTIPLE_CONSTRAINTS_WITH_SAME_COLUMNS, cdn.getConstraintMoniker(), destName); } constraintsVector.addElement(cdn); } /* Make sure that there are no duplicate constraint names in the list */ if (cdn instanceof ConstraintDefinitionNode) checkForDuplicateConstraintNames(ddlStmt, constraintHT, cdn.getConstraintMoniker()); /* Make sure that the constraint we are trying to drop exists */ if (cdn.getConstraintType() == DataDictionary.DROP_CONSTRAINT) { /* ** If no schema descriptor, then must be an invalid ** schema name. */ String dropConstraintName = cdn.getConstraintMoniker(); if (dropConstraintName != null) { String dropSchemaName = cdn.getDropSchemaName(); SchemaDescriptor sd = dropSchemaName == null ? td.getSchemaDescriptor() : getSchemaDescriptor(dropSchemaName); ConstraintDescriptor cd = dd.getConstraintDescriptorByName( td, sd, dropConstraintName, false); if (cd == null) { throw StandardException.newException(SQLState.LANG_DROP_NON_EXISTENT_CONSTRAINT, (sd.getSchemaName() + "."+ dropConstraintName), td.getQualifiedName()); } /* Statement is dependendent on the ConstraintDescriptor */ getCompilerContext().createDependency(cd); } } if (cdn.hasPrimaryKeyConstraint()) { // for PRIMARY KEY, check that columns are unique verifyUniqueColumnList(ddlStmt, cdn); if (td == null) { // in CREATE TABLE so set PRIMARY KEY columns to NOT NULL setColumnListToNotNull(cdn); } else { // in ALTER TABLE so raise error if any columns are nullable checkForNullColumns(cdn, td); } } else if (cdn.hasUniqueKeyConstraint()) { // for UNIQUE, check that columns are unique and NOT NULL verifyUniqueColumnList(ddlStmt, cdn); checkForNullColumns(cdn, td); } else if (cdn.hasForeignKeyConstraint()) { // for FOREIGN KEY, check that columns are unique verifyUniqueColumnList(ddlStmt, cdn); } } /* Can have only one autoincrement column in DB2 mode */ if (numAutoCols > 1) throw StandardException.newException(SQLState.LANG_MULTIPLE_AUTOINCREMENT_COLUMNS); } /** * Count the number of constraints of the specified type. * * @param constraintType The constraint type to search for. * * @return int The number of constraints of the specified type. */ public int countConstraints(int constraintType) { int numConstraints = 0; int size = size(); for (int index = 0; index < size; index++) { ConstraintDefinitionNode cdn; TableElementNode element = (TableElementNode) elementAt(index); if (! (element instanceof ConstraintDefinitionNode)) { continue; } cdn = (ConstraintDefinitionNode) element; if (constraintType == cdn.getConstraintType()) { numConstraints++; } } return numConstraints; } /** * Count the number of columns. * * @return int The number of columns. */ public int countNumberOfColumns() { return numColumns; } /** * Fill in the ColumnInfo[] for this table element list. * * @param colInfos The ColumnInfo[] to be filled in. * * @return int The number of constraints in the create table. */ public int genColumnInfos(ColumnInfo[] colInfos) { int numConstraints = 0; int size = size(); for (int index = 0; index < size; index++) { if (((TableElementNode) elementAt(index)).getElementType() == TableElementNode.AT_DROP_COLUMN) { colInfos[index] = new ColumnInfo( ((TableElementNode) elementAt(index)).getName(), null, null, null, null, null, ColumnInfo.DROP, 0, 0); break; } if (! (elementAt(index) instanceof ColumnDefinitionNode)) { if (SanityManager.DEBUG) { SanityManager.ASSERT( elementAt(index) instanceof ConstraintDefinitionNode, "elementAt(index) expected to be instanceof " + "ConstraintDefinitionNode"); } /* Remember how many constraints that we've seen */ numConstraints++; continue; } ColumnDefinitionNode coldef = (ColumnDefinitionNode) elementAt(index); colInfos[index - numConstraints] = new ColumnInfo(coldef.getColumnName(), coldef.getDataTypeServices(), coldef.getDefaultValue(), coldef.getDefaultInfo(), (UUID) null, coldef.getOldDefaultUUID(), coldef.getAction(), (coldef.isAutoincrementColumn() ? coldef.getAutoincrementStart() : 0), (coldef.isAutoincrementColumn() ? coldef.getAutoincrementIncrement() : 0)); /* Remember how many constraints that we've seen */ if (coldef.hasConstraint()) { numConstraints++; } } return numConstraints; } /** * Append goobered up ResultColumns to the table's RCL. * This is useful for binding check constraints for CREATE and ALTER TABLE. * * @param table The table in question. * * @exception StandardException Thrown on error */ public void appendNewColumnsToRCL(FromBaseTable table) throws StandardException { int size = size(); ResultColumnList rcl = table.getResultColumns(); TableName exposedName = table.getTableName(); for (int index = 0; index < size; index++) { if (elementAt(index) instanceof ColumnDefinitionNode) { ColumnDefinitionNode cdn = (ColumnDefinitionNode) elementAt(index); ResultColumn resultColumn; ValueNode valueNode; /* Build a ResultColumn/BaseColumnNode pair for the column */ valueNode = (ValueNode) getNodeFactory().getNode( C_NodeTypes.BASE_COLUMN_NODE, cdn.getColumnName(), exposedName, cdn.getDataTypeServices(), getContextManager()); resultColumn = (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, cdn.getDataTypeServices(), valueNode, getContextManager()); resultColumn.setName(cdn.getColumnName()); rcl.addElement(resultColumn); } } } /** * Bind and validate all of the check constraints in this list against * the specified FromList. * * @param fromList The FromList in question. * * @exception StandardException Thrown on error */ void bindAndValidateCheckConstraints(FromList fromList) throws StandardException { CompilerContext cc; FromBaseTable table = (FromBaseTable) fromList.elementAt(0); int size = size(); cc = getCompilerContext(); Vector aggregateVector = new Vector(); for (int index = 0; index < size; index++) { ConstraintDefinitionNode cdn; TableElementNode element = (TableElementNode) elementAt(index); ValueNode checkTree; if (! (element instanceof ConstraintDefinitionNode)) { continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -