Search in sources :

Example 6 with BatchedUpdateCommand

use of org.teiid.query.sql.lang.BatchedUpdateCommand in project teiid by teiid.

the class TestInsertProcessing method helpInsertIntoWithSubquery2.

public void helpInsertIntoWithSubquery2(boolean doBatching, boolean doBulkInsert) {
    FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
    BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
    caps.setCapabilitySupport(Capability.BATCHED_UPDATES, doBatching);
    caps.setCapabilitySupport(Capability.BULK_UPDATE, doBulkInsert);
    caps.setCapabilitySupport(Capability.INSERT_WITH_ITERATOR, doBulkInsert);
    caps.setCapabilitySupport(Capability.QUERY_FROM_GROUP_ALIAS, false);
    // $NON-NLS-1$
    capFinder.addCapabilities("pm1", caps);
    QueryMetadataInterface metadata = RealMetadataFactory.example1Cached();
    HardcodedDataManager dataManager = new HardcodedDataManager();
    // $NON-NLS-1$
    dataManager.addData(// $NON-NLS-1$
    "SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 FROM pm1.g1", new List[] { // $NON-NLS-1$
    Arrays.asList(new Object[] { "1", new Integer(1), Boolean.FALSE, new Double(1) }), // $NON-NLS-1$
    Arrays.asList(new Object[] { "2", new Integer(2), Boolean.TRUE, new Double(2) }) });
    if (doBulkInsert) {
        // $NON-NLS-1$
        dataManager.addData(// $NON-NLS-1$
        "INSERT INTO pm1.g2 (e1, e2, e3, e4) VALUES (...)", new List[] { Arrays.asList(1), Arrays.asList(1), Arrays.asList(1), Arrays.asList(1) });
    } else if (doBatching) {
        // $NON-NLS-1$
        dataManager.addData(// $NON-NLS-1$
        "BatchedUpdate{I,I}", new List[] { Arrays.asList(1), Arrays.asList(1) });
    } else {
        // $NON-NLS-1$
        dataManager.addData(// $NON-NLS-1$
        "INSERT INTO pm1.g2 (e1, e2, e3, e4) VALUES ('1', 1, FALSE, 1.0)", new List[] { Arrays.asList(new Object[] { new Integer(1) }) });
        // $NON-NLS-1$
        dataManager.addData(// $NON-NLS-1$
        "INSERT INTO pm1.g2 (e1, e2, e3, e4) VALUES ('2', 2, TRUE, 2.0)", new List[] { Arrays.asList(new Object[] { new Integer(1) }) });
    }
    // $NON-NLS-1$
    String sql = "INSERT INTO pm1.g2 SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 from pm1.g1 UNION ALL SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 from pm1.g1";
    // String sql = "SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 INTO pm1.g2 from pm1.g1"; //$NON-NLS-1$
    Command command = helpParse(sql);
    ProcessorPlan plan = helpGetPlan(command, metadata, capFinder);
    List<?>[] expected = new List[] { Arrays.asList(new Object[] { new Integer(4) }) };
    helpProcess(plan, dataManager, expected);
    // check the command hist to ensure it contains the expected commands
    if (!doBulkInsert && doBatching) {
        BatchedUpdateCommand bu = (BatchedUpdateCommand) dataManager.getCommandHistory().get(2);
        assertEquals(2, bu.getUpdateCommands().size());
        // $NON-NLS-1$
        assertEquals("INSERT INTO pm1.g2 (e1, e2, e3, e4) VALUES ('1', 1, FALSE, 1.0)", bu.getUpdateCommands().get(0).toString());
        // $NON-NLS-1$
        assertEquals("INSERT INTO pm1.g2 (e1, e2, e3, e4) VALUES ('2', 2, TRUE, 2.0)", bu.getUpdateCommands().get(1).toString());
    }
}
Also used : FakeCapabilitiesFinder(org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder) BasicSourceCapabilities(org.teiid.query.optimizer.capabilities.BasicSourceCapabilities) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) Command(org.teiid.query.sql.lang.Command) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) List(java.util.List) QueryMetadataInterface(org.teiid.query.metadata.QueryMetadataInterface)

Example 7 with BatchedUpdateCommand

use of org.teiid.query.sql.lang.BatchedUpdateCommand in project teiid by teiid.

the class HardcodedDataManager method registerRequest.

/**
 * @see org.teiid.query.processor.ProcessorDataManager#registerRequest(CommandContext, org.teiid.query.sql.lang.Command, java.lang.String, RegisterRequestParameter)
 * @since 4.2
 */
public TupleSource registerRequest(CommandContext context, Command command, String modelName, RegisterRequestParameter parameterObject) throws TeiidComponentException {
    if (modelName != null && validModels != null && !validModels.contains(modelName)) {
        // $NON-NLS-1$//$NON-NLS-2$
        throw new TeiidComponentException("Detected query against invalid model: " + modelName + ": " + command);
    }
    this.commandHistory.add(command);
    List<Expression> projectedSymbols = command.getProjectedSymbols();
    String commandString = null;
    if (lbf == null) {
        if (command instanceof BatchedUpdateCommand && fullBatchedUpdate) {
            commandString = ((BatchedUpdateCommand) command).getStringForm(true);
        } else {
            commandString = command.toString();
        }
    } else {
        org.teiid.language.Command cmd = lbf.translate(command);
        this.pushdownCommands.add(cmd);
        commandString = cmd.toString();
    }
    List<?>[] rows = getData(commandString);
    if (rows == null) {
        if (mustRegisterCommands) {
            // $NON-NLS-1$
            throw new TeiidComponentException("Unknown command: " + commandString);
        }
        // Create one row of nulls
        rows = new List[1];
        rows[0] = new ArrayList();
        for (int i = 0; i < projectedSymbols.size(); i++) {
            rows[0].add(null);
        }
    }
    FakeTupleSource source = new FakeTupleSource(projectedSymbols, rows);
    if (blockOnce) {
        source.setBlockOnce();
    }
    return source;
}
Also used : ArrayList(java.util.ArrayList) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) Expression(org.teiid.query.sql.symbol.Expression) TeiidComponentException(org.teiid.core.TeiidComponentException) ArrayList(java.util.ArrayList) List(java.util.List)

Example 8 with BatchedUpdateCommand

use of org.teiid.query.sql.lang.BatchedUpdateCommand in project teiid by teiid.

the class DataTierTupleSource method nextTuple.

public List<?> nextTuple() throws TeiidComponentException, TeiidProcessingException {
    if (waitUntil > 0 && waitUntil > System.currentTimeMillis()) {
        if (!this.cwi.isDataAvailable()) {
            // $NON-NLS-1$
            throw BlockedException.block(aqr.getAtomicRequestID(), "Blocking until", waitUntil);
        }
        this.waitUntil = 0;
    }
    while (true) {
        if (arm == null) {
            if (isDone()) {
                // TODO: could throw an illegal state exception
                return null;
            }
            boolean partial = false;
            AtomicResultsMessage results = null;
            boolean noResults = false;
            try {
                if (futureResult != null || !aqr.isSerial()) {
                    results = asynchGet();
                } else {
                    results = getResults();
                }
                // check for update events
                if (index == 0 && this.dtm.detectChangeEvents()) {
                    Command command = aqr.getCommand();
                    int commandIndex = 0;
                    if (RelationalNodeUtil.isUpdate(command)) {
                        long ts = System.currentTimeMillis();
                        checkForUpdates(results, command, dtm.getEventDistributor(), commandIndex, ts);
                    } else if (command instanceof BatchedUpdateCommand) {
                        long ts = System.currentTimeMillis();
                        BatchedUpdateCommand bac = (BatchedUpdateCommand) command;
                        for (Command uc : bac.getUpdateCommands()) {
                            checkForUpdates(results, uc, dtm.getEventDistributor(), commandIndex++, ts);
                        }
                    }
                }
            } catch (TranslatorException e) {
                errored = true;
                results = exceptionOccurred(e);
                partial = true;
            } catch (BlockedException e) {
                noResults = true;
                throw e;
            } catch (DataNotAvailableException e) {
                noResults = true;
                handleDataNotAvailable(e);
                continue;
            } finally {
                if (!noResults && results == null) {
                    errored = true;
                }
            }
            receiveResults(results, partial);
        }
        if (index < arm.getResults().length) {
            if (limit-- == 0) {
                this.done = true;
                arm = null;
                return null;
            }
            return this.arm.getResults()[index++];
        }
        arm = null;
        if (isDone()) {
            return null;
        }
    }
}
Also used : Command(org.teiid.query.sql.lang.Command) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) AtomicResultsMessage(org.teiid.dqp.message.AtomicResultsMessage) TranslatorException(org.teiid.translator.TranslatorException) DataNotAvailableException(org.teiid.translator.DataNotAvailableException) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) BlockedException(org.teiid.common.buffer.BlockedException)

Example 9 with BatchedUpdateCommand

use of org.teiid.query.sql.lang.BatchedUpdateCommand 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 10 with BatchedUpdateCommand

use of org.teiid.query.sql.lang.BatchedUpdateCommand in project teiid by teiid.

the class BatchedUpdatePlanner method optimize.

/**
 * Optimizes batched updates by batching all contiguous commands that relate to the same physical model.
 * For example, for the following batch of commands:
 * <br/>
 * <ol>
 *      <li>1.  INSERT INTO physicalModel.myPhysical ...</li>
 *      <li>2.  UPDATE physicalModel.myPhysical ... </li>
 *      <li>3.  DELETE FROM virtualmodel.myVirtual ... </li>
 *      <li>4.  UPDATE virtualmodel.myVirtual ... </li>
 *      <li>5.  UPDATE physicalModel.myOtherPhysical ...</li>
 *      <li>6.  INSERT INTO physicalModel.myOtherPhysical ... <li>
 *      <li>7.  DELETE FROM physicalModel.myOtherPhysical ...</li>
 *      <li>8.  INSERT INTO physicalModel.myPhysical ... </li>
 *      <li>9.  INSERT INTO physicalModel.myPhysical ... </li>
 *      <li>10. INSERT INTO physicalModel.myPhysical ... </li>
 *      <li>11. INSERT INTO physicalModel.myPhysical ... </li>
 *      <li>12. INSERT INTO physicalModel.myPhysical ... </li>
 * </ol>
 * <br/> this implementation will batch as follows: (1,2), (5, 6, 7), (8 thru 12).
 * The remaining commands/plans will be executed individually.
 * @see org.teiid.query.optimizer.CommandPlanner#optimize(Command, org.teiid.core.id.IDGenerator, org.teiid.query.metadata.QueryMetadataInterface, org.teiid.query.optimizer.capabilities.CapabilitiesFinder, org.teiid.query.analysis.AnalysisRecord, CommandContext)
 * @since 4.2
 */
public ProcessorPlan optimize(Command command, IDGenerator idGenerator, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    BatchedUpdateCommand batchedUpdateCommand = (BatchedUpdateCommand) command;
    List<ProcessorPlan> childPlans = new ArrayList<ProcessorPlan>(batchedUpdateCommand.getUpdateCommands().size());
    List<Command> updateCommands = batchedUpdateCommand.getUpdateCommands();
    int numCommands = updateCommands.size();
    List<VariableContext> allContexts = batchedUpdateCommand.getVariableContexts();
    List<VariableContext> planContexts = null;
    if (allContexts != null) {
        planContexts = new ArrayList<VariableContext>(allContexts.size());
    }
    for (int commandIndex = 0; commandIndex < numCommands; commandIndex++) {
        // Potentially the first command of a batch
        Command updateCommand = updateCommands.get(commandIndex);
        boolean commandWasBatched = false;
        // If this command can be placed in a batch
        if (isEligibleForBatching(updateCommand, metadata)) {
            // Get the model ID. Subsequent and contiguous commands that update a group in this model are candidates for this batch
            Object batchModelID = metadata.getModelID(getUpdatedGroup(updateCommand).getMetadataID());
            String modelName = metadata.getFullName(batchModelID);
            SourceCapabilities caps = capFinder.findCapabilities(modelName);
            // Only attempt batching if the source supports batching
            if (caps.supportsCapability(Capability.BATCHED_UPDATES)) {
                // Start a new batch
                List<Command> batch = new ArrayList<Command>();
                List<VariableContext> contexts = new ArrayList<VariableContext>();
                List<Boolean> shouldEvaluate = new ArrayList<Boolean>();
                // This is the first command in a potential batch, so add it to the batch
                batch.add(updateCommand);
                if (allContexts != null) {
                    contexts.add(allContexts.get(commandIndex));
                    shouldEvaluate.add(Boolean.TRUE);
                } else {
                    shouldEvaluate.add(EvaluatableVisitor.needsProcessingEvaluation(updateCommand));
                }
                // immediately and contiguously after this one
                batchLoop: for (int batchIndex = commandIndex + 1; batchIndex < numCommands; batchIndex++) {
                    Command batchingCandidate = updateCommands.get(batchIndex);
                    // If this command updates the same model, and is eligible for batching, add it to the batch
                    if (canBeAddedToBatch(batchingCandidate, batchModelID, metadata, capFinder)) {
                        batch.add(batchingCandidate);
                        if (allContexts != null) {
                            contexts.add(allContexts.get(batchIndex));
                            shouldEvaluate.add(Boolean.TRUE);
                        } else {
                            shouldEvaluate.add(EvaluatableVisitor.needsProcessingEvaluation(batchingCandidate));
                        }
                    } else {
                        // Otherwise, stop batching at this point. The next command may well be the start of a new batch
                        break batchLoop;
                    }
                }
                // If two or more contiguous commands made on the same model were found, then batch them
                if (batch.size() > 1) {
                    ProjectNode projectNode = new ProjectNode(idGenerator.nextInt());
                    // Create a BatchedUpdateNode that creates a batched request for the connector
                    BatchedUpdateNode batchNode = new BatchedUpdateNode(idGenerator.nextInt(), batch, contexts, shouldEvaluate, modelName);
                    List symbols = batchedUpdateCommand.getProjectedSymbols();
                    projectNode.setSelectSymbols(symbols);
                    projectNode.setElements(symbols);
                    batchNode.setElements(symbols);
                    projectNode.addChild(batchNode);
                    // Add a new RelationalPlan that represents the plan for this batch.
                    childPlans.add(new RelationalPlan(projectNode));
                    if (planContexts != null) {
                        planContexts.add(new VariableContext());
                    }
                    // Skip those commands that were added to this batch
                    commandIndex += batch.size() - 1;
                    commandWasBatched = true;
                }
            }
        }
        if (!commandWasBatched) {
            // If the command wasn't batched, just add the plan for this command to the list of plans
            Command cmd = batchedUpdateCommand.getUpdateCommands().get(commandIndex);
            ProcessorPlan plan = cmd.getProcessorPlan();
            if (plan == null) {
                plan = QueryOptimizer.optimizePlan(cmd, metadata, idGenerator, capFinder, analysisRecord, context);
            }
            childPlans.add(plan);
            if (allContexts != null) {
                planContexts.add(allContexts.get(commandIndex));
            }
        }
    }
    return new BatchedUpdatePlan(childPlans, batchedUpdateCommand.getUpdateCommands().size(), planContexts, batchedUpdateCommand.isSingleResult());
}
Also used : ArrayList(java.util.ArrayList) VariableContext(org.teiid.query.sql.util.VariableContext) RelationalPlan(org.teiid.query.processor.relational.RelationalPlan) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) Command(org.teiid.query.sql.lang.Command) BatchedUpdateCommand(org.teiid.query.sql.lang.BatchedUpdateCommand) BatchedUpdateNode(org.teiid.query.processor.relational.BatchedUpdateNode) ProjectNode(org.teiid.query.processor.relational.ProjectNode) ArrayList(java.util.ArrayList) List(java.util.List) SourceCapabilities(org.teiid.query.optimizer.capabilities.SourceCapabilities) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) BatchedUpdatePlan(org.teiid.query.processor.BatchedUpdatePlan)

Aggregations

BatchedUpdateCommand (org.teiid.query.sql.lang.BatchedUpdateCommand)17 Command (org.teiid.query.sql.lang.Command)13 List (java.util.List)10 ArrayList (java.util.ArrayList)8 QueryMetadataInterface (org.teiid.query.metadata.QueryMetadataInterface)5 BasicSourceCapabilities (org.teiid.query.optimizer.capabilities.BasicSourceCapabilities)4 FakeCapabilitiesFinder (org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder)4 Insert (org.teiid.query.sql.lang.Insert)4 Test (org.junit.Test)3 BlockedException (org.teiid.common.buffer.BlockedException)2 AtomicRequestMessage (org.teiid.dqp.message.AtomicRequestMessage)2 Evaluator (org.teiid.query.eval.Evaluator)2 SourceCapabilities (org.teiid.query.optimizer.capabilities.SourceCapabilities)2 RelationalPlan (org.teiid.query.processor.relational.RelationalPlan)2 Constant (org.teiid.query.sql.symbol.Constant)2 VariableContext (org.teiid.query.sql.util.VariableContext)2 CommandContext (org.teiid.query.util.CommandContext)2 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 Set (java.util.Set)1