Search in sources :

Example 26 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class RelationalPlanner method addNestedCommand.

private void addNestedCommand(PlanNode node, GroupSymbol group, Command nestedCommand, Command toPlan, boolean merge, boolean isStackEntry) throws TeiidComponentException, QueryMetadataException, TeiidProcessingException {
    if (nestedCommand instanceof QueryCommand) {
        // remove unnecessary order by
        QueryCommand queryCommand = (QueryCommand) nestedCommand;
        if (queryCommand.getLimit() == null) {
            queryCommand.setOrderBy(null);
        }
    }
    Set<PlanningStackEntry> entries = null;
    PlanningStackEntry entry = null;
    if (isStackEntry) {
        entries = planningStack.get();
        entry = createPlanningStackEntry(group, nestedCommand, toPlan.getType() == Command.TYPE_UPDATE_PROCEDURE, entries);
    }
    try {
        node.setProperty(NodeConstants.Info.NESTED_COMMAND, nestedCommand);
        if (merge) {
            mergeTempMetadata(nestedCommand, parentCommand);
            PlanNode childRoot = generatePlan(nestedCommand);
            node.addFirstChild(childRoot);
            List<Expression> projectCols = nestedCommand.getProjectedSymbols();
            SymbolMap map = SymbolMap.createSymbolMap(group, projectCols, metadata);
            node.setProperty(NodeConstants.Info.SYMBOL_MAP, map);
        } else {
            QueryMetadataInterface actualMetadata = metadata;
            if (actualMetadata instanceof TempMetadataAdapter) {
                actualMetadata = ((TempMetadataAdapter) metadata).getMetadata();
            }
            ProcessorPlan plan = QueryOptimizer.optimizePlan(toPlan, actualMetadata, idGenerator, capFinder, analysisRecord, context);
            // hack for the optimizer not knowing the containing command when forming the plan
            if (nestedCommand instanceof StoredProcedure && plan instanceof ProcedurePlan) {
                StoredProcedure container = (StoredProcedure) nestedCommand;
                ProcedurePlan pp = (ProcedurePlan) plan;
                pp.setUpdateCount(container.getUpdateCount());
                if (container.returnParameters()) {
                    List<ElementSymbol> outParams = new LinkedList<ElementSymbol>();
                    for (SPParameter param : container.getParameters()) {
                        if (param.getParameterType() == SPParameter.RETURN_VALUE) {
                            outParams.add(param.getParameterSymbol());
                        }
                    }
                    for (SPParameter param : container.getParameters()) {
                        if (param.getParameterType() == SPParameter.INOUT || param.getParameterType() == SPParameter.OUT) {
                            outParams.add(param.getParameterSymbol());
                        }
                    }
                    if (outParams.size() > 0) {
                        pp.setOutParams(outParams);
                    }
                }
                pp.setParams(container.getProcedureParameters());
            }
            node.setProperty(NodeConstants.Info.PROCESSOR_PLAN, plan);
        }
    } finally {
        if (entries != null) {
            entries.remove(entry);
        }
    }
}
Also used : TempMetadataAdapter(org.teiid.query.metadata.TempMetadataAdapter) SymbolMap(org.teiid.query.sql.util.SymbolMap) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) ProcedurePlan(org.teiid.query.processor.proc.ProcedurePlan) QueryMetadataInterface(org.teiid.query.metadata.QueryMetadataInterface) ProcessorPlan(org.teiid.query.processor.ProcessorPlan)

Example 27 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class PlanNode method getCorrelatedReferences.

public List<SymbolMap> getCorrelatedReferences() {
    List<SubqueryContainer<?>> containers = getSubqueryContainers();
    if (containers.isEmpty()) {
        return Collections.emptyList();
    }
    ArrayList<SymbolMap> result = new ArrayList<SymbolMap>(containers.size());
    for (SubqueryContainer<?> container : containers) {
        SymbolMap map = container.getCommand().getCorrelatedReferences();
        if (map != null) {
            result.add(map);
        }
    }
    return result;
}
Also used : SubqueryContainer(org.teiid.query.sql.lang.SubqueryContainer) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 28 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class RuleMergeCriteria method planQuery.

public boolean planQuery(Collection<GroupSymbol> leftGroups, boolean requireDistinct, PlannedResult plannedResult) throws QueryMetadataException, TeiidComponentException {
    if ((plannedResult.query.getLimit() != null && !plannedResult.query.getLimit().isImplicit()) || plannedResult.query.getFrom() == null) {
        return false;
    }
    if ((plannedResult.type == ExistsCriteria.class || plannedResult.type == ScalarSubquery.class) && plannedResult.query.getCorrelatedReferences() == null) {
        // TODO: do this check earlier
        return false;
    }
    plannedResult.query = (Query) plannedResult.query.clone();
    for (Command c : CommandCollectorVisitor.getCommands(plannedResult.query)) {
        // subqueries either need to be re-resolved or replanned to maintain
        // multilevel correlated references.  it's easier for now to replan
        c.setProcessorPlan(null);
    }
    plannedResult.query.setLimit(null);
    List<GroupSymbol> rightGroups = plannedResult.query.getFrom().getGroups();
    Set<Expression> requiredExpressions = new LinkedHashSet<Expression>();
    final SymbolMap refs = plannedResult.query.getCorrelatedReferences();
    boolean addGroupBy = false;
    if (refs != null) {
        boolean hasAggregates = plannedResult.query.hasAggregates();
        Criteria where = plannedResult.query.getCriteria();
        if (plannedResult.query.getGroupBy() == null) {
            plannedResult.query.setCriteria(null);
        }
        Criteria having = plannedResult.query.getHaving();
        plannedResult.query.setHaving(null);
        if (hasCorrelatedReferences(plannedResult.query, refs)) {
            return false;
        }
        if (plannedResult.query.getGroupBy() == null) {
            processCriteria(leftGroups, plannedResult, rightGroups, requiredExpressions, refs, where, null, true);
            if (hasAggregates) {
                if (!plannedResult.nonEquiJoinCriteria.isEmpty()) {
                    return false;
                }
                addGroupBy = true;
            }
        }
        processCriteria(leftGroups, plannedResult, rightGroups, requiredExpressions, refs, having, plannedResult.query.getGroupBy(), false);
    }
    if (plannedResult.additionalCritieria != null) {
        RuleChooseJoinStrategy.separateCriteria(leftGroups, rightGroups, plannedResult.leftExpressions, plannedResult.rightExpressions, Criteria.separateCriteriaByAnd(plannedResult.additionalCritieria), plannedResult.nonEquiJoinCriteria);
    }
    if (plannedResult.leftExpressions.isEmpty()) {
        return false;
    }
    plannedResult.leftExpressions = RuleChooseJoinStrategy.createExpressionSymbols(plannedResult.leftExpressions);
    plannedResult.rightExpressions = RuleChooseJoinStrategy.createExpressionSymbols(plannedResult.rightExpressions);
    if (requireDistinct && !addGroupBy) {
        // ensure that uniqueness applies to the in condition
        if (plannedResult.rightExpressions.size() > 1 && (plannedResult.type != SubquerySetCriteria.class || !isDistinct(plannedResult.query, plannedResult.rightExpressions.subList(plannedResult.rightExpressions.size() - 1, plannedResult.rightExpressions.size()), metadata))) {
            return false;
        }
        if (!isDistinct(plannedResult.query, plannedResult.rightExpressions, metadata)) {
            if (plannedResult.type == ExistsCriteria.class) {
                if (requiredExpressions.size() > plannedResult.leftExpressions.size()) {
                    // not an equi join
                    return false;
                }
            } else if (!requiredExpressions.isEmpty() && !isDistinct(plannedResult.query, plannedResult.query.getProjectedSymbols(), metadata)) {
                return false;
            }
            plannedResult.query.getSelect().setDistinct(true);
            plannedResult.madeDistinct = true;
        }
    }
    // it doesn't matter what the select columns are
    if (plannedResult.type == ExistsCriteria.class) {
        plannedResult.query.getSelect().clearSymbols();
    }
    if (addGroupBy) {
        LinkedHashSet<Expression> groupingSymbols = new LinkedHashSet<Expression>();
        for (Expression expr : (List<Expression>) plannedResult.rightExpressions) {
            AggregateSymbolCollectorVisitor.getAggregates(expr, null, groupingSymbols, null, null, null);
        }
        if (!groupingSymbols.isEmpty()) {
            plannedResult.query.setGroupBy((GroupBy) new GroupBy(new ArrayList<Expression>(groupingSymbols)).clone());
        }
    }
    HashSet<Expression> projectedSymbols = new HashSet<Expression>();
    for (Expression ses : plannedResult.query.getProjectedSymbols()) {
        projectedSymbols.add(SymbolMap.getExpression(ses));
    }
    for (Expression ses : requiredExpressions) {
        if (projectedSymbols.add(ses)) {
            plannedResult.query.getSelect().addSymbol((Expression) ses.clone());
        }
    }
    for (Expression ses : (List<Expression>) plannedResult.rightExpressions) {
        if (projectedSymbols.add(SymbolMap.getExpression(ses))) {
            plannedResult.query.getSelect().addSymbol((Expression) ses.clone());
        }
    }
    return true;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ScalarSubquery(org.teiid.query.sql.symbol.ScalarSubquery) ArrayList(java.util.ArrayList) SymbolMap(org.teiid.query.sql.util.SymbolMap) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 29 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class RulePlanJoins method execute.

/**
 * @see org.teiid.query.optimizer.relational.OptimizerRule#execute(org.teiid.query.optimizer.relational.plantree.PlanNode, org.teiid.query.metadata.QueryMetadataInterface, org.teiid.query.optimizer.capabilities.CapabilitiesFinder, org.teiid.query.optimizer.relational.RuleStack, org.teiid.query.analysis.AnalysisRecord, org.teiid.query.util.CommandContext)
 */
public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    List<JoinRegion> joinRegions = new LinkedList<JoinRegion>();
    findJoinRegions(plan, null, joinRegions);
    // dependency phase
    List<JoinRegion> leftOuterJoinRegions = new LinkedList<JoinRegion>();
    for (Iterator<JoinRegion> joinRegionIter = joinRegions.iterator(); joinRegionIter.hasNext(); ) {
        JoinRegion joinRegion = joinRegionIter.next();
        // skip regions that have nothing to plan
        if (joinRegion.getJoinSourceNodes().size() + joinRegion.getDependentJoinSourceNodes().size() < 2) {
            joinRegionIter.remove();
            if (joinRegion.getLeft() != null) {
                leftOuterJoinRegions.add(joinRegion);
            }
            continue;
        }
        joinRegion.initializeJoinInformation();
        // account for nested table correlations
        for (PlanNode joinSource : joinRegion.getJoinSourceNodes().keySet()) {
            SymbolMap map = (SymbolMap) joinSource.getProperty(NodeConstants.Info.CORRELATED_REFERENCES);
            if (map != null) {
                joinSource.setProperty(NodeConstants.Info.REQUIRED_ACCESS_PATTERN_GROUPS, GroupsUsedByElementsVisitor.getGroups(map.getValues()));
                joinRegion.setContainsNestedTable(true);
            }
        }
        // check for unsatisfied dependencies
        if (joinRegion.getUnsatisfiedAccessPatterns().isEmpty()) {
            continue;
        }
        // quick check for satisfiability
        if (!joinRegion.isSatisfiable()) {
            throw new QueryPlannerException(QueryPlugin.Event.TEIID30275, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30275, joinRegion.getUnsatisfiedAccessPatterns()));
        }
        planForDependencies(joinRegion);
    }
    // optimization phase
    for (JoinRegion joinRegion : joinRegions) {
        groupJoinsForPushing(metadata, capabilitiesFinder, joinRegion, context);
    }
    // check for optimizing across left outer joins
    for (JoinRegion joinRegion : leftOuterJoinRegions) {
        groupAcrossLeftOuter(metadata, capabilitiesFinder, context, joinRegion);
    }
    for (Iterator<JoinRegion> joinRegionIter = joinRegions.iterator(); joinRegionIter.hasNext(); ) {
        JoinRegion joinRegion = joinRegionIter.next();
        // move the dependent nodes back into all joinSources
        joinRegion.getJoinSourceNodes().putAll(joinRegion.getDependentJoinSourceNodes());
        joinRegion.getCriteriaNodes().addAll(joinRegion.getDependentCriteriaNodes());
        joinRegion.getDependentJoinSourceNodes().clear();
        joinRegion.getDependentCriteriaNodes().clear();
        if (joinRegion.getJoinSourceNodes().size() < 2) {
            joinRegion.reconstructJoinRegoin();
            joinRegionIter.remove();
            continue;
        }
        joinRegion.initializeCostingInformation(metadata);
        Object[] bestOrder = findBestJoinOrder(joinRegion, metadata, capabilitiesFinder, context);
        // if no best order was found, just stick with how the user entered the query
        if (bestOrder == null) {
            continue;
        }
        joinRegion.changeJoinOrder(bestOrder);
        joinRegion.reconstructJoinRegoin();
    }
    return plan;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) SymbolMap(org.teiid.query.sql.util.SymbolMap) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException)

Example 30 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class RulePushAggregates method collectAggregates.

/**
 * Walk up the plan from the GROUP node. Should encounter only (optionally) a SELECT and can stop at the PROJECT node. Need to
 * collect any AggregateSymbols used in the select criteria or projected columns.
 *
 * @param groupNode
 * @return the set of aggregate symbols found
 * @since 4.2
 */
static LinkedHashSet<AggregateSymbol> collectAggregates(PlanNode groupNode) {
    LinkedHashSet<AggregateSymbol> aggregates = new LinkedHashSet<AggregateSymbol>();
    PlanNode currentNode = groupNode.getParent();
    SymbolMap symbolMap = (SymbolMap) groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
    while (currentNode != null) {
        if (currentNode.getType() == NodeConstants.Types.PROJECT) {
            List<Expression> projectedSymbols = (List<Expression>) currentNode.getProperty(NodeConstants.Info.PROJECT_COLS);
            for (Expression symbol : projectedSymbols) {
                mapAggregates(ElementCollectorVisitor.getAggregates(symbol, true), symbolMap, aggregates);
            }
            break;
        }
        if (currentNode.getType() == NodeConstants.Types.SELECT) {
            Criteria crit = (Criteria) currentNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
            mapAggregates(ElementCollectorVisitor.getAggregates(crit, true), symbolMap, aggregates);
        }
        currentNode = currentNode.getParent();
    }
    return aggregates;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) SymbolMap(org.teiid.query.sql.util.SymbolMap) IsNullCriteria(org.teiid.query.sql.lang.IsNullCriteria) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria)

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