📄 unionnode.java
字号:
{ Optimizable retOptimizable; retOptimizable = super.modifyAccessPath(outerTables); /* We only want call addNewNodes() once */ if (addNewNodesCalled) { return retOptimizable; } return (Optimizable) addNewNodes(); } /** * @see ResultSetNode#modifyAccessPaths * * @exception StandardException Thrown on error */ public ResultSetNode modifyAccessPaths() throws StandardException { ResultSetNode retRSN; retRSN = super.modifyAccessPaths(); /* We only want call addNewNodes() once */ if (addNewNodesCalled) { return retRSN; } return addNewNodes(); } /** * Add any new ResultSetNodes that are necessary to the tree. * We wait until after optimization to do this in order to * make it easier on the optimizer. * * @return (Potentially new) head of the ResultSetNode tree. * * @exception StandardException Thrown on error */ private ResultSetNode addNewNodes() throws StandardException { ResultSetNode treeTop = this; /* Only call addNewNodes() once */ if (addNewNodesCalled) { return this; } addNewNodesCalled = true; /* RESOLVE - We'd like to generate any necessary NormalizeResultSets * above our children here, in the tree. However, doing so causes * the following query to fail because the where clause goes against * the NRS instead of the Union: * SELECT TABLE_TYPE * FROM SYS.SYSTABLES, * (VALUES ('T','TABLE') , * ('S','SYSTEM TABLE') , ('V', 'VIEW')) T(TTABBREV,TABLE_TYPE) * WHERE TTABBREV=TABLETYPE; * Thus, we are forced to skip over generating the nodes in the tree * and directly generate the execution time code in generate() instead. * This solves the problem for some unknown reason. */ /* Simple solution (for now) to eliminating duplicates - * generate a distinct above the union. */ if (! all) { /* We need to generate a NormalizeResultSetNode above us if the column * types and lengths don't match. (We need to do it here, since they * will end up agreeing in the PRN, which will be the immediate * child of the DistinctNode, which means that the NormalizeResultSet * won't get generated above the PRN.) */ if (! columnTypesAndLengthsMatch()) { treeTop = genNormalizeResultSetNode(this, false); } treeTop = (ResultSetNode) getNodeFactory().getNode( C_NodeTypes.DISTINCT_NODE, treeTop.genProjectRestrict(), Boolean.FALSE, tableProperties, getContextManager()); /* HACK - propagate our table number up to the new DistinctNode * so that arbitrary hash join will work correctly. (Otherwise it * could have a problem dividing up the predicate list at the end * of modifyAccessPath() because the new child of the PRN above * us would have a tableNumber of -1 instead of our tableNumber.) */ ((FromTable)treeTop).setTableNumber(tableNumber); treeTop.setReferencedTableMap((JBitSet) referencedTableMap.clone()); all = true; } /* Generate the OrderByNode if a sort is still required for * the order by. */ if (orderByList != null) { treeTop = (ResultSetNode) getNodeFactory().getNode( C_NodeTypes.ORDER_BY_NODE, treeTop, orderByList, tableProperties, getContextManager()); } return treeTop; } /** * 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 "tableConstructor: " + tableConstructor + "\n" + super.toString(); } else { return ""; } } /** * 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 { super.bindExpressions(fromListParam); /* ** Each ? parameter in a table constructor that is not in an insert ** statement takes its type from the first non-? in its column ** of the table constructor. It's an error to have a column that ** has all ?s. Do this only for the top of the table constructor ** list - we don't want to do this for every level of union node ** in the table constructor. Also, don't do this for an INSERT - ** the types of the ? parameters come from the columns being inserted ** into in that case. */ if (topTableConstructor && ( ! insertSource) ) { /* ** Step through all the rows in the table constructor to ** get the type of the first non-? in each column. */ DataTypeDescriptor[] types = new DataTypeDescriptor[leftResultSet.getResultColumns().size()]; ResultSetNode rsn; int numTypes = 0; /* By looping through the union nodes, we avoid recursion */ for (rsn = this; rsn instanceof SetOperatorNode; ) { SetOperatorNode setOperator = (SetOperatorNode) rsn; /* ** Assume that table constructors are left-deep trees of ** SetOperatorNodes with RowResultSet nodes on the right. */ if (SanityManager.DEBUG) SanityManager.ASSERT( setOperator.rightResultSet instanceof RowResultSetNode, "A " + setOperator.rightResultSet.getClass().getName() + " is on the right side of a setOperator in a table constructor"); RowResultSetNode rrsn = (RowResultSetNode) setOperator.rightResultSet; numTypes += getParamColumnTypes(types, rrsn); rsn = setOperator.leftResultSet; } /* The last node on the left should be a result set node */ if (SanityManager.DEBUG) SanityManager.ASSERT(rsn instanceof RowResultSetNode); numTypes += getParamColumnTypes(types, (RowResultSetNode) rsn); /* Are there any columns that are all ? parameters? */ if (numTypes < types.length) { throw StandardException.newException(SQLState.LANG_TABLE_CONSTRUCTOR_ALL_PARAM_COLUMN); } /* ** Loop through the nodes again. This time, look for parameter ** nodes, and give them the type from the type array we just ** constructed. */ for (rsn = this; rsn instanceof SetOperatorNode; ) { SetOperatorNode setOperator = (SetOperatorNode) rsn; RowResultSetNode rrsn = (RowResultSetNode) setOperator.rightResultSet; setParamColumnTypes(types, rrsn); rsn = setOperator.leftResultSet; } setParamColumnTypes(types, (RowResultSetNode) rsn); } } /** * Generate the code for this UnionNode. * * @exception StandardException Thrown on error */ public void generate(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException { /* By the time we get here we should be a union all. * (We created a DistinctNode above us, if needed, * to eliminate the duplicates earlier.) */ if (SanityManager.DEBUG) { SanityManager.ASSERT(all, "all expected to be true"); } /* Get the next ResultSet #, so that we can number this ResultSetNode, its * ResultColumnList and ResultSet. */ assignResultSetNumber(); // Get our final cost estimate based on the child estimates. costEstimate = getFinalCostEstimate(); // build up the tree. acb.pushGetResultSetFactoryExpression(mb); // instance for getUnionResultSet /* Generate the left and right ResultSets */ leftResultSet.generate(acb, mb); /* Do we need a NormalizeResultSet above the left ResultSet? */ if (! resultColumns.isExactTypeAndLengthMatch(leftResultSet.getResultColumns())) { acb.pushGetResultSetFactoryExpression(mb); mb.swap(); generateNormalizationResultSet(acb, mb, getCompilerContext().getNextResultSetNumber(), makeResultDescription() ); } rightResultSet.generate(acb, mb); /* Do we need a NormalizeResultSet above the right ResultSet? */ if (! resultColumns.isExactTypeAndLengthMatch(rightResultSet.getResultColumns())) { acb.pushGetResultSetFactoryExpression(mb); mb.swap(); generateNormalizationResultSet(acb, mb, getCompilerContext().getNextResultSetNumber(), makeResultDescription() ); } /* Generate the UnionResultSet: * arg1: leftExpression - Expression for leftResultSet * arg2: rightExpression - Expression for rightResultSet * arg3: Activation * arg4: resultSetNumber * arg5: estimated row count * arg6: estimated cost * arg7: close method */ acb.pushThisAsActivation(mb); mb.push(resultSetNumber); mb.push(costEstimate.rowCount()); mb.push(costEstimate.getEstimatedCost()); closeMethodArgument(acb, mb); mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getUnionResultSet", ClassName.NoPutResultSet, 7); } /** * @see ResultSetNode#getFinalCostEstimate * * Get the final CostEstimate for this UnionNode. * * @return The final CostEstimate for this UnionNode, which is * the sum of the two child costs. */ public CostEstimate getFinalCostEstimate() throws StandardException { // If we already found it, just return it. if (finalCostEstimate != null) return finalCostEstimate; CostEstimate leftCE = leftResultSet.getFinalCostEstimate(); CostEstimate rightCE = rightResultSet.getFinalCostEstimate(); finalCostEstimate = getNewCostEstimate(); finalCostEstimate.setCost(leftCE.getEstimatedCost(), leftCE.rowCount(), leftCE.singleScanRowCount() + rightCE.singleScanRowCount()); finalCostEstimate.add(rightCE, finalCostEstimate); return finalCostEstimate; } String getOperatorName() { return "UNION"; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -