/*
 * 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
//     07/13/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     08/24/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     09/03/2015 - Will Dazey
//       - 456067 : Added support for defining query timeout units
package org.eclipse.persistence.internal.queries;

import java.util.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.databaseaccess.*;
import org.eclipse.persistence.internal.expressions.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.queries.*;

/**
 * <p><b>Purpose</b>:
 * Mechanism used for custom SQL and stored procedure queries.
 * </p>
 * <p><b>Responsibilities</b>:
 * Executes the appropriate call.
 * </p>
 * @author James Sutherland
 * @since TOPLink/Java 2.0
 */
public class CallQueryMechanism extends DatasourceCallQueryMechanism {

    public CallQueryMechanism() {
    }

    /**
     * Initialize the state of the query
     * @param query - owner of mechanism
     */
    public CallQueryMechanism(DatabaseQuery query) {
        super(query);
    }

    /**
     * Initialize the state of the query
     * @param query - owner of mechanism
     * @param call - sql call
     */
    public CallQueryMechanism(DatabaseQuery query, DatabaseCall call) {
        super(query, call);
        call.setIsFieldMatchingRequired(true);
    }

    /**
     * Return the call.
     */
    public DatabaseCall getDatabaseCall() {
        return (DatabaseCall)call;
    }

    /**
     * Unprepare the call if required.
     * Clone and unprepare stored procedure calls, so they can be reprepared with possible different optional arguments.
     */
    @Override
    public void unprepare() {
        DatabaseQuery query = this.query;
        if (hasMultipleCalls()) {
            this.calls = ((Vector)this.calls.clone());
            int size = this.calls.size();
            for (int index = 0; index < size; index++) {
                DatabaseCall call = (DatabaseCall)this.calls.get(index);
                if (call.isPrepared() && call.isStoredProcedureCall()
                        && ((StoredProcedureCall)call).hasOptionalArguments()) {
                    call = (DatabaseCall)call.clone();
                    call.setIsPrepared(false);
                    call.setQuery(query);
                    this.calls.set(index, call);
                }
            }
        } else if (this.call != null) {
            if (this.call.isPrepared() && this.call.isStoredProcedureCall()
                    && ((StoredProcedureCall)this.call).hasOptionalArguments()) {
                this.call = (DatabaseCall)this.call.clone();
                this.call.setIsPrepared(false);
                this.call.setQuery(query);
            }
        }
    }

    /**
     * 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 prepareCall() throws QueryException {
        DatabaseQuery query = this.query;
        AbstractSession executionSession = query.getExecutionSession();
        if (hasMultipleCalls()) {
            if (query.shouldCloneCall()) {
                this.calls = ((Vector)this.calls.clone());
            }
            int size = this.calls.size();
            for (int index = 0; index < size; index++) {
                DatasourceCall call = (DatasourceCall)this.calls.get(index);
                if (query.shouldCloneCall()) {
                    // Need to clone the call if setting query specific properties on it as the call may be shared.
                    call = (DatabaseCall)call.clone();
                    call.setQuery(query);
                    this.calls.set(index, call);
                }
                if (call instanceof DatabaseCall) {
                    configureDatabaseCall((DatabaseCall)call);
                }
                call.prepare(executionSession);
            }
        } else if (this.call != null) {
            if (query.shouldCloneCall()) {
                // Need to clone the call if setting query specific properties on it as the call may be shared.
                this.call = (DatasourceCall)this.call.clone();
                this.call.setQuery(query);
            }
            DatasourceCall call = this.call;
            if (call instanceof DatabaseCall) {
                configureDatabaseCall((DatabaseCall)call);
            }
            this.call.prepare(executionSession);
        }
    }

    /**
     * Set the call level query options into the call.
     */
    protected void configureDatabaseCall(DatabaseCall call) {
        if (!this.query.shouldIgnoreBindAllParameters()) {
            call.setUsesBinding(this.query.shouldBindAllParameters());
        }
        if (!this.query.shouldIgnoreCacheStatement()) {
            call.setShouldCacheStatement(this.query.shouldCacheStatement());
        }
        call.setQueryTimeout(this.query.getQueryTimeout());
        call.setQueryTimeoutUnit(this.query.getQueryTimeoutUnit());
        if (this.query.isNativeConnectionRequired()) {
            call.setIsNativeConnectionRequired(true);
        }
        if (this.query.isReadQuery()) {
            ReadQuery readQuery = (ReadQuery)this.query;
            // Some DB don't support FirstRow in SELECT statements in spite of supporting MaxResults(Symfoware).
            // We should check FirstRow and MaxResults separately.
            if (!call.shouldIgnoreFirstRowSetting()){
                if (readQuery.getFirstResult() != 0) {
                    call.setFirstResult(readQuery.getFirstResult());
                    call.setIsResultSetScrollable(true);
                    call.setResultSetType(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE);
                    call.setResultSetConcurrency(java.sql.ResultSet.CONCUR_READ_ONLY);
                }
            }
            if (!call.shouldIgnoreMaxResultsSetting()){
                call.setMaxRows(readQuery.getMaxRows());
            }
            call.setResultSetFetchSize(readQuery.getFetchSize());
        }
    }

    /**
     * Pre-build configure the SQL call.
     */
    @Override
    public void prepareCursorSelectAllRows() throws QueryException {
        getCall().returnCursor();

        ContainerPolicy cp;
        DatabaseQuery query = getQuery();
        if (query.isReadAllQuery()) {
            cp = ((ReadAllQuery)query).getContainerPolicy();
        } else {
            cp = ((DataReadQuery)query).getContainerPolicy();
        }
        if (cp.isScrollableCursorPolicy()) {
            ScrollableCursorPolicy scp = (ScrollableCursorPolicy)cp;
            DatabaseCall call = getDatabaseCall();
            call.setIsResultSetScrollable(true);
            call.setResultSetType(scp.getResultSetType());
            call.setResultSetConcurrency(scp.getResultSetConcurrency());
            // Only set the fetch size to be the page size, if the fetch size was not set on the query.
            if (((ReadQuery)getQuery()).getFetchSize() == 0) {
                call.setResultSetFetchSize(scp.getPageSize());
            }
        }
        if (getQuery().isReportQuery()){
            prepareReportQueryItems();
        }
        prepareCall();
    }

    /**
     * Pre-build configure the SQL call.
     */
    @Override
    public void prepareDeleteAll() {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatabaseCall call = (DatabaseCall)callsEnum.nextElement();
                call.returnNothing();
            }
        } else {
            getCall().returnNothing();
        }

        prepareCall();
    }

    /**
     * Pre-build configure the SQL call.
     */
    @Override
    public void prepareDeleteObject() {
        boolean usesOptimisticLocking = ((DeleteObjectQuery)getQuery()).usesOptimisticLocking();
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatabaseCall call = (DatabaseCall)callsEnum.nextElement();
                call.returnNothing();
                if (usesOptimisticLocking) {
                    call.setHasOptimisticLock(true);
                }
            }
        } else {
            getCall().returnNothing();
            if (usesOptimisticLocking) {
                getDatabaseCall().setHasOptimisticLock(true);
            }
        }
        prepareCall();
    }

    /**
     * Pre-build configure the SQL call.
     */
    @Override
    public void prepareDoesExist(DatabaseField field) {
        getCall().returnOneRow();
        Vector fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
        fields.addElement(field);
        getDatabaseCall().setFields(fields);
        prepareCall();
    }

    /**
     * Pre-build configure the SQL call for an execute call.
     */
    @Override
    public void prepareExecute() {
        DatabaseCall call = getDatabaseCall();
        call.setExecuteUpdate();
        call.setIsFieldMatchingRequired(isCallQueryMechanism());
        prepareCall();
    }

    /**
     * Pre-build configure the SQL call.
     */
    @Override
    public void prepareExecuteSelect() {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatabaseCall databseCall = (DatabaseCall)callsEnum.nextElement();
                databseCall.returnManyRows();
                databseCall.setIsFieldMatchingRequired(isCallQueryMechanism());
            }
        } else {
            DatabaseCall call = getDatabaseCall();
            call.returnManyRows();
            call.setIsFieldMatchingRequired(isCallQueryMechanism());
        }
        prepareCall();
    }

    /**
     * Pre-build configure the SQL call.
     */
    @Override
    public void prepareSelectAllRows() {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatabaseCall call = (DatabaseCall)callsEnum.nextElement();
                call.returnManyRows();
                if (isCallQueryMechanism()) {
                    call.setIsFieldMatchingRequired(true);
                    // Set the fields including joined and partial fields and compute joined indexes,
                    // this requires and assume that the custom SQL returns the fields in the correct order.
                    call.setFields(((ObjectLevelReadQuery)getQuery()).getSelectionFields());
                    prepareJoining((ObjectLevelReadQuery)getQuery());
                }
            }
        } else {
            getCall().returnManyRows();
            if (isCallQueryMechanism()) {
                DatabaseCall call = getDatabaseCall();
                call.setIsFieldMatchingRequired(true);
                // Set the fields including joined and partial fields and compute joined indexes,
                // this requires and assume that the custom SQL returns the fields in the correct order.
                call.setFields(((ObjectLevelReadQuery)getQuery()).getSelectionFields());
                prepareJoining((ObjectLevelReadQuery)getQuery());
            }
        }
        prepareCall();
    }

    /**
     * Prepare the joining indexes if joining.
     */
    protected void prepareJoining(ObjectLevelReadQuery query) {
        if (query.hasJoining()) {
            query.getJoinedAttributeManager().computeJoiningMappingIndexes(true, getSession(), 0);
        }
    }

    /**
     * Pre-build configure the SQL call.
     */
    @Override
    public void prepareSelectOneRow() {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatabaseCall call = (DatabaseCall)callsEnum.nextElement();
                call.returnOneRow();
                if (isCallQueryMechanism()) {
                    call.setIsFieldMatchingRequired(true);
                    // Set the fields including joined and partial fields and compute joined indexes,
                    // this requires and assume that the custom SQL returns the fields in the correct order.
                    call.setFields(((ObjectLevelReadQuery)getQuery()).getSelectionFields());
                    prepareJoining((ObjectLevelReadQuery)getQuery());
                }
            }
        } else {
            getCall().returnOneRow();
            if (isCallQueryMechanism()) {
                DatabaseCall call = getDatabaseCall();
                call.setIsFieldMatchingRequired(true);
                // Set the fields including joined and partial fields and compute joined indexes,
                // this requires and assume that the custom SQL returns the fields in the correct order.
                call.setFields(((ObjectLevelReadQuery)getQuery()).getSelectionFields());
                prepareJoining((ObjectLevelReadQuery)getQuery());
            }
        }
        prepareCall();
    }

    /**
     * Pre-build configure the SQL call.
     */
    @Override
    public void prepareUpdateObject() {
        if (hasMultipleCalls()) {
            int size = this.calls.size();
            for (int index = 0; index < size; index++) {
                DatabaseCall call = (DatabaseCall)this.calls.get(index);
                if (!call.isReturnSet()) {
                    call.returnNothing();
                }
                if (this.query.getDescriptor().usesOptimisticLocking()) {
                    call.setHasOptimisticLock(true);
                }
            }
        } else if (this.call != null) {
            if (!call.isReturnSet()) {
                this.call.returnNothing();
            }
            if (this.query.getDescriptor().usesOptimisticLocking()) {
                ((DatabaseCall)this.call).setHasOptimisticLock(true);
            }
        }
        prepareCall();
    }

    /**
     * INTERNAL:
     * Configure the call to be a dynamic custom SQL call, so that it ignores the # token.
     */
    public void setCallHasCustomSQLArguments() {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatabaseCall databaseCall = (DatabaseCall)callsEnum.nextElement();
                if (databaseCall.isSQLCall()) {
                    ((SQLCall)databaseCall).setHasCustomSQLArguments(true);
                }
            }
        } else if (getCall().isSQLCall()) {
            ((SQLCall)getCall()).setHasCustomSQLArguments(true);
        }
    }

    /**
     * Update the foreign key fields when resolving a bi-directional reference in a UOW.
     * This must always be dynamic as it is called within an insert query and is really part of the insert
     * and does not fire update events or worry about locking.
     */
    @Override
    protected void updateForeignKeyFieldAfterInsert(WriteObjectQuery writeQuery) {
        ClassDescriptor descriptor = getDescriptor();
        for (DatabaseTable table : descriptor.getTables()) {
            AbstractRecord row = descriptor.getObjectBuilder().buildRowForUpdateAfterShallowInsert(writeQuery.getObject(), writeQuery.getSession(), table);
            if (!row.isEmpty()) {
                SQLUpdateStatement updateStatement = new SQLUpdateStatement();
                updateStatement.setModifyRow(row);
                updateStatement.setTranslationRow(getTranslationRow());
                updateStatement.setTable(table);
                updateStatement.setWhereClause(descriptor.getObjectBuilder().buildPrimaryKeyExpression(table));// Must not check version, ok as just inserted it.
                // Bug 2996585
                StatementQueryMechanism updateMechanism = new StatementQueryMechanism(writeQuery, updateStatement);
                writeQuery.setModifyRow(row);
                updateMechanism.updateObject();
            }
        }
    }

    /**
     * Update the foreign key fields to null when resolving a deletion cycle.
     * This must always be dynamic as it is called within an delete query and is really part of the delete
     * and does not fire update events or worry about locking.
     */
    @Override
    public void updateForeignKeyFieldBeforeDelete() {
        ClassDescriptor descriptor = getDescriptor();
        DeleteObjectQuery deleteQuery = (DeleteObjectQuery)getQuery();
        for (DatabaseTable table : descriptor.getTables()) {
            // need nullify the same fields that would be updated after shallow insert
            AbstractRecord row = descriptor.getObjectBuilder().buildRowForUpdateBeforeShallowDelete(deleteQuery.getObject(), deleteQuery.getSession(), table);
            if (!row.isEmpty()) {
                SQLUpdateStatement updateStatement = new SQLUpdateStatement();
                updateStatement.setModifyRow(row);
                updateStatement.setTranslationRow(getTranslationRow());
                updateStatement.setTable(table);
                updateStatement.setWhereClause(descriptor.getObjectBuilder().buildPrimaryKeyExpression(table));// Must not check version, ok as delete will.
                StatementQueryMechanism updateMechanism = new StatementQueryMechanism(deleteQuery, updateStatement);
                deleteQuery.setModifyRow(row);
                updateMechanism.updateObject();
            }
        }
    }
}
