Search in sources :

Example 1 with SubqueryAwareRelationalNode

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

Aggregations

ProcessorPlan (org.teiid.query.processor.ProcessorPlan)1 AccessNode (org.teiid.query.processor.relational.AccessNode)1 PlanExecutionNode (org.teiid.query.processor.relational.PlanExecutionNode)1 RelationalNode (org.teiid.query.processor.relational.RelationalNode)1 RelationalPlan (org.teiid.query.processor.relational.RelationalPlan)1 SubqueryAwareRelationalNode (org.teiid.query.processor.relational.SubqueryAwareRelationalNode)1 LanguageObject (org.teiid.query.sql.LanguageObject)1 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)1