📄 altertableconstantaction.java
字号:
/* Derby - Class org.apache.derby.impl.sql.execute.AlterTableConstantAction Copyright 1998, 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.execute;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.io.StreamStorable;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;import org.apache.derby.iapi.sql.dictionary.ReferencedKeyConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;import org.apache.derby.iapi.sql.dictionary.DataDictionary;import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;import org.apache.derby.iapi.sql.dictionary.DefaultDescriptor;import org.apache.derby.iapi.sql.dictionary.IndexLister;import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;import org.apache.derby.iapi.sql.dictionary.TableDescriptor;import org.apache.derby.iapi.sql.dictionary.StatisticsDescriptor;import org.apache.derby.iapi.sql.dictionary.DependencyDescriptor;import org.apache.derby.iapi.sql.dictionary.CheckConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.GenericDescriptorList;import org.apache.derby.iapi.sql.dictionary.TriggerDescriptor;import org.apache.derby.impl.sql.catalog.DDColumnDependableFinder;import org.apache.derby.iapi.sql.StatementType;import org.apache.derby.iapi.types.DataValueDescriptor;import org.apache.derby.iapi.types.DataTypeDescriptor;import org.apache.derby.iapi.types.DataValueFactory;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.sql.depend.Dependency;import org.apache.derby.iapi.sql.depend.DependencyManager;import org.apache.derby.iapi.sql.depend.Provider;import org.apache.derby.iapi.sql.depend.ProviderInfo;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.sql.execute.ConstantAction;import org.apache.derby.iapi.sql.execute.ExecIndexRow;import org.apache.derby.iapi.sql.execute.ExecRow;import org.apache.derby.iapi.sql.execute.ExecutionFactory;import org.apache.derby.iapi.store.access.ColumnOrdering;import org.apache.derby.iapi.store.access.ConglomerateController;import org.apache.derby.iapi.store.access.GroupFetchScanController;import org.apache.derby.iapi.store.access.Qualifier;import org.apache.derby.iapi.store.access.RowLocationRetRowSource;import org.apache.derby.iapi.store.access.RowSource;import org.apache.derby.iapi.store.access.RowUtil;import org.apache.derby.iapi.store.access.ScanController;import org.apache.derby.iapi.store.access.SortController;import org.apache.derby.iapi.store.access.SortObserver;import org.apache.derby.iapi.store.access.TransactionController;import org.apache.derby.iapi.types.NumberDataValue;import org.apache.derby.iapi.sql.Activation;import org.apache.derby.iapi.sql.ResultSet;import org.apache.derby.iapi.sql.Statement;import org.apache.derby.iapi.sql.PreparedStatement;import org.apache.derby.iapi.types.RowLocation;import org.apache.derby.catalog.UUID;import org.apache.derby.catalog.IndexDescriptor;import org.apache.derby.catalog.DependableFinder;import org.apache.derby.catalog.types.DefaultInfoImpl;import org.apache.derby.catalog.types.StatisticsImpl;import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;import java.sql.SQLException;import java.util.Properties;import java.util.Enumeration;import org.apache.derby.iapi.services.io.FormatableBitSet;import java.util.List;import java.util.Iterator;/** * This class describes actions that are ALWAYS performed for an * ALTER TABLE Statement at Execution time. * * @author Jerry Brenner. */class AlterTableConstantAction extends DDLSingleTableConstantAction implements RowLocationRetRowSource{ protected SchemaDescriptor sd; protected String tableName; protected UUID schemaId; protected int tableType; protected long tableConglomerateId; protected ColumnInfo[] columnInfo; protected ConstraintConstantAction[] constraintActions; protected char lockGranularity; private boolean compressTable; private boolean sequential; private int behavior; // Alter table compress and Drop column private boolean doneScan; private boolean[] needToDropSort; private boolean[] validRow; private int bulkFetchSize = 16; private int currentCompressRow; private int numIndexes; private int rowCount; private long estimatedRowCount; private long[] indexConglomerateNumbers; private long[] sortIds; private FormatableBitSet indexedCols; private ConglomerateController compressHeapCC; private ExecIndexRow[] indexRows; private ExecRow[] baseRow; private ExecRow currentRow; private GroupFetchScanController compressHeapGSC; private IndexRowGenerator[] compressIRGs; private DataValueDescriptor[][] baseRowArray; private RowLocation[] compressRL; private SortController[] sorters; private int columnPosition; private ColumnOrdering[][] ordering; private TableDescriptor td; //truncate table private boolean truncateTable; // CONSTRUCTORS private LanguageConnectionContext lcc; private DataDictionary dd; private DependencyManager dm; private TransactionController tc; private Activation activation; /** * Make the AlterAction for an ALTER TABLE statement. * * @param sd descriptor for the schema that table lives in. * @param tableName Name of table. * @param tableId UUID of table * @param tableConglomerateId heap conglomerate number of table * @param tableType Type of table (e.g., BASE). * @param columnInfo Information on all the columns in the table. * @param constraintActions ConstraintConstantAction[] for constraints * @param lockGranularity The lock granularity. * @param compressTable Whether or not this is a compress table * @param behavior drop behavior for dropping column * @param sequential If compress table/drop column, whether or not sequential * @param truncateTable Whether or not this is a truncate table */ AlterTableConstantAction( SchemaDescriptor sd, String tableName, UUID tableId, long tableConglomerateId, int tableType, ColumnInfo[] columnInfo, ConstraintConstantAction[] constraintActions, char lockGranularity, boolean compressTable, int behavior, boolean sequential, boolean truncateTable) { super(tableId); this.sd = sd; this.tableName = tableName; this.tableConglomerateId = tableConglomerateId; this.tableType = tableType; this.columnInfo = columnInfo; this.constraintActions = constraintActions; this.lockGranularity = lockGranularity; this.compressTable = compressTable; this.behavior = behavior; this.sequential = sequential; this.truncateTable = truncateTable; if (SanityManager.DEBUG) { SanityManager.ASSERT(sd != null, "schema descriptor is null"); } } // OBJECT METHODS public String toString() { // Do not put this under SanityManager.DEBUG - it is needed for // error reporting. // we don't bother trying to print out the // schema because we don't have it until execution if(truncateTable) return "TRUNCATE TABLE " + tableName; else return "ALTER TABLE " + tableName; } // INTERFACE METHODS /** * This is the guts of the Execution-time logic for ALTER TABLE. * * @see ConstantAction#executeConstantAction * * @exception StandardException Thrown on failure */ public void executeConstantAction( Activation activation ) throws StandardException { LanguageConnectionContext lcc = activation.getLanguageConnectionContext(); DataDictionary dd = lcc.getDataDictionary(); DependencyManager dm = dd.getDependencyManager(); TransactionController tc = lcc.getTransactionExecute(); /* ** Inform the data dictionary that we are about to write to it. ** There are several calls to data dictionary "get" methods here ** that might be done in "read" mode in the data dictionary, but ** it seemed safer to do this whole operation in "write" mode. ** ** We tell the data dictionary we're done writing at the end of ** the transaction. */ dd.startWriting(lcc); // now do the real work // get an exclusive lock of the heap, to avoid deadlock on rows of // SYSCOLUMNS etc datadictionary tables (track 879) and phantom table // descriptor, in which case table shape could be changed by a // concurrent thread doing add/drop column (track 3804 and 3825) // older version (or at target) has to get td first, potential deadlock if (tableConglomerateId == 0) { td = dd.getTableDescriptor(tableId); if (td == null) { throw StandardException.newException( SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName); } tableConglomerateId = td.getHeapConglomerateId(); } lockTableForDDL(tc, tableConglomerateId, true); td = dd.getTableDescriptor(tableId); if (td == null) { throw StandardException.newException( SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName); } if(truncateTable) dm.invalidateFor(td, DependencyManager.TRUNCATE_TABLE, lcc); else dm.invalidateFor(td, DependencyManager.ALTER_TABLE, lcc); execGuts( activation ); } /** * Wrapper for this DDL action. Factored out so that our child, * RepAlterTableConstantAction * could enjoy the benefits of the startWriting() method above. * * @param dd the data dictionary * * @exception StandardException Thrown on failure */ public void execGuts( Activation activation) throws StandardException { ColumnDescriptor columnDescriptor; int numRows = 0; boolean tableNeedsScanning = false; boolean tableScanned = false; LanguageConnectionContext lcc = activation.getLanguageConnectionContext(); DataDictionary dd = lcc.getDataDictionary(); DependencyManager dm = dd.getDependencyManager(); TransactionController tc = lcc.getTransactionExecute(); // Save the TableDescriptor off in the Activation activation.setDDLTableDescriptor(td); /* ** If the schema descriptor is null, then ** we must have just read ourselves in. ** So we will get the corresponding schema ** descriptor from the data dictionary. */ if (sd == null) { sd = getAndCheckSchemaDescriptor(dd, schemaId, "ALTER TABLE"); } /* Prepare all dependents to invalidate. (This is there chance * to say that they can't be invalidated. For example, an open * cursor referencing a table/view that the user is attempting to * alter.) If no one objects, then invalidate any dependent objects. */ if(truncateTable) dm.invalidateFor(td, DependencyManager.TRUNCATE_TABLE, lcc); else dm.invalidateFor(td, DependencyManager.ALTER_TABLE, lcc); // Are we working on columns? if (columnInfo != null) { /* NOTE: We only allow a single column to be added within * each ALTER TABLE command at the language level. However, * this may change some day, so we will try to plan for it. */ /* for each new column, see if the user is adding a non-nullable * column. This is only allowed on an empty table. */ for (int ix = 0; ix < columnInfo.length; ix++) { /* Is this new column non-nullable? * If so, it can only be added to an * empty table if it does not have a default value. * We need to scan the table to find out how many rows * there are. */ if ((columnInfo[ix].action == ColumnInfo.CREATE) && !(columnInfo[ix].dataType.isNullable()) && (columnInfo[ix].defaultInfo == null) && (columnInfo[ix].autoincInc == 0) ) { tableNeedsScanning = true; } } // Scan the table if necessary if (tableNeedsScanning) { numRows = getSemiRowCount(tc); // Don't allow user to add non-nullable column to non-empty table if (numRows > 0) { throw StandardException.newException(SQLState.LANG_ADDING_NON_NULL_COLUMN_TO_NON_EMPTY_TABLE, td.getQualifiedName()); } tableScanned = true; } // for each related column, stuff system.column for (int ix = 0; ix < columnInfo.length; ix++) { ColumnDescriptorList cdl = new ColumnDescriptorList(); /* If there is a default value, use it, otherwise use null */ // Are we adding a new column or modifying a default? if (columnInfo[ix].action == ColumnInfo.CREATE) { addNewColumnToTable(activation, ix); } else if (columnInfo[ix].action == ColumnInfo.MODIFY_COLUMN_DEFAULT) { modifyColumnDefault(activation, ix); } else if (columnInfo[ix].action == ColumnInfo.MODIFY_COLUMN_TYPE) { modifyColumnType(activation, ix); } else if (columnInfo[ix].action == ColumnInfo.MODIFY_COLUMN_CONSTRAINT) { modifyColumnConstraint(activation, columnInfo[ix].name, true);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -