All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mariadb.jdbc.internal.queryresults.MultiVariableIntExecutionResult Maven / Gradle / Ivy

package org.mariadb.jdbc.internal.queryresults;

import org.mariadb.jdbc.internal.queryresults.resultset.MariaSelectResultSet;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

public class MultiVariableIntExecutionResult implements MultiExecutionResult {

    private Statement statement = null;
    private boolean moreResultAvailable;
    private int fetchSize;
    private boolean selectPossible;
    private boolean canHaveCallableResultset;
    public Deque cachedExecutionResults;
    private MariaSelectResultSet resultSet = null;
    private List insertId;
    private List affectedRows;
    private int waitedSize;

    /**
     * Constructor. Creating resultSet data with size according to datas.
     *
     * @param statement current statement
     * @param size      initial data size
     * @param fetchSize resultet fetch size
     * @param selectPossible is select command possible
     */
    public MultiVariableIntExecutionResult(Statement statement, int size, int fetchSize, boolean selectPossible) {
        this.statement = statement;
        this.fetchSize = fetchSize;
        this.selectPossible = selectPossible;
        this.canHaveCallableResultset = false;
        this.cachedExecutionResults = new ArrayDeque<>();

        affectedRows = new ArrayList<>(size);
        insertId = new ArrayList<>(size);
    }

    /**
     * Add a resultSet information.
     *
     * @param result              resultset implementation
     * @param moreResultAvailable is there additional packet
     */
    public void addResultSet(MariaSelectResultSet result, boolean moreResultAvailable) {
        this.resultSet = result;
        this.insertId.add((long) Statement.SUCCESS_NO_INFO);
        this.affectedRows.add(-1);
        this.setMoreResultAvailable(moreResultAvailable);
    }

    /**
     * Add execution statistics.
     *
     * @param affectedRows        number of affected rows
     * @param insertId            primary key
     * @param moreResultAvailable is there additional packet
     */
    public void addStats(long affectedRows, long insertId, boolean moreResultAvailable) {
        this.insertId.add(insertId);
        this.affectedRows.add((int) affectedRows);
        setMoreResultAvailable(moreResultAvailable);
    }

    /**
     * Get insert ids.
     * @return insert ids results
     */
    public long[] getInsertIds() {
        long[] ret = new long[insertId.size()];
        Iterator iterator = insertId.iterator();
        for (int i = 0; i < ret.length; i++) {
            ret[i] = iterator.next().longValue();
        }
        return ret;
    }

    /**
     * Get update array.
     * @return update array.
     */
    public int[] getAffectedRows() {
        int[] ret = new int[affectedRows.size()];
        Iterator iterator = affectedRows.iterator();
        for (int i = 0; i < ret.length; i++) {
            ret[i] = iterator.next().intValue();
        }
        return ret;
    }

    public boolean hasMoreThanOneAffectedRows() {
        return affectedRows.size() > 0;
    }

    public int getFirstAffectedRows() {
        return affectedRows.get(0);
    }

    /**
     * Add resutl information when an Exception occur during batch.
     * @param moreResultAvailable has more result flag
     */
    public void addStatsError(boolean moreResultAvailable) {
        this.affectedRows.add(Statement.EXECUTE_FAILED);
        this.insertId.add(null);
        setMoreResultAvailable(moreResultAvailable);
    }

    public void addStatsError() {
        this.affectedRows.add(Statement.EXECUTE_FAILED);
        this.insertId.add(null);
    }

    /**
     * Add missing information when Exception is thrown.
     * @param sendCommand send number of command
     */
    public void fixStatsError(int sendCommand) {
        for (;this.affectedRows.size() < sendCommand;) {
            this.affectedRows.add(Statement.EXECUTE_FAILED);
            this.insertId.add(null);
        }
    }

    /**
     * Set resultSet for rewrite queries.
     *
     * INSERT INTO XX VALUES (YYY)
     * INSERT INTO XX VALUES (ZZZ)
     * is rewritten
     * INSERT INTO XX VALUES (YYY), (ZZZ)
     *
     * so modified row, will all be on the first row, or on a few rows :
     * queries will split to have query size under the max_allowed_size, so data can be on multiple rows
     *
     * @param waitedSize  batchSize
     * @param hasException has exception
     * @return affected rows
     */
    public int[] updateResultsForRewrite(int waitedSize, boolean hasException) {
        this.waitedSize = waitedSize;
        long totalAffectedRows = 0;
        Iterator iterator = affectedRows.iterator();

        while (iterator.hasNext()) {
            totalAffectedRows += iterator.next().intValue();
        }
        int realSize = (int) Math.max(waitedSize, totalAffectedRows);
        int baseResult = totalAffectedRows == realSize ? 1 : Statement.SUCCESS_NO_INFO;

        int[] arr = new int[realSize];
        int counter = 0;
        iterator = affectedRows.iterator();
        while (iterator.hasNext()) {
            int affectedRow = iterator.next().intValue();
            for (int i = 0; i < affectedRow; i++) arr[counter++] = baseResult;
        }
        for (;counter < realSize;) arr[counter++] = hasException ? Statement.EXECUTE_FAILED : Statement.SUCCESS_NO_INFO;
        return arr;
    }

    /**
     * Generate insert id's array for rewrite operation.
     * Rewrite operation will return only the first insert ids.
     * Problem is rewrite queries cannot exceed max_allowed_packet size.
     * so when sending many packet, driver must reconstruct the insert ids according to each packet first insert ids
     * and connection AUTO_INCREMENT.
     *
     * //TODO innodb_autoinc_lock_mode if  changed to "Interleaved Lock Mode", driver cannot ensure that insert ids values.
     *
     * Id's can be reconstruct using
     *
     *
     * @param autoIncrementIncrement connection AUTO_INCREMENT variable
     * @return insert ids array
     */
    public long[] getInsertIdsForRewrite(int autoIncrementIncrement) {
        long totalAffectedRows = 0L;
        Iterator iterator = affectedRows.iterator();
        Iterator idsIterator = insertId.iterator();

        while (iterator.hasNext()) {
            int affectedRow = iterator.next().intValue();
            if (affectedRow == Statement.EXECUTE_FAILED) return new long[0];
            totalAffectedRows += affectedRow;
        }
        long realSize = Math.max(waitedSize, totalAffectedRows);

        long[] arr = new long[(int) realSize];
        int counter = 0;
        iterator = affectedRows.iterator();
        while (iterator.hasNext()) {
            long id = idsIterator.next().longValue();
            int affectedRow = iterator.next().intValue();
            if (affectedRow == Statement.EXECUTE_FAILED) break;
            for (int i = 0; i < affectedRow; i++) arr[counter++] = id + i * autoIncrementIncrement;
        }
        for (;counter < realSize;) arr[counter++] = Statement.EXECUTE_FAILED;
        return arr;
    }

    /**
     * Set update resultSet right on multiple rewrite.
     *
     * INSERT XXXX
     * INSERT XXXX
     * is rewritten
     * INSERT XXXX;INSERT XXXX
     *
     * So affected rows and insert Id are separate in as many okPacket.
     *
     * @param waitedSize  batchSize
     * @param hasException has exception
     */
    public int[] updateResultsMultiple(int waitedSize, boolean hasException) {
        if (hasException) {
            for (int i = affectedRows.size() ; i < waitedSize; i++) {
                addStatsError();
            }
        }
        return getAffectedRows();
    }

    public MariaSelectResultSet getResultSet() {
        return resultSet;
    }

    public Statement getStatement() {
        return statement;
    }

    public boolean hasMoreResultAvailable() {
        return moreResultAvailable;
    }

    protected void setMoreResultAvailable(boolean moreResultAvailable) {
        this.moreResultAvailable = moreResultAvailable;
    }

    public int getFetchSize() {
        return fetchSize;
    }

    public void setFetchSize(int fetchSize) {
        this.fetchSize = fetchSize;
    }

    /**
     * Close resultset if needed.
     *
     * @throws SQLException if exception occur during resultset close.
     */
    public void close() throws SQLException {
        if (resultSet != null) {
            resultSet.close();
        }
    }

    public boolean isSelectPossible() {
        return selectPossible;
    }

    public boolean isCanHaveCallableResultset() {
        return canHaveCallableResultset;
    }

    public Deque getCachedExecutionResults() {
        return cachedExecutionResults;
    }

    public void addResult(ExecutionResult executionResult) {
        cachedExecutionResults.add(executionResult);
    }

    public boolean isSingleExecutionResult() {
        return false;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy