}
int outputColumnIndex = 0;
for (ParsedSelectStmt.ParsedColInfo col : m_parsedSelect.displayColumns) {
AbstractExpression rootExpr = col.expression;
ExpressionType agg_expression_type = rootExpr.getExpressionType();
if (rootExpr.getExpressionType() == ExpressionType.AGGREGATE_SUM ||
rootExpr.getExpressionType() == ExpressionType.AGGREGATE_MIN ||
rootExpr.getExpressionType() == ExpressionType.AGGREGATE_MAX ||
rootExpr.getExpressionType() == ExpressionType.AGGREGATE_AVG ||
rootExpr.getExpressionType() == ExpressionType.AGGREGATE_COUNT ||
rootExpr.getExpressionType() == ExpressionType.AGGREGATE_COUNT_STAR)
{
PlanColumn aggregateColumn = null;
if (rootExpr.getLeft() instanceof TupleValueExpression)
{
TupleValueExpression nested =
(TupleValueExpression) rootExpr.getLeft();
if (((AggregateExpression)rootExpr).m_distinct) {
root = addDistinctNode(root, nested);
}
aggregateColumn =
root.findMatchingOutputColumn(nested.getTableName(),
nested.getColumnName(),
nested.getColumnAlias());
}
// count(*) hack. we're not getting AGGREGATE_COUNT_STAR
// expression types from the parsing, so we have
// to detect the null inner expression case and do the
// switcharoo ourselves.
else if (rootExpr.getExpressionType() == ExpressionType.AGGREGATE_COUNT &&
rootExpr.getLeft() == null)
{
aggregateColumn =
m_context.get(root.getOutputColumnGUIDs().get(0));
agg_expression_type = ExpressionType.AGGREGATE_COUNT_STAR;
}
else
{
throw new PlanningErrorException("Expressions in aggregates currently unsupported");
}
aggNode.getAggregateColumnGuids().add(aggregateColumn.guid());
aggNode.getAggregateColumnNames().add(aggregateColumn.getDisplayName());
aggNode.getAggregateTypes().add(agg_expression_type);
// A bit of a hack: ProjectionNodes using PlanColumns after the
// aggregate node need the output columns here to
// contain TupleValueExpressions (effectively on a temp table).
// So we construct one based on the output of the
// aggregate expression, the column alias provided by HSQL,
// and the offset into the output table schema for the
// aggregate node that we're computing.
TupleValueExpression tve = new TupleValueExpression();
// If this is an AVG, then our type should be DECIMAL
if (agg_expression_type == ExpressionType.AGGREGATE_AVG) {
tve.setValueType(VoltType.FLOAT);
tve.setValueSize(VoltType.FLOAT.getLengthInBytesForFixedTypes());
}
// Otherwise it can be whatever the rootExpression is
else {
tve.setValueType(rootExpr.getValueType());
tve.setValueSize(rootExpr.getValueSize());
}
tve.setColumnIndex(outputColumnIndex);
tve.setColumnName("");
tve.setColumnAlias(col.alias);
tve.setTableName(AGGREGATE_TEMP_TABLE);