/*
 * 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
            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;
    }
}
