/*
 * 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/12/2018 - Will Dazey
//       - 391279: Add support for Unidirectional OneToMany mappings with non-nullable values
package org.eclipse.persistence.internal.queries;

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventManager;
import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.descriptors.VersionLockingPolicy;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.OptimisticLockException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatasourceCall;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.CommitManager;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork;
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DoesExistQuery;
import org.eclipse.persistence.queries.ModifyQuery;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.tools.profiler.QueryMonitor;

/**
 * <p><b>Purpose</b>:
 * Abstract class for all database query mechanism objects.
 * DatabaseQueryMechanism is actually a helper class and currently is required
 * for all types of queries.  Most of the work performed by the query framework is
 * performed in the query mechanism.  The query mechanism contains the internal
 * knowledge necessary to perform the specific database operation.
 * </p>
 * <p><b>Responsibilities</b>:
 * Provide a common protocol for query mechanism objects.
 * Provides all of the database specific work for the assigned query.</p>
 *
 * @author Yvon Lavoie
 * @since TOPLink/Java 1.0
 */
public abstract class DatabaseQueryMechanism implements Cloneable, Serializable {

    /** The database query that uses this mechanism. */
    protected DatabaseQuery query;

    /**
     * Initialize the state of the query.
     */
    protected DatabaseQueryMechanism() {
    }

    /**
     * Initialize the state of the query
     * @param query - owner of mechanism
     */
    protected DatabaseQueryMechanism(DatabaseQuery query) {
        this.query = query;
    }

    /**
     * Add the initial write lock value to the row for insert.
     */
    protected void addWriteLockFieldForInsert() {
        if (getDescriptor().usesOptimisticLocking()) {
            getDescriptor().getOptimisticLockingPolicy().setupWriteFieldsForInsert(getWriteObjectQuery());
        }
    }

    /**
     * Internal:
     * In the case of EJBQL, an expression needs to be generated. Build the required expression.
     */
    public void buildSelectionCriteria(AbstractSession session) {
        // Default is do nothing
    }

    /**
     * Perform a cache lookup for the query. If the translation row contains
     * all the parameters (which are part of the primary key) from the prepared
     * call, then a cache check will be performed.
     *
     * If the object is found in the cache, return it; otherwise return null.
     */
    public Object checkCacheForObject(AbstractRecord translationRow, AbstractSession session) {
        // Null check added for CR#4295 - TW
        if ((translationRow == null) || (translationRow.isEmpty())) {
            return null;
        }

        // Bug 5529564
        // The query wasn't prepared most likely because arguments were
        // provided. Use them for the cache lookup.
        List queryFields;
        if (query.getCall() == null) {
            // TODO: This is a bug, arguments is a list of Strings, not fields.
            // Also if the call was null, it would be an expression, if it was not
            // prepared the parameters would be empty.
            queryFields = query.getArguments();
        } else {
            // The query was prepared. Use the parameters of the call to look
            // up the object in cache.
            queryFields = query.getCall().getParameters();
        }

        ClassDescriptor descriptor = getDescriptor();
        List<DatabaseField> primaryKeyFields = descriptor.getPrimaryKeyFields();

        // Check that the query is by primary key.
        for (DatabaseField primaryKeyField : primaryKeyFields) {
            if (!queryFields.contains(primaryKeyField)) {
                return null;
            }
        }
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromRow(translationRow, session);
        if (primaryKey == null) {
            return null;
        }

        if (query.isObjectBuildingQuery() && ((ObjectBuildingQuery)query).requiresDeferredLocks() || descriptor.shouldAcquireCascadedLocks()) {
            return session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(primaryKey, getReadObjectQuery().getReferenceClass(), false, descriptor);
        } else {
            return session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(primaryKey, getReadObjectQuery().getReferenceClass(), false, descriptor);
        }
    }

    /**
     * Clone the mechanism
     */
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }

    /**
     * Clone the mechanism for the specified query clone.
     */
    public DatabaseQueryMechanism clone(DatabaseQuery queryClone) {
        DatabaseQueryMechanism clone = (DatabaseQueryMechanism)clone();
        clone.setQuery(queryClone);
        return clone;
    }

    /**
     * Read all rows from the database using a cursored stream.
     * @exception  DatabaseException - an error has occurred on the database
     */
    public abstract DatabaseCall cursorSelectAllRows() throws DatabaseException;

    /**
     * Delete a collection of objects
     * This should be overridden by subclasses.
     * @exception  DatabaseException - an error has occurred on the database
     */
    public boolean isJPQLCallQueryMechanism() {
        return false;
    }

    public abstract Integer deleteAll() throws DatabaseException;

    /**
     * Delete an object
     * This should be overridden by subclasses.
     * @return the row count.
     */
    public abstract Integer deleteObject() throws DatabaseException;

    /**
     * Execute a execute SQL call.
     * This should be overridden by subclasses.
     * @return true if the first result is a result set and false if it is an
     *   update count or there are no results other than through INOUT and OUT
     *   parameterts, if any.
     */
    public abstract Object execute() throws DatabaseException;

    /**
     * Execute a non selecting SQL call
     * This should be overridden by subclasses.
     * @return the row count.
     */
    public abstract Integer executeNoSelect() throws DatabaseException;

    /**
     * Execute a select SQL call and return the rows.
     * This should be overriden by subclasses.
     */
    public abstract Vector executeSelect() throws DatabaseException;

    /**
     * Check whether the object already exists on the database; then
     * perform an insert or update, as appropriate.
     * This write is used for non-unit of work (old-commit) operations.
     * Return the object being written.
     */
    public Object executeWrite() throws DatabaseException, OptimisticLockException {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();
        CommitManager commitManager = getSession().getCommitManager();

        // if the object has already been committed, no work is required
        if (commitManager.isCommitCompletedInPostOrIgnore(object)) {
            return object;
        }

        // check whether the object is already being committed -
        // if it is and it is new, then a shallow insert must be done
        if (commitManager.isCommitInPreModify(object)) {
            shallowInsertObjectForWrite(object, writeQuery, commitManager);
            return object;
        }

        try {
            getSession().beginTransaction();

            if (writeQuery.getObjectChangeSet() == null) {
                // PERF: Avoid events if no listeners.
                if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                    // only throw the events if there is no changeset otherwise the event will be thrown twice
                    // once by the calculate changes code and here
                    getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreWriteEvent, writeQuery));
                }
            }
            writeQuery.executeCommit();

            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostWriteEvent, writeQuery));
            }

            getSession().commitTransaction();

            // notify the commit manager of the completion to the commit
            commitManager.markCommitCompleted(object);

            return object;

        } catch (RuntimeException exception) {
            getSession().rollbackTransaction();
            commitManager.markCommitCompleted(object);
            throw exception;
        }
    }

    /**
     * Execute the call that was deferred to the commit manager.
     * This is used to allow multiple table batching and deadlock avoidance.
     */
    public void executeDeferredCall(DatasourceCall call) {
        // Do nothing by default.
    }

    /**
     * Check whether the object already exists on the cadatabase; then
     * perform an insert or update, as appropriate.
     * This method was moved here, from WriteObjectQuery.execute(),
     * so we can hide the source.
     * Return the object being written.
     */
    public Object executeWriteWithChangeSet() throws DatabaseException, OptimisticLockException {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
        ClassDescriptor descriptor = getDescriptor();
        AbstractSession session = getSession();
        CommitManager commitManager = session.getCommitManager();
        Object object = writeQuery.getObject();
        // If there are no changes then there is no work required
        // Check for forcedUpdate Version and Optimistic read lock (hasForcedChanges() set in ObjectChangePolicy)
        if (!objectChangeSet.hasChanges() && !objectChangeSet.hasForcedChanges()) {
            commitManager.markCommitCompleted(object);
            return object;
        }
        // If the object has already been committed, no work is required
        // need to check for the object to ensure insert wasn't completed already.
        if (commitManager.isCommitCompletedInPostOrIgnore(object)) {
            return object;
        }
        try {
            writeQuery.executeCommitWithChangeSet();

            // PERF: Avoid events if no listeners.
            if (descriptor.getEventManager().hasAnyEventListeners()) {
                descriptor.getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostWriteEvent, writeQuery));
            }

            // Notify the commit manager of the completion to the commit.
            commitManager.markCommitCompleted(object);

            return object;

        } catch (RuntimeException exception) {
            commitManager.markCommitCompleted(object);
            throw exception;
        }
    }

    /**
     * Convenience method
     */
    protected ClassDescriptor getDescriptor() {
        return this.query.getDescriptor();
    }

    /**
     * Convenience method
     */
    public AbstractRecord getModifyRow() {
        if (this.query.isModifyQuery()) {
            return ((ModifyQuery)this.query).getModifyRow();
        } else {
            return null;
        }
    }

    /**
     * Return the query that uses the mechanism.
     */
    public DatabaseQuery getQuery() {
        return query;
    }

    /**
     * Convenience method
     */
    protected ReadObjectQuery getReadObjectQuery() {
        return (ReadObjectQuery)this.query;
    }

    /**
     * Return the selection criteria for the mechanism.
     * By default this is null. This method exists because both statement and expression
     * mechanisms use an expression and some code in the mappings depends on returning this.
     */
    public Expression getSelectionCriteria() {
        return null;
    }

    /**
     * Convenience method
     */
    protected AbstractSession getSession() {
        return this.query.getSession();
    }

    /**
     * Convenience method
     */
    protected AbstractSession getExecutionSession() {
        return this.query.getExecutionSession();
    }

    /**
     * Convenience method
     */
    protected AbstractRecord getTranslationRow() {
        return this.query.getTranslationRow();
    }

    /**
     * Convenience method
     */
    protected WriteObjectQuery getWriteObjectQuery() {
        return (WriteObjectQuery)this.query;
    }

    /**
     * Insert an object.
     */
    public abstract void insertObject() throws DatabaseException;

    /**
     *  Insert an object and provide the opportunity to reprepare prior to the insert.
     *  This will be overridden
     *  CR#3237
     */
    public void insertObject(boolean reprepare) {
        insertObject();
    }

    /**
     * Insert an object in the database.
     * This is used for both uow and non-uow (old-commit and change-set) operations.
     */
    public void insertObjectForWrite() {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ClassDescriptor descriptor = getDescriptor();
        DescriptorQueryManager queryManager = descriptor.getQueryManager();
        boolean isFKUpdate = false; // Bug 319276

        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 && queryManager.hasInsertQuery()// there is a user-defined query
                 && isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            performUserDefinedInsert();
            return;
        }
        Object object = writeQuery.getObject();
        AbstractSession session = writeQuery.getSession();
        ObjectChangeSet changeSet = writeQuery.getObjectChangeSet();
        CommitManager commitManager = session.getCommitManager();
        DescriptorEventManager eventManager = descriptor.getEventManager();

        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(object);

        if (changeSet == null) {
            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                // only throw the events if there is no changeset otherwise the event will be thrown twice
                // once by the calculate changes code and here
                eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PreInsertEvent, writeQuery));
            }
        }

        // check whether deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preInsert(writeQuery);
        }

        // In a unit of work/writeObjects the preInsert may have caused a shallow insert of this object,
        // in this case this second write must do an update.
        if (commitManager.isShallowCommitted(object)) {
            isFKUpdate = true; // Bug 319276
            updateForeignKeyFieldAfterInsert();
        } else {
            AbstractRecord modifyRow = writeQuery.getModifyRow();
            if (modifyRow == null) {// Maybe have been passed in as in aggregate collection.
                if (writeQuery.shouldCascadeParts()) {
                    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, session, WriteType.INSERT));
                } else {
                    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForShallowInsert(object, session));
                }
            } else {
                if (writeQuery.shouldCascadeParts()) {
                    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(modifyRow, object, session, WriteType.INSERT));
                } else {
                    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForShallowInsert(modifyRow, object, session));
                }
            }
            modifyRow = getModifyRow();
            // the modify row and the translation row are the same for insert
            writeQuery.setTranslationRow(modifyRow);
            if (!descriptor.isAggregateCollectionDescriptor()) {// Should/cannot be recomputed in aggregate collection.
                writeQuery.setPrimaryKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, session));
            }
            addWriteLockFieldForInsert();
            if (descriptor.hasSerializedObjectPolicy()) {
                descriptor.getSerializedObjectPolicy().putObjectIntoRow(modifyRow, object, session);
            }

            // CR#3237
            // Store the size of the modify row so we can determine if the user has added to the row in the insert.
            int modifyRowSize = modifyRow.size();

            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToInsertEvent, writeQuery);
                event.setRecord(modifyRow);
                eventManager.executeEvent(event);
            }

            if (QueryMonitor.shouldMonitor()) {
                QueryMonitor.incrementInsert(writeQuery);
            }
            // CR#3237
            // Call insert with a boolean that tells it to reprepare if the user has altered the modify row.
            insertObject(modifyRowSize != modifyRow.size());

            // register the object before post insert to resolve possible cycles
            registerObjectInIdentityMap(object, descriptor, session);
        }

        commitManager.markPostModifyCommitInProgress(object);
        // Verify if deep shallow modify is turned on.
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postInsert(writeQuery);
        }

        if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
            if (isFKUpdate) { // Bug 319276
                descriptor.getHistoryPolicy().postUpdate(writeQuery, true);
            }
            else {
                descriptor.getHistoryPolicy().postInsert(writeQuery);
            }
        }

        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostInsertEvent, writeQuery));
        }
    }

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

    /**
     * Return true if this is an expression query mechanism
     */
    public boolean isExpressionQueryMechanism() {
        return false;
    }

    /**
     * Return true if this is a query by example mechanism
     */
    public boolean isQueryByExampleMechanism() {
        return false;
    }

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

    /**
     * Insert the object using the user defined query.
     * This ensures that the query is cloned and prepared correctly.
     */
    protected void performUserDefinedInsert() {
        performUserDefinedWrite(getDescriptor().getQueryManager().getInsertQuery());
    }

    /**
     * Update the object using the user defined query.
     * This ensures that the query is cloned and prepared correctly.
     */
    protected void performUserDefinedUpdate() {
        performUserDefinedWrite(getDescriptor().getQueryManager().getUpdateQuery());
    }

    /**
     * Write the object using the specified user-defined query.
     * This ensures that the query is cloned and prepared correctly.
     */
    protected void performUserDefinedWrite(WriteObjectQuery userDefinedWriteQuery) {
        WriteObjectQuery query = getWriteObjectQuery();
        userDefinedWriteQuery.checkPrepare(query.getSession(), query.getTranslationRow());

        WriteObjectQuery writeQuery = (WriteObjectQuery)userDefinedWriteQuery.clone();
        writeQuery.setIsExecutionClone(true);
        writeQuery.setObject(query.getObject());
        writeQuery.setObjectChangeSet(query.getObjectChangeSet());
        writeQuery.setCascadePolicy(query.getCascadePolicy());
        writeQuery.setShouldMaintainCache(query.shouldMaintainCache());
        writeQuery.setTranslationRow(query.getTranslationRow());
        writeQuery.setModifyRow(query.getModifyRow());
        writeQuery.setPrimaryKey(query.getPrimaryKey());
        writeQuery.setSession(query.getSession());

        // If there is a changeset, the change set method must be used.
        if (writeQuery.getObjectChangeSet() != null) {
            writeQuery.executeCommitWithChangeSet();
        } else {
            writeQuery.executeCommit();
        }
    }

    /**
     * This is different from 'prepareForExecution()'
     * in that this is called on the original query,
     * and the other is called on the clone 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 prepare() throws QueryException {
        // the default is to do nothing
    }

    /**
     * Pre-pare for a cursored execute.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareCursorSelectAllRows() throws QueryException;

    /**
     * Prepare for a delete all.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareDeleteAll() throws QueryException;

    /**
     * Prepare for a delete.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareDeleteObject() throws QueryException;

    /**
     * Pre-pare for a select execute.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareDoesExist(DatabaseField field) throws QueryException;

    /**
     * Prepare for a raw (non-object), non-selecting call.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareExecuteNoSelect() throws QueryException;

    /**
     * Prepare for a raw execute call.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareExecute() throws QueryException;

    /**
     * Prepare for a raw (non-object) select call.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareExecuteSelect() throws QueryException;

    /**
     * Prepare for an insert.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareInsertObject() throws QueryException;

    /**
     * Pre-pare for a select execute.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareReportQuerySelectAllRows() throws QueryException;

    /**
     * Pre-pare a report query for a sub-select.
     */
    public abstract void prepareReportQuerySubSelect() throws QueryException;

    /**
     * Prepare for a select returning (possibly) multiple rows.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareSelectAllRows() throws QueryException;

    /**
     * Prepare for a select returning a single row.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareSelectOneRow() throws QueryException;

    /**
     * Prepare for an update.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareUpdateObject() throws QueryException;

    /**
       * Prepare for an update all.
       * This is sent to the original query before cloning.
       */
    public abstract void prepareUpdateAll() throws QueryException;

    /**
     * Store the query object in the identity map.
     */
    protected void registerObjectInIdentityMap(Object object, ClassDescriptor descriptor, AbstractSession session) {
        WriteObjectQuery query = getWriteObjectQuery();
        if (query.shouldMaintainCache()) {
            if (descriptor.usesOptimisticLocking()) {
                Object optimisticLockValue = descriptor.getOptimisticLockingPolicy().getValueToPutInCache(query.getModifyRow(), session);
                session.getIdentityMapAccessorInstance().putInIdentityMap(object, query.getPrimaryKey(), optimisticLockValue, System.currentTimeMillis(), descriptor);
            } else {
                session.getIdentityMapAccessorInstance().putInIdentityMap(object, query.getPrimaryKey(), null, System.currentTimeMillis(), descriptor);
            }
        }
    }

    /**
     * INTERNAL:
     * Read all rows from the database.
     */
    public abstract Vector selectAllReportQueryRows() throws DatabaseException;

    /**
     * Read and return rows from the database.
     */
    public abstract Vector selectAllRows() throws DatabaseException;

    /**
     * Read and return a row from the database.
     */
    public abstract AbstractRecord selectOneRow() throws DatabaseException;

    /**
     * Read and return a row from the database for an existence check.
     */
    public abstract AbstractRecord selectRowForDoesExist(DatabaseField field) throws DatabaseException;

    /**
     * Set the query that uses this mechanism.
     */
    public void setQuery(DatabaseQuery query) {
        this.query = query;
    }

    /**
     * Shallow insert the specified object, if necessary.
     */
    protected void shallowInsertObjectForWrite(Object object, WriteObjectQuery writeQuery, CommitManager commitManager) throws DatabaseException, OptimisticLockException {
        boolean doesExist;

        if (getSession().isUnitOfWork()) {
            UnitOfWorkImpl uow = (UnitOfWorkImpl)getSession();
            doesExist = !uow.isCloneNewObject(object);
            if (doesExist) {
                doesExist = uow.isObjectRegistered(object);
            }
        } else {
            // clone and initialize the does exist query
            DoesExistQuery existQuery = (DoesExistQuery)getDescriptor().getQueryManager().getDoesExistQuery().clone();
            existQuery.setObject(object);
            existQuery.setPrimaryKey(writeQuery.getPrimaryKey());
            existQuery.setDescriptor(getDescriptor());
            existQuery.setTranslationRow(getTranslationRow());

            doesExist = (Boolean) getSession().executeQuery(existQuery);
        }

        if (!doesExist) {
            // a shallow insert must be performed
            writeQuery.dontCascadeParts();
            insertObjectForWrite();
            // mark this object as shallow committed so that the insert will do an update
            commitManager.markShallowCommit(object);
        }
    }

    /**
     * Update the foreign key fields when resolving a bi-directonal 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.
     */
    protected void updateForeignKeyFieldAfterInsert() {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();

        writeQuery.setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()));
        // reset the translation row because the insert has occurred and the id has
        // been assigned to the object, but not the row
        writeQuery.setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(object, getSession()));

        updateForeignKeyFieldAfterInsert(writeQuery);
    }

    /**
       * Issue update SQL statement
       */
    public abstract Integer updateAll() throws DatabaseException;

    /**
     * Update an object.
     * Return the row count.
     */
    public abstract Integer updateObject() throws DatabaseException;

    /**
     * Update the foreign key fields when resolving a bi-directonal 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.
     */
    protected abstract void updateForeignKeyFieldAfterInsert(WriteObjectQuery writeQuery);

    /**
     * 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.
     */
    public void updateForeignKeyFieldBeforeDelete() {
        // Nothing by default.
    }

    protected void updateObjectAndRowWithReturnRow(Collection returnFields, boolean isFirstCallForInsert) {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        AbstractRecord outputRow = (AbstractRecord)writeQuery.getProperties().get("output");
        if ((outputRow == null) || outputRow.isEmpty()) {
            return;
        }
        AbstractRecord row = new DatabaseRecord();
        for (Iterator iterator = returnFields.iterator(); iterator.hasNext();) {
            DatabaseField field = (DatabaseField)iterator.next();
            if (outputRow.containsKey(field)) {
                row.put(field, outputRow.get(field));
            }
        }
        if (row.isEmpty()) {
            return;
        }

        Object object = writeQuery.getObject();

        ObjectChangeSet objectChangeSet = null;
        if (getSession().isUnitOfWork()) {
            objectChangeSet = writeQuery.getObjectChangeSet();
            if ((objectChangeSet == null) && (((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet() != null)) {
                objectChangeSet = (ObjectChangeSet)((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
            }
        }
        getDescriptor().getObjectBuilder().assignReturnRow(object, writeQuery.getSession(), row, objectChangeSet);

        Object primaryKey = null;
        if (isFirstCallForInsert) {
            AbstractRecord pkToModify = new DatabaseRecord();
            List primaryKeyFields = getDescriptor().getPrimaryKeyFields();
            for (int i = 0; i < primaryKeyFields.size(); i++) {
                DatabaseField field = (DatabaseField)primaryKeyFields.get(i);
                if (row.containsKey(field)) {
                    pkToModify.put(field, row.get(field));
                }
            }
            if (!pkToModify.isEmpty()) {
                primaryKey = getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession());
                writeQuery.setPrimaryKey(primaryKey);
                // Now I need to update the row
                getModifyRow().putAll(pkToModify);
                getDescriptor().getObjectBuilder().addPrimaryKeyForNonDefaultTable(getModifyRow(), object, getSession());
            }
        }

        if (objectChangeSet != null) {
            if (primaryKey != null) {
                objectChangeSet.setId(primaryKey);
            }
        }
    }

    /**
     * Update the object's primary key by fetching a new sequence number from the accessor.
     */
    protected void updateObjectAndRowWithSequenceNumber() throws DatabaseException {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        writeQuery.getDescriptor().getObjectBuilder().assignSequenceNumber(writeQuery);
    }

    /**
     * Update the object.
     * This is only used for non-unit-of-work updates.
     */
    public void updateObjectForWrite() {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ClassDescriptor descriptor = getDescriptor();
        DescriptorQueryManager queryManager = descriptor.getQueryManager();
        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 && queryManager.hasUpdateQuery()// there is a user-defined query
                 && isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            performUserDefinedUpdate();
            return;
        }
        Object object = writeQuery.getObject();
        AbstractSession session = getSession();
        CommitManager commitManager = session.getCommitManager();
        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(object);
        DescriptorEventManager eventManager = descriptor.getEventManager();
        if (writeQuery.getObjectChangeSet() == null) {
            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                // only throw the events if there is no changeset otherwise the event will be thrown twice
                // once by the calculate changes code and here
                eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PreUpdateEvent, writeQuery));
            }
        }

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preUpdate(writeQuery);
        }

        // The row must not be built until after preUpdate in case the object reference has changed.
        // For a user defined update in the uow to row must be built twice to check if any update is required.
        if ((writeQuery.isUserDefined() || writeQuery.isCallQuery()) && (!getSession().isUnitOfWork())) {
            writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, getSession(), WriteType.UNDEFINED));
        } else {
            writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForUpdate(writeQuery));
        }

        // Optimistic read lock implementation
        Boolean shouldModifyVersionField = null;
        if (session.isUnitOfWork() && ((UnitOfWorkImpl)session).hasOptimisticReadLockObjects()) {
            shouldModifyVersionField = (Boolean)((UnitOfWorkImpl)session).getOptimisticReadLockObjects().get(writeQuery.getObject());
        }

        if (!getModifyRow().isEmpty() || (shouldModifyVersionField != null) || ((descriptor.getCMPPolicy() != null) && (descriptor.getCMPPolicy().getForceUpdate()))) {
            // If user defined the entire row is required. Must not be built until change is known.
            if ((writeQuery.isUserDefined() || writeQuery.isCallQuery()) && getSession().isUnitOfWork()) {
                writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, getSession(), WriteType.UNDEFINED));
            }

            // Update the write lock field if required.
            if (descriptor.usesOptimisticLocking()) {
                OptimisticLockingPolicy policy = descriptor.getOptimisticLockingPolicy();
                policy.addLockValuesToTranslationRow(writeQuery);

                if (!getModifyRow().isEmpty() || shouldModifyVersionField) {
                    // Update the row with newer lock value.
                    policy.updateRowAndObjectForUpdate(writeQuery, object);
                } else if (!shouldModifyVersionField && (policy instanceof VersionLockingPolicy)) {
                    // Add the existing write lock value to the for a "read" lock (requires something to update).
                    ((VersionLockingPolicy)policy).writeLockValueIntoRow(writeQuery, object);
                }
            }
            if (descriptor.hasSerializedObjectPolicy()) {
                descriptor.getSerializedObjectPolicy().putObjectIntoRow(getModifyRow(), object, session);
            }

            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
                event.setRecord(getModifyRow());
                eventManager.executeEvent(event);
            }

            if (QueryMonitor.shouldMonitor()) {
                QueryMonitor.incrementUpdate(getWriteObjectQuery());
            }
            int rowCount = updateObject();

            if (rowCount < 1) {
                if (session.hasEventManager()) {
                    session.getEventManager().noRowsModified(writeQuery, object);
                }
            }
            if (descriptor.usesOptimisticLocking()) {
                descriptor.getOptimisticLockingPolicy().validateUpdate(rowCount, object, writeQuery);
            }
        }

        commitManager.markPostModifyCommitInProgress(object);

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postUpdate(writeQuery);
        }
        if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
            descriptor.getHistoryPolicy().postUpdate(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
        }
    }

    /**
     * Update the object.
     * This is used by the unit-of-work update.
     */
    public void updateObjectForWriteWithChangeSet() {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ObjectChangeSet changeSet = writeQuery.getObjectChangeSet();
        Object object = writeQuery.getObject();
        ClassDescriptor descriptor = getDescriptor();
        DescriptorQueryManager queryManager = descriptor.getQueryManager();
        AbstractSession session = getSession();
        CommitManager commitManager = session.getCommitManager();
        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 && queryManager.hasUpdateQuery()// there is a user-defined query
                 && isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            // This must be done here because the user defined update does not use a changeset so it will not be set otherwise
            commitManager.markPreModifyCommitInProgress(object);
            performUserDefinedUpdate();
            return;
        }
        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(object);
        DescriptorEventManager eventManager = descriptor.getEventManager();

        if (changeSet.hasChanges()) {
            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.PreUpdateWithChangesEvent, writeQuery);
                eventManager.executeEvent(event);

                // PreUpdateWithChangesEvent listeners may have altered the object - should recalculate the change set.
                UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)((UnitOfWorkImpl)session).getUnitOfWorkChangeSet();
                if (!uowChangeSet.isChangeSetFromOutsideUOW() && writeQuery.getObjectChangeSet().shouldRecalculateAfterUpdateEvent()){
                    // writeQuery.getObjectChangeSet() is mapped to object in uowChangeSet.
                    // It is first cleared then re-populated by calculateChanges method.
                    if (!descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy() ){
                        // clear the change set without clearing the maps keys since they are not alterable by the event
                        // if the map is changed, it will be changed in the owning object and the
                        // change set will be changed there as well.
                        writeQuery.getObjectChangeSet().clear(false);
                    }
                    if (descriptor.getObjectChangePolicy().calculateChangesForExistingObject(object, uowChangeSet, ((UnitOfWorkImpl)session), descriptor, false) == null) {
                        // calculateChanges returns null in case the changeSet doesn't have changes.
                        // It should be removed from the list of ObjectChangeSets that have changes in uowChangeSet.
                        uowChangeSet.getAllChangeSets().remove(writeQuery.getObjectChangeSet());
                    }
                }
            }
        }

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preUpdate(writeQuery);
        }

        // The row must not be built until after preUpdate in case the object reference has changed.
        // For a user defined update in the uow to row must be built twice to check if any update is required.
        writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForUpdateWithChangeSet(writeQuery));

        Boolean shouldModifyVersionField = changeSet.shouldModifyVersionField();
        if (!getModifyRow().isEmpty() || shouldModifyVersionField != null || changeSet.hasCmpPolicyForcedUpdate()) {
            // If user defined the entire row is required. Must not be built until change is known.
            if (writeQuery.isUserDefined() || writeQuery.isCallQuery()) {
                writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, session, WriteType.UNDEFINED));
            }
            OptimisticLockingPolicy lockingPolicy = descriptor.getOptimisticLockingPolicy();

            // Update the write lock field if required.
            if (lockingPolicy != null) {
                lockingPolicy.addLockValuesToTranslationRow(writeQuery);
                // Do not lock an object that has previously been optimistically locked within the RWUoW
                boolean existingOptimisticLock = false;
                if (session instanceof RepeatableWriteUnitOfWork) {
                    RepeatableWriteUnitOfWork uow = (RepeatableWriteUnitOfWork)session;
                    if (uow.getOptimisticReadLockObjects().get(object) != null && uow.getCumulativeUOWChangeSet() != null
                            && uow.getCumulativeUOWChangeSet().getObjectChangeSetForClone(object) != null) {
                        existingOptimisticLock = true;
                    }
                }
                if (!existingOptimisticLock) {
                    // update the row and object if shouldModifyVersionField is non null and has a value of true (a forced update),
                    // or if there is no forced update and modifyRow has modifications
                    if ((shouldModifyVersionField != null && shouldModifyVersionField) || !getModifyRow().isEmpty()) {
                        // Update the row with newer lock value.
                        lockingPolicy.updateRowAndObjectForUpdate(writeQuery, object);
                    } else if (!shouldModifyVersionField && (lockingPolicy instanceof VersionLockingPolicy)) {
                        // Add the existing write lock value to the for a "read" lock (requires something to update).
                        ((VersionLockingPolicy)lockingPolicy).writeLockValueIntoRow(writeQuery, object);
                    }
                }
            }
            if (descriptor.hasSerializedObjectPolicy()) {
                descriptor.getSerializedObjectPolicy().putObjectIntoRow(getModifyRow(), object, session);
            }

            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
                event.setRecord(getModifyRow());
                eventManager.executeEvent(event);
            }

            if (QueryMonitor.shouldMonitor()) {
                QueryMonitor.incrementUpdate(getWriteObjectQuery());
            }
            int rowCount = updateObject();

            if (rowCount < 1) {
                if (session.hasEventManager()) {
                    session.getEventManager().noRowsModified(writeQuery, object);
                }
            }
            if (lockingPolicy != null) {
                lockingPolicy.validateUpdate(rowCount, object, writeQuery);
            }
        }

        commitManager.markPostModifyCommitInProgress(object);

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postUpdate(writeQuery);
        }
        if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
            descriptor.getHistoryPolicy().postUpdate(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
        }
    }

    /**
     * Unprepare the call if required.
     */
    public void unprepare() {

    }
}
