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")
));
}
}