Search in sources :

Example 11 with QueryPlannerException

use of org.teiid.api.exception.query.QueryPlannerException in project teiid by teiid.

the class RelationalPlanner method optimize.

public RelationalPlan optimize(Command command) throws QueryPlannerException, QueryMetadataException, TeiidComponentException, QueryResolverException {
    boolean debug = analysisRecord.recordDebug();
    if (debug) {
        // $NON-NLS-1$
        analysisRecord.println("\n----------------------------------------------------------------------------");
        // $NON-NLS-1$
        analysisRecord.println("GENERATE CANONICAL: \n" + command);
    }
    SourceHint previous = this.sourceHint;
    this.sourceHint = SourceHint.combine(previous, command.getSourceHint());
    PlanToProcessConverter planToProcessConverter = new PlanToProcessConverter(metadata, idGenerator, analysisRecord, capFinder, context);
    WithPlanningState saved = this.withPlanningState;
    this.withPlanningState = new WithPlanningState();
    Command original = (Command) command.clone();
    PlanNode plan;
    try {
        plan = generatePlan(command);
    } catch (TeiidProcessingException e) {
        throw new QueryPlannerException(e);
    }
    planWith(plan, command);
    if (plan.getType() == NodeConstants.Types.SOURCE) {
        // this was effectively a rewrite
        return (RelationalPlan) plan.getProperty(Info.PROCESSOR_PLAN);
    }
    if (debug) {
        // $NON-NLS-1$
        analysisRecord.println("\nCANONICAL PLAN: \n" + plan);
    }
    // Connect ProcessorPlan to SubqueryContainer (if any) of SELECT or PROJECT nodes
    // TODO: merge with node creation
    connectSubqueryContainers(plan);
    // Set top column information on top node
    List<Expression> topCols = Util.deepClone(command.getProjectedSymbols(), Expression.class);
    // Build rule set based on hints
    RuleStack rules = buildRules();
    // Run rule-based optimizer
    plan = executeRules(rules, plan);
    RelationalPlan result = planToProcessConverter.convert(plan);
    boolean fullPushdown = false;
    if (!this.withPlanningState.pushdownWith.isEmpty()) {
        AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(result);
        if (aNode != null) {
            QueryCommand queryCommand = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
            if (queryCommand != null) {
                fullPushdown = true;
                for (SubqueryContainer<?> container : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(queryCommand)) {
                    if (container instanceof Evaluatable<?> && ((Evaluatable<?>) container).shouldEvaluate()) {
                        // we could more deeply check, but we'll just assume that the references are needed
                        fullPushdown = false;
                        break;
                    }
                }
            }
        }
        // distribute the appropriate clauses to the pushdowns
        assignWithClause(result.getRootNode(), this.withPlanningState.pushdownWith, false);
        List<String> toReplan = new ArrayList<String>();
        for (Map.Entry<String, Object> entry : this.withPlanningState.pushdownState.entrySet()) {
            if (Boolean.TRUE.equals(entry.getValue())) {
                GroupSymbol gs = this.withPlanningState.pushdownWith.get(entry.getKey()).getGroupSymbol();
                TempMetadataID tmi = (TempMetadataID) gs.getMetadataID();
                tmi.getTableData().setModel(TempMetadataAdapter.TEMP_MODEL);
                toReplan.add(entry.getKey());
            }
        }
        if (!toReplan.isEmpty()) {
            for (WithQueryCommand wqc : this.withPlanningState.withList.values()) {
                this.context.getGroups().remove(wqc.getGroupSymbol().getName());
            }
            this.sourceHint = previous;
            this.withPlanningState = saved;
            if (debug) {
                // $NON-NLS-1$ //$NON-NLS-2$
                analysisRecord.println("\nReplanning due to multiple common table references: " + toReplan + "\n");
            }
            return optimize(original);
        }
    }
    if (!fullPushdown && !this.withPlanningState.withList.isEmpty()) {
        // generally any with item associated with a pushdown will not be needed as we're converting to a source query
        result.setWith(new ArrayList<WithQueryCommand>(this.withPlanningState.withList.values()));
        // assign any with clauses in this subplan
        for (WithQueryCommand wqc : this.withPlanningState.withList.values()) {
            if (wqc.isRecursive()) {
                SetQuery sq = (SetQuery) wqc.getCommand();
                assignWithClause(((RelationalPlan) sq.getLeftQuery().getProcessorPlan()).getRootNode(), this.withPlanningState.pushdownWith, false);
                assignWithClause(((RelationalPlan) sq.getRightQuery().getProcessorPlan()).getRootNode(), this.withPlanningState.pushdownWith, false);
            } else {
                assignWithClause(((RelationalPlan) wqc.getCommand().getProcessorPlan()).getRootNode(), this.withPlanningState.pushdownWith, false);
            }
        }
    }
    result.setOutputElements(topCols);
    this.sourceHint = previous;
    this.withPlanningState = saved;
    return result;
}
Also used : RelationalPlan(org.teiid.query.processor.relational.RelationalPlan) TeiidProcessingException(org.teiid.core.TeiidProcessingException) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) AccessNode(org.teiid.query.processor.relational.AccessNode) TempMetadataID(org.teiid.query.metadata.TempMetadataID) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) LanguageObject(org.teiid.query.sql.LanguageObject) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 12 with QueryPlannerException

use of org.teiid.api.exception.query.QueryPlannerException in project teiid by teiid.

the class RelationalPlanner method planSubqueries.

private void planSubqueries(ProcedureContainer container, Command c, List<SubqueryContainer<?>> subqueries, boolean initial) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    boolean isSourceTemp = c == null && container.getGroup().isTempTable() && metadata.getModelID(container.getGroup().getMetadataID()) == TempMetadataAdapter.TEMP_MODEL;
    for (SubqueryContainer<?> subqueryContainer : subqueries) {
        if (isSourceTemp) {
            if (subqueryContainer.getCommand().getCorrelatedReferences() == null) {
                if (subqueryContainer instanceof ScalarSubquery) {
                    ((ScalarSubquery) subqueryContainer).setShouldEvaluate(true);
                } else if (subqueryContainer instanceof ExistsCriteria) {
                    ((ExistsCriteria) subqueryContainer).setShouldEvaluate(true);
                } else {
                    throw new QueryPlannerException(QueryPlugin.Event.TEIID30253, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30253, container));
                }
            } else {
                throw new QueryPlannerException(QueryPlugin.Event.TEIID30253, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30253, container));
            }
        }
        if (subqueryContainer.getCommand().getProcessorPlan() == null) {
            Command subCommand = initial ? (Command) subqueryContainer.getCommand().clone() : subqueryContainer.getCommand();
            ProcessorPlan plan = QueryOptimizer.optimizePlan(subCommand, metadata, null, capFinder, analysisRecord, context);
            subqueryContainer.getCommand().setProcessorPlan(plan);
        }
        if (c == null && !initial) {
            RuleCollapseSource.prepareSubquery(subqueryContainer);
        }
    }
}
Also used : CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException)

Example 13 with QueryPlannerException

use of org.teiid.api.exception.query.QueryPlannerException in project teiid by teiid.

the class AliasGenerator method recontextGroup.

/**
 * @param symbol
 */
private String recontextGroup(GroupSymbol symbol, boolean virtual) {
    String newAlias = null;
    while (true) {
        if (virtual) {
            newAlias = view_prefix + viewIndex++;
        } else {
            newAlias = table_prefix + groupIndex++;
        }
        if (correlationGroups == null || !correlationGroups.contains(newAlias)) {
            break;
        }
    }
    if (this.aliasMapping != null && symbol.getDefinition() != null) {
        String oldAlias = this.aliasMapping.get(symbol.getName());
        if (oldAlias != null) {
            newAlias = oldAlias;
            if (newAlias.startsWith(table_prefix) || newAlias.startsWith(view_prefix)) {
                try {
                    Integer.parseInt(newAlias.substring(2, newAlias.length()));
                    throw new TeiidRuntimeException(new QueryPlannerException(QueryPlugin.Event.TEIID31127, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31127, newAlias)));
                } catch (NumberFormatException e) {
                }
            }
        }
    }
    visitor.namingContext.groupNames.put(symbol.getName(), newAlias);
    return newAlias;
}
Also used : TeiidRuntimeException(org.teiid.core.TeiidRuntimeException) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException)

Example 14 with QueryPlannerException

use of org.teiid.api.exception.query.QueryPlannerException 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 15 with QueryPlannerException

use of org.teiid.api.exception.query.QueryPlannerException in project teiid by teiid.

the class RulePlanJoins method planForDependencies.

/**
 * Greedily choose the first set of access patterns that can be satisfied
 * TODO: this is greedy.  the first access pattern that can be satisfied will be
 * TODO: order access patterns by number of dependent groups
 *
 * If we could flatten to a single set of dependencies, then a topological sort would be faster
 *
 * @param joinRegion
 * @throws QueryPlannerException
 */
private void planForDependencies(JoinRegion joinRegion) throws QueryPlannerException {
    if (joinRegion.getJoinSourceNodes().isEmpty()) {
        throw new QueryPlannerException(QueryPlugin.Event.TEIID30275, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30275, joinRegion.getUnsatisfiedAccessPatterns()));
    }
    HashSet<GroupSymbol> currentGroups = new HashSet<GroupSymbol>();
    for (PlanNode joinSource : joinRegion.getJoinSourceNodes().keySet()) {
        currentGroups.addAll(joinSource.getGroups());
    }
    HashMap<PlanNode, PlanNode> dependentNodes = new HashMap<PlanNode, PlanNode>(joinRegion.getDependentJoinSourceNodes());
    boolean satisfiedAP = true;
    while (!dependentNodes.isEmpty() && satisfiedAP) {
        satisfiedAP = false;
        for (Iterator<Map.Entry<PlanNode, PlanNode>> joinSources = dependentNodes.entrySet().iterator(); joinSources.hasNext(); ) {
            Map.Entry<PlanNode, PlanNode> entry = joinSources.next();
            PlanNode joinSource = entry.getKey();
            Collection accessPatterns = (Collection) joinSource.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
            for (Iterator i = accessPatterns.iterator(); i.hasNext(); ) {
                AccessPattern ap = (AccessPattern) i.next();
                boolean foundGroups = true;
                HashSet<GroupSymbol> allRequiredGroups = new HashSet<GroupSymbol>();
                for (ElementSymbol symbol : ap.getUnsatisfied()) {
                    Set<Collection<GroupSymbol>> requiredGroupsSet = joinRegion.getDependentCriteriaElements().get(symbol);
                    boolean elementSatisfied = false;
                    if (requiredGroupsSet != null) {
                        for (Collection<GroupSymbol> requiredGroups : requiredGroupsSet) {
                            if (currentGroups.containsAll(requiredGroups)) {
                                elementSatisfied = true;
                                allRequiredGroups.addAll(requiredGroups);
                                break;
                            }
                        }
                    }
                    if (!elementSatisfied) {
                        foundGroups = false;
                        break;
                    }
                }
                if (!foundGroups) {
                    continue;
                }
                joinSources.remove();
                currentGroups.addAll(joinSource.getGroups());
                satisfiedAP = true;
                joinSource.setProperty(NodeConstants.Info.ACCESS_PATTERN_USED, ap.clone());
                joinSource.setProperty(NodeConstants.Info.REQUIRED_ACCESS_PATTERN_GROUPS, allRequiredGroups);
                break;
            }
        }
    }
    if (!dependentNodes.isEmpty()) {
        throw new QueryPlannerException(QueryPlugin.Event.TEIID30275, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30275, joinRegion.getUnsatisfiedAccessPatterns()));
    }
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) AccessPattern(org.teiid.query.resolver.util.AccessPattern) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Aggregations

QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)27 TeiidProcessingException (org.teiid.core.TeiidProcessingException)11 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)11 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)11 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)8 Expression (org.teiid.query.sql.symbol.Expression)8 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)8 SymbolMap (org.teiid.query.sql.util.SymbolMap)8 TeiidRuntimeException (org.teiid.core.TeiidRuntimeException)6 QueryMetadataException (org.teiid.api.exception.query.QueryMetadataException)5 TempMetadataID (org.teiid.query.metadata.TempMetadataID)5 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)5 ArrayList (java.util.ArrayList)4 TeiidComponentException (org.teiid.core.TeiidComponentException)4 Criteria (org.teiid.query.sql.lang.Criteria)4 HashSet (java.util.HashSet)3 List (java.util.List)3 AnalysisRecord (org.teiid.query.analysis.AnalysisRecord)3 RelationalPlan (org.teiid.query.processor.relational.RelationalPlan)3 HashMap (java.util.HashMap)2