Search in sources :

Example 6 with AccessNode

use of org.teiid.query.processor.relational.AccessNode in project teiid by teiid.

the class RelationalPlanner method isPushdownValid.

private boolean isPushdownValid(WithQueryCommand with, SetQuery setQuery, Object modelID, QueryCommand withCommand, RelationalPlan subPlan1) throws QueryMetadataException, TeiidComponentException {
    AccessNode aNode1 = CriteriaCapabilityValidatorVisitor.getAccessNode(subPlan1);
    if (aNode1 == null) {
        return false;
    }
    Object modelID1 = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode1, false);
    QueryCommand withCommand1 = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode1);
    if (modelID1 == null || withCommand1 == null) {
        return false;
    }
    // if we are the same connector for each, then we should be good to proceed
    if (CapabilitiesUtil.isSameConnector(modelID, modelID1, metadata, capFinder)) {
        SetQuery pushdownSetQuery = new SetQuery(Operation.UNION, setQuery.isAll(), withCommand, withCommand1);
        WithQueryCommand wqc = new WithQueryCommand(with.getGroupSymbol(), with.getColumns(), pushdownSetQuery);
        wqc.setRecursive(true);
        this.withPlanningState.pushdownWith.put(with.getGroupSymbol().getName(), wqc);
        return true;
    }
    return false;
}
Also used : LanguageObject(org.teiid.query.sql.LanguageObject) AccessNode(org.teiid.query.processor.relational.AccessNode)

Example 7 with AccessNode

use of org.teiid.query.processor.relational.AccessNode in project teiid by teiid.

the class RelationalPlanner method assignWithClause.

private void assignWithClause(RelationalNode node, LinkedHashMap<String, WithQueryCommand> pushdownWith, boolean repeated) throws QueryPlannerException, TeiidComponentException {
    List<SubqueryContainer<?>> subCommands = new ArrayList<SubqueryContainer<?>>();
    if (node instanceof SubqueryAwareRelationalNode) {
        for (LanguageObject lo : ((SubqueryAwareRelationalNode) node).getObjects()) {
            ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(lo, subCommands);
            if (!subCommands.isEmpty()) {
                for (SubqueryContainer<?> subquery : subCommands) {
                    if (subquery.getCommand().getProcessorPlan() instanceof RelationalPlan) {
                        assignWithClause(((RelationalPlan) subquery.getCommand().getProcessorPlan()).getRootNode(), pushdownWith, repeated | (subquery.getCommand().getCorrelatedReferences() != null && !subquery.getCommand().getCorrelatedReferences().asMap().isEmpty()));
                    }
                }
                subCommands.clear();
            }
        }
    }
    if (node instanceof PlanExecutionNode) {
        // need to check for nested relational plans.  these are created by things such as the semi-join optimization in rulemergevirtual
        ProcessorPlan plan = ((PlanExecutionNode) node).getProcessorPlan();
        if (plan instanceof RelationalPlan) {
            // other types of plans will be contained under non-relational plans, which would be out of scope for the parent with
            node = ((RelationalPlan) plan).getRootNode();
        }
    }
    if (node instanceof AccessNode) {
        AccessNode accessNode = (AccessNode) node;
        Map<GroupSymbol, RelationalPlan> subplans = accessNode.getSubPlans();
        if (subplans != null) {
            for (RelationalPlan subplan : subplans.values()) {
                assignWithClause(subplan.getRootNode(), pushdownWith, false);
            }
        }
        Command command = accessNode.getCommand();
        if (command instanceof Insert && ((Insert) command).getQueryExpression() != null) {
            command = ((Insert) command).getQueryExpression();
        }
        if (command instanceof QueryCommand) {
            if (this.withGroups == null) {
                this.withGroups = new TreeSet<GroupSymbol>(nonCorrelatedComparator);
            } else {
                this.withGroups.clear();
            }
            GroupCollectorVisitor.getGroupsIgnoreInlineViewsAndEvaluatableSubqueries(command, this.withGroups);
            List<WithQueryCommand> with = new ArrayList<WithQueryCommand>();
            discoverWith(pushdownWith, command, with, new ArrayList<GroupSymbol>(this.withGroups));
            if (!with.isEmpty()) {
                List<WithQueryCommand> pushed = new ArrayList<WithQueryCommand>(with);
                final Map<GroupSymbol, Integer> order = new HashMap<GroupSymbol, Integer>();
                for (WithQueryCommand withQueryCommand : pushdownWith.values()) {
                    order.put(withQueryCommand.getGroupSymbol(), order.size());
                }
                Collections.sort(with, new Comparator<WithQueryCommand>() {

                    @Override
                    public int compare(WithQueryCommand o1, WithQueryCommand o2) {
                        return order.get(o1.getGroupSymbol()).compareTo(order.get(o2.getGroupSymbol()));
                    }
                });
                // pull up the with from the subqueries
                for (int i = 0; i < with.size(); i++) {
                    WithQueryCommand wqc = with.get(i);
                    List<WithQueryCommand> with2 = wqc.getCommand().getWith();
                    if (with2 != null) {
                        with.addAll(i, with2);
                        i += with2.size();
                        wqc.getCommand().setWith(null);
                    }
                }
                QueryCommand query = (QueryCommand) command;
                List<SubqueryContainer<?>> subqueries = ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(query);
                this.withGroups.clear();
                for (WithQueryCommand wqc : with) {
                    withGroups.add(wqc.getGroupSymbol());
                }
                pullupWith(with, subqueries, withGroups);
                if (query.getWith() != null) {
                    // we need to accumulate as a with clause could have been used at a lower scope
                    query.getWith().addAll(with);
                } else {
                    query.setWith(with);
                }
                for (WithQueryCommand wqc : pushed) {
                    Object o = this.withPlanningState.pushdownState.get(wqc.getGroupSymbol().getName());
                    if (o == null) {
                        if (!repeated) {
                            if (accessNode.info != null) {
                                o = accessNode.info.id;
                            } else {
                                o = Boolean.FALSE;
                            }
                        } else {
                            o = Boolean.TRUE;
                        }
                    } else if (o instanceof Integer) {
                        // check for shared
                        if (accessNode.info == null || !o.equals(accessNode.info.id)) {
                            o = Boolean.TRUE;
                        }
                    } else {
                        o = Boolean.TRUE;
                    }
                    this.withPlanningState.pushdownState.put(wqc.getGroupSymbol().getName(), o);
                }
                // TODO: this should be based upon whether any of the need evaluated
                accessNode.setShouldEvaluateExpressions(true);
            }
        }
    }
    // Recurse through children
    RelationalNode[] children = node.getChildren();
    for (int i = 0; i < node.getChildCount(); i++) {
        assignWithClause(children[i], pushdownWith, repeated);
    }
}
Also used : RelationalPlan(org.teiid.query.processor.relational.RelationalPlan) PlanExecutionNode(org.teiid.query.processor.relational.PlanExecutionNode) AccessNode(org.teiid.query.processor.relational.AccessNode) SubqueryAwareRelationalNode(org.teiid.query.processor.relational.SubqueryAwareRelationalNode) SubqueryAwareRelationalNode(org.teiid.query.processor.relational.SubqueryAwareRelationalNode) RelationalNode(org.teiid.query.processor.relational.RelationalNode) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) LanguageObject(org.teiid.query.sql.LanguageObject) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) LanguageObject(org.teiid.query.sql.LanguageObject)

Example 8 with AccessNode

use of org.teiid.query.processor.relational.AccessNode 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 9 with AccessNode

use of org.teiid.query.processor.relational.AccessNode in project teiid by teiid.

the class CriteriaCapabilityValidatorVisitor method getAccessNode.

public static AccessNode getAccessNode(ProcessorPlan plan) {
    if (!(plan instanceof RelationalPlan)) {
        return null;
    }
    RelationalPlan rplan = (RelationalPlan) plan;
    // Check that the plan is just an access node
    RelationalNode accessNode = rplan.getRootNode();
    if (accessNode instanceof LimitNode) {
        LimitNode ln = (LimitNode) accessNode;
        if (!ln.isImplicit()) {
            return null;
        }
        accessNode = ln.getChildren()[0];
    }
    if (!(accessNode instanceof AccessNode)) {
        return null;
    }
    return (AccessNode) accessNode;
}
Also used : RelationalNode(org.teiid.query.processor.relational.RelationalNode) LimitNode(org.teiid.query.processor.relational.LimitNode) AccessNode(org.teiid.query.processor.relational.AccessNode) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan)

Example 10 with AccessNode

use of org.teiid.query.processor.relational.AccessNode in project teiid by teiid.

the class CriteriaCapabilityValidatorVisitor method validateSubqueryPushdown.

/**
 * Return null if the subquery cannot be pushed down, otherwise the model
 * id of the pushdown target.
 * @param subqueryContainer
 * @param critNodeModelID
 * @param metadata
 * @param capFinder
 * @return
 * @throws TeiidComponentException
 */
public static Object validateSubqueryPushdown(SubqueryContainer<?> subqueryContainer, Object critNodeModelID, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord) throws TeiidComponentException {
    ProcessorPlan plan = subqueryContainer.getCommand().getProcessorPlan();
    if (plan != null) {
        AccessNode aNode = getAccessNode(plan);
        if (aNode == null) {
            return null;
        }
        critNodeModelID = validateCommandPushdown(critNodeModelID, metadata, capFinder, aNode, true);
    }
    if (critNodeModelID == null) {
        return null;
    }
    // Check whether source supports correlated subqueries and if not, whether criteria has them
    SymbolMap refs = subqueryContainer.getCommand().getCorrelatedReferences();
    try {
        if (refs != null && !refs.asMap().isEmpty()) {
            if (!CapabilitiesUtil.supports(Capability.QUERY_SUBQUERIES_CORRELATED, critNodeModelID, metadata, capFinder)) {
                return null;
            }
            if (!CapabilitiesUtil.supports(Capability.SUBQUERY_CORRELATED_LIMIT, critNodeModelID, metadata, capFinder)) {
                QueryCommand command = (QueryCommand) subqueryContainer.getCommand();
                if (command.getLimit() != null && !command.getLimit().isImplicit()) {
                    return null;
                }
            }
            // but this is only an issue with deeply nested subqueries
            if (!CriteriaCapabilityValidatorVisitor.canPushLanguageObject(subqueryContainer.getCommand(), critNodeModelID, metadata, capFinder, analysisRecord)) {
                return null;
            }
        } else if (CapabilitiesUtil.supports(Capability.QUERY_SUBQUERIES_ONLY_CORRELATED, critNodeModelID, metadata, capFinder)) {
            return null;
        }
    } catch (QueryMetadataException e) {
        throw new TeiidComponentException(QueryPlugin.Event.TEIID30271, e);
    }
    if (!CapabilitiesUtil.supports(Capability.SUBQUERY_COMMON_TABLE_EXPRESSIONS, critNodeModelID, metadata, capFinder) && subqueryContainer.getCommand() instanceof QueryCommand) {
        QueryCommand command = (QueryCommand) subqueryContainer.getCommand();
        if (command.getWith() != null) {
            return null;
        }
    }
    // Found no reason why this node is not eligible
    return critNodeModelID;
}
Also used : SymbolMap(org.teiid.query.sql.util.SymbolMap) TeiidComponentException(org.teiid.core.TeiidComponentException) AccessNode(org.teiid.query.processor.relational.AccessNode) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException)

Aggregations

AccessNode (org.teiid.query.processor.relational.AccessNode)12 RelationalPlan (org.teiid.query.processor.relational.RelationalPlan)8 RelationalNode (org.teiid.query.processor.relational.RelationalNode)4 LanguageObject (org.teiid.query.sql.LanguageObject)4 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)3 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)3 SymbolMap (org.teiid.query.sql.util.SymbolMap)3 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)2 TeiidProcessingException (org.teiid.core.TeiidProcessingException)2 TempMetadataID (org.teiid.query.metadata.TempMetadataID)2 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)2 SubqueryAwareRelationalNode (org.teiid.query.processor.relational.SubqueryAwareRelationalNode)2 Command (org.teiid.query.sql.lang.Command)2 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Set (java.util.Set)1 Test (org.junit.Test)1 QueryMetadataException (org.teiid.api.exception.query.QueryMetadataException)1