📄 dmlmodstatementnode.java
字号:
/* Derby - Class org.apache.derby.impl.sql.compile.DMLModStatementNode Copyright 1997, 2004 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.loader.GeneratedMethod;import org.apache.derby.iapi.services.context.ContextManager;import org.apache.derby.iapi.services.compiler.JavaFactory;import org.apache.derby.iapi.services.compiler.MethodBuilder;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.sql.depend.Dependent;import org.apache.derby.iapi.sql.compile.CompilerContext;import org.apache.derby.iapi.sql.compile.Parser;import org.apache.derby.iapi.sql.compile.CostEstimate;import org.apache.derby.iapi.sql.compile.OptimizerFactory;import org.apache.derby.iapi.sql.compile.C_NodeTypes;import org.apache.derby.iapi.sql.compile.NodeFactory;import org.apache.derby.iapi.reference.ClassName;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;import org.apache.derby.iapi.sql.dictionary.CheckConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;import org.apache.derby.iapi.sql.dictionary.ForeignKeyConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.GenericDescriptorList;import org.apache.derby.iapi.sql.dictionary.ReferencedKeyConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;import org.apache.derby.iapi.sql.dictionary.DataDictionary;import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;import org.apache.derby.iapi.sql.dictionary.TableDescriptor;import org.apache.derby.iapi.sql.dictionary.TriggerDescriptor;import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;import org.apache.derby.iapi.sql.StatementType;import org.apache.derby.iapi.store.access.TransactionController;import org.apache.derby.impl.sql.compile.ActivationClassBuilder;import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.impl.sql.execute.FKInfo; import org.apache.derby.impl.sql.execute.TriggerInfo;import org.apache.derby.iapi.types.RowLocation;import org.apache.derby.catalog.UUID;import java.util.Properties;import java.util.Vector;import java.util.Enumeration;import java.util.Hashtable;import org.apache.derby.iapi.services.io.FormatableBitSet;import org.apache.derby.iapi.services.classfile.VMOpcode;/** * A DMLStatement for a table modification: to wit, INSERT * UPDATE or DELETE. * * @author Jamie */public abstract class DMLModStatementNode extends DMLStatementNode{// protected DataDictionary dataDictionary; protected FromVTI targetVTI; protected TableName targetTableName; protected ResultColumnList resultColumnList; protected int lockMode; // lock mode for the target table protected FKInfo[] fkInfo; // array of FKInfo structures // generated during bind protected TriggerInfo triggerInfo; // generated during bind public TableDescriptor targetTableDescriptor; /* The indexes that could be affected by this statement */ public IndexRowGenerator[] indicesToMaintain; public long[] indexConglomerateNumbers; public String[] indexNames; protected ConstraintDescriptorList relevantCdl; protected GenericDescriptorList relevantTriggers; // PRIVATE private boolean requiresDeferredProcessing; private int statementType; private boolean bound; private ValueNode checkConstraints; /* Info required to perform referential actions */ protected String[] fkTableNames; // referencing table names. protected int[] fkRefActions; //type of referential actions protected ColumnDescriptorList[] fkColDescriptors; protected long[] fkIndexConglomNumbers; //conglomerate number of the backing index protected boolean isDependentTable; protected int[][] fkColArrays; protected Hashtable graphHashTable; // Hash Table which maitains the querytreenode graph /** * Initializer for a DMLModStatementNode -- delegate to DMLStatementNode * * @param resultSet A ResultSetNode for the result set of the * DML statement */ public void init(Object resultSet) { super.init(resultSet); statementType = getStatementType(); } /** * Initializer for a DMLModStatementNode -- delegate to DMLStatementNode * * @param resultSet A ResultSetNode for the result set of the * DML statement * @param statementType used by nodes that allocate a DMLMod directly * (rather than inheriting it). */ public void init(Object resultSet, Object statementType) { super.init(resultSet); this.statementType = ((Integer) statementType).intValue(); } void setTarget(QueryTreeNode targetName) { if (targetName instanceof TableName) { this.targetTableName = (TableName) targetName; } else { if (SanityManager.DEBUG) { if (! (targetName instanceof FromVTI)) { SanityManager.THROWASSERT( "targetName expected to be FromVTI, not " + targetName.getClass().getName()); } } this.targetVTI = (FromVTI) targetName; targetVTI.setTarget(); } } /** * If the DML is on a temporary table, generate the code to mark temporary table as modified in the current UOW. * At rollback transaction (or savepoint), we will check if the temporary table was modified in that UOW. * If yes, we will remove all the data from the temporary table * * @param acb The ActivationClassBuilder for the class being built * @param mb The execute() method to be built * * @exception StandardException Thrown on error */ protected void generateCodeForTemporaryTable(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException { if (targetTableDescriptor != null && targetTableDescriptor.getTableType() == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE && targetTableDescriptor.isOnRollbackDeleteRows() == true) { mb.pushThis(); mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Activation, "getLanguageConnectionContext", ClassName.LanguageConnectionContext, 0); mb.push(targetTableDescriptor.getName()); mb.callMethod(VMOpcode.INVOKEINTERFACE, null, "markTempTableAsModifiedInUnitOfWork", "void", 1); mb.endStatement(); } } /** * Verify the target table. Get the TableDescriptor * if the target table is not a VTI. * * @exception StandardException Thrown on error */ void verifyTargetTable() throws StandardException { DataDictionary dataDictionary = getDataDictionary(); if (targetTableName != null) { /* ** Get the TableDescriptor for the table we are inserting into */ SchemaDescriptor sdtc = getSchemaDescriptor(targetTableName.getSchemaName()); targetTableDescriptor = getTableDescriptor( targetTableName.getTableName(), sdtc); if (targetTableDescriptor == null) { // Check if the reference is for a synonym. TableName synonymTab = resolveTableToSynonym(targetTableName); if (synonymTab == null) throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, targetTableName); targetTableName = synonymTab; sdtc = getSchemaDescriptor(targetTableName.getSchemaName()); targetTableDescriptor = getTableDescriptor(synonymTab.getTableName(), sdtc); if (targetTableDescriptor == null) throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, targetTableName); } // Views are currently not updatable */ if (targetTableDescriptor.getTableType() == TableDescriptor.VIEW_TYPE) { throw StandardException.newException(SQLState.LANG_VIEW_NOT_UPDATEABLE, targetTableName); } /* System tables are not updatable */ if (targetTableDescriptor.getTableType() == TableDescriptor.SYSTEM_TABLE_TYPE) { throw StandardException.newException(SQLState.LANG_UPDATE_SYSTEM_TABLE_ATTEMPTED, targetTableName); } /* We need to get some kind of table lock (IX here), to prevent * another thread from adding a new index while we are binding, * if we are a reader in DDL mode. Just a row lock on system table * SYSCONGLOMERATE is not enough: that wouldn't prevent another * thread from adding a new entry. Part of the fix for Beetle 3976. * Same lock as in exec, compatible with row lock, for concurrency. */ targetTableDescriptor = lockTableForCompilation(targetTableDescriptor); getCompilerContext().createDependency(targetTableDescriptor); } else { /* VTI - VTIs in DML Mod are version 2 VTIs - They * must implement java.sql.PreparedStatement and have * the JDBC2.0 getMetaData() and getResultSetConcurrency() * methods and return an updatable ResultSet. */ FromList dummyFromList = new FromList(); targetVTI = (FromVTI) targetVTI.bindNonVTITables(dataDictionary, dummyFromList); targetVTI = (FromVTI) targetVTI.bindVTITables(dummyFromList); } } /** * * INSERT/UPDATE/DELETE are always atomic. * * @return true */ public boolean isAtomic() { return true; } /** * Get a schema descriptor for the given table. * Uses this.targetTableName. * * @return Schema Descriptor * * @exception StandardException throws on schema name * that doesn't exist */ public SchemaDescriptor getSchemaDescriptor() throws StandardException { SchemaDescriptor sd; sd = getSchemaDescriptor(targetTableName.getSchemaName()); return sd; } /** Get a map to efficiently find heap columns from a compressed set of read columns. The returns a map such that <PRE> map[heapColId (0 based)] -> readCol id (0 based) </PRE> @param column_map_length The number of columns(ints) in the map. @param readColsBitSet A language style (1 based) bit set with bits for read heap columns set. RESOLVE: Replace this with a call to RowUtil when the store and the language both use 0 base or 1 base offsets for columns. Today we can't use the store function because we have a 1 based FormatableBitSet. */ public static int[] getReadColMap(int column_map_length,FormatableBitSet readColsBitSet) { if (readColsBitSet == null) return null; int partial_col_cnt = 0; int column_map[] = new int[column_map_length]; int readColsBitSetSize = readColsBitSet.size(); for (int base_index = 0; base_index < column_map.length; base_index++) { if (readColsBitSetSize > base_index && readColsBitSet.get(base_index+1)) column_map[base_index] = partial_col_cnt++; else // this column map offset entry should never be referenced. column_map[base_index] = -1; } return(column_map); } /** * Get and bind the ResultColumnList representing the columns in the * target table, given the table's name. * * @exception StandardException Thrown on error */ protected void getResultColumnList() throws StandardException { if (targetVTI == null) { getResultColumnList((ResultColumnList) null); } else { /* binding VTI - just point to VTI's RCL, * which was already bound. */ resultColumnList = targetVTI.getResultColumns(); } } /** * Get and bind the ResultColumnList representing the columns in the * target table, given the table's name. * * @exception StandardException Thrown on error */ protected FromBaseTable getResultColumnList(ResultColumnList inputRcl) throws StandardException { /* Get a ResultColumnList representing all the columns in the target */ FromBaseTable fbt = (FromBaseTable) (getNodeFactory().getNode( C_NodeTypes.FROM_BASE_TABLE, targetTableName, null, null, null, getContextManager()) ); fbt.bindNonVTITables( getDataDictionary(), (FromList) getNodeFactory().getNode( C_NodeTypes.FROM_LIST, getNodeFactory().doJoinOrderOptimization(), getContextManager())); getResultColumnList( fbt, inputRcl ); return fbt; } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -