/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.databaseaccess;

import java.io.StringWriter;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.OptimisticLockException;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.queries.ModifyQuery;
import org.eclipse.persistence.sessions.SessionProfiler;

/**
 * INTERNAL:
 *    <p>DynamicSQLBatchWritingMechanism is a private class, used by the DatabaseAccessor.
 *    It provides the required behavior for batching statements, for write, with parameter binding turned off.</p>
 */
public class DynamicSQLBatchWritingMechanism extends BatchWritingMechanism {

    /**
     * This variable is used to store the SQLStrings that are being batched
     */
    protected List<String> sqlStrings;

    /**
     * Stores the statement indexes for statements that are using optimistic locking.  This allows us to check individual
     * statement results on supported platforms
     */

    /**
     * This attribute is used to store the maximum length of all strings batched together
     */
    protected long batchSize;

    /**
     * Records if this batch uses optimistic locking.
     */
    protected boolean usesOptimisticLocking;

    protected DatabaseCall lastCallAppended;

    public DynamicSQLBatchWritingMechanism(DatabaseAccessor databaseAccessor) {
        this.databaseAccessor = databaseAccessor;
        this.sqlStrings = new ArrayList();
        this.batchSize = 0;
        this.maxBatchSize = this.databaseAccessor.getLogin().getPlatform().getMaxBatchWritingSize();
        if (this.maxBatchSize == 0) {
            // the max size was not set on the platform - use default
            this.maxBatchSize = DatabasePlatform.DEFAULT_MAX_BATCH_WRITING_SIZE;
        }
    }

    /**
     * INTERNAL:
     * This method is called by the DatabaseAccessor to add this statement to the list of statements
     * being batched.  This call may result in the Mechanism executing the batched statements and
     * possibly, switching out the mechanisms
     */
    @Override
    public void appendCall(AbstractSession session, DatabaseCall dbCall) {
        if (!dbCall.hasParameters()) {
            if ((this.batchSize + dbCall.getSQLString().length()) > this.maxBatchSize) {
                executeBatchedStatements(session);
            }
            if (this.usesOptimisticLocking != dbCall.hasOptimisticLock) {
                executeBatchedStatements(session);
            }
            this.sqlStrings.add(dbCall.getSQLString());
            this.lastCallAppended = dbCall;
            this.batchSize += dbCall.getSQLString().length();
            this.usesOptimisticLocking = dbCall.hasOptimisticLock;
            this.statementCount++;
            // Store the largest queryTimeout on a single call for later use by the single statement in prepareJDK12BatchStatement
            if (dbCall != null) {
                cacheQueryTimeout(session, dbCall);
            }
            // feature for bug 4104613, allows users to force statements to flush on execution
            if (((ModifyQuery) dbCall.getQuery()).forceBatchStatementExecution()) {
              executeBatchedStatements(session);
            }
        } else {
            executeBatchedStatements(session);
            switchMechanisms(session, dbCall);
        }
    }

    /**
     * INTERNAL:
     * This method is used to clear the batched statements without the need to execute the statements first
     * This is used in the case of rollback.
     */
    @Override
    public void clear() {
        //Bug#419326 : A clone may be holding a reference to this.parameters.
        //So, instead of clearing the parameters, just initialize with a new reference.
        this.sqlStrings = new ArrayList();
        this.statementCount = executionCount  = 0;
        this.usesOptimisticLocking = false;
        this.batchSize = 0;
        this.queryTimeoutCache = DescriptorQueryManager.NoTimeout;
        this.lastCallAppended = null;
    }

    /**
     * INTERNAL:
     * This method is used by the DatabaseAccessor to execute and clear the batched statements in the
     * case that a non batchable statement is being executed
     */
    @Override
    public void executeBatchedStatements(AbstractSession session) {
        if (this.sqlStrings.isEmpty()) {
            return;
        }
        //Bug#419326 : Added below clone, clear and clone.executeBatch(session)
        //Cloning the mechanism and clearing the current mechanism ensures that the current batch
        //is not visible to recursive calls to executeBatchedStatements(session).
        DynamicSQLBatchWritingMechanism currentBatch = (DynamicSQLBatchWritingMechanism) this.clone();
        this.clear();
        currentBatch.executeBatch(session);
    }

    /**
     * INTERNAL:
     * This method is added to execute and clear the batched statements on the cloned batch mechanism which
     * is created in executeBatchedStatements(session).
     *
     * Introduced in fix for bug#419326.
     */
    private void executeBatch(AbstractSession session) {

        if (this.sqlStrings.size() == 1) {
            // If only one call, just execute normally.
            try {
                int rowCount = (Integer)this.databaseAccessor.basicExecuteCall(this.lastCallAppended, null, session, false);
                if (this.usesOptimisticLocking) {
                    if (rowCount != 1) {
                        throw OptimisticLockException.batchStatementExecutionFailure();
                    }
                }
            } finally {
                clear();
            }
            return;
        }

        try {
            this.databaseAccessor.writeStatementsCount++;
            this.databaseAccessor.incrementCallCount(session);// Decrement occurs in close.

            if (session.shouldLog(SessionLog.FINE, SessionLog.SQL)) {
                session.log(SessionLog.FINER, SessionLog.SQL, "begin_batch_statements", null, this.databaseAccessor);
                for (String sql : this.sqlStrings) {
                    session.log(SessionLog.FINE, SessionLog.SQL, sql, null, this.databaseAccessor, false);
                }
                session.log(SessionLog.FINER, SessionLog.SQL, "end_batch_statements", null, this.databaseAccessor);
            }

            if (!session.getPlatform().usesJDBCBatchWriting()) {
                PreparedStatement statement = prepareBatchStatement(session);
                this.databaseAccessor.executeBatchedStatement(statement, session);
            } else {
                //lets add optimistic locking support.
                Statement statement = prepareJDK12BatchStatement(session);
                this.executionCount = this.databaseAccessor.executeJDK12BatchStatement(statement, null, session, false);
                if (this.usesOptimisticLocking && (executionCount != statementCount)) {
                    throw OptimisticLockException.batchStatementExecutionFailure();
                }
            }
        } finally {
            // Reset the batched sql string
            clear();
        }
    }

    /**
     * INTERNAL:
     * This method is used to switch from this mechanism to the alternate automatically
     */
    protected void switchMechanisms(AbstractSession session, DatabaseCall dbCall) {
        this.databaseAccessor.setActiveBatchWritingMechanismToParameterizedSQL();
        this.databaseAccessor.getActiveBatchWritingMechanism(session).appendCall(session, dbCall);
    }

    /**
     * INTERNAL:
     * This method is used to build the batch statement by concatenating the strings
     * together.
     */
    protected PreparedStatement prepareBatchStatement(AbstractSession session) throws DatabaseException {
        PreparedStatement statement = null;
        boolean isDelimiterStringNeeded = false;
        StringWriter writer = new StringWriter();
        DatabasePlatform platform = session.getPlatform();

        writer.write(platform.getBatchBeginString());
        for (String sql : this.sqlStrings) {
            if (isDelimiterStringNeeded) {
                writer.write(platform.getBatchDelimiterString());
            }
            writer.write(sql);
            isDelimiterStringNeeded = true;
        }
        writer.write(platform.getBatchDelimiterString());
        writer.write(platform.getBatchEndString());

        try {
            session.startOperationProfile(SessionProfiler.SqlPrepare, null, SessionProfiler.ALL);
            try {
                statement = this.databaseAccessor.getConnection().prepareStatement(writer.toString());
            } finally {
                session.endOperationProfile(SessionProfiler.SqlPrepare, null, SessionProfiler.ALL);
            }
        } catch (SQLException exception) {
            //If this is a connection from an external pool then closeStatement will close the connection.
            //we must test the connection before that happens.
            DatabaseException exceptionToThrow = this.databaseAccessor.processExceptionForCommError(session, exception, null);
            try {// Ensure that the statement is closed, but still ensure that the real exception is thrown.
                this.databaseAccessor.closeStatement(statement, session, null);
            } catch (SQLException closeException) {
            }
            if (exceptionToThrow == null){
                throw DatabaseException.sqlException(exception, this.databaseAccessor, session, false);
            }
            throw exceptionToThrow;
        } catch (RuntimeException exception) {
            try {// Ensure that the statement is closed, but still ensure that the real exception is thrown.
                this.databaseAccessor.closeStatement(statement, session, null);
            } catch (SQLException closeException) {
            }
            throw exception;
        }
        return statement;
    }

    /**
     * INTERNAL:
     * This method is used to build the batch statement for the JDBC2.0 specification
     */
    protected Statement prepareJDK12BatchStatement(AbstractSession session) throws DatabaseException {
        Statement statement = null;

        try {
            session.startOperationProfile(SessionProfiler.SqlPrepare, null, SessionProfiler.ALL);
            try {
                statement = this.databaseAccessor.getConnection().createStatement();
                for (String sql : this.sqlStrings) {
                    statement.addBatch(sql);
                }
                // Set the query timeout that was cached during the multiple calls to appendCall
                if (this.queryTimeoutCache > DescriptorQueryManager.NoTimeout) {
                    statement.setQueryTimeout(this.queryTimeoutCache);
                }
            } finally {
                session.endOperationProfile(SessionProfiler.SqlPrepare, null, SessionProfiler.ALL);
            }
        } catch (SQLException exception) {
            //If this is a connection from an external pool then closeStatement will close the connection.
            //we must test the connection before that happens.
            RuntimeException exceptionToThrow = this.databaseAccessor.processExceptionForCommError(session, exception, null);
            try {// Ensure that the statement is closed, but still ensure that the real exception is thrown.
                this.databaseAccessor.closeStatement(statement, session, null);
            } catch (SQLException closeException) {
            }
            if (exceptionToThrow == null){
                throw DatabaseException.sqlException(exception, this.databaseAccessor, session, false);
            }
            throw exceptionToThrow;
        } catch (RuntimeException exception) {
            try {// Ensure that the statement is closed, but still ensure that the real exception is thrown.
                this.databaseAccessor.closeStatement(statement, session, null);
            } catch (SQLException closeException) {
            }
            throw exception;
        }
        return statement;
    }
}
