📄 resultcolumn.java
字号:
public void setVirtualColumnId(int id) { virtualColumnId = id; } /** * Get the virtualColumnId for this ResultColumn * * @return virtualColumnId for this ResultColumn */ public int getVirtualColumnId() { return virtualColumnId; } /** * Generate a unique (across the entire statement) column name for unnamed * ResultColumns * * @return None. * * @exception StandardException Thrown on error */ public void guaranteeColumnName() throws StandardException { if (exposedName == null) { /* Unions may also need generated names, if both sides name don't match */ exposedName ="SQLCol" + getCompilerContext().getNextColumnNumber(); isNameGenerated = 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 "exposedName: " + exposedName + "\n" + "name: " + name + "\n" + "tableName: " + tableName + "\n" + "isNameGenerated: " + isNameGenerated + "\n" + "sourceTableName: " + sourceTableName + "\n" + "type: " + dataTypeServices + "\n" + "columnDescriptor: " + columnDescriptor + "\n" + "isGenerated: " + isGenerated + "\n" + "isGeneratedForUnmatchedColumnInInsert: " + isGeneratedForUnmatchedColumnInInsert + "\n" + "isGroupingColumn: " + isGroupingColumn + "\n" + "isReferenced: " + isReferenced + "\n" + "isRedundant: " + isRedundant + "\n" + "virtualColumnId: " + virtualColumnId + "\n" + "resultSetNumber: " + resultSetNumber + "\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 (expression != null) { printLabel(depth, "expression: "); expression.treePrint(depth + 1); } if (reference != null) { printLabel(depth, "reference: "); reference.treePrint(depth + 1); } } } /** * Bind this expression. This means binding the sub-expressions. * In this case, we figure out what the result type of this result * column is when we call one of the bindResultColumn*() methods. * The reason is that there are different ways of binding the * result columns depending on the statement type, and this is * a standard interface that does not take the statement type as * a parameter. * * @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 { /* ** Set the type of a parameter to the type of the result column. ** Don't do it if this result column doesn't have a type yet. ** This can happen if the parameter is part of a table constructor. */ if (expression.isParameterNode()) { if (getTypeServices() != null) { ((ParameterNode) expression).setDescriptor(getTypeServices()); } } expression = expression.bindExpression(fromList, subqueryList, aggregateVector); if (expression instanceof ColumnReference) { autoincrement = ((ColumnReference)expression).getSource().isAutoincrement(); } return this; } /** * Bind this result column by ordinal position and set the VirtualColumnId. * This is useful for INSERT statements like "insert into t values (1, 2, 3)", * where the user did not specify a column list. * If a columnDescriptor is not found for a given position, then * the user has specified more values than the # of columns in * the table and an exception is thrown. * * NOTE: We must set the VirtualColumnId here because INSERT does not * construct the ResultColumnList in the usual way. * * @param tableDescriptor The descriptor for the table being * inserted into * @param columnId The ordinal position of the column * in the table, starting at 1. * * @return Nothing * * @exception StandardException Thrown on error */ void bindResultColumnByPosition(TableDescriptor tableDescriptor, int columnId) throws StandardException { ColumnDescriptor columnDescriptor; columnDescriptor = tableDescriptor.getColumnDescriptor(columnId); if (columnDescriptor == null) { String errorString; String schemaName; errorString = ""; schemaName = tableDescriptor.getSchemaName(); if (schemaName != null) errorString += schemaName + "."; errorString += tableDescriptor.getName(); throw StandardException.newException(SQLState.LANG_TOO_MANY_RESULT_COLUMNS, errorString); } setColumnDescriptor(tableDescriptor, columnDescriptor); setVirtualColumnId(columnId); } /** * Bind this result column by its name and set the VirtualColumnId. * This is useful for update statements, and for INSERT statements * like "insert into t (a, b, c) values (1, 2, 3)" where the user * specified a column list. * An exception is thrown when a columnDescriptor cannot be found for a * given name. (There is no column with that name.) * * NOTE: We must set the VirtualColumnId here because INSERT does not * construct the ResultColumnList in the usual way. * * @param tableDescriptor The descriptor for the table being * updated or inserted into * @param columnId The ordinal position of the column * in the table, starting at 1. (Used to * set the VirtualColumnId.) * * @return Nothing * * @exception StandardException Thrown on error */ public void bindResultColumnByName(TableDescriptor tableDescriptor, int columnId) throws StandardException { ColumnDescriptor columnDescriptor; columnDescriptor = tableDescriptor.getColumnDescriptor(exposedName); if (columnDescriptor == null) { String errorString; String schemaName; errorString = ""; schemaName = tableDescriptor.getSchemaName(); if (schemaName != null) errorString += schemaName + "."; errorString += tableDescriptor.getName(); throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, exposedName, errorString); } setColumnDescriptor(tableDescriptor, columnDescriptor); setVirtualColumnId(columnId); } /** * Change an untyped null to a typed null. * * @param typeId The type of the null. * * @return Nothing. * * @exception StandardException Thrown on error */ public void typeUntypedNullExpression( ResultColumn bindingRC) throws StandardException { TypeId typeId = bindingRC.getTypeId(); /* This is where we catch null in a VALUES clause outside * of INSERT VALUES() */ if (typeId == null) { throw StandardException.newException(SQLState.LANG_NULL_IN_VALUES_CLAUSE); } if( expression instanceof UntypedNullConstantNode) expression = getNullNode( typeId, getContextManager()); else if( ( expression instanceof ColumnReference) && expression.getTypeServices() == null) { // The expression must be a reference to a null column in a values table. expression.setType( bindingRC.getType()); } } /** * Set the column descriptor for this result column. It also gets * the data type services from the column descriptor and stores it in * this result column: this is redundant, but we have to store the result * type here for SELECT statements, and it is more orthogonal if the type * can be found here regardless of what type of statement it is. * * @param tableDescriptor The TableDescriptor for the table * being updated or inserted into. * This parameter is used only for * error reporting. * @param columnDescriptor The ColumnDescriptor to set in * this ResultColumn. * * @return Nothing * @exception StandardException tableNameMismatch */ void setColumnDescriptor(TableDescriptor tableDescriptor, ColumnDescriptor columnDescriptor) throws StandardException { /* Callers are responsible for verifying that the column exists */ if (SanityManager.DEBUG) SanityManager.ASSERT(columnDescriptor != null, "Caller is responsible for verifying that column exists"); setType(columnDescriptor.getType()); this.columnDescriptor = columnDescriptor; /* If the node was created using a reference, the table name of the reference must agree with that of the tabledescriptor. */ if (reference != null && reference.getTableName() != null) { if (! tableDescriptor.getName().equals( reference.getTableName()) ) { /* REMIND: need to have schema name comparison someday as well... ** left out for now, lots of null checking needed... ** || ! tableDescriptor.getSchemaName().equals( ** reference.getTableNameNode().getSchemaName())) { */ String realName = tableDescriptor.getName(); String refName = reference.getTableName(); throw StandardException.newException(SQLState.LANG_TABLE_NAME_MISMATCH, realName, refName); } } } /** * Bind the result column to the expression that lives under it. * All this does is copy the datatype information to this node. * This is useful for SELECT statements, where the result type * of each column is the type of the column's expression. * * @return Nothing * * @exception StandardException Thrown on error */ public void bindResultColumnToExpression() throws StandardException { /* ** This gets the same DataTypeServices object as ** is used in the expression. It is probably not ** necessary to clone the object here. */ setType(expression.getTypeServices()); if (expression instanceof ColumnReference) { ColumnReference cr = (ColumnReference) expression; tableName = cr.getTableName(); sourceTableName = cr.getSourceTableName(); sourceSchemaName = cr.getSourceSchemaName(); } } /** * Preprocess an expression tree. We do a number of transformations * here (including subqueries, IN lists, LIKE and BETWEEN) plus * subquery flattening. * NOTE: This is done before the outer ResultSetNode is preprocessed. * * @param numTables Number of tables in the DML Statement * @param outerFromList FromList from outer query block * @param outerSubqueryList SubqueryList from outer query block * @param outerPredicateList PredicateList from outer query block * * @return The modified expression * * @exception StandardException Thrown on error */ public ValueNode preprocess(int numTables, FromList outerFromList, SubqueryList outerSubqueryList, PredicateList outerPredicateList) throws StandardException { if (expression == null) return this; expression = expression.preprocess(numTables, outerFromList, outerSubqueryList, outerPredicateList); return this; } /** This verifies that the expression is storable into the result column. It checks versus the given ResultColumn. This method should not be called until the result column and expression both have a valid type, i.e. after they are bound appropriately. Its use is for statements like insert, that need to verify if a given value can be stored into a column. @exception StandardException thrown if types not suitable. */ public void checkStorableExpression(ResultColumn toStore) throws StandardException { TypeId columnTypeId, toStoreTypeId; toStoreTypeId = toStore.getTypeId(); if( toStoreTypeId == null) return; columnTypeId = getTypeId(); if (! getTypeCompiler().storable(toStoreTypeId, getClassFactory())) throw StandardException.newException(SQLState.LANG_NOT_STORABLE, columnTypeId.getSQLTypeName(), toStoreTypeId.getSQLTypeName() ); } /** This verifies that the expression is storable into the result column. It checks versus the expression under this ResultColumn. This method should not be called until the result column and expression both have a valid type, i.e. after they are bound appropriately. Its use is for statements like update, that need to verify if a given value can be stored into a column. @exception StandardException thrown if types not suitable. */ public void checkStorableExpression() throws StandardException { TypeId columnTypeId = getTypeId(); TypeId toStoreTypeId = getExpressionType().getTypeId(); if (! getTypeCompiler().storable(toStoreTypeId, getClassFactory())) throw StandardException.newException(SQLState.LANG_NOT_STORABLE, columnTypeId.getSQLTypeName(), toStoreTypeId.getSQLTypeName() ); } /** * Do code generation for a result column. This consists of doing the code * generation for the underlying expression. * * @param ecb The ExpressionClassBuilder for the class we're generating * @param mb The method the expression will go into * * * @exception StandardException Thrown on error */ public void generateExpression(ExpressionClassBuilder ecb, MethodBuilder mb) throws StandardException { expression.generateExpression(ecb, mb); } /** * Do code generation to return a Null of the appropriate type * for the result column. Requires the getCOlumnExpress value pushed onto the stack * * @param acb The ActivationClassBuilder for the class we're generating * @param eb The ExpressionBlock that the generate code is to go into * @param getColumnExpression "fieldx.getColumn(y)" * * @return An Expression representing a Null for the result * column.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -