** 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.
*/
LanguageFactory lf = getLanguageConnectionContext().getLanguageFactory();
ReplaceAggregatesWithCRVisitor replaceAggsVisitor =
new ReplaceAggregatesWithCRVisitor(
(ResultColumnList) getNodeFactory().getNode(
C_NodeTypes.RESULT_COLUMN_LIST,
getContextManager()),
((FromTable) childResult).getTableNumber(),
ResultSetNode.class);
parent.getResultColumns().accept(replaceAggsVisitor);
if (havingClause != null)
{
// replace aggregates in the having clause with column references.
replaceAggsVisitor = new ReplaceAggregatesWithCRVisitor(
(ResultColumnList) getNodeFactory().getNode(
C_NodeTypes.RESULT_COLUMN_LIST,
getContextManager()),
((FromTable)childResult).getTableNumber());
havingClause.accept(replaceAggsVisitor);
// make having clause a restriction list in the parent
// project restrict node.
ProjectRestrictNode parentPRSN = (ProjectRestrictNode)parent;
parentPRSN.setRestriction(havingClause);
}
/*
** For each aggregate
*/
int alSize = aggregateVector.size();
for (int index = 0; index < alSize; index++)
{
aggregate = (AggregateNode) aggregateVector.get(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
** ReplaceAggregatesWithCRVisitor()
*/
newColumnRef = (ColumnReference) getNodeFactory().getNode(
C_NodeTypes.COLUMN_REFERENCE,
newRC.getName(),
null,
getContextManager());
newColumnRef.setSource(newRC);
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();
aggResultRC = (ResultColumn) getNodeFactory().getNode(
C_NodeTypes.RESULT_COLUMN,
"##aggregate expression",
aggregate.getNewNullResultExpression(),
getContextManager());
/*
** 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(aggResultRC);
/*
** 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")
));
}
}