public void addView(PlanNode root, PlanNode unionSource, boolean pushdown, List<SingleElementSymbol> groupingExpressions,
Set<AggregateSymbol> aggregates, List<ElementSymbol> virtualElements,
QueryMetadataInterface metadata, CapabilitiesFinder capFinder)
throws TeiidComponentException, QueryPlannerException, QueryResolverException {
PlanNode originalNode = unionSource;
//branches other than the first need to have their projected column names updated
PlanNode sortNode = NodeEditor.findNodePreOrder(unionSource, NodeConstants.Types.SORT, NodeConstants.Types.SOURCE);
List<SingleElementSymbol> sortOrder = null;
OrderBy orderBy = null;
if (sortNode != null) {
orderBy = (OrderBy)sortNode.getProperty(Info.SORT_ORDER);
sortOrder = orderBy.getSortKeys();
}
List<SingleElementSymbol> projectCols = FrameUtil.findTopCols(unionSource);
for (int i = 0; i < virtualElements.size(); i++) {
ElementSymbol virtualElem = virtualElements.get(i);
SingleElementSymbol projectedSymbol = projectCols.get(i);
if (!projectedSymbol.getShortCanonicalName().equals(virtualElem.getShortCanonicalName())) {
if (sortOrder != null) {
int sortIndex = sortOrder.indexOf(projectedSymbol);
if (sortIndex > -1) {
updateSymbolName(sortOrder, sortIndex, virtualElem, sortOrder.get(sortIndex));
orderBy.getOrderByItems().get(sortIndex).setSymbol(sortOrder.get(sortIndex));
}
}
updateSymbolName(projectCols, i, virtualElem, projectedSymbol);
}
}
GroupSymbol group = new GroupSymbol("X"); //$NON-NLS-1$
PlanNode intermediateView = createView(group, virtualElements, unionSource, metadata);
SymbolMap symbolMap = (SymbolMap)intermediateView.getProperty(Info.SYMBOL_MAP);
unionSource = intermediateView;
Set<SingleElementSymbol> newGroupingExpressions = Collections.emptySet();
if (groupingExpressions != null) {
newGroupingExpressions = new HashSet<SingleElementSymbol>();
for (SingleElementSymbol singleElementSymbol : groupingExpressions) {
newGroupingExpressions.add((SingleElementSymbol)symbolMap.getKeys().get(virtualElements.indexOf(singleElementSymbol)).clone());
}
}
List<SingleElementSymbol> projectedViewSymbols = Util.deepClone(symbolMap.getKeys(), SingleElementSymbol.class);
PlanNode parent = NodeEditor.findParent(unionSource, NodeConstants.Types.SOURCE);
SymbolMap parentMap = (SymbolMap) parent.getProperty(NodeConstants.Info.SYMBOL_MAP);
SymbolMap viewMapping = SymbolMap.createSymbolMap(parentMap.getKeys(), projectedViewSymbols);
for (AggregateSymbol agg : aggregates) {
agg = (AggregateSymbol)agg.clone();
ExpressionMappingVisitor.mapExpressions(agg, viewMapping.asMap());
if (pushdown) {
projectedViewSymbols.add(agg);
} else {
if (agg.getAggregateFunction() == Type.COUNT) {
if (agg.getExpression() == null) {
projectedViewSymbols.add(new ExpressionSymbol("stagedAgg", new Constant(1))); //$NON-NLS-1$
} else {
SearchedCaseExpression count = new SearchedCaseExpression(Arrays.asList(new IsNullCriteria(agg.getExpression())), Arrays.asList(new Constant(Integer.valueOf(0))));
count.setElseExpression(new Constant(Integer.valueOf(1)));
count.setType(DataTypeManager.DefaultDataClasses.INTEGER);
projectedViewSymbols.add(new ExpressionSymbol("stagedAgg", count)); //$NON-NLS-1$
}
} else { //min, max, sum
Expression ex = agg.getExpression();
ex = ResolverUtil.convertExpression(ex, DataTypeManager.getDataTypeName(agg.getType()), metadata);
projectedViewSymbols.add(new ExpressionSymbol("stagedAgg", ex)); //$NON-NLS-1$
}
}
}
if (pushdown) {
unionSource = addGroupBy(unionSource, newGroupingExpressions, new LinkedList<AggregateSymbol>());
}
PlanNode projectPlanNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
unionSource.addAsParent(projectPlanNode);
unionSource = projectPlanNode;
//create proper names for the aggregate symbols
Select select = new Select(projectedViewSymbols);
QueryRewriter.makeSelectUnique(select, false);
projectedViewSymbols = select.getProjectedSymbols();
projectPlanNode.setProperty(NodeConstants.Info.PROJECT_COLS, projectedViewSymbols);
projectPlanNode.addGroup(group);
if (pushdown) {
while (RuleRaiseAccess.raiseAccessNode(root, originalNode, metadata, capFinder, true, null) != null) {
//continue to raise
}
}