private static Map<AggregateSymbol, Expression> buildAggregateMap(Collection<? extends SingleElementSymbol> aggregateExpressions,
QueryMetadataInterface metadata, Set<AggregateSymbol> nestedAggregates) throws QueryResolverException,
TeiidComponentException {
Map<AggregateSymbol, Expression> aggMap = new HashMap<AggregateSymbol, Expression>();
for (SingleElementSymbol symbol : aggregateExpressions) {
AggregateSymbol partitionAgg = (AggregateSymbol)symbol;
Expression newExpression = null;
Type aggFunction = partitionAgg.getAggregateFunction();
if (aggFunction == Type.COUNT) {
//COUNT(x) -> CONVERT(SUM(COUNT(x)), INTEGER)
AggregateSymbol newAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, partitionAgg); //$NON-NLS-1$
// Build conversion function to convert SUM (which returns LONG) back to INTEGER
Function convertFunc = new Function(FunctionLibrary.CONVERT, new Expression[] {newAgg, new Constant(DataTypeManager.getDataTypeName(partitionAgg.getType()))});
ResolverVisitor.resolveLanguageObject(convertFunc, metadata);
newExpression = convertFunc;
nestedAggregates.add(partitionAgg);
} else if (aggFunction == Type.AVG) {
//AVG(x) -> SUM(SUM(x)) / SUM(COUNT(x))
AggregateSymbol countAgg = new AggregateSymbol("stagedAgg", NonReserved.COUNT, false, partitionAgg.getExpression()); //$NON-NLS-1$
AggregateSymbol sumAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, partitionAgg.getExpression()); //$NON-NLS-1$
AggregateSymbol sumSumAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, sumAgg); //$NON-NLS-1$
AggregateSymbol sumCountAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, countAgg); //$NON-NLS-1$
Expression convertedSum = new Function(FunctionLibrary.CONVERT, new Expression[] {sumSumAgg, new Constant(DataTypeManager.getDataTypeName(partitionAgg.getType()))});
Expression convertCount = new Function(FunctionLibrary.CONVERT, new Expression[] {sumCountAgg, new Constant(DataTypeManager.getDataTypeName(partitionAgg.getType()))});
Function divideFunc = new Function("/", new Expression[] {convertedSum, convertCount}); //$NON-NLS-1$
ResolverVisitor.resolveLanguageObject(divideFunc, metadata);
newExpression = divideFunc;
nestedAggregates.add(countAgg);
nestedAggregates.add(sumAgg);
} else if (partitionAgg.isEnhancedNumeric()) {
//e.g. STDDEV_SAMP := CASE WHEN COUNT(X) > 1 THEN SQRT((SUM(X^2) - SUM(X)^2/COUNT(X))/(COUNT(X) - 1))
AggregateSymbol countAgg = new AggregateSymbol("stagedAgg", NonReserved.COUNT, false, partitionAgg.getExpression()); //$NON-NLS-1$
AggregateSymbol sumAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, partitionAgg.getExpression()); //$NON-NLS-1$
AggregateSymbol sumSqAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, new Function(SourceSystemFunctions.POWER, new Expression[] {partitionAgg.getExpression(), new Constant(2)})); //$NON-NLS-1$
AggregateSymbol sumSumAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, sumAgg); //$NON-NLS-1$
AggregateSymbol sumCountAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, countAgg); //$NON-NLS-1$
AggregateSymbol sumSumSqAgg = new AggregateSymbol("stagedAgg", NonReserved.SUM, false, sumSqAgg); //$NON-NLS-1$
Expression convertedSum = new Function(FunctionLibrary.CONVERT, new Expression[] {sumSumAgg, new Constant(DataTypeManager.DefaultDataTypes.DOUBLE)});
Function divideFunc = new Function(SourceSystemFunctions.DIVIDE_OP, new Expression[] {new Function(SourceSystemFunctions.POWER, new Expression[] {convertedSum, new Constant(2)}), sumCountAgg});
Function minusFunc = new Function(SourceSystemFunctions.SUBTRACT_OP, new Expression[] {sumSumSqAgg, divideFunc});
Expression divisor = null;
if (aggFunction == Type.STDDEV_SAMP || aggFunction == Type.VAR_SAMP) {
divisor = new Function(SourceSystemFunctions.SUBTRACT_OP, new Expression[] {sumCountAgg, new Constant(1)});
} else {
divisor = sumCountAgg;
}
Expression result = new Function(SourceSystemFunctions.DIVIDE_OP, new Expression[] {minusFunc, divisor});
if (aggFunction == Type.STDDEV_POP || aggFunction == Type.STDDEV_SAMP) {
result = new Function(SourceSystemFunctions.SQRT, new Expression[] {result});
} else {
result = new Function(FunctionLibrary.CONVERT, new Expression[] {result, new Constant(DataTypeManager.DefaultDataTypes.DOUBLE)});
}
Expression n = new Constant(0);
if (aggFunction == Type.STDDEV_SAMP || aggFunction == Type.VAR_SAMP) {
n = new Constant(1);
}
result = new SearchedCaseExpression(Arrays.asList(new CompareCriteria(sumCountAgg, CompareCriteria.GT, n)), Arrays.asList(result));
ResolverVisitor.resolveLanguageObject(result, metadata);
newExpression = result;
nestedAggregates.add(countAgg);
nestedAggregates.add(sumAgg);
nestedAggregates.add(sumSqAgg);
} else if (aggFunction == Type.TEXTAGG) {
continue;
}
else {
//AGG(X) -> AGG(AGG(X))
newExpression = new AggregateSymbol("stagedAgg", aggFunction.name(), false, partitionAgg); //$NON-NLS-1$
nestedAggregates.add(partitionAgg);
}
aggMap.put(partitionAgg, newExpression);
}