📄 fromvti.java
字号:
/* Derby - Class org.apache.derby.impl.sql.compile.FromVTI Copyright 1998, 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.ClassInspector;import org.apache.derby.iapi.services.loader.GeneratedMethod;import org.apache.derby.iapi.services.context.ContextManager;import org.apache.derby.iapi.services.compiler.MethodBuilder;import org.apache.derby.iapi.services.compiler.LocalField;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.OptimizablePredicateList;import org.apache.derby.iapi.sql.compile.Optimizer;import org.apache.derby.iapi.sql.compile.OptimizablePredicate;import org.apache.derby.iapi.sql.compile.Optimizable;import org.apache.derby.iapi.sql.compile.CostEstimate;import org.apache.derby.iapi.sql.compile.Visitable;import org.apache.derby.iapi.sql.compile.Visitor;import org.apache.derby.iapi.sql.compile.RowOrdering;import org.apache.derby.iapi.sql.compile.C_NodeTypes;import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;import org.apache.derby.iapi.sql.dictionary.DataDictionary;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.TableDescriptor;import org.apache.derby.iapi.reference.ClassName;import org.apache.derby.iapi.reference.JDBC20Translation;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.sql.Activation;import org.apache.derby.catalog.UUID;import org.apache.derby.vti.DeferModification;import org.apache.derby.vti.VTICosting;import org.apache.derby.vti.VTIEnvironment;import org.apache.derby.iapi.util.JBitSet;import org.apache.derby.iapi.services.io.FormatableBitSet;import org.apache.derby.iapi.services.classfile.VMOpcode;import org.apache.derby.iapi.services.info.JVMInfo;import org.apache.derby.impl.sql.compile.ActivationClassBuilder;import org.apache.derby.iapi.sql.execute.ExecutionContext;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.sql.Types;import java.util.Enumeration;import java.util.Properties; import java.util.Vector;import org.apache.derby.iapi.services.io.FormatableHashtable;import java.lang.reflect.Modifier;/** * A FromVTI represents a VTI in the FROM list of a DML statement. * * @author Jerry Brenner */public class FromVTI extends FromTable implements VTIEnvironment{ JBitSet correlationMap; JBitSet dependencyMap; NewInvocationNode newInvocation; TableName exposedName; SubqueryList subqueryList; boolean implementsVTICosting; boolean optimized; boolean materializable; boolean isTarget; ResultSet rs; private FormatableHashtable compileTimeConstants; // Number of columns returned by the VTI protected int numVTICols; private PredicateList restrictionList; /** Was a FOR UPDATE clause specified in a SELECT statement. */ private boolean forUpdatePresent; /** Was the FOR UPDATE clause empty (no columns specified). */ private boolean emptyForUpdate; /* ** We don't know how expensive a virtual table will be. ** Let's say it has 10000 rows with a cost of 100000. */ double estimatedCost = VTICosting.defaultEstimatedCost; double estimatedRowCount = VTICosting.defaultEstimatedRowCount; boolean supportsMultipleInstantiations = true; boolean vtiCosted; /* Version 1 or 2 VTI*/ protected boolean version2; private boolean implementsPushable; private PreparedStatement ps; private JavaValueNode[] methodParms; private boolean controlsDeferral; private boolean isInsensitive; private int resultSetType = ResultSet.TYPE_FORWARD_ONLY; /** * @param newInvocation The constructor for the VTI * @param correlationName The correlation name * @param derivedRCL The derived column list * @param tableProperties Properties list associated with the table * * @exception StandardException Thrown on error */ public void init( Object newInvocation, Object correlationName, Object derivedRCL, Object tableProperties) throws StandardException { init( newInvocation, correlationName, derivedRCL, tableProperties, makeTableName(null, (String) correlationName)); } /** * @param newInvocation The constructor for the VTI * @param correlationName The correlation name * @param derivedRCL The derived column list * @param tableProperties Properties list associated with the table * @param exposedTableName The table name (TableName class) * * @exception StandardException Thrown on error */ public void init( Object newInvocation, Object correlationName, Object derivedRCL, Object tableProperties, Object exposedTableName) throws StandardException { super.init(correlationName, tableProperties); this.newInvocation = (NewInvocationNode) newInvocation; resultColumns = (ResultColumnList) derivedRCL; subqueryList = (SubqueryList) getNodeFactory().getNode( C_NodeTypes.SUBQUERY_LIST, getContextManager()); /* Cache exposed name for this table. * The exposed name becomes the qualifier for each column * in the expanded list. */ this.exposedName = (TableName) exposedTableName; } // Optimizable interface /** * @see Optimizable#estimateCost * * @exception StandardException Thrown on error */ public CostEstimate estimateCost( OptimizablePredicateList predList, ConglomerateDescriptor cd, CostEstimate outerCost, Optimizer optimizer, RowOrdering rowOrdering) throws StandardException { costEstimate = getCostEstimate(optimizer); /* Cost the VTI if it implements VTICosting. * Otherwise we use the defaults. * NOTE: We only cost the VTI once. */ if (implementsVTICosting && ! vtiCosted) { try { VTICosting vtic = (version2) ? (VTICosting) ps : (VTICosting) rs; estimatedCost = vtic.getEstimatedCostPerInstantiation(this); estimatedRowCount = vtic.getEstimatedRowCount(this); supportsMultipleInstantiations = vtic.supportsMultipleInstantiations(this); if (ps != null) { ps.close(); ps = null; } if (rs != null) { rs.close(); rs = null; } } catch (SQLException sqle) { throw StandardException.unexpectedUserException(sqle); } vtiCosted = true; } costEstimate.setCost(estimatedCost, estimatedRowCount, estimatedRowCount); /* ** Let the join strategy decide whether the cost of the base ** scan is a single scan, or a scan per outer row. ** NOTE: The multiplication should only be done against the ** total row count, not the singleScanRowCount. ** RESOLVE - If the join strategy does not do materialization, ** the VTI does not support multiple instantiations and the ** outer row count is not exactly 1 row, then we need to change ** the costing formula to take into account the cost of creating ** the temp conglomerate, writing to it and reading from it ** outerCost.rowCount() - 1 times. */ if (getCurrentAccessPath(). getJoinStrategy(). multiplyBaseCostByOuterRows()) { costEstimate.multiply(outerCost.rowCount(), costEstimate); } if ( ! optimized) { subqueryList.optimize(optimizer.getDataDictionary(), costEstimate.rowCount()); subqueryList.modifyAccessPaths(); } optimized = true; return costEstimate; } /** * @see Optimizable#legalJoinOrder */ public boolean legalJoinOrder(JBitSet assignedTableMap) { /* In order to tell if this is a legal join order, we * need to see if the assignedTableMap, ORed with the * outer tables that we are correlated with, contains * our dependency map. */ JBitSet tempBitSet = (JBitSet) assignedTableMap; tempBitSet.or(correlationMap); /* Have all of our dependencies been satisified? */ return tempBitSet.contains(dependencyMap); } /** @see Optimizable#isMaterializable * */ public boolean isMaterializable() { return materializable; } /** @see Optimizable#supportsMultipleInstantiations */ public boolean supportsMultipleInstantiations() { return supportsMultipleInstantiations; } /** * @see Optimizable#modifyAccessPath * * @exception StandardException Thrown on error */ public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException { /* Close the rs if one was instantiated */ if (rs != null) { try { rs.close(); rs = null; } catch(Throwable t) { throw StandardException.unexpectedUserException(t); } } return super.modifyAccessPath(outerTables); } public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate) throws StandardException { if (!implementsPushable) return false; // Do not push down join predicates: those referencing more than one table. if( ! optimizablePredicate.getReferencedMap().hasSingleBitSet()) return false; if (restrictionList == null) { restrictionList = (PredicateList) getNodeFactory().getNode( C_NodeTypes.PREDICATE_LIST, getContextManager()); } restrictionList.addPredicate((Predicate) optimizablePredicate); return true; } /** * 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) { return "materializable: " + materializable + "\n" + super.toString(); } else { return ""; } } /** * Prints the sub-nodes of this object. See QueryTreeNode.java for * how tree printing is supposed to work. * * @param depth The depth of this node in the tree * * @return Nothing */ public void printSubNodes(int depth) { if (SanityManager.DEBUG) { super.printSubNodes(depth); if (newInvocation != null) { printLabel(depth, "newInvocation: "); newInvocation.treePrint(depth + 1); } if (exposedName != null) { printLabel(depth, "exposedName: "); exposedName.treePrint(depth + 1); } if (subqueryList != null) { printLabel(depth, "subqueryList: "); subqueryList.treePrint(depth + 1); } } } /** * Return the new invocation from this node. * * @return ResultSetNode The new invocation from this node. */ public NewInvocationNode getNewInvocation() { return newInvocation; } /** * Get the exposed name for this table, which is the name that can * be used to refer to it in the rest of the query. * * @return The exposed name for this table. */ public String getExposedName() { return correlationName; } /** * @return the table name used for matching with column references. * */ public TableName getExposedTableName() { return exposedName; } /** * Mark this VTI as the target of a delete or update. * * @return Nothing. */ void setTarget() { isTarget = true; version2 = true; } /** * Bind the non VTI tables in this ResultSetNode. This includes getting their * descriptors from the data dictionary and numbering them. * * @param dataDictionary The DataDictionary to use for binding * @param fromListParam FromList to use/append to. * * @return ResultSetNode * * @exception StandardException Thrown on error */ public ResultSetNode bindNonVTITables(DataDictionary dataDictionary, FromList fromListParam) throws StandardException { /* Assign the tableNumber. (All other work done in bindVTITables() */ if (tableNumber == -1) // allow re-bind, in which case use old number tableNumber = getCompilerContext().getNextTableNumber(); return this; } /** * @return The name of the VTI, mainly for debugging and error messages. */ String getVTIName() { return newInvocation.getJavaClassName(); } // end of getVTIName /** * Bind this VTI that appears in the FROM list. * * @param fromListParam FromList to use/append to. * * @return ResultSetNode The bound FromVTI. * * @exception StandardException Thrown on error */ public ResultSetNode bindVTITables(FromList fromListParam) throws StandardException { ResultColumnList derivedRCL = resultColumns; LanguageConnectionContext lcc = getLanguageConnectionContext(); /* NOTE - setting of table number moved to FromList.bindTables() * in order to avoid an ordering problem with join columns in * parameters. */ /* Bind the constructor - does basic error checking. * Correlated subqueries are not allowed as parameters to * a VTI, so pass an empty FromList. */ Vector aggregateVector = new Vector(); newInvocation.bindExpression(fromListParam, subqueryList, aggregateVector); /* We have a valid constructor. Does class implement the correct interface?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -