Search in sources :

Example 36 with SymbolMap

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;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 37 with SymbolMap

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);
    }
}
Also used : SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 38 with SymbolMap

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;
}
Also used : HashMap(java.util.HashMap) Operation(org.teiid.query.sql.lang.SetQuery.Operation) TeiidRuntimeException(org.teiid.core.TeiidRuntimeException) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) List(java.util.List) ArrayList(java.util.ArrayList) QueryMetadataInterface(org.teiid.query.metadata.QueryMetadataInterface) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) SymbolMap(org.teiid.query.sql.util.SymbolMap) TeiidException(org.teiid.core.TeiidException)

Example 39 with SymbolMap

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);
}
Also used : SymbolMap(org.teiid.query.sql.util.SymbolMap) AccessNode(org.teiid.query.processor.relational.AccessNode) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan) ExpressionMappingVisitor(org.teiid.query.sql.visitor.ExpressionMappingVisitor)

Example 40 with SymbolMap

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;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Aggregations

SymbolMap (org.teiid.query.sql.util.SymbolMap)56 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)37 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)28 Expression (org.teiid.query.sql.symbol.Expression)28 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)21 ArrayList (java.util.ArrayList)16 List (java.util.List)15 Criteria (org.teiid.query.sql.lang.Criteria)10 LinkedList (java.util.LinkedList)8 Map (java.util.Map)8 HashMap (java.util.HashMap)6 Constant (org.teiid.query.sql.symbol.Constant)6 LinkedHashSet (java.util.LinkedHashSet)5 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)5 CompareCriteria (org.teiid.query.sql.lang.CompareCriteria)5 OrderBy (org.teiid.query.sql.lang.OrderBy)5 HashSet (java.util.HashSet)4 ExpressionMappingVisitor (org.teiid.query.sql.visitor.ExpressionMappingVisitor)4 LinkedHashMap (java.util.LinkedHashMap)3 Set (java.util.Set)3