/*
 * 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.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>ParameterizedSQLBatchWritingMechanism is a private class, used by the DatabaseAccessor. it provides the required
 * behavior for batching statements, for write, with parameter binding turned on.</p>
 *
 * @since OracleAS TopLink 10<i>g</i> (9.0.4)
 */
public class ParameterizedSQLBatchWritingMechanism extends BatchWritingMechanism {

    /**
     * This member variable is used to keep track of the last SQL string that was executed
     * by this mechanism.  If the current string and previous string match then simply
     * bind in the arguments, otherwise end previous batch and start a new batch
     */
    protected DatabaseCall previousCall;

    /**
     * This variable contains a list of the parameters list passed into the query
     */
    protected List<List> parameters;
    protected DatabaseCall lastCallAppended;

    public ParameterizedSQLBatchWritingMechanism() {
        super();
    }

    public ParameterizedSQLBatchWritingMechanism(DatabaseAccessor databaseAccessor) {
        this.databaseAccessor = databaseAccessor;
        this.parameters = new ArrayList<>();
        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_PARAMETERIZED_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()) {
            //make an equality check on the String, because if we are caching statements then
            //we will not have to perform the string comparison multiple times.
            if (this.previousCall == null) {
                this.previousCall = dbCall;
                this.parameters.add(dbCall.getParameters());
            } else {
                if (this.previousCall.getSQLString().equals(dbCall.getSQLString()) && (this.parameters.size() < this.maxBatchSize)) {
                    this.parameters.add(dbCall.getParameters());
                } else {
                    executeBatchedStatements(session);
                    this.previousCall = dbCall;
                    this.parameters.add(dbCall.getParameters());
                }
            }
            // Store the largest queryTimeout on a single call for later use by the single statement in prepareBatchStatements
            if (dbCall != null) {
                cacheQueryTimeout(session, dbCall);
            }
            this.lastCallAppended = 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() {
        this.previousCall = null;
        //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.parameters = new ArrayList<>();
        this.statementCount = 0;
        this.executionCount  = 0;
        this.queryTimeoutCache = DescriptorQueryManager.NoTimeout;
        // bug 229831 : BATCH WRITING CAUSES MEMORY LEAKS WITH UOW
        this.lastCallAppended = null;
    }

    /**
     * INTERNAL:
     * This method is used by the DatabaseAccessor to clear the batched statements in the
     * case that a non batchable statement is being executed
     */
    @Override
    public void executeBatchedStatements(AbstractSession session) {
        if (this.parameters.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).
        ParameterizedSQLBatchWritingMechanism currentBatch = (ParameterizedSQLBatchWritingMechanism) 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.parameters.size() == 1) {
            // If only one call, just execute normally.
            try {
                int rowCount = (Integer)this.databaseAccessor.basicExecuteCall(this.previousCall, null, session, false);
                if (this.previousCall.hasOptimisticLock()) {
                    if (rowCount != 1) {
                        throw OptimisticLockException.batchStatementExecutionFailure();
                    }
                }
            } finally {
                clear();
            }
            return;
        }

        try {
            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);
                session.log(SessionLog.FINE, SessionLog.SQL, this.previousCall.getSQLString(), null, this.databaseAccessor, false);
                // took this logging part from SQLCall
                for (List callParameters : this.parameters) {
                    StringWriter writer = new StringWriter();
                    DatabaseCall.appendLogParameters(callParameters, this.databaseAccessor, writer, session);
                    session.log(SessionLog.FINE, SessionLog.SQL, writer.toString(), null, this.databaseAccessor, false);
                }
                session.log(SessionLog.FINER, SessionLog.SQL, "end_batch_statements", null, this.databaseAccessor);
            }

            //bug 4241441: need to keep track of rows modified and throw opti lock exception if needed
            PreparedStatement statement = prepareBatchStatements(session);
            // += is used as native batch writing can return a row count before execution.
            this.executionCount += this.databaseAccessor.executeJDK12BatchStatement(statement, this.lastCallAppended, session, true);
            this.databaseAccessor.writeStatementsCount++;

            if (this.previousCall.hasOptimisticLock() && (this.executionCount != this.statementCount)) {
                throw OptimisticLockException.batchStatementExecutionFailure();
            }
        } finally {
            // Reset the batched sql string
            //we MUST clear the mechanism here in order to append the new statement.
            this.clear();
        }
    }

    /**
     * INTERNAL:
     * Swaps out the Mechanism for the other Mechanism
     */
    protected void switchMechanisms(AbstractSession session, DatabaseCall dbCall) {
        this.databaseAccessor.setActiveBatchWritingMechanismToDynamicSQL();
        this.databaseAccessor.getActiveBatchWritingMechanism(session).appendCall(session, dbCall);
    }

    /**
     * INTERNAL:
     * This method is used to build the parameterized batch statement for the JDBC2.0 specification
     */
    protected PreparedStatement prepareBatchStatements(AbstractSession session) throws DatabaseException {
        PreparedStatement statement = null;
        try {
            session.startOperationProfile(SessionProfiler.SqlPrepare, null, SessionProfiler.ALL);
            try {
                DatabasePlatform platform = session.getPlatform();
                boolean shouldUnwrapConnection = platform.usesNativeBatchWriting();
                statement = (PreparedStatement)this.databaseAccessor.prepareStatement(this.previousCall, session, shouldUnwrapConnection);
                // Perform platform specific preparations
                platform.prepareBatchStatement(statement, this.maxBatchSize);
                   if (this.queryTimeoutCache > DescriptorQueryManager.NoTimeout) {
                    // Set the query timeout that was cached during the multiple calls to appendCall
                       statement.setQueryTimeout(this.queryTimeoutCache);
                }

                // Iterate over the parameter lists that were batched.
                int statementSize = this.parameters.size();
                for (int statementIndex = 0; statementIndex < statementSize; ++statementIndex) {
                    List parameterList = this.parameters.get(statementIndex);
                    int size = parameterList.size();
                    for (int index = 0; index < size; index++) {
                        platform.setParameterValueInDatabaseCall(parameterList.get(index), statement, index+1, session);
                    }

                    // Batch the parameters to the statement.
                    this.statementCount++;
                    this.executionCount += platform.addBatch(statement);
                }
            } 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, lastCallAppended);
            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;
    }

    public DatabaseCall getPreviousCall() {
        return previousCall;
    }

    public void setPreviousCall(DatabaseCall previousCall) {
        this.previousCall = previousCall;
    }

    public List<List> getParameters() {
        return parameters;
    }

    public void setParameters(List<List> parameters) {
        this.parameters = parameters;
    }

    public DatabaseCall getLastCallAppended() {
        return lastCallAppended;
    }

    public void setLastCallAppended(DatabaseCall lastCallAppended) {
        this.lastCallAppended = lastCallAppended;
    }
}
