📄 fromlist.java
字号:
/* Derby - Class org.apache.derby.impl.sql.compile.FromList 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.sql.compile.CompilerContext;import org.apache.derby.iapi.sql.compile.Optimizable;import org.apache.derby.iapi.sql.compile.OptimizableList;import org.apache.derby.iapi.sql.compile.Optimizer;import org.apache.derby.iapi.sql.compile.Visitable;import org.apache.derby.iapi.sql.compile.Visitor;import org.apache.derby.iapi.sql.compile.C_NodeTypes;import org.apache.derby.iapi.sql.dictionary.DataDictionary;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.util.JBitSet;import org.apache.derby.iapi.util.StringUtil;import java.util.Properties;import java.util.Enumeration;import java.util.Vector;/** * A FromList represents the list of tables in a FROM clause in a DML * statement. It extends QueryTreeNodeVector. * * @author Jeff Lichtman */public class FromList extends QueryTreeNodeVector implements OptimizableList{ Properties properties; // RESOLVE: The default should be false boolean fixedJoinOrder = true; // true by default. boolean useStatistics = true; // FromList could have a view in it's list. If the view is defined in SESSION // schema, then we do not want to cache the statement's plan. This boolean // will help keep track of such a condition. private boolean referencesSessionSchema; /** Initializer for a FromList */ public void init(Object optimizeJoinOrder) { fixedJoinOrder = ! (((Boolean) optimizeJoinOrder).booleanValue()); } /** * Initializer for a FromList * * @exception StandardException Thrown on error */ public void init(Object optimizeJoinOrder, Object fromTable) throws StandardException { init(optimizeJoinOrder); addFromTable((FromTable) fromTable); } /* * OptimizableList interface */ /** * @see org.apache.derby.iapi.sql.compile.OptimizableList#getOptimizable */ public Optimizable getOptimizable(int index) { return (Optimizable) elementAt(index); } /** * @see org.apache.derby.iapi.sql.compile.OptimizableList#setOptimizable */ public void setOptimizable(int index, Optimizable optimizable) { setElementAt((FromTable) optimizable, index); } /** * @see OptimizableList#verifyProperties * @exception StandardException Thrown on error */ public void verifyProperties(DataDictionary dDictionary) throws StandardException { int size = size(); for (int index = 0; index < size; index++) { ((Optimizable) elementAt(index)).verifyProperties(dDictionary); } } /** * Add a table to the FROM list. * * @param fromTable A FromTable to add to the list * * @return Nothing * * @exception StandardException Thrown on error */ public void addFromTable(FromTable fromTable) throws StandardException { /* Don't worry about checking TableOperatorNodes since * they don't have exposed names. This will potentially * allow duplicate exposed names in some degenerate cases, * but the binding of the ColumnReferences will catch those * cases with a different error. If the query does not have * any ColumnReferences from the duplicate exposed name, the * user is executing a really dumb query and we won't throw * and exception - consider it an ANSI extension. */ TableName leftTable = null; TableName rightTable = null; if (! (fromTable instanceof TableOperatorNode)) { /* Check for duplicate table name in FROM list */ int size = size(); for (int index = 0; index < size; index++) { leftTable = fromTable.getTableName(); if(((FromTable) elementAt(index)) instanceof TableOperatorNode) { continue; } else { rightTable = ((FromTable) elementAt(index)).getTableName(); } if(leftTable.equals(rightTable)) { throw StandardException.newException(SQLState.LANG_FROM_LIST_DUPLICATE_TABLE_NAME, fromTable.getExposedName()); } } } addElement(fromTable); } /** * Search to see if a query references the specifed table name. * * @param name Table name (String) to search for. * @param baseTable Whether or not name is for a base table * * @return true if found, else false * * @exception StandardException Thrown on error */ public boolean referencesTarget(String name, boolean baseTable) throws StandardException { FromTable fromTable; boolean found = false; /* Check for table or VTI name in FROM list */ int size = size(); for (int index = 0; index < size; index++) { fromTable = (FromTable) elementAt(index); if (fromTable.referencesTarget(name, baseTable)) { found = true; break; } } return found; } /** * Return true if the node references SESSION schema tables (temporary or permanent) * * @return true if references SESSION schema tables, else false * * @exception StandardException Thrown on error */ public boolean referencesSessionSchema() throws StandardException { FromTable fromTable; boolean found = false; // Following if will return true if this FromList object had any VIEWs // from SESSION schema as elements. This information is gathered during // the bindTables method. At the end of the bindTables, we loose // the information on VIEWs since they get replaced with their view // definition. Hence, we need to intercept in the middle on the bindTables // method and save that information in referencesSeesionSchema field. if (referencesSessionSchema) return true; /* Check for table or VTI name in FROM list */ int size = size(); for (int index = 0; index < size; index++) { fromTable = (FromTable) elementAt(index); if (fromTable.referencesSessionSchema()) { found = true; break; } } return found; } /** * Determine whether or not the specified name is an exposed name in * the current query block. * * @param name The specified name to search for as an exposed name. * @param schemaName Schema name, if non-null. * @param exactMatch Whether or not we need an exact match on specified schema and table * names or match on table id. * * @return The FromTable, if any, with the exposed name. * * @exception StandardException Thrown on error */ protected FromTable getFromTableByName(String name, String schemaName, boolean exactMatch) throws StandardException { boolean found = false; FromTable fromTable; FromTable result = null; int size = size(); for (int index = 0; index < size; index++) { fromTable = (FromTable) elementAt(index); result = fromTable.getFromTableByName(name, schemaName, exactMatch); if (result != null) { return result; } } return result; } /** * Bind the tables in this FromList. This includes looking them up in * the DataDictionary, getting their TableDescriptors and assigning the * table numbers. * * @param dataDictionary The DataDictionary to use for binding * @param fromListParam FromList to use/append to. * * @return Nothing. * * @exception StandardException Thrown on error */ public void bindTables(DataDictionary dataDictionary, FromList fromListParam) throws StandardException { FromTable fromTable; /* Now we bind the tables - this is a 2 step process. * We first bind all of the non-VTIs, then we bind the VTIs. * This enables us to handle the passing of correlation * columns in VTI parameters. * NOTE: We set the table numbers for all of the VTIs in the * first step, when we find them, in order to avoid an ordering * problem with join columns in parameters. */ int size = size(); for (int index = 0; index < size; index++) { fromTable = (FromTable) elementAt(index); ResultSetNode newNode = fromTable.bindNonVTITables(dataDictionary, fromListParam); // If the fromTable is a view in the SESSION schema, then we need to save that information // in referencesSessionSchema element. The reason for this is that the view will get // replaced by it's view definition and we will loose the information that the statement // was referencing a SESSION schema object. if (fromTable.referencesSessionSchema()) referencesSessionSchema = true; setElementAt(newNode, index); } for (int index = 0; index < size; index++) { fromTable = (FromTable) elementAt(index); ResultSetNode newNode = fromTable.bindVTITables(fromListParam); if (fromTable.referencesSessionSchema()) referencesSessionSchema = true; setElementAt(newNode, index); } } /** * Bind the expressions in this FromList. 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() throws StandardException { FromTable fromTable; int size = size(); for (int index = 0; index < size; index++) { fromTable = (FromTable) elementAt(index); fromTable.bindExpressions(this); } } /** * Bind the result columns of the ResultSetNodes in this FromList when there is no * base table to bind them to. This is useful for SELECT statements, * where the result columns get their types from the expressions that * live under them. * * @param fromListParam FromList to use/append to. * * @return Nothing * * @exception StandardException Thrown on error */ public void bindResultColumns(FromList fromListParam) throws StandardException { FromTable fromTable; int origList = fromListParam.size(); int size = size(); for (int index = 0; index < size; index++) { fromTable = (FromTable) elementAt(index); if (fromTable.needsSpecialRCLBinding()) fromTable.bindResultColumns(fromListParam); fromListParam.insertElementAt(fromTable, 0); } /* Remove all references added here */ while (fromListParam.size() > origList) fromListParam.removeElementAt(0); } /** * Returns true if any Outer joins present. Used to set Nullability * * @return True if has any outer joins. False otherwise. */ public boolean hasOuterJoins() throws StandardException { FromTable fromTable; int size = size(); for (int index = 0; index < size; index++) { fromTable = (FromTable) elementAt(index);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -