📄 groupbynode.java
字号:
ResultColumn rcBottom; ResultColumn newRC; ResultColumn gbRC; ResultColumn tmpRC; ResultColumn aggInputRC; ResultColumnList bottomRCL = childResult.getResultColumns(); ResultColumnList groupByRCL = resultColumns; ResultColumnList aggRCL; int aggregatorVColId; int aggInputVColId; int aggResultVColId; LanguageFactory lf = getLanguageConnectionContext().getLanguageFactory(); dd = getDataDictionary(); aggInfo = new AggregatorInfoList(); /* ** Get a list of all column references in the ** parent RCL, skipping (not going below) AggregateNodes */ CollectNodesVisitor getUnaggVisitor = new CollectNodesVisitor(ColumnReference.class, AggregateNode.class); parent.getResultColumns().accept(getUnaggVisitor); Vector colRefVector = getUnaggVisitor.getList(); /* ** Walk the list of unaggregated column references ** and push them down. */ int crvSize = colRefVector.size(); for (int index = 0; index < crvSize; index++) { ColumnReference origColumnRef = (ColumnReference) colRefVector.elementAt(index); newColumnRef = (ColumnReference)origColumnRef.getClone(); /* ** Put the column reference in the bottom PR. */ newRC = (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, "##UnaggColumn", newColumnRef, getContextManager()); newRC.setExpression(newColumnRef); bottomRCL.addElement(newRC); newRC.markGenerated(); newRC.bindResultColumnToExpression(); newRC.setVirtualColumnId(bottomRCL.size()); /* ** Reset the group by column position */ if (groupingList != null) { GroupByColumn gbColumn; if ((gbColumn = groupingList.containsColumnReference(newColumnRef)) != null) { gbColumn.setColumnPosition(bottomRCL.size()); } } /* ** Add the column to the group by list */ gbRC = getColumnReference(newRC, dd); groupByRCL.addElement(gbRC); gbRC.markGenerated(); gbRC.bindResultColumnToExpression(); gbRC.setVirtualColumnId(groupByRCL.size()); /* ** Reset the original node to point to the ** Group By result set. */ origColumnRef.setSource(gbRC); } /* ** Now process all of the aggregates. Replace ** every aggregate with an RC. We toss out ** the list of RCs, we need to get each RC ** as we process its corresponding aggregate. */ ReplaceAggregatesWithCRVisitor replaceAggsVisitor = new ReplaceAggregatesWithCRVisitor( (ResultColumnList) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN_LIST, getContextManager()), ((FromTable) childResult).getTableNumber()); parent.getResultColumns().accept(replaceAggsVisitor); /* ** For each aggregate */ int alSize = aggregateVector.size(); for (int index = 0; index < alSize; index++) { aggregate = (AggregateNode) aggregateVector.elementAt(index); /* ** AGG RESULT: Set the aggregate result to null in the ** bottom project restrict. */ newRC = (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, "##aggregate result", aggregate.getNewNullResultExpression(), getContextManager()); newRC.markGenerated(); newRC.bindResultColumnToExpression(); bottomRCL.addElement(newRC); newRC.setVirtualColumnId(bottomRCL.size()); aggResultVColId = newRC.getVirtualColumnId(); /* ** Set the GB aggregrate result column to ** point to this. The GB aggregate result ** was created when we called ** ReplaceAggregatesWithColumnReferencesVisitor() */ newColumnRef = (ColumnReference) getNodeFactory().getNode( C_NodeTypes.COLUMN_REFERENCE, newRC.getName(), null, getContextManager()); newColumnRef.setSource(newRC); newColumnRef.setType(newRC.getExpressionType()); newColumnRef.setNestingLevel(this.getLevel()); newColumnRef.setSourceLevel(this.getLevel()); tmpRC = (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, newRC.getColumnName(), newColumnRef, getContextManager()); tmpRC.markGenerated(); tmpRC.bindResultColumnToExpression(); groupByRCL.addElement(tmpRC); tmpRC.setVirtualColumnId(groupByRCL.size()); /* ** Set the column reference to point to ** this. */ newColumnRef = aggregate.getGeneratedRef(); newColumnRef.setSource(tmpRC); /* ** AGG INPUT: Create a ResultColumn in the bottom ** project restrict that has the expression that is ** to be aggregated */ newRC = aggregate.getNewExpressionResultColumn(dd); newRC.markGenerated(); newRC.bindResultColumnToExpression(); bottomRCL.addElement(newRC); newRC.setVirtualColumnId(bottomRCL.size()); aggInputVColId = newRC.getVirtualColumnId(); aggInputRC = newRC; /* ** Add a reference to this column into the ** group by columns. */ tmpRC = getColumnReference(newRC, dd); groupByRCL.addElement(tmpRC); tmpRC.setVirtualColumnId(groupByRCL.size()); /* ** AGGREGATOR: Add a getAggregator method call ** to the bottom result column list. */ newRC = aggregate.getNewAggregatorResultColumn(dd); newRC.markGenerated(); newRC.bindResultColumnToExpression(); bottomRCL.addElement(newRC); newRC.setVirtualColumnId(bottomRCL.size()); aggregatorVColId = newRC.getVirtualColumnId(); /* ** Add a reference to this column in the Group By result ** set. */ tmpRC = getColumnReference(newRC, dd); groupByRCL.addElement(tmpRC); tmpRC.setVirtualColumnId(groupByRCL.size()); /* ** Piece together a fake one column rcl that we will use ** to generate a proper result description for input ** to this agg if it is a user agg. */ aggRCL = (ResultColumnList) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN_LIST, getContextManager()); aggRCL.addElement(aggInputRC); /* ** Note that the column ids in the row are 0 based ** so we have to subtract 1. */ aggInfo.addElement(new AggregatorInfo( aggregate.getAggregateName(), aggregate.getAggregatorClassName(), aggInputVColId - 1, // aggregate input column aggResultVColId -1, // the aggregate result column aggregatorVColId - 1, // the aggregator column aggregate.isDistinct(), lf.getResultDescription(aggRCL.makeResultDescriptors(), "SELECT") )); } } /** * Return the parent node to this one, if there is * one. It will return 'this' if there is no generated * node above this one. * * @return the parent node */ public FromTable getParent() { return parent; } /* * Optimizable interface */ /** * @see Optimizable#optimizeIt * * @exception StandardException Thrown on error */ public CostEstimate optimizeIt( Optimizer optimizer, OptimizablePredicateList predList, CostEstimate outerCost, RowOrdering rowOrdering) throws StandardException { // RESOLVE: NEED TO FACTOR IN THE COST OF GROUPING (SORTING) HERE CostEstimate childCost = ((Optimizable) childResult).optimizeIt( optimizer, predList, outerCost, rowOrdering); CostEstimate retval = super.optimizeIt( optimizer, predList, outerCost, rowOrdering ); return retval; } /** * @see Optimizable#estimateCost * * @exception StandardException Thrown on error */ public CostEstimate estimateCost(OptimizablePredicateList predList, ConglomerateDescriptor cd, CostEstimate outerCost, Optimizer optimizer, RowOrdering rowOrdering ) throws StandardException { // RESOLVE: NEED TO FACTOR IN THE COST OF GROUPING (SORTING) HERE // CostEstimate childCost = ((Optimizable) childResult).estimateCost( predList, cd, outerCost, optimizer, rowOrdering); CostEstimate costEstimate = getCostEstimate(optimizer); costEstimate.setCost(childCost.getEstimatedCost(), childCost.rowCount(), childCost.singleScanRowCount()); return costEstimate; } /** * @see org.apache.derby.iapi.sql.compile.Optimizable#pushOptPredicate * * @exception StandardException Thrown on error */ public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate) throws StandardException { return ((Optimizable) childResult).pushOptPredicate(optimizablePredicate); } /** * 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 "singleInputRowOptimization: " + singleInputRowOptimization + "\n" + childResult.toString() + "\n" + super.toString(); } else { return ""; } } /** * Evaluate whether or not the subquery in a FromSubquery is flattenable. * Currently, a FSqry is flattenable if all of the following are true: * o Subquery is a SelectNode. * o It contains no top level subqueries. (RESOLVE - we can relax this) * o It does not contain a group by or having clause * o It does not contain aggregates. * * @param fromList The outer from list * * @return boolean Whether or not the FromSubquery is flattenable. */ public boolean flattenableInFromSubquery(FromList fromList) { /* Can't flatten a GroupByNode */ return false; } /** * Optimize this GroupByNode. * * @param dataDictionary The DataDictionary to use for optimization * @param predicateList The PredicateList to optimize. This should * be a join predicate. * @param outerRows The number of outer joining rows * * @return ResultSetNode The top of the optimized subtree * * @exception StandardException Thrown on error */ public ResultSetNode optimize(DataDictionary dataDictionary, PredicateList predicates, double outerRows) throws StandardException { /* We need to implement this method since a PRN can appear above a * SelectNode in a query tree. */ childResult = (FromTable) childResult.optimize( dataDictionary, predicates, outerRows); Optimizer optimizer = getOptimizer( (FromList) getNodeFactory().getNode( C_NodeTypes.FROM_LIST, getNodeFactory().doJoinOrderOptimization(), getContextManager()),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -