}
numOfGroupByColumns = mvComplexGroupbyCols.size();
for (AbstractExpression expr: mvComplexGroupbyCols) {
if (expr instanceof TupleValueExpression) {
TupleValueExpression tve = (TupleValueExpression) expr;
if (tve.getColumnIndex() == partitionColIndex) {
// If group by columns contain partition column from source table.
// Then, query on MV table will have duplicates from each partition.
// There is no need to fix this case, so just return.
return false;
}
}
}
} else {
CatalogMap<ColumnRef> mvSimpleGroupbyCols = mvInfo.getGroupbycols();
numOfGroupByColumns = mvSimpleGroupbyCols.size();
for (ColumnRef colRef: mvSimpleGroupbyCols) {
if (colRef.getColumn().getIndex() == partitionColIndex) {
// If group by columns contain partition column from source table.
// Then, query on MV table will have duplicates from each partition.
// There is no need to fix this case, so just return.
return false;
}
}
}
assert(numOfGroupByColumns > 0);
m_mvTableScan = mvTableScan;
Set<String> mvDDLGroupbyColumnNames = new HashSet<String>();
List<Column> mvColumnArray =
CatalogUtil.getSortedCatalogItems(table.getColumns(), "index");
// Start to do real materialized view processing to fix the duplicates problem.
// (1) construct new projection columns for scan plan node.
Set<SchemaColumn> mvDDLGroupbyColumns = new HashSet<SchemaColumn>();
NodeSchema inlineProjSchema = new NodeSchema();
for (SchemaColumn scol: scanColumns) {
inlineProjSchema.addColumn(scol);
}
String mvTableAlias = getMVTableAlias();
for (int i = 0; i < numOfGroupByColumns; i++) {
Column mvCol = mvColumnArray.get(i);
String colName = mvCol.getName();
TupleValueExpression tve = new TupleValueExpression(mvTableName, mvTableAlias, colName, colName, i);
tve.setTypeSizeBytes(mvCol.getType(), mvCol.getSize(), mvCol.getInbytes());
mvDDLGroupbyColumnNames.add(colName);
SchemaColumn scol = new SchemaColumn(mvTableName, mvTableAlias, colName, colName, tve);
mvDDLGroupbyColumns.add(scol);
if (!scanColumns.contains(scol)) {
scanColumns.add(scol);
// construct new projection columns for scan plan node.
inlineProjSchema.addColumn(scol);
}
}
// Record the re-aggregation type for each scan columns.
Map<String, ExpressionType> mvColumnReAggType = new HashMap<String, ExpressionType>();
for (int i = numOfGroupByColumns; i < mvColumnArray.size(); i++) {
Column mvCol = mvColumnArray.get(i);
ExpressionType reAggType = ExpressionType.get(mvCol.getAggregatetype());
if (reAggType == ExpressionType.AGGREGATE_COUNT_STAR ||
reAggType == ExpressionType.AGGREGATE_COUNT) {
reAggType = ExpressionType.AGGREGATE_SUM;
}
mvColumnReAggType.put(mvCol.getName(), reAggType);
}
m_scanInlinedProjectionNode = new ProjectionPlanNode();
m_scanInlinedProjectionNode.setOutputSchema(inlineProjSchema);
// (2) Construct the reAggregation Node.
// Construct the reAggregation plan node's aggSchema
m_reAggNode = new HashAggregatePlanNode();
int outputColumnIndex = 0;
// inlineProjSchema contains the group by columns, while aggSchema may do not.
NodeSchema aggSchema = new NodeSchema();
// Construct reAggregation node's aggregation and group by list.
for (SchemaColumn scol: scanColumns) {
if (mvDDLGroupbyColumns.contains(scol)) {
// Add group by expression.
m_reAggNode.addGroupByExpression(scol.getExpression());
} else {
ExpressionType reAggType = mvColumnReAggType.get(scol.getColumnName());
assert(reAggType != null);
AbstractExpression agg_input_expr = scol.getExpression();
assert(agg_input_expr instanceof TupleValueExpression);
// Add aggregation information.
m_reAggNode.addAggregate(reAggType, false, outputColumnIndex, agg_input_expr);
}
aggSchema.addColumn(scol);
outputColumnIndex++;
}
m_reAggNode.setOutputSchema(aggSchema);
// Collect all TVEs that need to be do re-aggregation in coordinator.
List<TupleValueExpression> needReAggTVEs = new ArrayList<TupleValueExpression>();
List<AbstractExpression> aggPostExprs = new ArrayList<AbstractExpression>();
for (int i=numOfGroupByColumns; i < mvColumnArray.size(); i++) {
Column mvCol = mvColumnArray.get(i);
String colName = mvCol.getName();
TupleValueExpression tve = new TupleValueExpression(mvTableName, mvTableAlias, colName, colName);
tve.setTypeSizeBytes(mvCol.getType(), mvCol.getSize(), mvCol.getInbytes());
needReAggTVEs.add(tve);
}
collectReAggNodePostExpressions(joinTree, needReAggTVEs, aggPostExprs);