/*
 * Copyright (c) 1998, 2019 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.queries;

import java.util.Enumeration;
import java.util.Vector;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.databaseaccess.DatasourceCall;
import org.eclipse.persistence.internal.expressions.SQLModifyStatement;
import org.eclipse.persistence.internal.expressions.SQLStatement;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.sessions.SessionProfiler;
/**
 * <p><b>Purpose</b>:
 * Mechanism used for all  statement objects.
 * <p><b>Responsibilities</b>:
 * Executes the appropriate statement.
 *
 * @author Yvon Lavoie
 * @since TOPLink/Java 1.0
 */
public class StatementQueryMechanism extends CallQueryMechanism {
    protected SQLStatement sqlStatement;

    /** Normally only a single statement is used, however multiple table may require multiple statements on write. */
    protected Vector sqlStatements;

    public StatementQueryMechanism() {
    }

    /**
     * INTERNAL:
     * Return a new mechanism for the query
     * @param query - owner of mechanism
     */
    public StatementQueryMechanism(DatabaseQuery query) {
        super(query);
    }

    /**
     * Return a new mechanism for the query
     * @param query - owner of mechanism
     * @param statement - sql statement
     */
    public StatementQueryMechanism(DatabaseQuery query, SQLStatement statement) {
        super(query);
        this.sqlStatement = statement;
    }

    /**
     * The statement is no longer require after prepare so can be released.
     */
    public void clearStatement() {
        // Only clear the statement if it is an expression query, otherwise the statement may still be needed.
    }

    /**
     * Clone the mechanism for the specified query clone.
     */
    @Override
    public DatabaseQueryMechanism clone(DatabaseQuery queryClone) {
        StatementQueryMechanism clone = (StatementQueryMechanism)super.clone(queryClone);
        if ((!hasMultipleStatements()) && (getSQLStatement() != null)) {
            clone.setSQLStatement((SQLStatement)sqlStatement.clone());
        } else {
            Vector currentStatements = getSQLStatements();
            if (currentStatements != null) {
                Vector statementClone = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(currentStatements.size());
                Enumeration enumtr = currentStatements.elements();
                while (enumtr.hasMoreElements()) {
                    statementClone.addElement(((SQLStatement)enumtr.nextElement()).clone());
                }
                clone.setSQLStatements(statementClone);
            }
        }
        return clone;
    }

    /**
     * INTERNAL:
     * delete the object
     * @exception  DatabaseException - an error has occurred on the database.
     * @return the row count.
     */
    @Override
    public Integer deleteObject() throws DatabaseException {
        // Prepare the calls if not already set (prepare may not have had the modify row).
        if ((this.call == null) && (!hasMultipleCalls())) {
            prepareDeleteObject();
            if ((this.call == null) && (!hasMultipleCalls())) {
                return Integer.valueOf(1);// Must be 1 otherwise locking error will occur.
            }
        }

        return super.deleteObject();
    }

    /**
     * Update the object
     * @exception  DatabaseException - an error has occurred on the database.
     * @return the row count.
     */
    @Override
    public Integer executeNoSelect() throws DatabaseException {
        // Prepare the calls if not already set (prepare may not have had the modify row).
        if ((this.call == null) && (!hasMultipleCalls())) {
            prepareExecuteNoSelect();
        }

        return super.executeNoSelect();
    }

    /**
     * Return the selection criteria for the statement.
     */
    @Override
    public Expression getSelectionCriteria() {
        return getSQLStatement().getWhereClause();
    }

    /**
     * INTERNAL:
     * Return the sqlStatement
     */
    public SQLStatement getSQLStatement() {
        return sqlStatement;
    }

    /**
     * Normally only a single statement is used, however multiple table may require multiple statements on write.
     * This is lazy initialied to conserv space.
     */
    public Vector getSQLStatements() {
        if (sqlStatements == null) {
            sqlStatements = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(3);
        }
        return sqlStatements;
    }

    /**
     * Normally only a single statement is used, however multiple table may require multiple statements on write.
     * This is lazy initialized to conserve space.
     */
    public boolean hasMultipleStatements() {
        return (sqlStatements != null) && (!sqlStatements.isEmpty());
    }

    /**
     * Insert the object
     * @exception  DatabaseException - an error has occurred on the database.
     */
    @Override
    public void insertObject() throws DatabaseException {
        // Prepare the calls if not already set (prepare may not have had the modify row).
        if ((this.call == null) && (!hasMultipleCalls())) {
            prepareInsertObject();
        }

        super.insertObject();
    }

    /**
     * Insert the object if the reprepare flag is set, first reprepare the query.
     * Added for CR#3237
     * @param reprepare whether to reprepare the query.
     */
    @Override
    public void insertObject(boolean reprepare) {
        if (reprepare) {
            // Clear old calls, and reprepare.
            setCalls(null);
            trimFieldsForInsert();
            prepareInsertObject();
        }
        insertObject();
    }

    /**
     * INTERNAL
     * Remove a potential sequence number field and invoke the ReturningPolicy trimModifyRowsForInsert method
     */
    public void trimFieldsForInsert() {
        getDescriptor().getObjectBuilder().trimFieldsForInsert(getSession(), getModifyRow());
    }

    /**
     * Return true if this is a call query mechanism
     */
    @Override
    public boolean isCallQueryMechanism() {
        return false;
    }

    /**
     * Return true if this is a statement query mechanism
     */
    @Override
    public boolean isStatementQueryMechanism() {
        return true;
    }

    /**
     * INTERNAL:
     * This is different from 'prepareForExecution' in that this is called on the original query,
     * and the other is called on the copy of the query.
     * This query is copied for concurrency so this prepare can only setup things that
     * will apply to any future execution of this query.
     */
    @Override
    public void prepare() {
        if ((!hasMultipleStatements()) && (getSQLStatement() == null)) {
            throw QueryException.sqlStatementNotSetProperly(getQuery());
        }

        // Cannot call super yet as the call is not built.
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareCursorSelectAllRows() {
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareCursorSelectAllRows();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareDeleteAll() {
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareDeleteAll();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareDeleteObject() {
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareDeleteObject();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareDoesExist(DatabaseField field) {
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        getCall().returnOneRow();
        prepareCall();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareExecuteNoSelect() {
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareExecuteNoSelect();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareExecuteSelect() {
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareExecuteSelect();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareInsertObject() {
        // Require modify row to prepare.
        if (getModifyRow() == null) {
            return;
        }

        if (hasMultipleStatements()) {
            for (Enumeration statementEnum = getSQLStatements().elements();
                     statementEnum.hasMoreElements();) {
                ((SQLModifyStatement)statementEnum.nextElement()).setModifyRow(getModifyRow());
            }
        } else if (getSQLStatement() != null) {
            ((SQLModifyStatement)getSQLStatement()).setModifyRow(getModifyRow());
        }
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareInsertObject();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareSelectAllRows() {
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareSelectAllRows();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareSelectOneRow() {
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareSelectOneRow();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareUpdateObject() {
        // Require modify row to prepare.
        if (getModifyRow() == null) {
            return;
        }

        if (hasMultipleStatements()) {
            for (Enumeration statementEnum = getSQLStatements().elements();
                     statementEnum.hasMoreElements();) {
                ((SQLModifyStatement)statementEnum.nextElement()).setModifyRow(getModifyRow());
            }
        } else if (getSQLStatement() != null) {
            ((SQLModifyStatement)getSQLStatement()).setModifyRow(getModifyRow());
        }
        setCallFromStatement();
        // The statement is no longer require so can be released.
        clearStatement();

        super.prepareUpdateObject();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    @Override
    public void prepareUpdateAll() {
        setCallFromStatement();// Will build an SQLUpdateAllStatement
        clearStatement();// The statement is no longer require so can be released.
        super.prepareUpdateAll();
    }

    /**
     * Pre-build the SQL call from the statement.
     */
    protected void setCallFromStatement() {
        // Profile SQL generation.
        getSession().startOperationProfile(SessionProfiler.SqlGeneration, getQuery(), SessionProfiler.ALL);
        try {
            if (hasMultipleStatements()) {
                for (Enumeration statementEnum = getSQLStatements().elements(); statementEnum.hasMoreElements();) {
                    DatasourceCall call = null;
                    if (getDescriptor() != null) {
                        call = getDescriptor().buildCallFromStatement((SQLStatement)statementEnum.nextElement(), getQuery(), getExecutionSession());
                    } else {
                        call = ((SQLStatement)statementEnum.nextElement()).buildCall(getExecutionSession());
                    }

                    // In case of update call may be null if no update required.
                    if (call != null) {
                        addCall(call);
                    }
                }
            } else {
                DatasourceCall call = null;
                if (getDescriptor() != null) {
                    call = getDescriptor().buildCallFromStatement(getSQLStatement(), getQuery(), getExecutionSession());
                } else {
                    call = getSQLStatement().buildCall(getExecutionSession());
                }

                // In case of update call may be null if no update required.
                if (call != null) {
                    setCall(call);
                }
            }
        } finally {
            // Profile SQL generation.
            getSession().endOperationProfile(SessionProfiler.SqlGeneration, getQuery(), SessionProfiler.ALL);
        }
    }

    /**
     * Set the sqlStatement
     */
    public void setSQLStatement(SQLStatement statement) {
        this.sqlStatement = statement;
    }

    /**
     * Normally only a single statement is used, however multiple table may require multiple statements on write.
     * This is lazy initialized to conserve space.
     */
    protected void setSQLStatements(Vector sqlStatements) {
        this.sqlStatements = sqlStatements;
    }

    /**
     * Update the object
     * @exception  DatabaseException - an error has occurred on the database.
     * @return the row count.
     */
    @Override
    public Integer updateObject() throws DatabaseException {
        // Prepare the calls if not already set (prepare may not have had the modify row).
        if ((this.call == null) && (!hasMultipleCalls())) {
            prepareUpdateObject();
            if ((this.call == null) && (!hasMultipleCalls())) {
                return Integer.valueOf(1);// Must be 1 otherwise locking error will occur.
            }
        }

        return super.updateObject();
    }
}
