use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RelationalPlanner method getCorrelatedReferences.
private SymbolMap getCorrelatedReferences(PlanNode parent, PlanNode node, LanguageObject lo) {
PlanNode rootJoin = parent;
Set<GroupSymbol> groups = new HashSet<GroupSymbol>(rootJoin.getGroups());
while (rootJoin.getParent() != null && rootJoin.getParent().getType() == NodeConstants.Types.JOIN) {
rootJoin = rootJoin.getParent();
// accumulate groups as we go, as intermediate joins may not contribute groups to the final join
groups.addAll(rootJoin.getGroups());
}
List<Reference> correlatedReferences = new ArrayList<Reference>();
CorrelatedReferenceCollectorVisitor.collectReferences(lo, groups, correlatedReferences, metadata);
if (correlatedReferences.isEmpty()) {
return null;
}
SymbolMap map = new SymbolMap();
for (Reference reference : correlatedReferences) {
map.addMapping(reference.getExpression(), reference.getExpression());
}
node.setProperty(NodeConstants.Info.CORRELATED_REFERENCES, map);
return map;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RelationalPlanner method setCorrelatedReferences.
private void setCorrelatedReferences(SubqueryContainer<?> container, List<Reference> correlatedReferences) {
if (!correlatedReferences.isEmpty()) {
SymbolMap map = new SymbolMap();
for (Reference reference : correlatedReferences) {
map.addMapping(reference.getExpression(), reference.getExpression());
}
container.getCommand().setCorrelatedReferences(map);
}
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RuleCollapseSource method createQuery.
private QueryCommand createQuery(CommandContext context, CapabilitiesFinder capFinder, PlanNode accessRoot, PlanNode node) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
QueryMetadataInterface metadata = context.getMetadata();
PlanNode setOpNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.SET_OP, NodeConstants.Types.SOURCE);
Object modelID = RuleRaiseAccess.getModelIDFromAccess(accessRoot, metadata);
if (setOpNode != null) {
Operation setOp = (Operation) setOpNode.getProperty(NodeConstants.Info.SET_OPERATION);
SetQuery unionCommand = new SetQuery(setOp);
boolean unionAll = ((Boolean) setOpNode.getProperty(NodeConstants.Info.USE_ALL)).booleanValue();
unionCommand.setAll(unionAll);
int count = 0;
OrderBy orderBy = null;
PlanNode sort = NodeEditor.findNodePreOrder(node, NodeConstants.Types.SORT, NodeConstants.Types.SET_OP);
if (sort != null) {
processOrderBy(sort, unionCommand, modelID, context, capFinder);
orderBy = unionCommand.getOrderBy();
unionCommand.setOrderBy(null);
// we have to remap if the primary projection is from a grouping
PlanNode groupNode = NodeEditor.findNodePreOrder(setOpNode.getFirstChild(), NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE);
if (groupNode != null) {
SymbolMap symbolMap = (SymbolMap) groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
ExpressionMappingVisitor.mapExpressions(orderBy, symbolMap.asMap(), true);
}
}
for (PlanNode child : setOpNode.getChildren()) {
QueryCommand command = createQuery(context, capFinder, accessRoot, child);
if (count == 0) {
unionCommand.setLeftQuery(command);
} else if (count == 1) {
unionCommand.setRightQuery(command);
} else {
unionCommand = new SetQuery(setOp, unionAll, unionCommand, command);
}
count++;
}
PlanNode limit = NodeEditor.findNodePreOrder(node, NodeConstants.Types.TUPLE_LIMIT, NodeConstants.Types.SET_OP);
if (limit != null) {
processLimit(limit, unionCommand, metadata);
}
unionCommand.setOrderBy(orderBy);
return unionCommand;
}
Query query = new Query();
Select select = new Select();
List<Expression> columns = (List<Expression>) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
prepareSubqueries(ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(columns));
select.addSymbols(columns);
query.setSelect(select);
query.setFrom(new From());
buildQuery(accessRoot, node, query, context, capFinder);
if (!CapabilitiesUtil.useAnsiJoin(modelID, metadata, capFinder)) {
simplifyFromClause(query);
}
if (query.getCriteria() instanceof CompoundCriteria) {
query.setCriteria(QueryRewriter.optimizeCriteria((CompoundCriteria) query.getCriteria(), metadata));
}
if (columns.isEmpty()) {
if (CapabilitiesUtil.supports(Capability.QUERY_SELECT_EXPRESSION, modelID, metadata, capFinder)) {
// $NON-NLS-1$
select.addSymbol(new ExpressionSymbol("dummy", new Constant(1)));
} else {
// TODO: need to ensure the type is consistent
// - should be rare as the source would typically support select expression if it supports union
select.addSymbol(selectOutputElement(query.getFrom().getGroups(), metadata));
}
}
PlanNode groupNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE);
if (groupNode != null) {
if (query.getOrderBy() != null) {
query.setOrderBy(query.getOrderBy().clone());
}
if (query.getHaving() != null) {
query.setHaving((Criteria) query.getHaving().clone());
}
query.setSelect(query.getSelect().clone());
SymbolMap symbolMap = (SymbolMap) groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
// map back to expression form
ExpressionMappingVisitor.mapExpressions(query.getOrderBy(), symbolMap.asMap(), true);
ExpressionMappingVisitor.mapExpressions(query.getSelect(), symbolMap.asMap(), true);
ExpressionMappingVisitor.mapExpressions(query.getHaving(), symbolMap.asMap(), true);
if (query.getHaving() != null && !CapabilitiesUtil.supports(Capability.QUERY_HAVING, modelID, metadata, capFinder)) {
Select sel = query.getSelect();
GroupBy groupBy = query.getGroupBy();
Criteria having = query.getHaving();
query.setHaving(null);
OrderBy orderBy = query.getOrderBy();
query.setOrderBy(null);
Limit limit = query.getLimit();
query.setLimit(null);
Set<AggregateSymbol> aggs = new HashSet<AggregateSymbol>();
aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(having, true));
Set<Expression> expr = new HashSet<Expression>();
for (Expression ex : sel.getProjectedSymbols()) {
Expression selectExpression = SymbolMap.getExpression(ex);
aggs.remove(selectExpression);
expr.add(selectExpression);
}
int originalSelect = sel.getSymbols().size();
sel.addSymbols(aggs);
if (groupBy != null) {
for (Expression ex : groupBy.getSymbols()) {
ex = SymbolMap.getExpression(ex);
if (expr.add(ex)) {
sel.addSymbol(ex);
}
}
}
Query outerQuery = null;
try {
// $NON-NLS-1$
outerQuery = QueryRewriter.createInlineViewQuery(new GroupSymbol("X"), query, metadata, query.getSelect().getProjectedSymbols());
} catch (TeiidException err) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30257, err);
}
Iterator<Expression> iter = outerQuery.getSelect().getProjectedSymbols().iterator();
HashMap<Expression, Expression> expressionMap = new HashMap<Expression, Expression>();
for (Expression symbol : query.getSelect().getProjectedSymbols()) {
// need to unwrap on both sides as the select expression could be aliased
// TODO: could add an option to createInlineViewQuery to disable alias creation
expressionMap.put(SymbolMap.getExpression(symbol), SymbolMap.getExpression(iter.next()));
}
ExpressionMappingVisitor.mapExpressions(having, expressionMap, true);
outerQuery.setCriteria(having);
ExpressionMappingVisitor.mapExpressions(orderBy, expressionMap, true);
outerQuery.setOrderBy(orderBy);
outerQuery.setLimit(limit);
ExpressionMappingVisitor.mapExpressions(select, expressionMap, true);
outerQuery.getSelect().setSymbols(outerQuery.getSelect().getProjectedSymbols().subList(0, originalSelect));
outerQuery.setOption(query.getOption());
query = outerQuery;
}
if (query.getGroupBy() != null) {
// we check for group by expressions here to create an ANSI SQL plan
boolean hasExpression = false;
boolean hasLiteral = false;
for (final Iterator<Expression> iterator = query.getGroupBy().getSymbols().iterator(); iterator.hasNext(); ) {
Expression ex = iterator.next();
hasExpression |= !(ex instanceof ElementSymbol);
hasLiteral |= EvaluatableVisitor.willBecomeConstant(ex, true);
}
if ((hasExpression && !CapabilitiesUtil.supports(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, modelID, metadata, capFinder)) || hasLiteral) {
// if group by expressions are not support, add an inline view to compensate
query = RuleCollapseSource.rewriteGroupByAsView(query, metadata, false);
if (query.getHaving() != null) {
// dependent sets will have been added a having
List<Criteria> crits = Criteria.separateCriteriaByAnd(query.getHaving());
for (Iterator<Criteria> iter = crits.iterator(); iter.hasNext(); ) {
Criteria crit = iter.next();
if (crit instanceof DependentSetCriteria) {
query.setCriteria(Criteria.combineCriteria(query.getCriteria(), crit));
iter.remove();
}
}
query.setHaving(Criteria.combineCriteria(crits));
}
}
if (query.getOrderBy() != null && groupNode.hasBooleanProperty(Info.ROLLUP) && !CapabilitiesUtil.supports(Capability.QUERY_ORDERBY_EXTENDED_GROUPING, modelID, metadata, capFinder)) {
// if ordering is not directly supported over extended grouping, add an inline view to compensate
query = RuleCollapseSource.rewriteGroupByAsView(query, metadata, true);
}
}
}
return query;
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RuleCollapseSource method prepareSubquery.
public static void prepareSubquery(SubqueryContainer container) {
RelationalPlan subqueryPlan = (RelationalPlan) container.getCommand().getProcessorPlan();
AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(subqueryPlan);
QueryCommand command = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
if (command == null) {
return;
}
final SymbolMap map = container.getCommand().getCorrelatedReferences();
if (map != null) {
ExpressionMappingVisitor visitor = new RuleMergeCriteria.ReferenceReplacementVisitor(map);
DeepPostOrderNavigator.doVisit(command, visitor);
}
command.setProcessorPlan(container.getCommand().getProcessorPlan());
boolean removeLimit = false;
if (container instanceof ExistsCriteria) {
removeLimit = !((ExistsCriteria) container).shouldEvaluate();
} else if (container instanceof ScalarSubquery) {
removeLimit = !((ScalarSubquery) container).shouldEvaluate();
}
if (removeLimit && command.getLimit() != null && command.getLimit().isImplicit()) {
command.setLimit(null);
}
container.setCommand(command);
}
use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.
the class RuleDecomposeJoin method rebuild.
/**
* Add the new union back in under a view
*/
static PlanNode rebuild(GroupSymbol group, PlanNode toReplace, PlanNode newUnion, QueryMetadataInterface metadata, CommandContext context, PlanNode... toMap) throws TeiidComponentException, QueryPlannerException, QueryMetadataException {
Set<String> groups = context.getGroups();
group = RulePlaceAccess.recontextSymbol(group, groups);
PlanNode projectNode = NodeEditor.findNodePreOrder(newUnion, NodeConstants.Types.PROJECT);
List<? extends Expression> projectedSymbols = (List<? extends Expression>) projectNode.getProperty(Info.PROJECT_COLS);
SymbolMap newSymbolMap = RulePushAggregates.createSymbolMap(group, projectedSymbols, newUnion, metadata);
PlanNode view = RuleDecomposeJoin.createSource(group, newUnion, newSymbolMap);
Map<Expression, ElementSymbol> inverseMap = newSymbolMap.inserseMapping();
if (toReplace != null) {
toReplace.getParent().replaceChild(toReplace, view);
}
Set<GroupSymbol> newGroups = Collections.singleton(group);
for (PlanNode node : toMap) {
FrameUtil.convertFrame(view, node.getGroups().iterator().next(), newGroups, inverseMap, metadata);
}
return view;
}
Aggregations