Search in sources :

Example 1 with TranslatorBatchException

use of org.teiid.translator.TranslatorBatchException in project teiid by teiid.

the class JDBCUpdateExecution method execute.

public int[] execute(BatchedUpdates batchedCommand) throws TranslatorException {
    boolean succeeded = false;
    boolean commitType = false;
    if (batchedCommand.isSingleResult()) {
        commitType = getAutoCommit(null);
    }
    Command[] commands = batchedCommand.getUpdateCommands().toArray(new Command[batchedCommand.getUpdateCommands().size()]);
    result = new int[commands.length];
    TranslatedCommand tCommand = null;
    int batchStart = 0;
    int i = 0;
    try {
        // before at the end of the command execution.
        if (commitType) {
            connection.setAutoCommit(false);
        }
        List<TranslatedCommand> executedCmds = new ArrayList<TranslatedCommand>();
        TranslatedCommand previousCommand = null;
        for (; i < commands.length; i++) {
            tCommand = translateCommand(commands[i]);
            if (tCommand.isPrepared()) {
                PreparedStatement pstmt = null;
                if (previousCommand != null && previousCommand.isPrepared() && previousCommand.getSql().equals(tCommand.getSql())) {
                    pstmt = (PreparedStatement) statement;
                } else {
                    if (!executedCmds.isEmpty()) {
                        executeBatch(i, result, executedCmds);
                        batchStart = i;
                    }
                    pstmt = getPreparedStatement(tCommand.getSql());
                }
                bind(pstmt, tCommand.getPreparedValues(), null);
                pstmt.addBatch();
            } else {
                if (previousCommand != null && previousCommand.isPrepared()) {
                    executeBatch(i, result, executedCmds);
                    batchStart = i;
                    getStatement();
                }
                if (statement == null) {
                    getStatement();
                }
                statement.addBatch(tCommand.getSql());
            }
            executedCmds.add(tCommand);
            previousCommand = tCommand;
        }
        if (!executedCmds.isEmpty()) {
            executeBatch(commands.length, result, executedCmds);
        }
        succeeded = true;
    } catch (TranslatorException e) {
        if (batchedCommand.isSingleResult()) {
            throw e;
        }
        int size = i + 1;
        // if there is a BatchUpdateException, there are more update counts to accumulate
        if (e.getCause() instanceof BatchUpdateException) {
            BatchUpdateException bue = (BatchUpdateException) e.getCause();
            int[] batchResults = bue.getUpdateCounts();
            for (int j = 0; j < batchResults.length; j++) {
                result[batchStart + j] = batchResults[j];
            }
            size = batchStart + batchResults.length;
        } else {
            size = batchStart;
        }
        // resize the result and throw exception
        throw new TranslatorBatchException(e, Arrays.copyOf(result, size));
    } catch (SQLException e) {
        if (batchedCommand.isSingleResult()) {
            throw new JDBCExecutionException(JDBCPlugin.Event.TEIID11011, e, tCommand);
        }
        // resize the result and throw exception
        throw new TranslatorBatchException(e, Arrays.copyOf(result, batchStart));
    } finally {
        if (commitType) {
            restoreAutoCommit(!succeeded, null);
        }
    }
    return result;
}
Also used : SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) PreparedStatement(java.sql.PreparedStatement) TranslatorBatchException(org.teiid.translator.TranslatorBatchException) Command(org.teiid.language.Command) BulkCommand(org.teiid.language.BulkCommand) TranslatorException(org.teiid.translator.TranslatorException) BatchUpdateException(java.sql.BatchUpdateException)

Example 2 with TranslatorBatchException

use of org.teiid.translator.TranslatorBatchException in project teiid by teiid.

the class JDBCUpdateExecution method executeTranslatedCommand.

/**
 * @param translatedComm
 * @throws TranslatorException
 * @since 4.3
 */
private void executeTranslatedCommand(TranslatedCommand translatedComm) throws TranslatorException {
    // create statement or PreparedStatement and execute
    String sql = translatedComm.getSql();
    boolean commitType = false;
    boolean succeeded = false;
    try {
        int updateCount = 0;
        Class<?>[] keyColumnDataTypes = null;
        String[] keyColumnNames = null;
        if (command instanceof Insert && context.getCommandContext().isReturnAutoGeneratedKeys() && executionFactory.supportsGeneratedKeys(context, command)) {
            Insert insert = (Insert) command;
            NamedTable nt = insert.getTable();
            if (nt.getMetadataObject() != null) {
                KeyRecord key = nt.getMetadataObject().getPrimaryKey();
                if (key != null) {
                    List<Column> cols = key.getColumns();
                    keyColumnDataTypes = new Class<?>[cols.size()];
                    keyColumnNames = new String[cols.size()];
                    for (int i = 0; i < cols.size(); i++) {
                        Column c = cols.get(i);
                        keyColumnDataTypes[i] = c.getJavaType();
                        // won't work in scenarios where the teiid name is changed or contains a .
                        keyColumnNames[i] = c.getName();
                    }
                }
            }
        }
        if (!translatedComm.isPrepared()) {
            statement = getStatement();
            // handle autoGeneratedKeys
            if (keyColumnDataTypes != null) {
                if (executionFactory.useColumnNamesForGeneratedKeys()) {
                    updateCount = statement.executeUpdate(sql, keyColumnNames);
                } else {
                    updateCount = statement.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
                }
            } else {
                updateCount = statement.executeUpdate(sql);
            }
            result = new int[] { updateCount };
            addStatementWarnings();
        } else {
            PreparedStatement pstatement = null;
            if (statement != null) {
                statement.close();
            }
            if (keyColumnDataTypes != null) {
                if (executionFactory.useColumnNamesForGeneratedKeys()) {
                    pstatement = connection.prepareStatement(sql, keyColumnNames);
                } else {
                    pstatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                }
            } else {
                pstatement = getPreparedStatement(sql);
            }
            statement = pstatement;
            Iterator<? extends List<?>> vi = null;
            if (command instanceof BulkCommand) {
                BulkCommand batchCommand = (BulkCommand) command;
                vi = batchCommand.getParameterValues();
            }
            int k = 0;
            int batchStart = 0;
            if (vi != null) {
                try {
                    commitType = getAutoCommit(translatedComm);
                    if (commitType) {
                        connection.setAutoCommit(false);
                    }
                    int maxBatchSize = (command instanceof Insert) ? maxPreparedInsertBatchSize : Integer.MAX_VALUE;
                    boolean done = false;
                    outer: while (!done) {
                        for (int i = 0; i < maxBatchSize; i++) {
                            if (vi.hasNext()) {
                                List<?> values = vi.next();
                                bind(pstatement, translatedComm.getPreparedValues(), values);
                                k++;
                            } else {
                                if (i == 0) {
                                    break outer;
                                }
                                done = true;
                                break;
                            }
                        }
                        int[] results = pstatement.executeBatch();
                        batchStart = k;
                        if (result == null) {
                            result = results;
                        } else {
                            int len = result.length;
                            result = Arrays.copyOf(result, len + results.length);
                            System.arraycopy(results, 0, result, len, results.length);
                        }
                    }
                } catch (SQLException e) {
                    int size = k + 1;
                    if (result == null) {
                        result = new int[size];
                    } else {
                        result = Arrays.copyOf(result, size);
                    }
                    // if there is a BatchUpdateException, there are more update counts to accumulate
                    if (e instanceof BatchUpdateException) {
                        BatchUpdateException bue = (BatchUpdateException) e;
                        int[] batchResults = bue.getUpdateCounts();
                        for (int j = 0; j < batchResults.length; j++) {
                            result[batchStart + j] = batchResults[j];
                        }
                        size = batchStart + batchResults.length;
                    } else {
                        size = batchStart;
                    }
                    // resize the result and throw exception
                    throw new TranslatorBatchException(e, Arrays.copyOf(result, size));
                }
            } else {
                bind(pstatement, translatedComm.getPreparedValues(), null);
                updateCount = pstatement.executeUpdate();
                result = new int[] { updateCount };
            }
            addStatementWarnings();
            succeeded = true;
        }
        if (keyColumnDataTypes != null) {
            try {
                ResultSet keys = statement.getGeneratedKeys();
                GeneratedKeys generatedKeys = context.getCommandContext().returnGeneratedKeys(keyColumnNames, keyColumnDataTypes);
                // many databases only support returning a single generated value, but we'll still attempt to gather all
                outer: while (keys.next()) {
                    List<Object> vals = new ArrayList<Object>(keyColumnDataTypes.length);
                    for (int i = 0; i < keyColumnDataTypes.length; i++) {
                        Object value = this.executionFactory.retrieveValue(keys, i + 1, keyColumnDataTypes[i]);
                        if (value != null && TypeFacility.getRuntimeType(value.getClass()) != keyColumnDataTypes[i]) {
                            // TODO we may need to let the engine to the final conversion
                            LogManager.logDetail(LogConstants.CTX_CONNECTOR, JDBCPlugin.Util.gs(JDBCPlugin.Event.TEIID11023, keyColumnDataTypes[i], keyColumnNames[i], value.getClass()));
                            continue outer;
                        }
                        vals.add(value);
                    }
                    generatedKeys.addKey(vals);
                }
            } catch (SQLException e) {
                context.addWarning(e);
                // $NON-NLS-1$
                LogManager.logDetail(LogConstants.CTX_CONNECTOR, e, "Exception determining generated keys, no keys will be returned");
            }
        }
    } catch (SQLException err) {
        throw new JDBCExecutionException(JDBCPlugin.Event.TEIID11013, err, translatedComm);
    } finally {
        if (commitType) {
            restoreAutoCommit(!succeeded, translatedComm);
        }
    }
}
Also used : NamedTable(org.teiid.language.NamedTable) SQLException(java.sql.SQLException) PreparedStatement(java.sql.PreparedStatement) GeneratedKeys(org.teiid.GeneratedKeys) Insert(org.teiid.language.Insert) TranslatorBatchException(org.teiid.translator.TranslatorBatchException) KeyRecord(org.teiid.metadata.KeyRecord) Column(org.teiid.metadata.Column) BulkCommand(org.teiid.language.BulkCommand) ResultSet(java.sql.ResultSet) ArrayList(java.util.ArrayList) List(java.util.List) BatchUpdateException(java.sql.BatchUpdateException)

Example 3 with TranslatorBatchException

use of org.teiid.translator.TranslatorBatchException in project teiid by teiid.

the class TestJDBCUpdateExecution method testPreparedBatchedUpdateFailed.

@Test
public void testPreparedBatchedUpdateFailed() throws Exception {
    // $NON-NLS-1$
    Insert command = (Insert) TranslationHelper.helpTranslate(TranslationHelper.BQT_VDB, "insert into BQT1.SmallA (IntKey) values (1)");
    Parameter param = new Parameter();
    param.setType(DataTypeManager.DefaultDataClasses.INTEGER);
    param.setValueIndex(0);
    List<Expression> values = ((ExpressionValueSource) command.getValueSource()).getValues();
    values.set(0, param);
    command.setParameterValues(Arrays.asList(Arrays.asList(1), Arrays.asList(1)).iterator());
    Connection connection = Mockito.mock(Connection.class);
    PreparedStatement s = Mockito.mock(PreparedStatement.class);
    Mockito.stub(s.executeBatch()).toThrow(new BatchUpdateException(new int[] { 1, Statement.EXECUTE_FAILED }));
    Mockito.stub(connection.prepareStatement("INSERT INTO SmallA (IntKey) VALUES (?)")).toReturn(s);
    JDBCExecutionFactory config = new JDBCExecutionFactory();
    ResultSet r = Mockito.mock(ResultSet.class);
    ResultSetMetaData rs = Mockito.mock(ResultSetMetaData.class);
    Mockito.stub(r.getMetaData()).toReturn(rs);
    FakeExecutionContextImpl context = new FakeExecutionContextImpl();
    JDBCUpdateExecution updateExecution = new JDBCUpdateExecution(command, connection, context, config);
    try {
        updateExecution.execute();
        fail();
    } catch (TranslatorBatchException e) {
        int[] counts = e.getUpdateCounts();
        assertArrayEquals(new int[] { 1, -3 }, counts);
    }
    // test multiple batches
    connection = Mockito.mock(Connection.class);
    updateExecution = new JDBCUpdateExecution(command, connection, context, config);
    command.setParameterValues(Arrays.asList(Arrays.asList(1), Arrays.asList(1)).iterator());
    s = Mockito.mock(PreparedStatement.class);
    Mockito.stub(connection.prepareStatement("INSERT INTO SmallA (IntKey) VALUES (?)")).toReturn(s);
    Mockito.stub(s.executeBatch()).toReturn(new int[] { 1 }).toThrow(new BatchUpdateException(new int[] { Statement.EXECUTE_FAILED }));
    updateExecution.setMaxPreparedInsertBatchSize(1);
    try {
        updateExecution.execute();
        fail();
    } catch (TranslatorBatchException e) {
        int[] counts = e.getUpdateCounts();
        assertArrayEquals(new int[] { 1, -3 }, counts);
    }
    // test only a single update count
    connection = Mockito.mock(Connection.class);
    updateExecution = new JDBCUpdateExecution(command, connection, context, config);
    command.setParameterValues(Arrays.asList(Arrays.asList(1), Arrays.asList(1)).iterator());
    s = Mockito.mock(PreparedStatement.class);
    Mockito.stub(connection.prepareStatement("INSERT INTO SmallA (IntKey) VALUES (?)")).toReturn(s);
    Mockito.stub(s.executeBatch()).toThrow(new BatchUpdateException(new int[] { 1 }));
    try {
        updateExecution.execute();
        fail();
    } catch (TranslatorBatchException e) {
        int[] counts = e.getUpdateCounts();
        assertArrayEquals(new int[] { 1 }, counts);
    }
}
Also used : FakeExecutionContextImpl(org.teiid.dqp.internal.datamgr.FakeExecutionContextImpl) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) Insert(org.teiid.language.Insert) TranslatorBatchException(org.teiid.translator.TranslatorBatchException) ResultSetMetaData(java.sql.ResultSetMetaData) Expression(org.teiid.language.Expression) ResultSet(java.sql.ResultSet) Parameter(org.teiid.language.Parameter) ExpressionValueSource(org.teiid.language.ExpressionValueSource) BatchUpdateException(java.sql.BatchUpdateException) Test(org.junit.Test)

Example 4 with TranslatorBatchException

use of org.teiid.translator.TranslatorBatchException in project teiid by teiid.

the class TestJDBCUpdateExecution method testBatchedUpdateFailed.

@Test
public void testBatchedUpdateFailed() throws Exception {
    // $NON-NLS-1$
    Insert command = (Insert) TranslationHelper.helpTranslate(TranslationHelper.BQT_VDB, "insert into BQT1.SmallA (IntKey) values (1)");
    // $NON-NLS-1$
    Insert command1 = (Insert) TranslationHelper.helpTranslate(TranslationHelper.BQT_VDB, "insert into BQT1.SmallA (StringKey) values ('1')");
    Connection connection = Mockito.mock(Connection.class);
    Statement s = Mockito.mock(Statement.class);
    Mockito.stub(s.executeBatch()).toThrow(new BatchUpdateException(new int[] { Statement.EXECUTE_FAILED }));
    Mockito.stub(connection.createStatement()).toReturn(s);
    JDBCExecutionFactory config = new JDBCExecutionFactory();
    ResultSet r = Mockito.mock(ResultSet.class);
    ResultSetMetaData rs = Mockito.mock(ResultSetMetaData.class);
    Mockito.stub(r.getMetaData()).toReturn(rs);
    Mockito.stub(s.getGeneratedKeys()).toReturn(r);
    FakeExecutionContextImpl context = new FakeExecutionContextImpl();
    JDBCUpdateExecution updateExecution = new JDBCUpdateExecution(new BatchedUpdates(Arrays.asList((Command) command, command1)), connection, context, config);
    try {
        updateExecution.execute();
        fail();
    } catch (TranslatorBatchException e) {
        int[] counts = e.getUpdateCounts();
        assertArrayEquals(new int[] { -3 }, counts);
    }
}
Also used : ResultSetMetaData(java.sql.ResultSetMetaData) FakeExecutionContextImpl(org.teiid.dqp.internal.datamgr.FakeExecutionContextImpl) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) Insert(org.teiid.language.Insert) TranslatorBatchException(org.teiid.translator.TranslatorBatchException) BatchUpdateException(java.sql.BatchUpdateException) BatchedUpdates(org.teiid.language.BatchedUpdates) Test(org.junit.Test)

Example 5 with TranslatorBatchException

use of org.teiid.translator.TranslatorBatchException in project teiid by teiid.

the class BatchedUpdatePlan method nextBatch.

/**
 * @see org.teiid.query.processor.ProcessorPlan#nextBatch()
 * @since 4.2
 */
public TupleBatch nextBatch() throws BlockedException, TeiidComponentException, TeiidProcessingException {
    for (; planIndex < updatePlans.length && (getContext() == null || getContext().getBatchUpdateException() == null); ) {
        try {
            if (!planOpened[planIndex]) {
                // Open the plan only once
                /* Defect 16166
	                 * Some commands in a batch may depend on updates by previous commands in the same batch. A call
	                 * to open() usually submits an atomic command, so calling open() on all the child plans at the same time
	                 * will mean that the datasource may not be in the state expected by a later command within the batch. So,
	                 * for a batch of commands, we only open() a later plan when we are finished with the previous plan to
	                 * guarantee that the commands in the previous plan are completed before the commands in any subsequent
	                 * plans are executed.
	                 */
                openPlan();
            } else if (this.planContexts[planIndex] != null) {
                this.getContext().getTransactionServer().resume(this.planContexts[planIndex]);
            }
            // Execute nextBatch() on each plan in sequence
            TupleBatch nextBatch = null;
            do {
                // Can throw BlockedException
                nextBatch = updatePlans[planIndex].nextBatch();
                List<List<?>> currentBatch = nextBatch.getTuples();
                for (int i = 0; i < currentBatch.size(); i++, commandIndex++) {
                    updateCounts[commandIndex] = currentBatch.get(i);
                }
            } while (!nextBatch.getTerminationFlag());
            // since we are done with the plan explicitly close it.
            updatePlans[planIndex].close();
            if (this.planContexts[planIndex] != null) {
                TransactionService ts = this.getContext().getTransactionServer();
                ts.commit(this.planContexts[planIndex]);
                this.planContexts[planIndex] = null;
            }
            planIndex++;
        } catch (BlockedException e) {
            throw e;
        } catch (TeiidComponentException | TeiidProcessingException e) {
            if (singleResult) {
                throw e;
            }
            Throwable cause = e;
            if (e.getCause() instanceof TranslatorBatchException) {
                TranslatorBatchException tbe = (TranslatorBatchException) e.getCause();
                for (int i = 0; i < tbe.getUpdateCounts().length; i++) {
                    updateCounts[commandIndex++] = Arrays.asList(tbe.getUpdateCounts()[i]);
                }
            }
            updateCounts = Arrays.copyOf(updateCounts, commandIndex);
            getContext().setBatchUpdateException(cause);
        } finally {
            if (planIndex < updatePlans.length && this.planContexts[planIndex] != null) {
                this.getContext().getTransactionServer().suspend(this.planContexts[planIndex]);
            }
        }
    }
    if (singleResult) {
        long result = 0;
        for (int i = 0; i < updateCounts.length; i++) {
            int value = (Integer) updateCounts[i].get(0);
            if (value == Statement.EXECUTE_FAILED) {
                // the batch results rather than throwing an exception
                throw new TeiidProcessingException(QueryPlugin.Event.TEIID31199, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31198));
            }
            if (value > 0) {
                result += value;
            }
        }
        TupleBatch batch = new TupleBatch(1, new List<?>[] { Arrays.asList((int) Math.min(Integer.MAX_VALUE, result)) });
        batch.setTerminationFlag(true);
        return batch;
    }
    // Add tuples to current batch
    TupleBatch batch = new TupleBatch(1, updateCounts);
    batch.setTerminationFlag(true);
    return batch;
}
Also used : TransactionService(org.teiid.dqp.service.TransactionService) BlockedException(org.teiid.common.buffer.BlockedException) TranslatorBatchException(org.teiid.translator.TranslatorBatchException) TeiidProcessingException(org.teiid.core.TeiidProcessingException) ArrayList(java.util.ArrayList) List(java.util.List) TeiidComponentException(org.teiid.core.TeiidComponentException) TupleBatch(org.teiid.common.buffer.TupleBatch)

Aggregations

TranslatorBatchException (org.teiid.translator.TranslatorBatchException)6 BatchUpdateException (java.sql.BatchUpdateException)4 PreparedStatement (java.sql.PreparedStatement)4 ResultSet (java.sql.ResultSet)3 ArrayList (java.util.ArrayList)3 Test (org.junit.Test)3 Insert (org.teiid.language.Insert)3 Connection (java.sql.Connection)2 ResultSetMetaData (java.sql.ResultSetMetaData)2 SQLException (java.sql.SQLException)2 List (java.util.List)2 FakeExecutionContextImpl (org.teiid.dqp.internal.datamgr.FakeExecutionContextImpl)2 BulkCommand (org.teiid.language.BulkCommand)2 TranslatorException (org.teiid.translator.TranslatorException)2 Statement (java.sql.Statement)1 GeneratedKeys (org.teiid.GeneratedKeys)1 ModelMetaData (org.teiid.adminapi.impl.ModelMetaData)1 BlockedException (org.teiid.common.buffer.BlockedException)1 TupleBatch (org.teiid.common.buffer.TupleBatch)1 TeiidComponentException (org.teiid.core.TeiidComponentException)1