/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2019 IBM Corporation. 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
//     01/31/2017-2.6 Will Dazey
//       - 511426: Adding cloning support
//     04/11/2018 - Will Dazey
//       - 533148 : Add the eclipselink.jpa.sql-call-deferral property
package org.eclipse.persistence.internal.queries;

import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatasourceCall;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.queries.ConstructorReportItem;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DeleteAllQuery;
import org.eclipse.persistence.queries.ReportQuery;
import org.eclipse.persistence.queries.UpdateAllQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;

/**
 * <p><b>Purpose</b>:
 * Mechanism used for call queries.
 * </p>
 * <p><b>Responsibilities</b>:
 * Executes the appropriate call.
 * </p>
 * @author James Sutherland
 * @since OracleAS TopLink 10<i>g</i> (10.0.3)
 */
public class DatasourceCallQueryMechanism extends DatabaseQueryMechanism {
    protected DatasourceCall call;

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

    public DatasourceCallQueryMechanism() {
    }

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

    /**
     * Initialize the state of the query
     * @param query - owner of mechanism
     */
    public DatasourceCallQueryMechanism(DatabaseQuery query, DatasourceCall call) {
        super(query);
        this.call = call;
        call.setQuery(query);
    }

    /**
     * Add the call.
     */
    public void addCall(DatasourceCall call) {
        getCalls().addElement(call);
        call.setQuery(getQuery());
    }

    /**
     * Clone the DatasourceCall and {@code Vector<DatasourceCall>}.
     */
    @Override
    public DatabaseQueryMechanism clone(DatabaseQuery queryClone) {
        DatasourceCallQueryMechanism clone = (DatasourceCallQueryMechanism)super.clone(queryClone);
        if(this.call != null) {
            DatasourceCall callclone = (DatasourceCall)this.call.clone();
            clone.setCall(callclone);
        }
        if(this.calls != null) {
            Vector callsclone = (Vector)this.calls.clone();
            clone.setCalls(callsclone);
        }
        return clone;
    }

    /**
     * Read all rows from the database using a cursored stream.
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public DatabaseCall cursorSelectAllRows() throws DatabaseException {
        try {
            return (DatabaseCall)executeCall();
        } catch (java.lang.ClassCastException e) {
            throw QueryException.mustUseCursorStreamPolicy();
        }
    }

    /**
     * Read all rows from the database, return ResultSet
     * @exception  DatabaseException - an error has occurred on the database
     */
    public DatabaseCall selectResultSet() throws DatabaseException {
        try {
            // For CR 2923 must move to session we will execute call on now
            // so correct DatasourcePlatform used by translate.
            AbstractSession sessionToUse = this.query.getExecutionSession();
            DatabaseCall clonedCall = (DatabaseCall)this.call.clone();
            clonedCall.setQuery(this.query);
            clonedCall.translate(this.query.getTranslationRow(), getModifyRow(), sessionToUse);
            clonedCall.returnCursor();
            return (DatabaseCall)sessionToUse.executeCall(clonedCall, this.query.getTranslationRow(), this.query);
        } catch (java.lang.ClassCastException e) {
            throw QueryException.invalidDatabaseCall(this.call);
        }
    }

    /**
     * INTERNAL:
     * Delete a collection of objects. Assume call is correct.
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public Integer deleteAll() throws DatabaseException {
        if(((DeleteAllQuery)this.query).isPreparedUsingTempStorage()) {
            return deleteAllUsingTempTables();
        } else {
            if (hasMultipleCalls()) {
                Integer returnedRowCount = null;

                // Deletion must occur in reverse order.
                for (int index = getCalls().size() - 1; index >= 0; index--) {
                    DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(index);
                    returnedRowCount = (Integer)executeCall(databseCall);
                }
                // returns the number of rows removed from the first table in insert order
                return returnedRowCount;
            } else {
                return (Integer)executeCall();
            }
        }
    }

    /**
     * Execute deleteAll using temp tables
     * @exception  DatabaseException - an error has occurred on the database.
     * @return the row count.
     */
    public Integer deleteAllUsingTempTables() throws DatabaseException {
        DatabaseException ex = null;
        Integer returnedRowCount = null;

        // Deletion must occur in reverse order.

        // first call - crete temp table.
        // may fail in case global temp table already exists.
        try {
            DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(getCalls().size() - 1);
            executeCall(databseCall);
        } catch (DatabaseException databaseEx) {
            // ignore
        }

        // second call - populate temp table.
        // if that fails save the exception and untill cleanup
        try {
            DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(getCalls().size() - 2);
            executeCall(databseCall);
        } catch (DatabaseException databaseEx) {
            ex = databaseEx;
        }

        // third (a call per table) - delete from original tables calls.
        // if that fails save the exception untill cleanup
        for (int index = getCalls().size() - 3; index >= 1 && ex == null; index--) {
            DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(index);
            try {
                // returns the number of rows removed from the first table in insert order
                returnedRowCount = (Integer)executeCall(databseCall);
            } catch (DatabaseException databaseEx) {
                ex = databaseEx;
            }
        }

        // last call - cleanup temp table.
        // ignore exceptions here.
        try {
            DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(0);
            executeCall(databseCall);
        } catch (DatabaseException databaseEx) {
            // ignore
        }

        if(ex != null) {
            throw ex;
        }

        return returnedRowCount;
    }

    /**
     * INTERNAL:
     * Delete an object.  Assume call is correct
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public Integer deleteObject() throws DatabaseException {
        if (hasMultipleCalls()) {
            Integer returnedRowCount = null;

            // Deletion must occur in reverse order.
            for (int index = getCalls().size() - 1; index >= 0; index--) {
                DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(index);
                Integer rowCount = (Integer)executeCall(databseCall);
                if ((index == (getCalls().size() - 1)) || (rowCount.intValue() <= 0)) {// Row count returned must be from first table or zero if any are zero.
                    returnedRowCount = rowCount;
                }
            }
            return returnedRowCount;
        } else {
            return (Integer)executeCall();
        }
    }

    /**
     * INTERNAL:
     * Execute a call.
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public Object execute() throws DatabaseException {
        return executeCall();
    }

    /**
     * Execute the call.  It is assumed the call has been fully prepared.
     * @exception  DatabaseException - an error has occurred on the database.
     */
    protected Object executeCall() throws DatabaseException {
        return executeCall(this.call);
    }

    /**
     * Execute the call.  It is assumed the call has been fully prepared.
     * @exception  DatabaseException - an error has occurred on the database.
     */
    protected Object executeCall(DatasourceCall databaseCall) throws DatabaseException {
        // For CR 2923 must move to session we will execute call on now
        // so correct DatasourcePlatform used by translate.
        AbstractSession sessionToUse = this.query.getExecutionSession();
        DatasourceCall clonedCall = (DatasourceCall)databaseCall.clone();
        clonedCall.setQuery(this.query);
        clonedCall.translate(this.query.getTranslationRow(), getModifyRow(), sessionToUse);
        return sessionToUse.executeCall(clonedCall, this.query.getTranslationRow(), this.query);
    }

    /**
     * Execute a non selecting call.
     * @exception  DatabaseException - an error has occurred on the database.
     * @return the row count.
     */
    @Override
    public Integer executeNoSelect() throws DatabaseException {
        return executeNoSelectCall();
    }

    /**
     * Execute a non selecting call.
     * @exception  DatabaseException - an error has occurred on the database.
     * @return the row count.
     */
    public Integer executeNoSelectCall() throws DatabaseException {
        if (hasMultipleCalls()) {
            Integer returnedRowCount = null;
            for (int index = 0; index < getCalls().size(); index++) {
                DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(index);
                Integer rowCount = (Integer)executeCall(databseCall);
                if ((index == 0) || (rowCount.intValue() <= 0)) {// Row count returned must be from first table or zero if any are zero.
                    returnedRowCount = rowCount;
                }
            }
            return returnedRowCount;
        } else {
            return (Integer)executeCall();
        }
    }

    /**
     * INTERNAL:
     * Execute a selecting call.
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public Vector executeSelect() throws DatabaseException {
        return executeSelectCall();
    }

    /**
     * INTERNAL:
     * Execute a selecting call.
     * @exception  DatabaseException - an error has occurred on the database
     */
    public Vector executeSelectCall() throws DatabaseException {
        if (hasMultipleCalls()) {
            Vector results = new Vector();
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatasourceCall databseCall = (DatasourceCall)callsEnum.nextElement();
                Helper.addAllToVector(results, (Vector)executeCall(databseCall));
            }

            return results;
        } else {
            return (Vector)executeCall();
        }
    }

    /**
     * Return the call.
     */
    public DatasourceCall getCall() {
        return call;
    }

    /**
     * Normally only a single call is used, however multiple table may require multiple calls on write.
     * This is lazy initialised to conserve space.
     */
    public Vector getCalls() {
        if (calls == null) {
            calls = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(3);
        }
        return calls;
    }

    /**
     * Normally only a single call is used, however multiple table may require multiple calls on write.
     * This is lazy initialised to conserve space.
     */
    public boolean hasMultipleCalls() {
        return (this.calls != null) && (!this.calls.isEmpty());
    }

    /**
     * Insert the object.  Assume the call is correct.
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public void insertObject() throws DatabaseException {
        ClassDescriptor descriptor = getDescriptor();
        boolean usesSequencing = descriptor.usesSequenceNumbers();
        boolean shouldAcquireValueAfterInsert = false;
        if (usesSequencing) {
            shouldAcquireValueAfterInsert = descriptor.getSequence().shouldAcquireValueAfterInsert();
        }
        Collection returnFields = null;
        if (descriptor.getReturnFieldsToMergeInsert() != null) {
            returnFields = descriptor.getReturnFieldsToMergeInsert();
        }

        // Check to see if sequence number should be retrieved after insert
        if (usesSequencing && !shouldAcquireValueAfterInsert) {
            // PERF: Unit of work always assigns sequence, so only need to check it here for non unit of work/change set query.
            if (getWriteObjectQuery().getObjectChangeSet() == null) {
                // This is the normal case.  Update object with sequence number before insert.
                updateObjectAndRowWithSequenceNumber();
            }
        }

        if (hasMultipleCalls()) {
            int size = this.calls.size();
            for (int index = 0; index < size; index++) {
                DatasourceCall databseCall = (DatasourceCall)this.calls.get(index);
                if ((index > 0) && isExpressionQueryMechanism()
                        && this.query.shouldCascadeOnlyDependentParts() && !descriptor.hasMultipleTableConstraintDependecy()
                        && this.query.getSession().getProject().allowSQLDeferral()) {
                    DatabaseTable table = descriptor.getMultipleTableInsertOrder().get(index);
                    this.query.getSession().getCommitManager().addDeferredCall(table, databseCall, this);
                } else {
                    Object result = executeCall(databseCall);
                    // Set the return row if one was returned (Postgres).
                    if (result instanceof AbstractRecord) {
                        this.query.setProperty("output", result);
                    }
                    if (returnFields != null) {
                        updateObjectAndRowWithReturnRow(returnFields, index == 0);
                    }
                    if ((index == 0) && usesSequencing && shouldAcquireValueAfterInsert) {
                        updateObjectAndRowWithSequenceNumber();
                    }
                }
            }
        } else {
            Object result = executeCall();
            // Set the return row if one was returned (Postgres).
            if (result instanceof AbstractRecord) {
                this.query.setProperty("output", result);
            }
            if (returnFields != null) {
                updateObjectAndRowWithReturnRow(returnFields, true);
            }
            if (usesSequencing && shouldAcquireValueAfterInsert) {
                updateObjectAndRowWithSequenceNumber();
            }
        }

        // Bug 3110860: RETURNINGPOLICY-OBTAINED PK CAUSES LOB TO BE INSERTED INCORRECTLY
        // The deferred locator SELECT calls should be generated and executed after ReturningPolicy
        // merges PK obtained from the db into the object held by the query.
        //
        //Oracle thin driver handles LOB differently. During the insert, empty lob would be
        //insert first, and then the LOb locator is retrieved and LOB data are written through
        //the locator.
        //
        // Bug 2804663 - LOBValueWriter is no longer a singleton, so we execute any deferred
        // select calls through the DatabaseAccessor which holds the writer instance
        AbstractSession executionSession = this.query.getExecutionSession();
        for (Accessor accessor : executionSession.getAccessors()) {
            accessor.flushSelectCalls(executionSession);
        }
    }

    /**
     * Execute the call that was deferred to the commit manager.
     * This is used to allow multiple table batching and deadlock avoidance.
     */
    @Override
    public void executeDeferredCall(DatasourceCall call) {
        Object result = executeCall(call);
        // Set the return row if one was returned (Postgres).
        if (result instanceof AbstractRecord) {
            this.query.setProperty("output", result);
        }
        Collection returnFields = null;
        if (this.query.getDescriptor().hasReturningPolicy()) {
            returnFields = this.query.getDescriptor().getReturningPolicy().getFieldsToMergeInsert();
        }
        if (returnFields != null) {
            updateObjectAndRowWithReturnRow(returnFields, false);
        }
    }

    /**
     * Return true if this is a call query mechanism
     */
    @Override
    public boolean isCallQueryMechanism() {
        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 ((!hasMultipleCalls()) && (getCall() == null)) {
            throw QueryException.sqlStatementNotSetProperly(getQuery());
        }
    }

    /**
     * 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.
     */
    public void prepareCall() throws QueryException {
        DatabaseQuery query = getQuery();
        AbstractSession executionSession = query.getExecutionSession();
        if (hasMultipleCalls()) {
            for (DatasourceCall call : (List<DatasourceCall>)getCalls()) {
                call.prepare(executionSession);
            }
        } else if (getCall() != null) {
            getCall().prepare(executionSession);
        }
    }

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

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

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

    /**
     * Pre-build configure the call.
     */
    @Override
    public void prepareDoesExist(DatabaseField field) {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                ((DatasourceCall)callsEnum.nextElement()).returnOneRow();
            }
        } else {
            getCall().returnOneRow();
        }
        prepareCall();
    }

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

    /**
     * Pre-build configure the call. This method assumes the query was built
     * using a stored procedure query which is a single call.
     *
     * The return type on the call will already be set and
     */
    @Override
    public void prepareExecute() {
        getCall().setExecuteUpdate();
        prepareCall();
    }

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

    /**
     * Pre-build configure the call.
     */
    @Override
    public void prepareInsertObject() {
        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();
                }
            }
        } else {
            if (!this.call.isReturnSet()) {
                this.call.returnNothing();
            }
        }
        prepareCall();
    }

    /**
     * Prepare the report items.
     * Indexes of results need to be calculated.
     */
    protected void prepareReportQueryItems(){
        //calculate indexes after normalize to insure expressions are set up correctly
        //take into account any field expressions added to the ReportQuery
        ReportQuery query = (ReportQuery)getQuery();
        computeAndSetItemOffset(query, query.getItems(), query.getQueryExpressions().size());
    }

    /**
     * calculate indexes for given items, given the current Offset
     */
    protected int computeAndSetItemOffset(ReportQuery query, List<ReportItem> items, int itemOffset) {
        for(ReportItem item : items) {
            if (item.isConstructorItem()) {
                List<ReportItem> reportItems = ((ConstructorReportItem) item).getReportItems();
                itemOffset = computeAndSetItemOffset(query, reportItems, itemOffset);
            } else {
                //Don't set the offset on the ConstructorItem
                item.setResultIndex(itemOffset);
                if (item.getAttributeExpression() != null) {
                    if (item.hasJoining()){
                        itemOffset = item.getJoinedAttributeManager().computeJoiningMappingIndexes(true, getSession(), itemOffset);
                    } else {
                        if (item.getDescriptor() != null) {
                            itemOffset += item.getDescriptor().getAllSelectionFields(query).size();
                        } else {
                            if (item.getMapping() != null && item.getMapping().isAggregateObjectMapping()) {
                                itemOffset += item.getMapping().getFields().size(); // Aggregate object may consist out of 1..n fields
                            } else {
                                ++itemOffset; //only a single attribute can be selected
                            }
                        }
                    }
                }
            }
        }
        return itemOffset;
    }

    /**
     * Pre-build configure the call.
     */
    @Override
    public void prepareReportQuerySelectAllRows() {
        prepareReportQueryItems();
        prepareExecuteSelect();
    }

    /**
     * Prepare for a sub select using a call.
     */
    @Override
    public void prepareReportQuerySubSelect() {
        prepareReportQueryItems();
        prepareCall();
    }

    /**
     * Pre-build configure the call.
     */
    @Override
    public void prepareSelectAllRows() {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatasourceCall databseCall = (DatasourceCall)callsEnum.nextElement();
                databseCall.returnManyRows();
            }
        } else {
            getCall().returnManyRows();
        }
        prepareCall();
    }

    /**
     * Pre-build configure the call.
     */
    @Override
    public void prepareSelectOneRow() {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatasourceCall databseCall = (DatasourceCall)callsEnum.nextElement();
                databseCall.returnOneRow();
            }
        } else {
            getCall().returnOneRow();
        }
        prepareCall();
    }

    /**
     * Pre-build configure the 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();
                }
            }
        } else if (getCall() != null) {
            if (!call.isReturnSet()) {
                this.call.returnNothing();
            }
        }
        prepareCall();
    }

    /**
       * Pre-build configure the call.
       */
    @Override
    public void prepareUpdateAll() {
        if (getCall() != null) {
            getCall().returnNothing();
        }

        prepareCall();
    }

    /**
     * Read all rows from the database. Assume call is correct returns the required fields.
     * @return Vector containing the database rows
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public Vector selectAllReportQueryRows() throws DatabaseException {
        return executeSelect();
    }

    /**
     * Read all rows from the database. Assume call is correct returns the required fields.
     * @return Vector containing the database rows
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public Vector selectAllRows() throws DatabaseException {
        return executeSelectCall();
    }

    /**
     * Read a single row from the database. Assume call is correct.
     * @return row containing data
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public AbstractRecord selectOneRow() throws DatabaseException {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatasourceCall databaseCall = (DatasourceCall)callsEnum.nextElement();
                AbstractRecord result = (AbstractRecord)executeCall(databaseCall);
                if (result != null) {
                    return result;
                }
            }

            return null;
        } else {
            return (AbstractRecord)executeCall();
        }
    }

    /**
     * Perform a does exist check
     * @param field - the field used for does exist check
     * @return  the associated row from the database
     * @exception  DatabaseException - an error has occurred on the database
     */
    @Override
    public AbstractRecord selectRowForDoesExist(DatabaseField field) throws DatabaseException {
        if (hasMultipleCalls()) {
            for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) {
                DatasourceCall databaseCall = (DatasourceCall)callsEnum.nextElement();
                AbstractRecord result = (AbstractRecord)executeCall(databaseCall);
                if (result != null) {
                    return result;
                }
            }

            return null;
        } else {
            return (AbstractRecord)executeCall();
        }
    }

    /**
     * Set the call.
     */
    public void setCall(DatasourceCall call) {
        this.call = call;
        if (call != null) {
            call.setQuery(getQuery());
        }
    }

    /**
     * Normally only a single call is used, however multiple table may require multiple calls on write.
     * This is lazy initialised to conserve space.
     */
    protected void setCalls(Vector calls) {
        this.calls = calls;
    }

    /**
     * Update the object.  Assume the call is correct.
     * @exception  DatabaseException - an error has occurred on the database.
     * @return the row count.
     */
    @Override
    public Integer updateObject() throws DatabaseException {
        ClassDescriptor descriptor = getDescriptor();
        Collection returnFields = null;
        if (descriptor.getReturnFieldsToMergeUpdate() != null) {
            returnFields = descriptor.getReturnFieldsToMergeUpdate();
        }
        Integer returnedRowCount = null;
        if (hasMultipleCalls()) {
            int size = this.calls.size();
            for (int index = 0; index < size; index++) {
                DatasourceCall databseCall = (DatasourceCall)this.calls.get(index);
                if ((index > 0) && isExpressionQueryMechanism()
                        && this.query.shouldCascadeOnlyDependentParts() && !descriptor.hasMultipleTableConstraintDependecy()
                        && this.query.getSession().getProject().allowSQLDeferral()) {
                    DatabaseTable table = descriptor.getMultipleTableInsertOrder().get(index);
                    this.query.getSession().getCommitManager().addDeferredCall(table, databseCall, this);
                } else {
                    Object result = executeCall(databseCall);
                    // Set the return row if one was returned (Postgres).
                    Integer rowCount;
                    if (result instanceof AbstractRecord) {
                        this.query.setProperty("output", result);
                        rowCount = Integer.valueOf(1);
                    } else {
                        rowCount = (Integer)result;
                    }
                    if ((index == 0) || (rowCount.intValue() <= 0)) {// Row count returned must be from first table or zero if any are zero.
                        returnedRowCount = rowCount;
                    }
                    if (returnFields != null) {
                        updateObjectAndRowWithReturnRow(returnFields, false);
                    }
                }
            }
        } else {
            Object result = executeCall();
            // Set the return row if one was returned (Postgres).
            if (result instanceof AbstractRecord) {
                this.query.setProperty("output", result);
                returnedRowCount = Integer.valueOf(1);
            } else {
                returnedRowCount = (Integer)result;
            }
            if (returnFields != null) {
                updateObjectAndRowWithReturnRow(returnFields, false);
            }
        }

        //Oracle thin driver handles LOB differently. During the insert, empty lob would be
        //insert first, and then the LOb locator is retrieved and LOB data are written through
        //the locator.
        //
        // Bug 2804663 - LOBValueWriter is no longer a singleton, so we execute any deferred
        // select calls through the DatabaseAccessor which holds the writer instance
        //
        // Building of SELECT statements is no longer done in DatabaseAccessor.basicExecuteCall
        // because DatabaseCall.isUpdateCall() can't recognize update in case StoredProcedureCall
        // is used.
        AbstractSession executionSession = this.query.getExecutionSession();
        for (Accessor accessor : executionSession.getAccessors()) {
            accessor.flushSelectCalls(executionSession);
        }
        return returnedRowCount;
    }

    /**
       * Update the rows on the database.  Assume the call is correct.
       * @exception  DatabaseException - an error has occurred on the database.
       */
    @Override
    public Integer updateAll() throws DatabaseException {
        if(((UpdateAllQuery)this.query).isPreparedUsingTempStorage() && getExecutionSession().getPlatform().supportsTempTables()) {
            return updateAllUsingTempTables();
        } else {
            Integer rowCount = executeNoSelectCall();
            if(((UpdateAllQuery)this.query).isPreparedUsingTempStorage()) {
                // the query was prepared using Oracle anonymous block
                AbstractRecord outputRow = (AbstractRecord)this.query.getProperty("output");
                rowCount = (Integer)outputRow.get("ROW_COUNT");
            }
            return rowCount;
        }
    }

    /**
     * Execute updateAll using temp tables
     * @exception  DatabaseException - an error has occurred on the database.
     * @return the row count.
     */
    public Integer updateAllUsingTempTables() throws DatabaseException {
        int nTables = getCalls().size() / 4;
        DatabaseException ex = null;
        Integer returnedRowCount = null;

        // first quarter - crete temp tables calls.
        // may fail in case global temp table already exists.
        for (int index = 0; index < nTables; index++) {
            try {
                DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(index);
                executeCall(databseCall);
            } catch (DatabaseException databaseEx) {
                // ignore
            }
        }

        // second quarter - populate temp tables calls.
        // if that fails save the exception and until cleanup
        for (int index = nTables; index < nTables*2 && ex == null; index++) {
            try {
                DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(index);
                executeCall(databseCall);
            } catch (DatabaseException databaseEx) {
                ex = databaseEx;
            }
        }

        // third quarter - update original tables calls.
        // if that fails save the exception and until cleanup
        for (int index = nTables*2; index < nTables*3 && ex == null; index++) {
            try {
                DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(index);
                Integer rowCount = (Integer)executeCall(databseCall);
                if ((index == nTables*2) || (rowCount.intValue() <= 0)) {// Row count returned must be from first table or zero if any are zero.
                    returnedRowCount = rowCount;
                }
            } catch (DatabaseException databaseEx) {
                ex = databaseEx;
            }
        }

        // last quarter - cleanup temp tables calls.
        // ignore exceptions here.
        for (int index = nTables*3; index < nTables*4; index++) {
            try {
                DatasourceCall databseCall = (DatasourceCall)getCalls().elementAt(index);
                executeCall(databseCall);
                } catch (DatabaseException databaseEx) {
                    // ignore
                }
        }

        if(ex != null) {
            throw ex;
        }

        return returnedRowCount;
    }

    /**
     * Update the foreign key fields when resolving a bi-directional reference in a UOW.
     * This is rare to occur for non-relational, however if it does each of the calls must be re-executed.
     */
    @Override
    protected void updateForeignKeyFieldAfterInsert(WriteObjectQuery writeQuery) {
        writeQuery.setModifyRow(this.getDescriptor().getObjectBuilder().buildRow(writeQuery.getObject(), this.getSession(), WriteType.INSERT));

        // For CR 2923 must move to session we will execute call on now
        // so correct DatasourcePlatform used by translate.
        AbstractSession sessionToUse = this.query.getExecutionSession();

        // yes - this is a bit ugly...
        Vector calls = ((DatasourceCallQueryMechanism)this.getDescriptor().getQueryManager().getUpdateQuery().getQueryMechanism()).getCalls();
        for (Enumeration stream = calls.elements(); stream.hasMoreElements();) {
            DatasourceCall call = (DatasourceCall)((DatasourceCall)stream.nextElement()).clone();
            call.setQuery(writeQuery);
            sessionToUse.executeCall(call, this.getTranslationRow(), writeQuery);
        }
    }
}
