📄 columnreference.java
字号:
/* Derby - Class org.apache.derby.impl.sql.compile.ColumnReference 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.sql.compile.C_NodeTypes;import org.apache.derby.iapi.sql.compile.NodeFactory;import org.apache.derby.iapi.sql.dictionary.DataDictionary;import org.apache.derby.iapi.types.DataTypeDescriptor;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;import org.apache.derby.iapi.services.compiler.MethodBuilder;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.store.access.Qualifier;import org.apache.derby.iapi.util.JBitSet;import java.util.Vector;/** * A ColumnReference represents a column in the query tree. The parser generates a * ColumnReference for each column reference. A column refercence could be a column in * a base table, a column in a view (which could expand into a complex * expression), or a column in a subquery in the FROM clause. * * @author Jerry Brenner */public class ColumnReference extends ValueNode{ public String columnName; /* ** This is the user-specified table name. It will be null if the ** user specifies a column without a table name. Leave it null even ** when the column is bound as it is only used in binding. */ public TableName tableName; /* The table this column reference is bound to */ public int tableNumber; /* The column number in the underlying base table */ public int columnNumber; /* This is where the value for this column reference will be coming from */ public ResultColumn source; /* For unRemapping */ ResultColumn origSource; public String origName; int origTableNumber = -1; int origColumnNumber = -1; /* Reuse generated code where possible */ //Expression genResult; private boolean replacesAggregate; private int nestingLevel = -1; private int sourceLevel = -1; /* ** These fields are used to track the being and end ** offset of the token from which the column name came. */ private int tokBeginOffset = -1; private int tokEndOffset = -1; /** * Initializer. * This one is called by the parser where we could * be dealing with delimited identifiers. * * @param columnName The name of the column being referenced * @param tableName The qualification for the column * @param tokBeginOffset begin position of token for the column name * identifier from parser. * @param tokEndOffset end position of token for the column name * identifier from parser. */ public void init(Object columnName, Object tableName, Object tokBeginOffset, Object tokEndOffset ) { this.columnName = (String) columnName; this.tableName = (TableName) tableName; this.tokBeginOffset = ((Integer) tokBeginOffset).intValue(); this.tokEndOffset = ((Integer) tokEndOffset).intValue(); tableNumber = -1; } /** * Initializer. * * @param columnName The name of the column being referenced * @param tableName The qualification for the column */ public void init(Object columnName, Object tableName) { this.columnName = (String) columnName; this.tableName = (TableName) tableName; tableNumber = -1; } /** * 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 "columnName: " + columnName + "\n" + "tableNumber: " + tableNumber + "\n" + "columnNumber: " + columnNumber + "\n" + "replacesAggregate: " + replacesAggregate + "\n" + ( ( tableName != null) ? tableName.toString() : "tableName: null\n") + "nestingLevel: " + nestingLevel + "\n" + "sourceLevel: " + sourceLevel + "\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 (source != null) { printLabel(depth, "source: "); source.treePrint(depth + 1); } } } /** * Get the begin offset of the parser token for the column name * Will only be set when the CR was generated by the * parser. * * @return the begin offset of the token. -1 means unknown */ public int getTokenBeginOffset() { /* We should never get called if not initialized, as * begin/end offset has no meaning unless this CR was * created in the parser. */ if (SanityManager.DEBUG) { if (tokBeginOffset == -1) { SanityManager.THROWASSERT( "tokBeginOffset not expected to be -1"); } } return tokBeginOffset; } /** * Get the end offset of the parser token for the column name. * Will only be set when the CR was generated by the * parser. * * @return the end offset of the token. -1 means unknown */ public int getTokenEndOffset() { /* We should never get called if not initialized, as * begin/end offset has no meaning unless this CR was * created in the parser. */ if (SanityManager.DEBUG) { if (tokEndOffset == -1) { SanityManager.THROWASSERT( "tokEndOffset not expected to be -1"); } } return tokEndOffset; } /** * Return whether or not this CR is correlated. * * @return Whether or not this CR is correlated. */ boolean getCorrelated() { if (SanityManager.DEBUG) { SanityManager.ASSERT(nestingLevel != -1, "nestingLevel on "+columnName+" is not expected to be -1"); SanityManager.ASSERT(sourceLevel != -1, "sourceLevel on "+columnName+" is not expected to be -1"); } return sourceLevel != nestingLevel; } /** * Set the nesting level for this CR. (The nesting level * at which the CR appears.) * * @param nestingLevel The Nesting level at which the CR appears. * * @return Nothing. */ void setNestingLevel(int nestingLevel) { if (SanityManager.DEBUG) { SanityManager.ASSERT(nestingLevel != -1, "nestingLevel is not expected to be -1"); } this.nestingLevel = nestingLevel; } /** * Get the nesting level for this CR. * * @return The nesting level for this CR. */ int getNestingLevel() { return nestingLevel; } /** * Set the source level for this CR. (The nesting level * of the source of the CR.) * * @param sourceLevel The Nesting level of the source of the CR. * * @return Nothing. */ void setSourceLevel(int sourceLevel) { if (SanityManager.DEBUG) { SanityManager.ASSERT(sourceLevel != -1, "sourceLevel is not expected to be -1"); } this.sourceLevel = sourceLevel; } /** * Get the source level for this CR. * * @return The source level for this CR. */ int getSourceLevel() { return sourceLevel; } /** * Mark this node as being generated to replace an aggregate. * (Useful for replacing aggregates in the HAVING clause with * column references to the matching aggregate in the * user's SELECT. * * @return Nothing. */ public void markGeneratedToReplaceAggregate() { replacesAggregate = true; } /** * Determine whether or not this node was generated to * replace an aggregate in the user's SELECT. * * @return boolean Whether or not this node was generated to replace * an aggregate in the user's SELECT. */ public boolean getGeneratedToReplaceAggregate() { return replacesAggregate; } /** * Return a clone of this node. * * @return ValueNode A clone of this node. * * @exception StandardException Thrown on error */ public ValueNode getClone() throws StandardException { ColumnReference newCR = (ColumnReference) getNodeFactory().getNode( C_NodeTypes.COLUMN_REFERENCE, columnName, tableName, getContextManager()); newCR.copyFields(this); return newCR; } /** * Copy all of the "appropriate fields" for a shallow copy. * * @param oldCR The ColumnReference to copy from. * * @exception StandardException Thrown on error */ public void copyFields(ColumnReference oldCR) throws StandardException { super.copyFields(oldCR); tableName = oldCR.getTableNameNode(); tableNumber = oldCR.getTableNumber(); columnNumber = oldCR.getColumnNumber(); source = oldCR.getSource(); nestingLevel = oldCR.getNestingLevel(); sourceLevel = oldCR.getSourceLevel(); replacesAggregate = oldCR.getGeneratedToReplaceAggregate(); } /** * Bind this expression. This means binding the sub-expressions, * as well as figuring out what the return type is for this expression. * * NOTE: We must explicitly check for a null FromList here, column reference * without a FROM list, as the grammar allows the following: * insert into t1 values(c1) * * @param fromList The FROM list for the query this * expression is in, for binding columns. * @param subqueryList The subquery list being built as we find SubqueryNodes * @param aggregateVector The aggregate vector being built as we find AggregateNodes * * @return The new top of the expression tree. * * @exception StandardException Thrown on error */ public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, Vector aggregateVector) throws StandardException { ResultColumn matchingRC; if (SanityManager.DEBUG) { SanityManager.ASSERT(fromList != null, "fromList is expected to be non-null"); } if (fromList.size() == 0) { throw StandardException.newException(SQLState.LANG_ILLEGAL_COLUMN_REFERENCE, columnName); } matchingRC = fromList.bindColumnReference(this); /* Error if no match found in fromList */ if (matchingRC == null) { throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND, getSQLColumnName()); } /* Set the columnNumber from the base table. * Useful for optimizer and generation. */ columnNumber = matchingRC.getColumnPosition(); return this; } /** * Get the column name for purposes of error * messages or debugging. This returns the column * name as used in the SQL statement. Thus if it was qualified * with a table, alias name that will be included. * * @return The column name in the form [[schema.]table.]column */ public String getSQLColumnName() { if (tableName == null) return columnName; return tableName.toString() + "." + columnName; } /** * Get the name of this column * * @return The name of this column */ public String getColumnName() { return columnName; } /** * Set the name of this column * * @param columName The name of this column * * @return None. */ public void setColumnName(String columnName) { this.columnName = columnName; } /** * Get the table number for this ColumnReference. * * @return int The table number for this ColumnReference */ public int getTableNumber() { return tableNumber; } /** * Set this ColumnReference to refer to the given table number. * * @param table The table number this ColumnReference will refer to * * @return Nothing */ public void setTableNumber(int tableNumber) { if (SanityManager.DEBUG) { SanityManager.ASSERT(tableNumber != -1, "tableNumber not expected to be -1"); } this.tableNumber = tableNumber; } /** * Get the user-supplied table name of this column. This will be null * if the user did not supply a name (for example, select a from t). * The method will return B for this example, select b.a from t as b * The method will return T for this example, select t.a from t * * @return The user-supplied name of this column. Null if no user- * supplied name. */ public String getTableName() { return ( ( tableName != null) ? tableName.getTableName() : null ); } /** * Get the name of the underlying(base) table this column comes from, if any. * Following example queries will all return T * select a from t * select b.a from t as b * select t.a from t * * @return The name of the base table that this column comes from. * Null if not a ColumnReference. */ public String getSourceTableName() { return ((source != null) ? source.getTableName() : null); } /** * Get the name of the schema for the Column's base table, if any. * Following example queries will all return APP (assuming user is in schema APP) * select t.a from t * select b.a from t as b * select app.t.a from t * * @return The name of the schema for Column's base table. If the column * is not in a schema (i.e. is a derived column), it returns NULL. */ public String getSourceSchemaName() throws StandardException { return ((source != null) ? source.getSchemaName() : null); } /** * Is the column wirtable by the cursor or not. (ie, is it in the list of FOR UPDATE columns list) * * @return TRUE, if the column is a base column of a table and is * writable by cursor. */ public boolean updatableByCursor() { return ((source != null) ? source.updatableByCursor() : false); } /** Return the table name as the node it is. @return the column's table name. */ public TableName getTableNameNode() { return tableName; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -