Search in sources :

Example 1 with BulkCommand

use of org.teiid.language.BulkCommand 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 2 with BulkCommand

use of org.teiid.language.BulkCommand in project teiid by teiid.

the class ConnectorWorkItem method setExecution.

private void setExecution(Command command, org.teiid.language.Command translatedCommand, final Execution exec) {
    if (translatedCommand instanceof Call) {
        // $NON-NLS-1$
        this.execution = Assertion.isInstanceOf(exec, ProcedureExecution.class, "Call Executions are expected to be ProcedureExecutions");
        StoredProcedure proc = (StoredProcedure) command;
        if (proc.returnParameters()) {
            this.procedureBatchHandler = new ProcedureBatchHandler((Call) translatedCommand, (ProcedureExecution) exec);
        }
    } else if (command instanceof QueryCommand) {
        // $NON-NLS-1$
        this.execution = Assertion.isInstanceOf(exec, ResultSetExecution.class, "QueryExpression Executions are expected to be ResultSetExecutions");
    } else {
        final boolean singleUpdateCount = connector.returnsSingleUpdateCount() && (translatedCommand instanceof BatchedUpdates || (translatedCommand instanceof BulkCommand && ((BulkCommand) translatedCommand).getParameterValues() != null));
        // $NON-NLS-1$
        Assertion.isInstanceOf(exec, UpdateExecution.class, "Update Executions are expected to be UpdateExecutions");
        this.execution = new ResultSetExecution() {

            private int[] results;

            private int index;

            @Override
            public void cancel() throws TranslatorException {
                exec.cancel();
            }

            @Override
            public void close() {
                exec.close();
            }

            @Override
            public void execute() throws TranslatorException {
                exec.execute();
            }

            @Override
            public List<?> next() throws TranslatorException, DataNotAvailableException {
                if (results == null) {
                    results = ((UpdateExecution) exec).getUpdateCounts();
                }
                if (singleUpdateCount) {
                    if (index++ < results[0]) {
                        return CollectionTupleSource.UPDATE_ROW;
                    }
                    return null;
                }
                if (index < results.length) {
                    return Arrays.asList(results[index++]);
                }
                return null;
            }
        };
    }
}
Also used : Call(org.teiid.language.Call) StoredProcedure(org.teiid.query.sql.lang.StoredProcedure) BulkCommand(org.teiid.language.BulkCommand) QueryCommand(org.teiid.query.sql.lang.QueryCommand) BatchedUpdates(org.teiid.language.BatchedUpdates)

Example 3 with BulkCommand

use of org.teiid.language.BulkCommand in project teiid by teiid.

the class CassandraUpdateExecution method internalExecute.

private void internalExecute() throws TranslatorException {
    if (this.command instanceof BatchedUpdates) {
        handleBatchedUpdates();
        return;
    }
    CassandraSQLVisitor visitor = new CassandraSQLVisitor();
    visitor.translateSQL(this.command);
    String cql = visitor.getTranslatedSQL();
    // $NON-NLS-1$
    LogManager.logDetail(LogConstants.CTX_CONNECTOR, "Source-Query:", cql);
    this.executionContext.logCommand(cql);
    if (this.command instanceof BulkCommand) {
        BulkCommand bc = (BulkCommand) this.command;
        if (bc.getParameterValues() != null) {
            int count = 0;
            List<Object[]> newValues = new ArrayList<Object[]>();
            Iterator<? extends List<?>> values = bc.getParameterValues();
            while (values.hasNext()) {
                Object[] bindValues = values.next().toArray();
                for (int i = 0; i < bindValues.length; i++) {
                    if (bindValues[i] instanceof Blob) {
                        Blob blob = (Blob) bindValues[i];
                        try {
                            if (blob.length() > Integer.MAX_VALUE) {
                                // $NON-NLS-1$
                                throw new AssertionError("Blob is too large");
                            }
                            byte[] bytes = ((Blob) bindValues[i]).getBytes(0, (int) blob.length());
                            bindValues[i] = ByteBuffer.wrap(bytes);
                        } catch (SQLException e) {
                            throw new TranslatorException(e);
                        }
                    } else if (bindValues[i] instanceof BinaryType) {
                        bindValues[i] = ByteBuffer.wrap(((BinaryType) bindValues[i]).getBytesDirect());
                    }
                }
                newValues.add(bindValues);
                count++;
            }
            updateCount = count;
            resultSetFuture = connection.executeBatch(cql, newValues);
            return;
        }
    }
    resultSetFuture = connection.executeQuery(cql);
}
Also used : Blob(java.sql.Blob) BinaryType(org.teiid.core.types.BinaryType) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) BulkCommand(org.teiid.language.BulkCommand) TranslatorException(org.teiid.translator.TranslatorException) BatchedUpdates(org.teiid.language.BatchedUpdates)

Aggregations

BulkCommand (org.teiid.language.BulkCommand)3 SQLException (java.sql.SQLException)2 ArrayList (java.util.ArrayList)2 BatchedUpdates (org.teiid.language.BatchedUpdates)2 BatchUpdateException (java.sql.BatchUpdateException)1 Blob (java.sql.Blob)1 PreparedStatement (java.sql.PreparedStatement)1 ResultSet (java.sql.ResultSet)1 List (java.util.List)1 GeneratedKeys (org.teiid.GeneratedKeys)1 BinaryType (org.teiid.core.types.BinaryType)1 Call (org.teiid.language.Call)1 Insert (org.teiid.language.Insert)1 NamedTable (org.teiid.language.NamedTable)1 Column (org.teiid.metadata.Column)1 KeyRecord (org.teiid.metadata.KeyRecord)1 QueryCommand (org.teiid.query.sql.lang.QueryCommand)1 StoredProcedure (org.teiid.query.sql.lang.StoredProcedure)1 TranslatorBatchException (org.teiid.translator.TranslatorBatchException)1 TranslatorException (org.teiid.translator.TranslatorException)1