Search in sources :

Example 6 with RelationalNode

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

the class RelationalPlanner method planWith.

private void planWith(PlanNode plan, Command command) throws QueryPlannerException, QueryMetadataException, TeiidComponentException, QueryResolverException {
    if (this.withPlanningState.withList.isEmpty()) {
        return;
    }
    // TODO: merge this logic inline with the main rule execution.
    RuleStack stack = new RuleStack();
    stack.push(new RuleAssignOutputElements(false));
    if (hints.hasRowBasedSecurity) {
        stack.push(new RuleApplySecurity());
    }
    // use a temporary planner to run just the assign output elements
    RelationalPlanner planner = new RelationalPlanner();
    // we don't want to trigger the with processing for just projection
    planner.processWith = false;
    planner.initialize(command, idGenerator, metadata, capFinder, analysisRecord, context);
    planner.executeRules(stack, plan);
    // discover all of the usage
    List<Command> commands = CommandCollectorVisitor.getCommands(command, true);
    while (!commands.isEmpty()) {
        Command cmd = commands.remove(commands.size() - 1);
        commands.addAll(CommandCollectorVisitor.getCommands(cmd, true));
        try {
            PlanNode temp = planner.generatePlan((Command) cmd.clone());
            stack.push(new RuleAssignOutputElements(false));
            planner.executeRules(stack, temp);
        } catch (TeiidProcessingException e) {
            throw new QueryPlannerException(e);
        }
    }
    // plan and minimize projection
    for (WithQueryCommand with : this.withPlanningState.withList.values()) {
        QueryCommand subCommand = with.getCommand();
        TempMetadataID tid = (TempMetadataID) with.getGroupSymbol().getMetadataID();
        if (tid.getTableData().getModel() != TempMetadataAdapter.TEMP_MODEL) {
            tid.getTableData().setModel(null);
        }
        List<TempMetadataID> elements = tid.getElements();
        List<Integer> toRemove = new ArrayList<Integer>();
        for (int i = elements.size() - 1; i >= 0; i--) {
            TempMetadataID elem = elements.get(i);
            if (!elem.isAccessed()) {
                toRemove.add(i);
            }
        }
        // the definition of the with clause consistent
        if (!toRemove.isEmpty()) {
            if (with.isRecursive()) {
                SetQuery setQuery = (SetQuery) subCommand;
                setQuery.setLeftQuery(removeUnusedProjection(with, setQuery.getLeftQuery(), elements, toRemove));
                setQuery.setRightQuery(removeUnusedProjection(with, setQuery.getRightQuery(), elements, toRemove));
            } else {
                subCommand = removeUnusedProjection(with, subCommand, elements, toRemove);
                with.setCommand(subCommand);
            }
        }
        if (with.isRecursive()) {
            SetQuery setQuery = (SetQuery) subCommand;
            QueryCommand qc = setQuery.getLeftQuery();
            final RelationalPlan subPlan = optimize(qc);
            qc.setProcessorPlan(subPlan);
            AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(subPlan);
            Object modelID = null;
            QueryCommand withCommand = null;
            if (aNode != null) {
                modelID = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode, false);
                if (modelID != null) {
                    if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.RECURSIVE_COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) {
                        modelID = null;
                    } else {
                        withCommand = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
                        if (withCommand != null) {
                            // provisionally set the source
                            ((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(modelID);
                        }
                    }
                }
            }
            // now that we possibly have a model id, plan the recursive part
            QueryCommand qc1 = setQuery.getRightQuery();
            RelationalPlan subPlan1 = optimize((Command) qc1.clone());
            qc1.setProcessorPlan(subPlan1);
            if (!isPushdownValid(with, setQuery, modelID, withCommand, subPlan1) && withCommand != null) {
                // reset the source to null and replan
                ((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(null);
                subPlan1 = optimize(qc1);
                qc1.setProcessorPlan(subPlan1);
            }
            continue;
        }
        RelationalPlan subPlan = optimize(subCommand);
        subCommand.setProcessorPlan(subPlan);
        RelationalPlan procPlan = subPlan;
        RelationalNode root = procPlan.getRootNode();
        Number planCardinality = root.getEstimateNodeCardinality();
        if (planCardinality != null) {
            ((TempMetadataID) with.getGroupSymbol().getMetadataID()).setCardinality(planCardinality.intValue());
        }
        AccessNode aNode = CriteriaCapabilityValidatorVisitor.getAccessNode(procPlan);
        if (aNode == null) {
            continue;
        }
        Object modelID = CriteriaCapabilityValidatorVisitor.validateCommandPushdown(null, metadata, capFinder, aNode, false);
        QueryCommand withCommand = CriteriaCapabilityValidatorVisitor.getQueryCommand(aNode);
        if (modelID == null || withCommand == null) {
            continue;
        }
        if (with.getGroupSymbol().getModelMetadataId() != null || !CapabilitiesUtil.supports(Capability.COMMON_TABLE_EXPRESSIONS, modelID, metadata, capFinder) || with.isMaterialize()) {
            continue;
        }
        WithQueryCommand wqc = new WithQueryCommand(with.getGroupSymbol(), with.getColumns(), withCommand);
        wqc.setNoInline(with.isNoInline());
        ((TempMetadataID) with.getGroupSymbol().getMetadataID()).getTableData().setModel(modelID);
        this.withPlanningState.pushdownWith.put(with.getGroupSymbol().getName(), wqc);
    }
}
Also used : TempMetadataID(org.teiid.query.metadata.TempMetadataID) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan) TeiidProcessingException(org.teiid.core.TeiidProcessingException) SubqueryAwareRelationalNode(org.teiid.query.processor.relational.SubqueryAwareRelationalNode) RelationalNode(org.teiid.query.processor.relational.RelationalNode) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) LanguageObject(org.teiid.query.sql.LanguageObject) AccessNode(org.teiid.query.processor.relational.AccessNode) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException)

Example 7 with RelationalNode

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

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

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

the class TestDependentJoins method getDependentGroups.

static void getDependentGroups(RelationalNode node, Set<String> depGroups, boolean depdenent) {
    if (node instanceof AccessNode) {
        if (node instanceof DependentAccessNode) {
            if (!depdenent) {
                return;
            }
        } else if (depdenent) {
            return;
        }
        AccessNode accessNode = (AccessNode) node;
        Command depCommand = accessNode.getCommand();
        Collection<GroupSymbol> groupSymbols = GroupCollectorVisitor.getGroups(depCommand, true);
        for (GroupSymbol groupSymbol : groupSymbols) {
            depGroups.add(groupSymbol.getNonCorrelationName().toUpperCase());
        }
    }
    // Recurse through children
    RelationalNode[] children = node.getChildren();
    for (int i = 0; i < children.length; i++) {
        if (children[i] != null) {
            getDependentGroups(node.getChildren()[i], depGroups, depdenent);
        }
    }
}
Also used : RelationalNode(org.teiid.query.processor.relational.RelationalNode) Command(org.teiid.query.sql.lang.Command) DependentAccessNode(org.teiid.query.processor.relational.DependentAccessNode) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) DependentAccessNode(org.teiid.query.processor.relational.DependentAccessNode) AccessNode(org.teiid.query.processor.relational.AccessNode)

Example 10 with RelationalNode

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

the class TestJoinOptimization method testOuterJoinRemoval.

@Test
public void testOuterJoinRemoval() throws Exception {
    BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
    caps.setCapabilitySupport(Capability.QUERY_FROM_JOIN_INNER, false);
    caps.setCapabilitySupport(Capability.QUERY_FROM_JOIN_OUTER, false);
    ProcessorPlan plan = // $NON-NLS-1$
    TestOptimizer.helpPlan(// $NON-NLS-1$
    "SELECT * from pm1.g1 inner join (pm1.g2 left outer join pm1.g3 on pm1.g2.e1=pm1.g3.e1) on pm1.g1.e1=pm1.g3.e1", RealMetadataFactory.example1Cached(), new String[] { "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g2 AS g_0 ORDER BY c_0", "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g1 AS g_0 ORDER BY c_0", "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g3 AS g_0 ORDER BY c_0" }, new DefaultCapabilitiesFinder(caps), // $NON-NLS-1$
    ComparisonMode.EXACT_COMMAND_STRING);
    RelationalNode node = ((RelationalPlan) plan).getRootNode().getChildren()[0];
    assertTrue(node instanceof JoinNode);
    node = node.getChildren()[0];
    assertTrue(node instanceof JoinNode);
    assertEquals(JoinType.JOIN_INNER, ((JoinNode) node).getJoinType());
}
Also used : RelationalNode(org.teiid.query.processor.relational.RelationalNode) BasicSourceCapabilities(org.teiid.query.optimizer.capabilities.BasicSourceCapabilities) JoinNode(org.teiid.query.processor.relational.JoinNode) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) DefaultCapabilitiesFinder(org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan) Test(org.junit.Test)

Aggregations

RelationalNode (org.teiid.query.processor.relational.RelationalNode)14 RelationalPlan (org.teiid.query.processor.relational.RelationalPlan)12 Test (org.junit.Test)6 JoinNode (org.teiid.query.processor.relational.JoinNode)6 QueryMetadataInterface (org.teiid.query.metadata.QueryMetadataInterface)5 BasicSourceCapabilities (org.teiid.query.optimizer.capabilities.BasicSourceCapabilities)5 FakeCapabilitiesFinder (org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder)5 Command (org.teiid.query.sql.lang.Command)5 AccessNode (org.teiid.query.processor.relational.AccessNode)4 List (java.util.List)3 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)3 CommandContext (org.teiid.query.util.CommandContext)3 BigInteger (java.math.BigInteger)2 TupleBatch (org.teiid.common.buffer.TupleBatch)2 DefaultCapabilitiesFinder (org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder)2 SubqueryAwareRelationalNode (org.teiid.query.processor.relational.SubqueryAwareRelationalNode)2 LanguageObject (org.teiid.query.sql.LanguageObject)2 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)2 ArrayList (java.util.ArrayList)1 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)1