📄 tableoperatornode.java
字号:
/* Derby - Class org.apache.derby.impl.sql.compile.TableOperatorNode 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.context.ContextManager;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;import org.apache.derby.iapi.sql.compile.CompilerContext;import org.apache.derby.iapi.sql.compile.Optimizable;import org.apache.derby.iapi.sql.compile.Visitable;import org.apache.derby.iapi.sql.compile.Visitor;import org.apache.derby.iapi.sql.compile.Optimizer;import org.apache.derby.iapi.sql.compile.OptimizableList;import org.apache.derby.iapi.sql.compile.CostEstimate;import org.apache.derby.iapi.sql.compile.OptimizerFactory;import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;import org.apache.derby.iapi.sql.compile.C_NodeTypes;import org.apache.derby.iapi.sql.dictionary.DataDictionary;import org.apache.derby.iapi.sql.dictionary.TableDescriptor;import org.apache.derby.iapi.util.JBitSet;import java.util.Properties;/** * A TableOperatorNode represents a relational operator like UNION, INTERSECT, * JOIN, etc. that takes two tables as parameters and returns a table. The * parameters it takes are represented as ResultSetNodes. * * Currently, all known table operators are binary operators, so there are no * subclasses of this node type called "BinaryTableOperatorNode" and * "UnaryTableOperatorNode". * * @author Jeff Lichtman */public abstract class TableOperatorNode extends FromTable{ boolean nestedInParens; ResultSetNode leftResultSet; ResultSetNode rightResultSet; Optimizer leftOptimizer; Optimizer rightOptimizer; private boolean leftModifyAccessPathsDone; private boolean rightModifyAccessPathsDone; /** * Initializer for a TableOperatorNode. * * @param leftResultSet The ResultSetNode on the left side of this node * @param rightResultSet The ResultSetNode on the right side of this node * @param tableProperties Properties list associated with the table * * @exception StandardException Thrown on error */ public void init(Object leftResultSet, Object rightResultSet, Object tableProperties) throws StandardException { /* correlationName is always null */ init(null, tableProperties); this.leftResultSet = (ResultSetNode) leftResultSet; this.rightResultSet = (ResultSetNode) rightResultSet; } /** * @see Optimizable#modifyAccessPath * * @exception StandardException Thrown on error */ public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException { boolean callModifyAccessPaths = false; if (leftResultSet instanceof FromTable) { if (leftOptimizer != null) leftOptimizer.modifyAccessPaths(); else { leftResultSet = (ResultSetNode) ((FromTable) leftResultSet).modifyAccessPath(outerTables); } leftModifyAccessPathsDone = true; } else { callModifyAccessPaths = true; } if (rightResultSet instanceof FromTable) { if (rightOptimizer != null) rightOptimizer.modifyAccessPaths(); else { rightResultSet = (ResultSetNode) ((FromTable) rightResultSet).modifyAccessPath(outerTables); } rightModifyAccessPathsDone = true; } else { callModifyAccessPaths = true; } if (callModifyAccessPaths) { return (Optimizable) modifyAccessPaths(); } return this; } /** @see Optimizable#verifyProperties * @exception StandardException Thrown on error */ public void verifyProperties(DataDictionary dDictionary) throws StandardException { if (leftResultSet instanceof Optimizable) { ((Optimizable) leftResultSet).verifyProperties(dDictionary); } if (rightResultSet instanceof Optimizable) { ((Optimizable) rightResultSet).verifyProperties(dDictionary); } super.verifyProperties(dDictionary); } /** * @see Optimizable#addOrLoadBestPlanMapping * * Makes a call to add/load the plan mapping for this node, * and then makes the necessary call to recurse on this node's * left and right child, in order to ensure that we have a * full plan mapped. */ public void addOrLoadBestPlanMapping(boolean doAdd, Object planKey) throws StandardException { super.addOrLoadBestPlanMapping(doAdd, planKey); // Now walk the children. Note that if either child is not // an Optimizable and the call to child.getOptimizerImpl() // returns null, then that means we haven't tried to optimize // the child yet. So in that case there's nothing to // add/load. if (leftResultSet instanceof Optimizable) { ((Optimizable)leftResultSet). addOrLoadBestPlanMapping(doAdd, planKey); } else if (leftResultSet.getOptimizerImpl() != null) { leftResultSet.getOptimizerImpl(). addOrLoadBestPlanMappings(doAdd, planKey); } if (rightResultSet instanceof Optimizable) { ((Optimizable)rightResultSet). addOrLoadBestPlanMapping(doAdd, planKey); } else if (rightResultSet.getOptimizerImpl() != null) { rightResultSet.getOptimizerImpl(). addOrLoadBestPlanMappings(doAdd, planKey); } } /** * 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 "nestedInParens: " + nestedInParens + "\n" + leftResultSet.toString() + "\n" + rightResultSet.toString() + "\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 (leftResultSet != null) { printLabel(depth, "leftResultSet: "); leftResultSet.printSubNodes(depth + 1); } if (rightResultSet != null) { printLabel(depth, "rightResultSet: "); rightResultSet.printSubNodes(depth + 1); } } } /** * Get the leftResultSet from this node. * * @return ResultSetNode The leftResultSet from this node. */ public ResultSetNode getLeftResultSet() { return leftResultSet; } /** * Get the rightResultSet from this node. * * @return ResultSetNode The rightResultSet from this node. */ public ResultSetNode getRightResultSet() { return rightResultSet; } public ResultSetNode getLeftmostResultSet() { if (leftResultSet instanceof TableOperatorNode) { return ((TableOperatorNode) leftResultSet).getLeftmostResultSet(); } else { return leftResultSet; } } public void setLeftmostResultSet(ResultSetNode newLeftResultSet) { if (leftResultSet instanceof TableOperatorNode) { ((TableOperatorNode) leftResultSet).setLeftmostResultSet(newLeftResultSet); } else { this.leftResultSet = newLeftResultSet; } } /** * Set the (query block) level (0-based) for this FromTable. * * @param level The query block level for this FromTable. * * @return Nothing */ public void setLevel(int level) { super.setLevel(level); if (leftResultSet instanceof FromTable) { ((FromTable) leftResultSet).setLevel(level); } if (rightResultSet instanceof FromTable) { ((FromTable) rightResultSet).setLevel(level); } } /** * Return the exposed name for this table, which is the name that * can be used to refer to this table in the rest of the query. * * @return The exposed name for this table. */ public String getExposedName() { return null; } /** * Mark whether or not this node is nested in parens. (Useful to parser * since some trees get created left deep and others right deep.) * * @param nestedInParens Whether or not this node is nested in parens. * * @return Nothing. */ public void setNestedInParens(boolean nestedInParens) { this.nestedInParens = nestedInParens; } /** * Return whether or not the table operator for this node was * nested in parens in the query. (Useful to parser * since some trees get created left deep and others right deep.) * * @return boolean Whether or not this node was nested in parens. */ public boolean getNestedInParens() { return nestedInParens; } /** * Bind the non VTI tables in this TableOperatorNode. This means getting * their TableDescriptors from the DataDictionary. * We will build an unbound RCL for this node. This RCL must be * "bound by hand" after the underlying left and right RCLs * are bound. * * @param dataDictionary The DataDictionary to use for binding * @param fromListParam FromList to use/append to. * * @return ResultSetNode Returns this. * * @exception StandardException Thrown on error */ public ResultSetNode bindNonVTITables(DataDictionary dataDictionary, FromList fromListParam) throws StandardException { leftResultSet = leftResultSet.bindNonVTITables(dataDictionary, fromListParam); rightResultSet = rightResultSet.bindNonVTITables(dataDictionary, fromListParam); /* Assign the tableNumber */ if (tableNumber == -1) // allow re-bind, in which case use old number tableNumber = getCompilerContext().getNextTableNumber(); return this; } /** * Bind the VTI tables in this TableOperatorNode. This means getting * their TableDescriptors from the DataDictionary. * We will build an unbound RCL for this node. This RCL must be * "bound by hand" after the underlying left and right RCLs * are bound. * * @param fromListParam FromList to use/append to. * * @return ResultSetNode Returns this. * * @exception StandardException Thrown on error */ public ResultSetNode bindVTITables(FromList fromListParam) throws StandardException { leftResultSet = leftResultSet.bindVTITables(fromListParam); rightResultSet = rightResultSet.bindVTITables(fromListParam); return this; } /** * Bind the expressions under this TableOperatorNode. This means * binding the sub-expressions, as well as figuring out what the * return type is for each expression. * * @return Nothing * * @exception StandardException Thrown on error */ public void bindExpressions(FromList fromListParam) throws StandardException { /* ** Parameters not allowed in select list of either side of union, ** except when the union is for a table constructor. */ if ( ! (this instanceof UnionNode) || ! ((UnionNode) this).tableConstructor()) { leftResultSet.rejectParameters(); rightResultSet.rejectParameters(); } leftResultSet.bindExpressions(fromListParam); rightResultSet.bindExpressions(fromListParam); } /** * Check for (and reject) ? parameters directly under the ResultColumns. * This is done for SELECT statements. For TableOperatorNodes, we * simply pass the check through to the left and right children. * * @return Nothing * * @exception StandardException Thrown if a ? parameter found * directly under a ResultColumn */ public void rejectParameters() throws StandardException { leftResultSet.rejectParameters(); rightResultSet.rejectParameters(); } /** * Bind the expressions in this ResultSetNode if it has tables. This means binding the * sub-expressions, as well as figuring out what the return type is for * each expression. * * @param fromListParam FromList to use/append to. * * @return Nothing * * @exception StandardException Thrown on error */ public void bindExpressionsWithTables(FromList fromListParam) throws StandardException { /* ** Parameters not allowed in select list of either side of a set operator, ** except when the set operator is for a table constructor. */ if ( ! (this instanceof UnionNode) || ! ((UnionNode) this).tableConstructor()) { leftResultSet.rejectParameters(); rightResultSet.rejectParameters(); } leftResultSet.bindExpressionsWithTables(fromListParam); rightResultSet.bindExpressionsWithTables(fromListParam);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -