Search in sources :

Example 21 with RelationalPlan

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

the class PreparedPlan method setPlan.

/**
 * Set the ProcessorPlan.
 * @param context
 */
public void setPlan(ProcessorPlan planValue, CommandContext context) {
    plan = planValue;
    this.accessInfo.populate(context, false);
    // TODO: expand this logic
    if (planValue instanceof RelationalPlan) {
        RelationalPlan rp = (RelationalPlan) planValue;
        if (rp.getRootNode() instanceof AccessNode) {
            this.accessInfo.setSensitiveToMetadataChanges(false);
        }
    }
}
Also used : AccessNode(org.teiid.query.processor.relational.AccessNode) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan)

Example 22 with RelationalPlan

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

the class PreparedStatementRequest method handlePreparedBatchUpdate.

/**
 * There are two cases
 *   if
 *     The source supports preparedBatchUpdate -> just let the command and values pass to the source
 *   else
 *     create a batchedupdatecommand that represents the batch operation
 * @param command
 * @throws QueryMetadataException
 * @throws TeiidComponentException
 * @throws QueryResolverException
 * @throws QueryPlannerException
 * @throws QueryValidatorException
 */
private void handlePreparedBatchUpdate() throws QueryMetadataException, TeiidComponentException, QueryResolverException, QueryPlannerException, QueryValidatorException {
    List<List<?>> paramValues = (List<List<?>>) requestMsg.getParameterValues();
    if (paramValues.isEmpty()) {
        throw new QueryValidatorException(QueryPlugin.Event.TEIID30555, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30555));
    }
    boolean supportPreparedBatchUpdate = false;
    Command command = null;
    if (this.processPlan instanceof RelationalPlan) {
        RelationalPlan rPlan = (RelationalPlan) this.processPlan;
        if (rPlan.getRootNode() instanceof AccessNode) {
            AccessNode aNode = (AccessNode) rPlan.getRootNode();
            String modelName = aNode.getModelName();
            command = aNode.getCommand();
            SourceCapabilities caps = capabilitiesFinder.findCapabilities(modelName);
            supportPreparedBatchUpdate = caps.supportsCapability(SourceCapabilities.Capability.BULK_UPDATE);
            if (supportPreparedBatchUpdate && // only allow the plan if the multi-valued references result in expressions that can be pushed
            !CriteriaCapabilityValidatorVisitor.canPushLanguageObject(command, metadata.getModelID(modelName), metadata, capabilitiesFinder, analysisRecord, false, false, true)) {
                supportPreparedBatchUpdate = false;
            }
        }
    }
    List<Command> commands = new LinkedList<Command>();
    List<VariableContext> contexts = new LinkedList<VariableContext>();
    List<List<Object>> multiValues = new ArrayList<List<Object>>(this.prepPlan.getReferences().size());
    for (List<?> values : paramValues) {
        PreparedStatementRequest.resolveParameterValues(this.prepPlan.getReferences(), values, this.context, this.metadata);
        contexts.add(this.context.getVariableContext());
        if (supportPreparedBatchUpdate) {
            if (multiValues.isEmpty()) {
                for (int i = 0; i < values.size(); i++) {
                    multiValues.add(new ArrayList<Object>(paramValues.size()));
                }
            }
            for (int i = 0; i < values.size(); i++) {
                List<Object> multiValue = multiValues.get(i);
                Object value = this.context.getVariableContext().getGlobalValue(this.prepPlan.getReferences().get(i).getContextSymbol());
                multiValue.add(value);
            }
        } else {
            // just accumulate copies of the command/plan - clones are not necessary
            if (command == null) {
                command = this.prepPlan.getCommand();
            }
            command.setProcessorPlan(this.processPlan);
            commands.add(command);
        }
    }
    if (paramValues.size() > 1) {
        this.context.setVariableContext(new VariableContext());
    }
    if (paramValues.size() == 1) {
        // just use the existing plan, and global reference evaluation
        return;
    }
    if (supportPreparedBatchUpdate) {
        for (int i = 0; i < this.prepPlan.getReferences().size(); i++) {
            Constant c = new Constant(null, this.prepPlan.getReferences().get(i).getType());
            c.setMultiValued(multiValues.get(i));
            this.context.getVariableContext().setGlobalValue(this.prepPlan.getReferences().get(i).getContextSymbol(), c);
        }
        return;
    }
    BatchedUpdateCommand buc = new BatchedUpdateCommand(commands);
    buc.setVariableContexts(contexts);
    BatchedUpdatePlanner planner = new BatchedUpdatePlanner();
    this.processPlan = planner.optimize(buc, idGenerator, metadata, capabilitiesFinder, analysisRecord, context);
}
Also used : Constant(org.teiid.query.sql.symbol.Constant) ArrayList(java.util.ArrayList) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan) VariableContext(org.teiid.query.sql.util.VariableContext) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) LinkedList(java.util.LinkedList) QueryValidatorException(org.teiid.api.exception.query.QueryValidatorException) Command(org.teiid.query.sql.lang.Command) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) AccessNode(org.teiid.query.processor.relational.AccessNode) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities) BatchedUpdatePlanner(org.teiid.query.optimizer.BatchedUpdatePlanner)

Example 23 with RelationalPlan

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

the class RelationalPlanner method createUpdatePlan.

PlanNode createUpdatePlan(Command command) throws TeiidComponentException, TeiidProcessingException {
    // Create top project node - define output columns for stored query / procedure
    PlanNode projectNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
    // Set output columns
    List<Expression> cols = command.getProjectedSymbols();
    projectNode.setProperty(NodeConstants.Info.PROJECT_COLS, cols);
    // Define source of data for stored query / procedure
    PlanNode sourceNode = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
    sourceNode.setProperty(NodeConstants.Info.ATOMIC_REQUEST, command);
    sourceNode.setProperty(NodeConstants.Info.VIRTUAL_COMMAND, command);
    boolean usingTriggerAction = false;
    if (command instanceof ProcedureContainer) {
        ProcedureContainer container = (ProcedureContainer) command;
        usingTriggerAction = addNestedProcedure(sourceNode, container, container.getGroup().getMetadataID());
    }
    GroupSymbol target = ((TargetedCommand) command).getGroup();
    sourceNode.addGroup(target);
    Object id = getTrackableGroup(target, metadata);
    if (id != null) {
        context.accessedPlanningObject(id);
    }
    attachLast(projectNode, sourceNode);
    // for INTO query, attach source and project nodes
    if (!usingTriggerAction && command instanceof Insert) {
        Insert insert = (Insert) command;
        if (insert.getQueryExpression() != null) {
            PlanNode plan = generatePlan(insert.getQueryExpression());
            attachLast(sourceNode, plan);
            mergeTempMetadata(insert.getQueryExpression(), insert);
            projectNode.setProperty(NodeConstants.Info.INTO_GROUP, insert.getGroup());
            if (this.sourceHint != null) {
                projectNode.setProperty(Info.SOURCE_HINT, this.sourceHint);
            }
            if (insert.getConstraint() != null) {
                projectNode.setProperty(NodeConstants.Info.CONSTRAINT, insert.getConstraint());
            }
            if (insert.isUpsert()) {
                projectNode.setProperty(NodeConstants.Info.UPSERT, true);
            }
        }
    }
    if (usingTriggerAction && FrameUtil.getNestedPlan(projectNode) instanceof RelationalPlan) {
        sourceNode.removeFromParent();
        return sourceNode;
    }
    return projectNode;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) LanguageObject(org.teiid.query.sql.LanguageObject) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan)

Example 24 with RelationalPlan

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

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

Aggregations

RelationalPlan (org.teiid.query.processor.relational.RelationalPlan)40 Test (org.junit.Test)25 RelationalNode (org.teiid.query.processor.relational.RelationalNode)12 BasicSourceCapabilities (org.teiid.query.optimizer.capabilities.BasicSourceCapabilities)11 Command (org.teiid.query.sql.lang.Command)10 List (java.util.List)9 FakeCapabilitiesFinder (org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder)9 QueryMetadataInterface (org.teiid.query.metadata.QueryMetadataInterface)8 DefaultCapabilitiesFinder (org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder)8 AccessNode (org.teiid.query.processor.relational.AccessNode)8 JoinNode (org.teiid.query.processor.relational.JoinNode)8 ArrayList (java.util.ArrayList)7 ProjectNode (org.teiid.query.processor.relational.ProjectNode)7 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)5 Annotation (org.teiid.client.plan.Annotation)4 AnalysisRecord (org.teiid.query.analysis.AnalysisRecord)4 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)4 LanguageObject (org.teiid.query.sql.LanguageObject)4 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)3 CapabilitiesFinder (org.teiid.query.optimizer.capabilities.CapabilitiesFinder)3