/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 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
//     05/5/2009-2.0 Guy Pelletier
//       - 248489: JPA 2.0 Pessimistic Locking/Lock Mode support
//       - Allows the configuration of pessimistic locking from JPA entity manager
//         functions (find, refresh, lock) and from individual query execution.
//         A pessimistic lock can be issued with a lock timeout value as well, in
//         which case, for those databases that support LOCK WAIT will cause
//         a LockTimeoutException to be thrown if the query fails as a result of
//         a timeout trying to acquire the lock. A PessimisticLockException is
//         thrown otherwise.
//     05/19/2010-2.1 ailitchev - Bug 244124 - Add Nested FetchGroup
//     09/21/2010-2.2 Frank Schwarz and ailitchev - Bug 325684 - QueryHints.BATCH combined with QueryHints.FETCH_GROUP_LOAD will cause NPE
//     3/13/2015 - Will Dazey
//       - 458301 : Added check so that aggregate results won't attempt force version lock if locking type is set
package org.eclipse.persistence.queries;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.FetchGroupManager;
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.expressions.ExpressionBuilder;
import org.eclipse.persistence.history.AsOfClause;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.expressions.FieldExpression;
import org.eclipse.persistence.internal.expressions.ForUpdateClause;
import org.eclipse.persistence.internal.expressions.ForUpdateOfClause;
import org.eclipse.persistence.internal.expressions.ObjectExpression;
import org.eclipse.persistence.internal.expressions.QueryKeyExpression;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DeferredLockManager;
import org.eclipse.persistence.internal.helper.InvalidObject;
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
import org.eclipse.persistence.internal.history.UniversalAsOfClause;
import org.eclipse.persistence.internal.queries.DatabaseQueryMechanism;
import org.eclipse.persistence.internal.queries.ExpressionQueryMechanism;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.queries.QueryByExampleMechanism;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;

/**
 * <p><b>Purpose</b>:
 * Abstract class for all read queries using objects.
 *
 * <p><b>Description</b>:
 * Contains common behavior for all read queries using objects.
 *
 * @author Yvon Lavoie
 * @since TOPLink/Java 1.0
 */
public abstract class ObjectLevelReadQuery extends ObjectBuildingQuery {
    /** Names of the possible lock mode types, JPA 1.0 and 2.0 */
    public static final String READ = "READ";
    public static final String WRITE = "WRITE";

    /** Names of the possible lock mode types, JPA 2.0 only */
    public static final String NONE = "NONE";
    public static final String PESSIMISTIC_ = "PESSIMISTIC_";
    public static final String PESSIMISTIC_READ = PESSIMISTIC_ + "READ";
    public static final String PESSIMISTIC_WRITE = PESSIMISTIC_ + "WRITE";
    public static final String PESSIMISTIC_FORCE_INCREMENT = PESSIMISTIC_ + "FORCE_INCREMENT";
    public static final String OPTIMISTIC = "OPTIMISTIC";
    public static final String OPTIMISTIC_FORCE_INCREMENT = "OPTIMISTIC_FORCE_INCREMENT";

    /** Provide a default builder so that it's easier to be consistent */
    protected ExpressionBuilder defaultBuilder;

    /** Allow for the cache usage to be specified to enable in-memory querying. */
    protected int cacheUsage;

    // Note: UseDescriptorSetting will result in CheckCacheByPrimaryKey for most cases
    // it simply allows the ClassDescriptor's disable cache hits to be used
    public static final int UseDescriptorSetting = -1;
    public static final int DoNotCheckCache = 0;
    public static final int CheckCacheByExactPrimaryKey = 1;
    public static final int CheckCacheByPrimaryKey = 2;
    public static final int CheckCacheThenDatabase = 3;
    public static final int CheckCacheOnly = 4;
    public static final int ConformResultsInUnitOfWork = 5;

    /**
     * Allow for additional fields to be selected, used for m-m batch reading.
     * Can contain DatabaseField or Expression.
     */
    protected List<Object> additionalFields;

    /** Allow for a complex result to be return including the rows and objects, used for m-m batch reading. */
    protected boolean shouldIncludeData;

    /** Allow a prePrepare stage to build the expression for EJBQL and QBE and resolve joining. */
    protected boolean isPrePrepared;

    /** Indicates if distinct should be used or not. */
    protected short distinctState;
    public static final short UNCOMPUTED_DISTINCT = 0;
    public static final short USE_DISTINCT = 1;
    public static final short DONT_USE_DISTINCT = 2;

    /**
     * Used to determine behavior of indirection in in-memory querying and conforming.
     */
    protected int inMemoryQueryIndirectionPolicy;

    /**
     * {@link FetchGroup} specified on this query. When set this FetchGroup will
     * override the {@link #fetchGroupName} and the use of the descriptor's
     * {@link FetchGroupManager#getDefaultFetchGroup()}
     */
    protected FetchGroup fetchGroup;

    /**
     * Name of {@link FetchGroup} stored in the {@link FetchGroupManager} of the
     * reference class' descriptor or any of its parent descriptors.
     */
    protected String fetchGroupName;

    /** Flag to turn on/off the use of the default fetch group. */
    protected boolean shouldUseDefaultFetchGroup = true;

    /** Specifies indirection that should be instantiated before returning result */
    protected LoadGroup loadGroup;

    /**
     * Stores the non fetchjoin attributes, these are joins that will be
     * represented in the where clause but not in the select.
     */
    protected List<Expression> nonFetchJoinAttributeExpressions;

    /**  Stores the partial attributes that have been added to this query */
    protected List<Expression> partialAttributeExpressions;

    /** Stores the helper object for dealing with joined attributes */
    protected JoinedAttributeManager joinedAttributeManager;

    /** Defines batch fetching configuration. */
    protected BatchFetchPolicy batchFetchPolicy;

    /** PERF: Caches locking policy isReferenceClassLocked setting. */
    protected Boolean isReferenceClassLocked;

    /** PERF: Allow queries to build directly from the database result-set. */
    protected boolean isResultSetOptimizedQuery = false;

    /** PERF: Allow queries to build while accessing the database result-set. Skips accessing result set non-pk fields in case the cached object is found.
     If ResultSet optimization is used (isResultSetOptimizedQuery is set to true) then ResultSet Access optimization is ignored. */
    protected Boolean isResultSetAccessOptimizedQuery;

    /** If neither query specifies isResultSetOptimizedQuery nor session specifies shouldOptimizeResultSetAccess
     * then this value is used to indicate whether optimization should be attempted
     */
    public static boolean isResultSetAccessOptimizedQueryDefault = false;

    /** PERF: Indicates whether the query is actually using ResultSet optimization. If isResultSetOptimizedQuery==null set automatically before executing call. */
    protected transient Boolean usesResultSetAccessOptimization;

    /** PERF: Allow queries to be defined as read-only in unit of work execution. */
    protected boolean isReadOnly = false;

    /** Define if an outer join should be used to read subclasses. */
    protected Boolean shouldOuterJoinSubclasses;

    /** Allow concrete subclasses calls to be prepared and cached for inheritance queries. */
    protected Map<Class, DatabaseCall> concreteSubclassCalls;

    /** Allow concrete subclasses queries to be prepared and cached for inheritance queries. */
    protected Map<Class, DatabaseQuery> concreteSubclassQueries;

    /** Allow aggregate queries to be prepared and cached. */
    protected Map<DatabaseMapping, ObjectLevelReadQuery> aggregateQueries;

    /** Allow concrete subclasses joined mapping indexes to be prepared and cached for inheritance queries. */
    protected Map<Class, Map<DatabaseMapping, Object>> concreteSubclassJoinedMappingIndexes;

    /** Used when specifying a lock mode for the query */
    protected String lockModeType;

    /**
     * waitTimeout has three possible setting: null, 0 and 1..N
     * null: use the session.getPessimisticLockTimeoutDefault() if available.
     * 0: issue a LOCK_NOWAIT
     * 1..N: use this value to set the WAIT clause.
     */
    protected Integer waitTimeout;
    
  //wait timeout unit
    protected TimeUnit waitTimeoutUnit;

    /** Used for ordering support. */
    protected List<Expression> orderByExpressions;

    /** Indicates whether pessimistic lock should also be applied to relation tables (ManyToMany and OneToOne mappings),
     *  reference tables (DirectCollection and AggregateCollection mapping).
     */
    protected boolean shouldExtendPessimisticLockScope;

    /**
     * Allow a query's results to be unioned (UNION, INTERSECT, EXCEPT) with another query results.
     */
    protected List<Expression> unionExpressions;

    /** Indicates whether the query is cached as an expression query in descriptor's query manager. */
    protected boolean isCachedExpressionQuery;

    /** default value for shouldUseSerializedObjectPolicy */
    public static boolean shouldUseSerializedObjectPolicyDefault = true;

    /** Indicates whether the query should use SerializedObjectPolicy if descriptor has it.*/
    protected boolean shouldUseSerializedObjectPolicy;

    /**
     * INTERNAL:
     * Initialize the state of the query
     */
    protected ObjectLevelReadQuery() {
        this.shouldRefreshIdentityMapResult = false;
        this.distinctState = UNCOMPUTED_DISTINCT;
        this.cacheUsage = UseDescriptorSetting;
        this.shouldIncludeData = false;
        this.inMemoryQueryIndirectionPolicy = InMemoryQueryIndirectionPolicy.SHOULD_THROW_INDIRECTION_EXCEPTION;
        this.isCacheCheckComplete = false;
        this.shouldUseSerializedObjectPolicy = shouldUseSerializedObjectPolicyDefault;
    }

    /**
     * PUBLIC:
     * Union the query results with the other query.
     */
    public void union(ReportQuery query) {
        addUnionExpression(getExpressionBuilder().union(query));
    }

    /**
     * PUBLIC:
     * Intersect the query results with the other query.
     */
    public void intersect(ReportQuery query) {
        addUnionExpression(getExpressionBuilder().intersect(query));
    }

    /**
     * PUBLIC:
     * Except the query results with the other query.
     */
    public void except(ReportQuery query) {
        addUnionExpression(getExpressionBuilder().except(query));
    }

    /**
     * PUBLIC:
     * Add the union expression to the query.
     * A union expression must be created with the query's expression builder
     * and one of union/unionAll/intersect/intersectAll/except/exceptAll with a subquery expression.
     */
    public void addUnionExpression(Expression union) {
        setIsPrepared(false);
        getUnionExpressions().add(union);
    }

    /**
     * Return any union expressions.
     */
    public List<Expression> getUnionExpressions() {
        if (unionExpressions == null) {
            unionExpressions = new ArrayList<>();
        }
        return unionExpressions;
    }

    /**
     * INTERNAL:
     * Set any union expressions.
     */
    public void setUnionExpressions(List<Expression> unionExpressions) {
        this.unionExpressions = unionExpressions;
    }

    /**
     * PUBLIC:
     * Order the query results by the object's attribute or query key name.
     */
    public void addDescendingOrdering(String queryKeyName) {
        addOrdering(getExpressionBuilder().get(queryKeyName).descending());
    }

    /**
     * PUBLIC:
     * Add the ordering expression.  This allows for ordering across relationships or functions.
     * Example: readAllQuery.addOrdering(expBuilder.get("address").get("city").toUpperCase().descending())
     */
    public void addOrdering(Expression orderingExpression) {
        getOrderByExpressions().add(orderingExpression);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
        setShouldOuterJoinSubclasses(true);
    }

    /**
     * INTERNAL:
     * Return if the query is equal to the other.
     * This is used to allow dynamic expression query SQL to be cached.
     */
    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if ((object == null) || (!getClass().equals(object.getClass())))  {
            return false;
        }
        ObjectLevelReadQuery query = (ObjectLevelReadQuery) object;
        // Only check expression queries for now.
        if ((!isExpressionQuery()) || (!isDefaultPropertiesQuery())) {
            return this == object;
        }
        if (!getExpressionBuilder().equals(query.getExpressionBuilder())) {
            return false;
        }
        if (this.distinctState != query.distinctState) {
            return false;
        }
        if (hasJoining()) {
            if (!query.hasJoining()) {
                return false;
            }
            List joinedAttributes = getJoinedAttributeManager().getJoinedAttributeExpressions();
            List otherJoinedAttributes = query.getJoinedAttributeManager().getJoinedAttributeExpressions();
            int size = joinedAttributes.size();
            if (size != otherJoinedAttributes.size()) {
                return false;
            }
            for (int index = 0; index < size; index++) {
                if (!joinedAttributes.get(index).equals(otherJoinedAttributes.get(index))) {
                    return false;
                }
            }
        } else if (query.hasJoining()) {
            return false;
        }
        if (hasOrderByExpressions()) {
            if (!query.hasOrderByExpressions()) {
                return false;
            }
            List orderBys = getOrderByExpressions();
            List otherOrderBys = query.getOrderByExpressions();
            int size = orderBys.size();
            if (size != otherOrderBys.size()) {
                return false;
            }
            for (int index = 0; index < size; index++) {
                if (!orderBys.get(index).equals(otherOrderBys.get(index))) {
                    return false;
                }
            }
        } else if (query.hasOrderByExpressions()) {
            return false;
        }
        if (! ((this.referenceClass == query.referenceClass) || ((this.referenceClass != null) && this.referenceClass.equals(query.referenceClass)))) {
            return false;
        }
        Expression selectionCriteria = getSelectionCriteria();
        Expression otherSelectionCriteria = query.getSelectionCriteria();
        return ((selectionCriteria == otherSelectionCriteria) || ((selectionCriteria != null) && selectionCriteria.equals(otherSelectionCriteria)));
    }

    /**
     * INTERNAL:
     * Compute a consistent hash-code for the expression.
     * This is used to allow dynamic expression's SQL to be cached.
     */
    @Override
    public int hashCode() {
        if (!isExpressionQuery()) {
            return super.hashCode();
        }
        int hashCode = 32;
        if (this.referenceClass != null) {
            hashCode = hashCode + this.referenceClass.hashCode();
        }
        Expression selectionCriteria = getSelectionCriteria();
        if (selectionCriteria != null) {
            hashCode = hashCode + selectionCriteria.hashCode();
        }
        return hashCode;
    }

    /**
     * PUBLIC:
     * Return if the query is read-only.
     * This allows queries executed against a UnitOfWork to be read-only.
     * This means the query will be executed against the Session,
     * and the resulting objects will not be tracked for changes.
     * The resulting objects are from the Session shared cache,
     * and must not be modified.
     */
    public boolean isReadOnly() {
        return isReadOnly;
    }

    /**
     * PUBLIC:
     * Set the query to be read-only.
     * This allows queries executed against a UnitOfWork to be read-only.
     * This means the query will be executed against the Session,
     * and the resulting objects will not be tracked for changes.
     * The resulting objects are from the Session shared cache,
     * and must not be modified.
     */
    public void setIsReadOnly(boolean isReadOnly) {
        this.isReadOnly = isReadOnly;
    }

    /**
     * PUBLIC:
     * Sets that this a pessimistic wait locking query.
     * <ul>
     * <li>ObjectBuildingQuery.LOCK: SELECT .... FOR UPDATE WAIT issued.
     * </ul>
     * <p>Fine Grained Locking: On execution the reference class and those of
     * all joined attributes will be checked. If any of these have a
     * PessimisticLockingPolicy set on their descriptor, they will be locked
     * in a SELECT ... FOR UPDATE OF ... {NO WAIT}. Issues fewer locks
     * and avoids setting the lock mode on each query.
     *
     * <p>Example:
     * <code>readAllQuery.setSelectionCriteria(employee.get("address").equal("Ottawa"));</code>
     * <ul>
     * <li>LOCK: all employees in Ottawa and all referenced Ottawa addresses
     * will be locked and the lock will wait only the specified amount of time.
     * </ul>
     * @see org.eclipse.persistence.descriptors.PessimisticLockingPolicy
     */
    public void setWaitTimeout(Integer waitTimeout) {
        this.waitTimeout = waitTimeout;
        setIsPrePrepared(false);
        setIsPrepared(false);
        setWasDefaultLockMode(false);
    }
    
    public void setWaitTimeoutUnit(TimeUnit waitTimeoutUnit) {
        this.waitTimeoutUnit = waitTimeoutUnit;
    }
    
    /**
     * INTERNAL:
     * Check and return custom query flag. Custom query flag value is initialized when stored value is {@code null}.
     * Called from {@link #checkForCustomQuery(AbstractSession, AbstractRecord)} to retrieve custom query flag.
     * @param session        Current session.
     * @param translationRow Database record.
     * @return Current custom query flag. Value shall never be {@code null}.
     */
    protected abstract Boolean checkCustomQueryFlag(final AbstractSession session, final AbstractRecord translationRow);

    /**
     * INTERNAL:
     * Get custom read query from query manager.
     * Called from {@link #checkForCustomQuery(AbstractSession, AbstractRecord)} to retrieve custom read query.
     * @return Custom read query from query manager.
     */
    protected abstract ObjectLevelReadQuery getReadQuery();

    /**
     * INTERNAL:
     * Check to see if a custom query should be used for this query.
     * This is done before the query is copied and prepared/executed. Value of {@code null} means there is none.
     * @param session        Current session.
     * @param translationRow Database record.
     * @return Custom database query or {@code null} when custom database query is not set.
     */
    @Override
    protected DatabaseQuery checkForCustomQuery(final AbstractSession session, final AbstractRecord translationRow) {
        final Boolean useCustomQuery = checkCustomQueryFlag(session, translationRow);
        checkDescriptor(session);
        ObjectLevelReadQuery customQuery;
        if (useCustomQuery != null && useCustomQuery.booleanValue()) {
            customQuery = getReadQuery();
            if (this.accessors != null) {
                customQuery = (ObjectLevelReadQuery) customQuery.clone();
                customQuery.setIsExecutionClone(true);
                customQuery.setAccessors(this.accessors);
            }
        } else {
            customQuery = null;
        }
        isCustomQueryUsed = useCustomQuery;
        return customQuery;
    }

    /**
     * INTERNAL:
     * Creates and returns a copy of this query.
     * @return A clone of this instance.
     */
    @Override
    public Object clone() {
        final ObjectLevelReadQuery cloneQuery = (ObjectLevelReadQuery)super.clone();
        // Must also clone the joined expressions as always joined attribute will be added
        // don't use setters as this will trigger unprepare.
        if (joinedAttributeManager != null) {
            cloneQuery.joinedAttributeManager = joinedAttributeManager.clone();
            cloneQuery.joinedAttributeManager.setBaseQuery(cloneQuery);
        }
        if (this.batchFetchPolicy != null) {
            cloneQuery.batchFetchPolicy = batchFetchPolicy.clone();
        }
        if (this.nonFetchJoinAttributeExpressions != null){
            cloneQuery.nonFetchJoinAttributeExpressions = new ArrayList<>(nonFetchJoinAttributeExpressions);
        }
        // Don't use setters as that will trigger unprepare
        if (this.orderByExpressions != null) {
            cloneQuery.orderByExpressions = new ArrayList<>(this.orderByExpressions);
        }
        if (this.fetchGroup != null) {
            cloneQuery.fetchGroup = fetchGroup.clone();
            // don't clone immutable entityFetchGroup
        }
        return cloneQuery;
    }

    /**
     * INTERNAL:
     * Clone the query, including its selection criteria.
     * <p>
     * Normally selection criteria are not cloned here as they are cloned
     * later on during prepare.
     */
    @Override
    public Object deepClone() {
        ObjectLevelReadQuery clone = (ObjectLevelReadQuery)clone();
        if (getSelectionCriteria() != null) {
            clone.setSelectionCriteria((Expression)getSelectionCriteria().clone());
        }
        if (defaultBuilder != null) {
            clone.defaultBuilder = (ExpressionBuilder)defaultBuilder.clone();
        }
        return clone;
    }

    /**
     * PUBLIC:
     * Set the query to lock, this will also turn refreshCache on.
     */
    public void acquireLocks() {
        setLockMode(LOCK);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    }

    /**
     * PUBLIC:
     * Set the query to lock without waiting (blocking), this will also turn refreshCache on.
     */
    public void acquireLocksWithoutWaiting() {
        setLockMode(LOCK_NOWAIT);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    }

    /**
     * INTERNAL:
     * Additional fields can be added to a query.  This is used in m-m batch reading to bring back the key from the join table.
     */
    public void addAdditionalField(DatabaseField field) {
        getAdditionalFields().add(field);
        // Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    }

    /**
     * INTERNAL:
     * Additional fields can be added to a query.  This is used in m-m batch reading to bring back the key from the join table.
     */
    public void addAdditionalField(Expression fieldExpression) {
        getAdditionalFields().add(fieldExpression);
        // Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    }

    /**
     * PUBLIC:
     * Specify the relationship attribute to be join fetched in this query.
     * The query will join the object(s) being read with the attribute,
     * this allows all of the data required for the object(s) to be read in a single query instead of (n) queries.
     * This should be used when the application knows that it requires the part for all of the objects being read.
     *
     * <p>Note: This cannot be used for objects where it is possible not to have a part,
     * as these objects will be omitted from the result set,
     * unless an outer join is used through passing and expression using "getAllowingNull".
     * To join fetch collection relationships use the addJoinedAttribute(Expression) using "anyOf" to "anyOfAllowingNone".
     *
     * <p>Example: query.addJoinedAttribute("address")
     *
     * @see #addJoinedAttribute(Expression)
     * @see ReadAllQuery#addBatchReadAttribute(Expression)
     */
    public void addJoinedAttribute(String attributeName) {
        addJoinedAttribute(getExpressionBuilder().get(attributeName));
    }

    /**
     * PUBLIC:
     * Specify the attribute to be join fetched in this query.
     * The query will join the object(s) being read with the specified attribute,
     * this allows all of the data required for the object(s) to be read in a single query instead of (n) queries.
     * This should be used when the application knows that it requires the part for all of the objects being read.
     *
     * <p>Note: This cannot be used for objects where it is possible not to have a part,
     * as these objects will be omitted from the result set,
     * unless an outer join is used through passing and expression using "getAllowingNull".
     *
     * <p>Example:
     * The following will fetch along with Employee(s) "Jones" all projects they participate in
     * along with teamLeaders and their addresses, teamMembers and their phones.
     *
     * query.setSelectionCriteria(query.getExpressionBuilder().get("lastName").equal("Jones"));
     * Expression projects = query.getExpressionBuilder().anyOf("projects");
     * query.addJoinedAttribute(projects);
     * Expression teamLeader = projects.get("teamLeader");
     * query.addJoinedAttribute(teamLeader);
     * Expression teamLeaderAddress = teamLeader.getAllowingNull("address");
     * query.addJoinedAttribute(teamLeaderAddress);
     * Expression teamMembers = projects.anyOf("teamMembers");
     * query.addJoinedAttribute(teamMembers);
     * Expression teamMembersPhones = teamMembers.anyOfAllowingNone("phoneNumbers");
     * query.addJoinedAttribute(teamMembersPhones);
     *
     * Note that:
     * the order is essential: an expression should be added before any expression derived from it;
     * the object is built once - it won't be rebuilt if it to be read again as a joined attribute:
     * in the example the query won't get phones for "Jones" -
     * even though they are among teamMembers (for whom phones are read).
     *
     */
    public void addJoinedAttribute(Expression attributeExpression) {
        getJoinedAttributeManager().addJoinedAttributeExpression(attributeExpression);
        // Bug2804042 Must un-prepare if prepared as the SQL may change.
        // Joined attributes are now calculated in prePrepare.
        setIsPrePrepared(false);
    }

    /**
     * PUBLIC:
     * Specify the relationship attribute to be join in this query.
     * This allows the query results to be filtered based on the relationship join.
     * The query will join the object(s) being read with the attribute.
     * The difference between this and a joined fetched attribute is that
     * it does not select the joined data nor populate the joined attribute,
     * it is only used to filter the query results.
     *
     * <p>Example: query.addNonFetchJoinedAttribute("address")
     *
     * @see #addNonFetchJoinedAttribute(Expression)
     */
    public void addNonFetchJoinedAttribute(String attributeName) {
        addNonFetchJoin(getExpressionBuilder().get(attributeName));
    }

    /**
     * PUBLIC:
     * Specify the relationship attribute to be join in this query.
     * This allows the query results to be filtered based on the relationship join.
     * The query will join the object(s) being read with the attribute.
     * The difference between this and a joined fetched attribute is that
     * it does not select the joined data nor populate the joined attribute,
     * it is only used to filter the query results.
     *
     * <p>Example: query.addNonFetchJoinedAttribute(query.getExpressionBuilder().get("teamLeader").get("address"))
     *
     * @see #addNonFetchJoinedAttribute(Expression)
     */
    public void addNonFetchJoinedAttribute(Expression attributeExpression) {
        addNonFetchJoin(attributeExpression);
    }

    /**
     * PUBLIC:
     * Specify the object expression to be joined in this query.
     * This allows the query results to be filtered based on the join to the object.
     * The object should define an on clause that defines the join condition.
     * This allows for two non-related objects to be joined.
     *
     * <p>Example: (select all employees that are a team leader)</p>
     * <pre>
     * ExpressionBuilder project = new ExpressionBuilder(Project.class);
     * ExpressionBuilder employee = new ExpressionBuilder(Employee.class);
     * ReadAllQuery query = new ReadAllQuery(Employee.class, employee);
     * query.addJoin(project.on(project.get("teamLeader").equal(employee)))
     * </pre>
     */
    public void addNonFetchJoin(Expression target) {
        getNonFetchJoinAttributeExpressions().add(target);
        if (target.isObjectExpression() && ((ObjectExpression)target).shouldUseOuterJoin()) {
            this.setShouldBuildNullForNullPk(true);
        }
        // Bug 2804042 Must un-prepare if prepared as the SQL may change.
        // Joined attributes are now calculated in prePrepare.
        setIsPrePrepared(false);
    }

    /**
     * PUBLIC:
     * Specify that only a subset of the class' attributes be selected in this query.
     * <p>
     * This allows for the query to be optimized through selecting less data.
     * <p>
     * Partial objects will be returned from the query, where the unspecified attributes will be left <code>null</code>.
     * The primary key will always be selected to allow re-querying of the whole object.
     * <p>Note: Because the object is not fully initialized it cannot be cached, and cannot be edited.
     * <p>Note: You cannot have 2 partial attributes of the same type.  You also cannot
     * add a partial attribute which is of the same type as the class being queried.
     * <p><b>Example</b>: query.addPartialAttribute("firstName")
     * @see #addPartialAttribute(Expression)
     * @deprecated since EclipseLink 2.1, partial attributes replaced by fetch groups.
     * @see FetchGroup
     * Example:
     * FetchGroup fetchGroup = new FetchGroup();
     * fetchGroup.addAttribute("address.city");
     * query.setFetchGroup(fetchGroup);
     */
    @Deprecated
    public void addPartialAttribute(String attributeName) {
        addPartialAttribute(getExpressionBuilder().get(attributeName));
    }

    /**
     * INTERNAL:
     * The method adds to the passed input vector the
     * fields or expressions corresponding to the passed join expression.
     */
    protected void addSelectionFieldsForJoinedExpression(List fields, boolean isCustomSQL, Expression expression) {
        if(isCustomSQL) {
            // Expression may not have been initialized.
            ExpressionBuilder builder = expression.getBuilder();
            builder.setSession(getSession().getRootSession(null));
            builder.setQueryClass(getReferenceClass());
        }
        ForeignReferenceMapping mapping = (ForeignReferenceMapping)((QueryKeyExpression)expression).getMapping();
        ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();

        // Add the fields defined by the nested fetch group - if it exists.
        ObjectLevelReadQuery nestedQuery = null;
        if (referenceDescriptor != null && referenceDescriptor.hasFetchGroupManager()) {
            nestedQuery = getJoinedAttributeManager().getNestedJoinedMappingQuery(expression);
            FetchGroup nestedFetchGroup = nestedQuery.getExecutionFetchGroup();
            if(nestedFetchGroup != null) {
                List<DatabaseField> nestedFields = nestedQuery.getFetchGroupSelectionFields(mapping);
                for(DatabaseField field : nestedFields) {
                    fields.add(new FieldExpression(field, expression));
                }
                return;
            }
        }

        if(isCustomSQL) {
            if(referenceDescriptor != null) {
                if (nestedQuery == null) {
                    nestedQuery = getJoinedAttributeManager().getNestedJoinedMappingQuery(expression);
                }
                fields.addAll(referenceDescriptor.getAllSelectionFields(nestedQuery));
            } else {
                fields.add(expression);
            }
        } else {
            fields.add(expression);
        }
    }

    /**
     * ADVANCED: Sets the query to execute as of the past time.
     * Both the query execution and result will conform to the database as it
     * existed in the past.
     * <p>
     * Equivalent to query.getSelectionCriteria().asOf(pastTime) called
     * immediately before query execution.
     * <p>An as of clause at the query level will override any clauses set at the
     * expression level.  Useful in cases where the selection criteria is not known in
     * advance, such as for query by example or primary key (selection object), or
     * where you do not need to cache the result (report query).
     * <p>Ideally an as of clause at the session level is superior as query
     * results can then be cached.  You must set
     * {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#setShouldMaintainCache setShouldMaintainCache(false)}
     * <p>To query all joined/batched attributes as of the same time set
     * this.{@link org.eclipse.persistence.queries.ObjectLevelReadQuery#cascadeAllParts cascadeAllParts()}.
     * @throws QueryException (at execution time) unless
     * <code>setShouldMaintainCache(false)</code> is set.  If some more recent
     * data were in the cache, this would be returned instead, and both the
     * cache and query result would become inconsistent.
     * @since OracleAS TopLink 10<i>g</i> (10.0.3)
     * @see #hasAsOfClause
     * @see org.eclipse.persistence.sessions.Session#acquireHistoricalSession(org.eclipse.persistence.history.AsOfClause)
     * @see org.eclipse.persistence.expressions.Expression#asOf(org.eclipse.persistence.history.AsOfClause)
     */
    public void setAsOfClause(AsOfClause pastTime) {
        getExpressionBuilder().asOf(new UniversalAsOfClause(pastTime));
        setIsPrepared(false);
    }

    /**
     * PUBLIC:
     * Specify that only a subset of the class' attributes be selected in this query.
     * <p>This allows for the query to be optimized through selecting less data.
     * <p>Partial objects will be returned from the query, where the unspecified attributes will be left <code>null</code>.
     * The primary key will always be selected to allow re-querying of the whole object.
     * <p>Note: Because the object is not fully initialized it cannot be cached, and cannot be edited.
     * <p>Note: You cannot have 2 partial attributes of the same type.  You also cannot
     * add a partial attribute which is of the same type as the class being queried.
     * <p><b>Example</b>: query.addPartialAttribute(query.getExpressionBuilder().get("address").get("city"))
     * @deprecated since EclipseLink 2.1, partial attributes replaced by fetch groups.
     * @see FetchGroup
     * Example:
     * FetchGroup fetchGroup = new FetchGroup();
     * fetchGroup.addAttribute("address.city");
     * query.setFetchGroup(fetchGroup);
     */
    @Deprecated
    public void addPartialAttribute(Expression attributeExpression) {
        getPartialAttributeExpressions().add(attributeExpression);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    }

    /**
     * INTERNAL:
     * Used to build the object, and register it if in the context of a unit of work.
     */
    @Override
    public Object buildObject(AbstractRecord row) {
        return this.descriptor.getObjectBuilder().buildObject(this, row, this.joinedAttributeManager);
    }

    /**
     * PUBLIC:
     * The cache will checked completely, if the object is not found null will be returned or an error if the query is too complex.
     * Queries can be configured to use the cache at several levels.
     * Other caching option are available.
     * @see #setCacheUsage(int)
     */
    public void checkCacheOnly() {
        setCacheUsage(CheckCacheOnly);
    }

    /**
     * INTERNAL:
     * Ensure that the descriptor has been set.
     * @param session Current session.
     */
    @Override
    public void checkDescriptor(AbstractSession session) throws QueryException {
        if (this.descriptor == null) {
            if (getReferenceClass() == null) {
                throw QueryException.referenceClassMissing(this);
            }
            ClassDescriptor referenceDescriptor = session.getDescriptor(getReferenceClass());
            if (referenceDescriptor == null) {
                throw QueryException.descriptorIsMissing(getReferenceClass(), this);
            }
            setDescriptor(referenceDescriptor);
        }
    }

    /**
     * INTERNAL:
     * Contains the body of the check early return call, implemented by subclasses.
     */
    protected abstract Object checkEarlyReturnLocal(AbstractSession session, AbstractRecord translationRow);

    /**
     * INTERNAL:
     * Check to see if this query already knows the return value without performing any further work.
     */
    @Override
    public Object checkEarlyReturn(AbstractSession session, AbstractRecord translationRow) {
        // For bug 3136413/2610803 building the selection criteria from an EJBQL string or
        // an example object is done just in time.
        // Also calls checkDescriptor here.
        //buildSelectionCriteria(session);
        checkPrePrepare(session);

        if (!session.isUnitOfWork()) {
            return checkEarlyReturnLocal(session, translationRow);
        }
        UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)session;

        // The cache check must happen on the UnitOfWork in these cases either
        // to access transient state or for pessimistic locking, as only the
        // UOW knows which objects it has locked.
        Object result = null;
        // PERF: Avoid uow check for read-only.
        if (!this.descriptor.shouldBeReadOnly()) {
            result = checkEarlyReturnLocal(unitOfWork, translationRow);
        }
        if (result != null) {
            return result;
        }

        // PERF: If a locking query, or isolated always, then cache is ignored, so no point checking.
        // An error should be thrown on prepare is checkCacheOnly is used with these.
        if ((!unitOfWork.isNestedUnitOfWork()) && (this.descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork()  || isLockQuery()) || unitOfWork.shouldForceReadFromDB(this, null)) {
            return null;
        }

        // follow the execution path in looking for the object.
        AbstractSession parentSession = unitOfWork.getParentIdentityMapSession(this);

        // assert parentSession != unitOfWork;
        result = checkEarlyReturn(parentSession, translationRow);

        if (result != null) {
            // Optimization: If find deleted object by exact primary key
            // treat this as cache hit but return null.  Bug 2782991.
            if (result == InvalidObject.instance) {
                return result;
            }
            Object clone = registerResultInUnitOfWork(result, unitOfWork, translationRow, false);
            if (shouldConformResultsInUnitOfWork() && unitOfWork.isObjectDeleted(clone)) {
                return InvalidObject.instance;
            }
            return clone;
        } else {
            return null;
        }
    }

    /**
     * INTERNAL:
     * Check to see if this query needs to be prepare and prepare it.
     * The prepare is done on the original query to ensure that the work is not repeated.
     */
    @Override
    public void checkPrepare(AbstractSession session, AbstractRecord translationRow, boolean force) {
        // CR#3823735 For custom queries the prePrepare may not have been called yet.
        if (!this.isPrePrepared || (this.descriptor == null)) {
            checkPrePrepare(session);
        }
        super.checkPrepare(session, translationRow, force);
    }

    /**
     * INTERNAL:
     * ObjectLevelReadQueries now have an explicit pre-prepare stage, which
     * is for checking for pessimistic locking, and computing any joined
     * attributes declared on the descriptor.
     */
    public void checkPrePrepare(AbstractSession session) {
        try {
            // This query is first prepared for global common state, this must be synced.
            if (!this.isPrePrepared) {// Avoid the monitor is already prePrepare, must check again for concurrency.
                synchronized (this) {
                    if (!isPrePrepared()) {
                        AbstractSession alreadySetSession = getSession();
                        setSession(session);// Session is required for some init stuff.
                        prePrepare();
                        setSession(alreadySetSession);
                        setIsPrePrepared(true);// MUST not set prepare until done as other thread may hit before finishing the prePrepare.
                    }
                }
            } else if (this.descriptor == null) {
                // Must always check descriptor as transient for remote.
                checkDescriptor(session);
            }
        } catch (QueryException knownFailure) {
            // Set the query, as preprepare can be called directly.
            if (knownFailure.getQuery() == null) {
                knownFailure.setQuery(this);
                knownFailure.setSession(session);
            }
            throw knownFailure;
        }
    }

    /**
     * INTERNAL:
     * The reference class has been changed, need to reset the
     * descriptor. Null out the current descriptor and call
     * checkDescriptor
     * Added Feb 27, 2001 JED for EJBQL feature
     */
    public void changeDescriptor(AbstractSession theSession) {
        setDescriptor(null);
        checkDescriptor(theSession);
    }

    /**
     * INTERNAL:
     * Conforms and registers an individual result.  This instance could be one
     * of the elements returned from a read all query, the result of a Read Object
     * query, or an element read from a cursor.
     * <p>
     * A result needs to be registered before it can be conformed, so
     * registerIndividualResult is called here.
     * <p>
     * Conforming on a result from the database is lenient.  Since the object
     * matched the query on the database we assume it matches here unless we can
     * determine for sure that it was changed in this UnitOfWork not to conform.
     * @param clone the clone to return
     * @param arguments the parameters this query was executed with
     * @param selectionCriteriaClone the expression to conform to.  If was a
     * selection object or key, null (which all conform to) is used
     * @param alreadyReturned a hashtable of objects already found by scanning
     * the UnitOfWork cache for conforming instances.  Prevents duplicates.
     * @param unitOfWork current UnitOfWork
     * @return a clone, or null if result does not conform.
     */
    protected Object conformIndividualResult(Object clone, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, Expression selectionCriteriaClone, Map alreadyReturned) {
        if (this.descriptor.hasWrapperPolicy() && this.descriptor.getWrapperPolicy().isWrapped(clone)) {
            // The only time the clone could be wrapped is if we are not registering
            // results in the unitOfWork and we are ready to return a final
            // (unregistered) result now.  Any further processing may accidentally
            // cause it to get registered.
            return clone;
        }
        //bug 4459976 in order to maintain backward compatibility on ordering
        // lets use the result as a guild for the final result not the hashtable
        // of found objects.
        if (unitOfWork.isObjectDeleted(clone) ) {
            return null;
        }
        // No need to conform if no expression, or primary key query.
        if (!isExpressionQuery() || (selectionCriteriaClone == null) || isPrimaryKeyQuery()) {
            if (alreadyReturned != null) {
                alreadyReturned.remove(clone);
            }
            return clone;
        }
        try {
            // pass in the policy to assume that the object conforms if indirection is not triggered.  This
            // is valid because the query returned the object and we should trust the query that the object
            // matches the selection criteria, and because the indirection is not triggered then the customer
            //has not changed the value.
            // bug 2637555
            // unless for bug 3568141 use the painstaking shouldTriggerIndirection if set
            int policy = getInMemoryQueryIndirectionPolicyState();
            if (policy != InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION) {
                policy = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED;
            }
            if (selectionCriteriaClone.doesConform(clone, unitOfWork, arguments, policy)) {
                 if (alreadyReturned != null) {
                    alreadyReturned.remove(clone);
                }
               return clone;
            }
        } catch (QueryException exception) {
            // bug 3570561: mask all-pervasive valueholder exceptions while conforming
            if ((unitOfWork.getShouldThrowConformExceptions() == UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS) && (exception.getErrorCode() != QueryException.MUST_INSTANTIATE_VALUEHOLDERS)) {
                throw exception;
            }
            if (alreadyReturned != null) {
                alreadyReturned.remove(clone);
            }
            return clone;
        }
        return null;
    }

    /**
     * PUBLIC:
     * The cache will checked completely, if the object is not found the database will be queried,
     * and the database result will be verified with what is in the cache and/or unit of work including new objects.
     * This can lead to poor performance so it is recommended that only the database be queried in most cases.
     * Queries can be configured to use the cache at several levels.
     * Other caching option are available.
     * @see #setCacheUsage(int)
     */
    public void conformResultsInUnitOfWork() {
        setCacheUsage(ConformResultsInUnitOfWork);
    }

    /**
     * PUBLIC:
     * Set the query not to lock.
     */
    public void dontAcquireLocks() {
        setLockMode(NO_LOCK);
    }

    /**
     * PUBLIC:
     * This can be used to explicitly disable the cache hit.
     * The cache hit may not be desired in some cases, such as
     * stored procedures that accept the primary key but do not query on it.
     */
    public void dontCheckCache() {
        setCacheUsage(DoNotCheckCache);
    }

    /**
     * PUBLIC:
     * When unset means perform read normally and dont do refresh.
     */
    @Override
    public void dontRefreshIdentityMapResult() {
        setShouldRefreshIdentityMapResult(false);
    }

    /**
     * PUBLIC:
     * When unset means perform read normally and dont do refresh.
     */
    @Override
    public void dontRefreshRemoteIdentityMapResult() {
        setShouldRefreshRemoteIdentityMapResult(false);
    }

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by EclipseLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public void dontUseDistinct() {
        setDistinctState(DONT_USE_DISTINCT);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    }

    /**
     * INTERNAL:
     * There is a very special case where a query may be a bean-level
     * pessimistic locking query.
     * <p>
     * If that is so, only queries executed inside of a UnitOfWork should
     * have a locking clause.  In the extremely rare case that we execute
     * a locking query outside of a UnitOfWork, must disable locking so that
     * we do not get a fetch out of sequence error.
     */
    public DatabaseQuery prepareOutsideUnitOfWork(AbstractSession session) {
        // Implementation is complicated because: if locking refresh will be
        // auto set to true preventing cache hit.
        // Must prepare this query from scratch if outside uow but locking
        // Must not reprepare this query as a NO_LOCK, but create a clone first
        // Must not cloneAndUnPrepare unless really have to
        if (isLockQuery(session) && getLockingClause().isForUpdateOfClause()) {
            ObjectLevelReadQuery clone = (ObjectLevelReadQuery)clone();
            clone.setIsExecutionClone(true);
            clone.dontAcquireLocks();
            clone.setIsPrepared(false);
            clone.checkPrePrepare(session);
            return clone;
        }
        return this;
    }

    /**
     * INTERNAL:
     * Execute the query. If there are objects in the cache  return the results
     * of the cache lookup.
     *
     * @param session - the session in which the receiver will be executed.
     * @exception  DatabaseException - an error has occurred on the database.
     * @exception  OptimisticLockException - an error has occurred using the optimistic lock feature.
     * @return An object, the result of executing the query.
     */
    @Override
    public Object execute(AbstractSession session, AbstractRecord translationRow) throws DatabaseException, OptimisticLockException {
        //Bug#2839852  Refreshing is not possible if the query uses checkCacheOnly.
        if (shouldRefreshIdentityMapResult() && shouldCheckCacheOnly()) {
            throw QueryException.refreshNotPossibleWithCheckCacheOnly(this);
        }

        return super.execute(session, translationRow);
    }

    /**
     * INTERNAL:
     * Executes the prepared query on the datastore.
     */
    @Override
    public Object executeDatabaseQuery() throws DatabaseException {
        // PERF: If the query has been set to optimize building its result
        // directly from the database result-set then follow an optimized path.
        if (this.isResultSetOptimizedQuery) {
            return executeObjectLevelReadQueryFromResultSet();
        }

        if (this.session.isUnitOfWork()) {
            UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)this.session;

            // Note if a nested unit of work this will recursively start a
            // transaction early on the parent also.
            if (isLockQuery()) {
                if ((!unitOfWork.getCommitManager().isActive()) && (!unitOfWork.wasTransactionBegunPrematurely())) {
                    unitOfWork.beginTransaction();
                    unitOfWork.setWasTransactionBegunPrematurely(true);
                }
            }
            if (unitOfWork.isNestedUnitOfWork()) {
                UnitOfWorkImpl nestedUnitOfWork = (UnitOfWorkImpl)this.session;
                setSession(nestedUnitOfWork.getParent());
                Object result = executeDatabaseQuery();
                setSession(nestedUnitOfWork);
                return registerResultInUnitOfWork(result, nestedUnitOfWork, getTranslationRow(), false);
            }
        }

        this.session.validateQuery(this);// this will update the query with any settings

        if (this.queryId == 0) {
            this.queryId = this.session.getNextQueryId();
        }

        Object result = executeObjectLevelReadQuery();
        if (result != null) {
            if (getLoadGroup() != null) {
                Object resultToLoad  = result;
                if (this.shouldIncludeData) {
                    resultToLoad = ((ComplexQueryResult)result).getResult();
                }
                session.load(resultToLoad, getLoadGroup(), getDescriptor(), false);
            } else {
                FetchGroup executionFetchGroup = getExecutionFetchGroup();
                if (executionFetchGroup != null) {
                    LoadGroup lg = executionFetchGroup.toLoadGroupLoadOnly();
                    if (lg != null) {
                        Object resultToLoad  = result;
                        if (this.shouldIncludeData) {
                            resultToLoad = ((ComplexQueryResult)result).getResult();
                        }
                        session.load(resultToLoad, lg, getDescriptor(), true);
                    }
                }
            }
        }
        return result;
    }

    /**
     * Executes the prepared query on the datastore.
     */
    protected abstract Object executeObjectLevelReadQuery() throws DatabaseException;

    /**
     * Executes the prepared query on the datastore.
     */
    protected abstract Object executeObjectLevelReadQueryFromResultSet() throws DatabaseException;

    /**
     * INTERNAL:
     * Execute the query in the unit of work.
     * This allows any pre-execute checks to be done for unit of work queries.
     */
    @Override
    public Object executeInUnitOfWork(UnitOfWorkImpl unitOfWork, AbstractRecord translationRow) throws DatabaseException, OptimisticLockException {
        Object result = null;

        if (!shouldMaintainCache() || isReadOnly()) {
            result = unitOfWork.getParent().executeQuery(this, translationRow);
        } else {
            result = execute(unitOfWork, translationRow);
        }

        // If a lockModeType was set (from JPA) we need to check if we need
        // to perform a force update to the version field.
        if (lockModeType != null && result != null) {
            if (lockModeType.equals(READ) || lockModeType.equals(WRITE) || lockModeType.contains(OPTIMISTIC) || lockModeType.equals(PESSIMISTIC_FORCE_INCREMENT)) {
                boolean forceUpdateToVersionField = lockModeType.equals(WRITE) || lockModeType.equals(OPTIMISTIC_FORCE_INCREMENT) || lockModeType.equals(PESSIMISTIC_FORCE_INCREMENT);

                if (result instanceof Collection) {
                    Iterator i = ((Collection) result).iterator();
                    while (i.hasNext()) {
                        Object obj = i.next();

                        if (obj != null) {
                            // If it is a report query the result could be an array of objects. Must
                            // also deal with null results.
                            if (obj instanceof Object[]) {
                                for (Object o : (Object[]) obj) {
                                    if (o != null && unitOfWork.isObjectRegistered(o)) {
                                        unitOfWork.forceUpdateToVersionField(o, forceUpdateToVersionField);
                                    }
                                }
                            } else if(unitOfWork.isObjectRegistered(obj)){
                                unitOfWork.forceUpdateToVersionField(obj, forceUpdateToVersionField);
                            }
                        }
                    }
                } else if(unitOfWork.isObjectRegistered(result)) {
                    unitOfWork.forceUpdateToVersionField(result, forceUpdateToVersionField);
                }
            }
        }

        return result;
    }

    /**
     * INTERNAL:
     * Additional fields can be added to a query.  This is used in m-m batch reading to bring back the key from the join table.
     */
    public List<Object> getAdditionalFields() {
        if (this.additionalFields == null) {
            this.additionalFields = new ArrayList<>();
        }
        return this.additionalFields;
    }

    /**
     * ADVANCED:
     * Answers the past time this query is as of.
     * @return An immutable object representation of the past time.
     * <code>null</code> if no clause set, <code>AsOfClause.NO_CLAUSE</code> if
     * clause explicitly set to <code>null</code>.
     * @see org.eclipse.persistence.history.AsOfClause
     * @see #setAsOfClause(org.eclipse.persistence.history.AsOfClause)
     * @see #hasAsOfClause
     */
    public AsOfClause getAsOfClause() {
        return (defaultBuilder != null) ? defaultBuilder.getAsOfClause() : null;
    }

    /**
     * PUBLIC:
     * Return the cache usage.
     * By default only primary key read object queries will first check the cache before accessing the database.
     * Any query can be configure to query against the cache completely, by key or ignore the cache check.
     * <p>Valid values are:
     * <ul>
     * <li> DoNotCheckCache
     * <li> CheckCacheByExactPrimaryKey
     * <li> CheckCacheByPrimaryKey
     * <li> CheckCacheThenDatabase
     * <li> CheckCacheOnly
     * <li> ConformResultsInUnitOfWork
     * <li> UseDescriptorSetting
     * Note: UseDescriptorSetting functions like CheckCacheByPrimaryKey, except checks the appropriate descriptor's
     * shouldDisableCacheHits setting when querying on the cache.
     * </ul>
     */
    public int getCacheUsage() {
        return cacheUsage;
    }

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by EclipseLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public short getDistinctState() {
        return distinctState;
    }

    /**
     * PUBLIC:
     * This method returns the current example object.  The "example" object is an actual domain object, provided
     * by the client, from which an expression is generated.
     * This expression is used for a query of all objects from the same class, that match the attribute values of
     * the "example" object.
     */
    public Object getExampleObject() {
        if (getQueryMechanism().isQueryByExampleMechanism()) {
            return ((QueryByExampleMechanism)getQueryMechanism()).getExampleObject();
        } else {
            return null;
        }
    }

    /**
     * REQUIRED:
     * Get the expression builder which should be used for this query.
     * This expression builder should be used to build all expressions used by this query.
     */
    public ExpressionBuilder getExpressionBuilder() {
        if (defaultBuilder == null) {
            initializeDefaultBuilder();
        }

        return defaultBuilder;
    }

    /**
     * INTERNAL
     * Sets the default expression builder for this query.
     */
    public void setExpressionBuilder(ExpressionBuilder builder) {
        this.defaultBuilder = builder;
    }

    /**
     * PUBLIC:
     * Returns the InMemoryQueryIndirectionPolicy for this query
     */
    public int getInMemoryQueryIndirectionPolicyState() {
        return this.inMemoryQueryIndirectionPolicy;
    }

    /**
     * PUBLIC:
     * Returns the InMemoryQueryIndirectionPolicy for this query
     */
    public InMemoryQueryIndirectionPolicy getInMemoryQueryIndirectionPolicy() {
        return new InMemoryQueryIndirectionPolicy(inMemoryQueryIndirectionPolicy, this);
    }

    /**
     * INTERNAL:
     * Return join manager responsible for managing all aspects of joining for the query.
     * Queries without joining should not have a joinedAttributeManager.
     */
    public JoinedAttributeManager getJoinedAttributeManager() {
        if (this.joinedAttributeManager == null) {
            this.joinedAttributeManager = new JoinedAttributeManager(getDescriptor(), getExpressionBuilder(), this);
        }
        return this.joinedAttributeManager;
    }

    /**
     * INTERNAL:
     * Set join manager responsible for managing all aspects of joining for the query.
     */
    public void setJoinedAttributeManager(JoinedAttributeManager joinedAttributeManager) {
        this.joinedAttributeManager = joinedAttributeManager;
    }

    /**
     * INTERNAL:
     * Return if any attributes are joined.
     * To avoid the initialization of the JoinedAttributeManager this should be first checked before accessing.
     */
    public boolean hasJoining() {
        return this.joinedAttributeManager != null;
    }

    /**
     * INTERNAL:
     * Convenience method for project mapping.
     */
    public List getJoinedAttributeExpressions() {
        return getJoinedAttributeManager().getJoinedAttributeExpressions();
    }

    /**
     * INTERNAL:
     * Convenience method for project mapping.
     */
    public void setJoinedAttributeExpressions(List expressions) {
        if (((expressions != null) && !expressions.isEmpty()) || hasJoining()) {
            getJoinedAttributeManager().setJoinedAttributeExpressions_(expressions);
        }
    }

    /**
     * INTERNAL:
     * Return the order expressions for the query.
     */
    public List<Expression> getOrderByExpressions() {
        if (orderByExpressions == null) {
            orderByExpressions = new ArrayList<>();
        }
        return orderByExpressions;
    }

    /**
     * INTERNAL:
     * Set the order expressions for the query.
     */
    public void setOrderByExpressions(List<Expression> orderByExpressions) {
        this.orderByExpressions = orderByExpressions;
    }

    /**
     * INTERNAL:
     * The order bys are lazy initialized to conserve space.
     */
    public boolean hasOrderByExpressions() {
        return (orderByExpressions != null) && (!orderByExpressions.isEmpty());
    }

    /**
     * INTERNAL:
     * The unions are lazy initialized to conserve space.
     */
    public boolean hasUnionExpressions() {
        return (unionExpressions != null) && (!unionExpressions.isEmpty());
    }

    /**
     * PUBLIC:
     * Return if duplicate rows should be filter when using 1-m joining.
     */
    public boolean shouldFilterDuplicates() {
        if (hasJoining()) {
            return getJoinedAttributeManager().shouldFilterDuplicates();
        }
        return true;
    }

    /**
     * PUBLIC:
     * Set if duplicate rows should be filter when using 1-m joining.
     */
    public void setShouldFilterDuplicates(boolean shouldFilterDuplicates) {
        getJoinedAttributeManager().setShouldFilterDuplicates(shouldFilterDuplicates);
    }

    /**
     * INTERNAL:
     * It is not exactly as simple as a query being either locking or not.
     * Any combination of the reference class object and joined attributes
     * may be locked.
     */
    public ForUpdateClause getLockingClause() {
        return lockingClause;
    }

    /**
     * INTERNAL:
     * Return the attributes that must be joined, but not fetched, that is,
     * do not trigger the value holder.
     */
    public List<Expression> getNonFetchJoinAttributeExpressions() {
        if (this.nonFetchJoinAttributeExpressions == null){
            this.nonFetchJoinAttributeExpressions = new ArrayList<>();
        }
        return nonFetchJoinAttributeExpressions;
    }

    /**
     * INTERNAL:
     * Return the partial attributes to select.
     */
    public List<Expression> getPartialAttributeExpressions() {
        if (this.partialAttributeExpressions == null) {
            this.partialAttributeExpressions = new ArrayList<>();
        }
        return this.partialAttributeExpressions;
    }

    /**
     * PUBLIC:
     * When using Query By Example, an instance of QueryByExamplePolicy is used to customize the query.
     * The policy is useful when special operations are to be used for comparisons (notEqual, lessThan,
     * greaterThan, like etc.), when a certain value is to be ignored, or when dealing with nulls.
     */
    public QueryByExamplePolicy getQueryByExamplePolicy() {
        if (getQueryMechanism().isQueryByExampleMechanism()) {
            return ((QueryByExampleMechanism)getQueryMechanism()).getQueryByExamplePolicy();
        } else {
            return null;
        }
    }

    /**
     * PUBLIC:
     * Return the reference class of the query.
     */
    @Override
    public Class getReferenceClass() {
        return referenceClass;
    }

    /**
     * INTERNAL:
     * Return the reference class of the query.
     */
    @Override
    public String getReferenceClassName() {
        if ((referenceClassName == null) && (referenceClass != null)) {
            referenceClassName = referenceClass.getName();
        }
        return referenceClassName;
    }

    /**
     * PUBLIC:
     * Answers if the domain objects are to be read as of a past time.
     * @see #getAsOfClause
     */
    public boolean hasAsOfClause() {
        return ((defaultBuilder != null) && defaultBuilder.hasAsOfClause());
    }

    /**
     * INTERNAL:
     * Return the attributes that must be joined.
     */
    public boolean hasNonFetchJoinedAttributeExpressions() {
        return this.nonFetchJoinAttributeExpressions != null && !this.nonFetchJoinAttributeExpressions.isEmpty();
    }

    /**
     * INTERNAL:
     * Return if partial attributes.
     */
    @Override
    public boolean hasPartialAttributeExpressions() {
        return (this.partialAttributeExpressions != null) && (!this.partialAttributeExpressions.isEmpty());
    }

    /**
     * INTERNAL:
     * Return if additional field.
     */
    public boolean hasAdditionalFields() {
        return (this.additionalFields != null) && (!this.additionalFields.isEmpty());
    }

    /**
     * INTERNAL:
     * Return the fields required in the select clause, for patial attribute reading.
     */
    public Vector getPartialAttributeSelectionFields(boolean isCustomSQL) {
        Vector localFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(getPartialAttributeExpressions().size());
        Vector foreignFields = null;

        //Add primary key and indicator fields.
        localFields.addAll(getDescriptor().getPrimaryKeyFields());
        if (getDescriptor().hasInheritance() && (getDescriptor().getInheritancePolicy().getClassIndicatorField() != null)) {
            localFields.addElement(getDescriptor().getInheritancePolicy().getClassIndicatorField());
        }

        //Add attribute fields
        for(Iterator it = getPartialAttributeExpressions().iterator();it.hasNext();){
            Expression expression = (Expression)it.next();
            if (expression.isQueryKeyExpression()) {
                expression.getBuilder().setSession(session.getRootSession(null));
                expression.getBuilder().setQueryClass(getDescriptor().getJavaClass());
                DatabaseMapping mapping = ((QueryKeyExpression)expression).getMapping();
                if (!((QueryKeyExpression)expression).getBaseExpression().isExpressionBuilder()) {
                    if(foreignFields==null){
                        foreignFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
                    }
                    if(!isCustomSQL){
                        foreignFields.add(expression);
                    }else{
                        foreignFields.addAll(expression.getSelectionFields(this));
                    }
                }else{
                    if (mapping == null) {
                        throw QueryException.specifiedPartialAttributeDoesNotExist(this, expression.getName(), descriptor.getJavaClass().getName());
                    }
                    if(mapping.isForeignReferenceMapping() ){
                        if(foreignFields==null){
                            foreignFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
                        }
                        if(!isCustomSQL){
                            foreignFields.add(expression);
                        }else{
                            foreignFields.addAll(expression.getSelectionFields(this));
                        }
                    }else{
                        localFields.addAll(expression.getSelectionFields(this));
                    }
                }
            } else {
                throw QueryException.expressionDoesNotSupportPartialAttributeReading(expression);
            }
        }
        //Build fields in same order as the fields of the descriptor to ensure field and join indexes match.
        Vector selectionFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
        for (Iterator iterator = getDescriptor().getFields().iterator(); iterator.hasNext();) {
            DatabaseField field = (DatabaseField)iterator.next();
            if (localFields.contains(field)) {
                selectionFields.add(field);
            } else {
                selectionFields.add(null);
            }
        }
        //Combine fields list for source descriptor and target descriptor.
        if(foreignFields!=null){
            selectionFields.addAll(foreignFields);
        }
        return selectionFields;
    }

    /**
     * INTERNAL:
     * Return the set of fields required in the select clause, for fetch group reading.
     */
    public Set<DatabaseField> getFetchGroupNonNestedFieldsSet() {
        return getFetchGroupNonNestedFieldsSet(null);
    }

    /**
     * INTERNAL:
     * Return the set of fields required in the select clause, for fetch group reading.
     */
    public Set<DatabaseField> getFetchGroupNonNestedFieldsSet(DatabaseMapping nestedMapping) {
        Set fetchedFields = new HashSet(getExecutionFetchGroup().getAttributeNames().size());

        // Add required fields.
        fetchedFields.addAll(getDescriptor().getPrimaryKeyFields());
        if (getDescriptor().hasInheritance() && (getDescriptor().getInheritancePolicy().getClassIndicatorField() != null)) {
            fetchedFields.add(getDescriptor().getInheritancePolicy().getClassIndicatorField());
        }
        if (shouldMaintainCache() && getDescriptor().usesOptimisticLocking()) {
            DatabaseField lockField = getDescriptor().getOptimisticLockingPolicy().getWriteLockField();
            if (lockField != null) {
                fetchedFields.add(lockField);
            }
        }
        // Add specified fields.
        for (Iterator iterator = getExecutionFetchGroup().getAttributeNames().iterator(); iterator.hasNext();) {
            String attribute = (String)iterator.next();
            DatabaseMapping mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(attribute);
            if (mapping == null) {
                throw QueryException.fetchGroupAttributeNotMapped(attribute);
            }
            fetchedFields.addAll(mapping.getFields());
        }
        if ((nestedMapping != null) && nestedMapping.isCollectionMapping()) {
            List<DatabaseField> additionalFields = nestedMapping.getContainerPolicy().getAdditionalFieldsForJoin((CollectionMapping)nestedMapping);
            if(additionalFields != null) {
                fetchedFields.addAll(additionalFields);
            }
        }
        return fetchedFields;
    }

    /**
     * INTERNAL:
     * Return the fields required in the select clause, for fetch group reading.
     */
    public List<DatabaseField> getFetchGroupSelectionFields() {
        return getFetchGroupSelectionFields(null);
    }

    /**
     * INTERNAL:
     * Return the fields required in the select clause, for fetch group reading.
     * Top level (not nested) passes null instead of nestedMapping.
     */
    protected List<DatabaseField> getFetchGroupSelectionFields(DatabaseMapping nestedMapping) {
        Set<DatabaseField> fetchedFields = getFetchGroupNonNestedFieldsSet(nestedMapping);

        // Build field list in the same order as descriptor's fields so that the fields printed in the usual order in SELECT clause.
        List<DatabaseField> fields = new ArrayList(fetchedFields.size());
        for (Iterator iterator = getDescriptor().getFields().iterator(); iterator.hasNext();) {
            DatabaseField field = (DatabaseField)iterator.next();
            if (fetchedFields.contains(field)) {
                fields.add(field);
            }
        }
        return fields;
    }

    /**
     * INTERNAL:
     * The method adds to the passed input vector the
     * fields or expressions corresponding to the joins.
     */
    public void addJoinSelectionFields(Vector fields, boolean isCustomSQL) {
        // executiveFetchGroup is used for warnings only - always null if no warnings logged
        FetchGroup executionFetchGroup = null;
        if(session.shouldLog(SessionLog.WARNING, SessionLog.QUERY)) {
            executionFetchGroup = getExecutionFetchGroup();
        }
        for(Expression expression : getJoinedAttributeManager().getJoinedAttributeExpressions()) {
            addSelectionFieldsForJoinedExpression(fields, isCustomSQL, expression);
            // executiveFetchGroup is used for warnings only - always null if no warnings logged
            if(executionFetchGroup != null) {
                String nestedAttributeName = ((QueryKeyExpression)expression).getNestedAttributeName();
                if(nestedAttributeName != null) {
                    if(!executionFetchGroup.containsAttributeInternal(nestedAttributeName)) {
                        getSession().log(SessionLog.WARNING, SessionLog.QUERY, "query_has_joined_attribute_outside_fetch_group", new Object[]{toString(), nestedAttributeName});
                    }
                }
            }
        }
        for(Expression expression : getJoinedAttributeManager().getJoinedMappingExpressions()) {
            addSelectionFieldsForJoinedExpression(fields, isCustomSQL, expression);
        }
    }

    /**
     * INTERNAL:
     * Return the fields selected by the query.
     * This includes the partial or joined fields.
     * This is only used for custom SQL executions.
     */
    public Vector getSelectionFields() {
        if (hasPartialAttributeExpressions()) {
            return getPartialAttributeSelectionFields(true);
        }

        Vector fields = NonSynchronizedVector.newInstance();
        if (getExecutionFetchGroup() != null) {
            fields.addAll(getFetchGroupSelectionFields());
        } else {
            fields.addAll(getDescriptor().getAllSelectionFields(this));
        }
        // Add joined fields.
        if (hasJoining()) {
            addJoinSelectionFields(fields, true);
        }
        if (hasAdditionalFields()) {
            // Add additional fields, use for batch reading m-m.
            fields.addAll(getAdditionalFields());
        }
        return fields;
    }


    /**
     * PUBLIC:
     * Return the WAIT timeout value of pessimistic locking query.
     */
    public Integer getWaitTimeout() {
        return waitTimeout;
    }
    
    public TimeUnit getWaitTimeoutUnit() {
        return waitTimeoutUnit;
    }
    
    /**
     * Initialize the expression builder which should be used for this query. If
     * there is a where clause, use its expression builder, otherwise
     * generate one and cache it. This helps avoid unnecessary rebuilds.
     */
    protected void initializeDefaultBuilder() {
        DatabaseQueryMechanism mech = getQueryMechanism();
        if (mech.isExpressionQueryMechanism() && ((ExpressionQueryMechanism)mech).getExpressionBuilder() != null) {
            this.defaultBuilder = ((ExpressionQueryMechanism)mech).getExpressionBuilder();
            if (this.defaultBuilder.getQueryClass() != null && !this.defaultBuilder.getQueryClass().equals(this.referenceClass)){
                this.defaultBuilder = new ExpressionBuilder();
            }
            return;
        }
        this.defaultBuilder = new ExpressionBuilder();
    }

    /**
     * INTERNAL:
     * return true if this query has computed its distinct value already
     */
    public boolean isDistinctComputed() {
        return this.distinctState != UNCOMPUTED_DISTINCT;
    }

    /**
     * PUBLIC:
     * Answers if the query lock mode is known to be LOCK or LOCK_NOWAIT.
     *
     * In the case of DEFAULT_LOCK_MODE and the query reference class being a CMP entity bean,
     * at execution time LOCK, LOCK_NOWAIT, or NO_LOCK will be decided.
     * <p>
     * If a single joined attribute was configured for pessimistic locking then
     * this will return true (after first execution) as the SQL contained a
     * FOR UPDATE OF clause.
     */
    @Override
    public boolean isLockQuery() {
        return (this.lockingClause != null) && (getLockMode() > NO_LOCK);
    }

    /**
     * ADVANCED:
     * Answers if this query will issue any pessimistic locks.
     * <p>
     * If the lock mode is not known (DEFAULT_LOCK_MODE / descriptor specified
     * fine-grained locking) the lock mode will be determined now, to be either
     * LOCK, LOCK_NOWAIT, or NO_LOCK.
     * @see #isLockQuery()
     */
    public boolean isLockQuery(org.eclipse.persistence.sessions.Session session) {
        checkPrePrepare((AbstractSession)session);
        return isLockQuery();
    }

    /**
     * PUBLIC:
     * Return if this is an object level read query.
     */
    @Override
    public boolean isObjectLevelReadQuery() {
        return true;
    }

    /**
     * INTERNAL:
     * Return if partial attribute.
     */
    public boolean isPartialAttribute(String attributeName) {
        if (this.partialAttributeExpressions == null) {
            return false;
        }
        List<Expression> partialAttributeExpressions = getPartialAttributeExpressions();
        int size = partialAttributeExpressions.size();
        for (int index = 0; index < size; index++) {
            QueryKeyExpression expression = (QueryKeyExpression)partialAttributeExpressions.get(index);
            while (!expression.getBaseExpression().isExpressionBuilder()) {
                expression = (QueryKeyExpression)expression.getBaseExpression();
            }
            if (expression.getName().equals(attributeName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * INTERNAL:
     * Indicates whether pessimistic lock should also be applied to relation tables (ManyToMany and OneToOne mappings),
     * reference tables (DirectCollection and AggregateCollection mapping).
     */
    public boolean shouldExtendPessimisticLockScope() {
        return shouldExtendPessimisticLockScope;
    }

    /**
     * PUBLIC:
     * Queries prepare common stated in themselves.
     */
    protected boolean isPrePrepared() {
        return isPrePrepared;
    }

    /**
     * INTERNAL:
     * If changes are made to the query that affect the derived SQL or Call
     * parameters the query needs to be prepared again.
     * <p>
     * Automatically called internally.
     * <p>
     * The early phase of preparation is to check if this is a pessimistic
     * locking query.
     */
    public void setIsPrePrepared(boolean isPrePrepared) {
        // Only unprepare if was prepared to begin with, prevent unpreparing during prepare.
        if (this.isPrePrepared && !isPrePrepared) {
            setIsPrepared(false);
            if (hasJoining()) {
                getJoinedAttributeManager().reset();
            }
        }
        this.isPrePrepared = isPrePrepared;
    }

    /**
     * INTERNAL:
     * Indicates whether pessimistic lock should also be applied to relation tables (ManyToMany and OneToOne mappings),
     * reference tables (DirectCollection and AggregateCollection mapping).
     */
    public void setShouldExtendPessimisticLockScope(boolean isExtended) {
        shouldExtendPessimisticLockScope = isExtended;
    }

    /**
     * INTERNAL:
     * Clear cached flags when un-preparing.
     */
    @Override
    public void setIsPrepared(boolean isPrepared) {
        boolean oldIsPrepared = this.isPrepared;
        super.setIsPrepared(isPrepared);
        if (!isPrepared) {
            // when the query is cached is not yet prepared and while the query is prepared setIsPrepared(false) may be called.
            // the intention is to remove the query from cache when it has been altered after prepare has completed.
            if (this.isCachedExpressionQuery && oldIsPrepared) {
                if (this.descriptor != null) {
                    this.descriptor.getQueryManager().removeCachedExpressionQuery(this);
                    this.isCachedExpressionQuery = false;
                }
            }
            this.isReferenceClassLocked = null;
            this.concreteSubclassCalls = null;
            this.concreteSubclassQueries = null;
            this.aggregateQueries = null;
            this.concreteSubclassJoinedMappingIndexes = null;
        }
    }

    /**
     * INTERNAL:
     * Clear cached flags when un-preparing.
     * The method always keeps concrete subclass data (unlike setIsPrepared(false)).
     */
    protected void setIsPreparedKeepingSubclassData(boolean isPrepared) {
        super.setIsPrepared(isPrepared);
        if (!isPrepared) {
            this.isReferenceClassLocked = null;
        }
    }

    /**
     * INTERNAL:
     * Prepare the receiver for execution in a session.
     */
    @Override
    protected void prepare() throws QueryException {
        super.prepare();
        prepareQuery();
        if (hasJoining()) {
            this.joinedAttributeManager.computeJoiningMappingQueries(session);
        }
        computeBatchReadMappingQueries();
        if (getLoadGroup() != null) {
            if (getLoadGroup().getIsConcurrent() == null) {
                getLoadGroup().setIsConcurrent(getSession().isConcurrent());
            }
        }
    }

    /**
     * INTERNAL:
     * Check if the query is cached and prepare from it.
     * Return true if the query was cached.
     */
    protected boolean prepareFromCachedQuery() {
        // PERF: Check if the equivalent expression query has already been prepared.
        // Only allow queries with default properties to be cached.
        boolean isCacheable = isExpressionQuery() && (!getQueryMechanism().isJPQLCallQueryMechanism()) && isDefaultPropertiesQuery() && (!getSession().isHistoricalSession());
        DatabaseQuery cachedQuery = null;
        if (isCacheable) {
            cachedQuery = this.descriptor.getQueryManager().getCachedExpressionQuery(this);
        } else {
            return false;
        }
        if ((cachedQuery != null) && cachedQuery.isPrepared()) {
            prepareFromQuery(cachedQuery);
            setIsPrepared(true);
            return true;
        }
        this.descriptor.getQueryManager().putCachedExpressionQuery(this);
        this.isCachedExpressionQuery = true;
        this.isExecutionClone = false;
        return false;
    }

    /**
     * INTERNAL:
     * Copy all setting from the query.
     * This is used to morph queries from one type to the other.
     * By default this calls prepareFromQuery, but additional properties may be required
     * to be copied as prepareFromQuery only copies properties that affect the SQL.
     */
    @Override
    public void copyFromQuery(DatabaseQuery query) {
        super.copyFromQuery(query);
        if (query.isObjectLevelReadQuery()) {
            ObjectLevelReadQuery readQuery = (ObjectLevelReadQuery)query;
            this.cacheUsage = readQuery.cacheUsage;
            this.isReadOnly = readQuery.isReadOnly;
            this.isResultSetOptimizedQuery = readQuery.isResultSetOptimizedQuery;
            this.shouldIncludeData = readQuery.shouldIncludeData;
            this.inMemoryQueryIndirectionPolicy = readQuery.inMemoryQueryIndirectionPolicy;
            this.lockModeType = readQuery.lockModeType;
            this.defaultBuilder = readQuery.defaultBuilder;
            this.distinctState = readQuery.distinctState;
            this.shouldUseSerializedObjectPolicy = readQuery.shouldUseSerializedObjectPolicy;
        }
    }

    /**
     * INTERNAL:
     * Prepare the query from the prepared query.
     * This allows a dynamic query to prepare itself directly from a prepared query instance.
     * This is used in the EJBQL parse cache to allow preparsed queries to be used to prepare
     * dynamic queries.
     * This only copies over properties that are configured through EJBQL.
     */
    @Override
    public void prepareFromQuery(DatabaseQuery query) {
        super.prepareFromQuery(query);
        if (query.isObjectLevelReadQuery()) {
            ObjectLevelReadQuery objectQuery = (ObjectLevelReadQuery)query;
            this.referenceClass = objectQuery.referenceClass;
            this.distinctState = objectQuery.distinctState;
            if (objectQuery.hasJoining()) {
                getJoinedAttributeManager().copyFrom(objectQuery.getJoinedAttributeManager());
            }
            if (objectQuery.hasBatchReadAttributes()) {
                this.batchFetchPolicy = objectQuery.getBatchFetchPolicy().clone();
            }
            this.nonFetchJoinAttributeExpressions = objectQuery.nonFetchJoinAttributeExpressions;
            this.defaultBuilder = objectQuery.defaultBuilder;
            this.fetchGroup = objectQuery.fetchGroup;
            this.fetchGroupName = objectQuery.fetchGroupName;
            this.isReferenceClassLocked = objectQuery.isReferenceClassLocked;
            this.shouldOuterJoinSubclasses = objectQuery.shouldOuterJoinSubclasses;
            this.shouldUseDefaultFetchGroup = objectQuery.shouldUseDefaultFetchGroup;
            this.concreteSubclassCalls = objectQuery.concreteSubclassCalls;
            this.concreteSubclassQueries = objectQuery.concreteSubclassQueries;
            this.aggregateQueries = objectQuery.aggregateQueries;
            this.concreteSubclassJoinedMappingIndexes = objectQuery.concreteSubclassJoinedMappingIndexes;
            this.additionalFields = objectQuery.additionalFields;
            this.partialAttributeExpressions = objectQuery.partialAttributeExpressions;
            if (objectQuery.hasOrderByExpressions()) {
                this.orderByExpressions = objectQuery.orderByExpressions;
            }
            if (objectQuery.hasUnionExpressions()) {
                this.unionExpressions = objectQuery.unionExpressions;
            }
        }
    }

    /**
     * INTERNAL:
     * Add mandatory attributes to fetch group, create entityFetchGroup.
     */
    public void prepareFetchGroup() throws QueryException {
        FetchGroupManager fetchGroupManager = this.descriptor.getFetchGroupManager();
        if (fetchGroupManager != null) {
            if (this.fetchGroup == null) {
                if (this.fetchGroupName != null) {
                    this.fetchGroup = fetchGroupManager.getFetchGroup(this.fetchGroupName);
                } else if (this.shouldUseDefaultFetchGroup) {
                    this.fetchGroup = this.descriptor.getFetchGroupManager().getDefaultFetchGroup();
                }
            }
            if (this.fetchGroup != null) {
                if (hasPartialAttributeExpressions()) {
                    //fetch group does not work with partial attribute reading
                    throw QueryException.fetchGroupNotSupportOnPartialAttributeReading();
                }
                // currently SOP is incompatible with fetch groups
                setShouldUseSerializedObjectPolicy(false);
                this.descriptor.getFetchGroupManager().prepareAndVerify(this.fetchGroup);
            }
        } else {
            // FetchGroupManager is null
            if (this.fetchGroup != null || this.fetchGroupName != null) {
                throw QueryException.fetchGroupValidOnlyIfFetchGroupManagerInDescriptor(getDescriptor().getJavaClassName(), getName());
            }
        }
    }

    /**
     * INTERNAL:
     * Prepare the receiver for execution in a session.
     */
    protected void prePrepare() throws QueryException {
        // For bug 3136413/2610803 building the selection criteria from an EJBQL string or
        // an example object is done just in time.
        buildSelectionCriteria(this.session);
        checkDescriptor(this.session);

        // Validate and prepare join expressions.
        if (hasJoining()) {
            this.joinedAttributeManager.prepareJoinExpressions(this.session);
        }

        prepareFetchGroup();

        // Add mapping joined attributes.
        if (getQueryMechanism().isExpressionQueryMechanism() && this.descriptor.getObjectBuilder().hasJoinedAttributes()) {
            getJoinedAttributeManager().processJoinedMappings(this.session);
            if (this.joinedAttributeManager.hasOrderByExpressions()) {
                for (Expression orderBy : this.joinedAttributeManager.getOrderByExpressions()) {
                    addOrdering(orderBy);
                }
            }
            if (this.joinedAttributeManager.hasAdditionalFieldExpressions()) {
                for (Expression additionalField : this.joinedAttributeManager.getAdditionalFieldExpressions()) {
                    addAdditionalField(additionalField);
                }
            }
        }

        if (this.lockModeType != null) {
            if (this.lockModeType.equals(NONE)) {
                setLockMode(ObjectBuildingQuery.NO_LOCK);
            } else if (this.lockModeType.contains(PESSIMISTIC_)) {
                // If no wait timeout was set from a query hint, grab the
                // default one from the session if one is available.
                Integer timeout = (this.waitTimeout == null) ? this.session.getPessimisticLockTimeoutDefault() : this.waitTimeout;
                Long convertedTimeout =null;
                TimeUnit timeoutUnit = (this.waitTimeoutUnit == null) ? this.session.getPessimisticLockTimeoutUnitDefault() : this.waitTimeoutUnit;
                if (timeout == null) {
                    setLockMode(ObjectBuildingQuery.LOCK);
                } else {
                    if (timeout.intValue() == 0) {
                        setLockMode(ObjectBuildingQuery.LOCK_NOWAIT);
                    } else {
                        convertedTimeout = TimeUnit.SECONDS.convert(timeout, timeoutUnit);
                        if(convertedTimeout > Integer.MAX_VALUE){
                            timeout = Integer.MAX_VALUE;
                        } else {
                            timeout = convertedTimeout.intValue();
                        }
                        //Round up the timeout if SECONDS are larger than the given units
                        if(TimeUnit.SECONDS.compareTo(timeoutUnit) > 0 && timeout % 1000 > 0){
                            timeout += 1;
                        }
                        this.lockingClause = ForUpdateClause.newInstance(timeout);
                    }
                }
            }
        }

        // modify query for locking only if locking has not been configured
        if (isDefaultLock()) {
            setWasDefaultLockMode(true);
            ForUpdateOfClause lockingClause = null;
            if (hasJoining()) {
                lockingClause = getJoinedAttributeManager().setupLockingClauseForJoinedExpressions(lockingClause, getSession());
            }
            if (this.descriptor.hasPessimisticLockingPolicy()) {
                lockingClause = new ForUpdateOfClause();
                lockingClause.setLockMode(this.descriptor.getCMPPolicy().getPessimisticLockingPolicy().getLockingMode());
                lockingClause.addLockedExpression(getExpressionBuilder());
            }
            if (lockingClause != null) {
                this.lockingClause = lockingClause;
                // SPECJ: Locking not compatible with distinct for batch reading.
                dontUseDistinct();
            }
        } else if ((getLockMode() <= NO_LOCK) && (!descriptor.hasPessimisticLockingPolicy())) {
            setWasDefaultLockMode(true);
        }
        setRequiresDeferredLocks(DeferredLockManager.SHOULD_USE_DEFERRED_LOCKS && (hasJoining() || (this.descriptor.shouldAcquireCascadedLocks())));

        if (hasJoining() && hasPartialAttributeExpressions()) {
            this.session.log(SessionLog.WARNING, SessionLog.QUERY, "query_has_both_join_attributes_and_partial_attributes", new Object[]{this, getName()});
        }
    }

    /**
     * INTERNAL:
     * Prepare the receiver for execution in a session.
     */
    protected void prepareQuery() throws QueryException {
        if ((!shouldMaintainCache()) && shouldRefreshIdentityMapResult() && (!this.descriptor.isAggregateCollectionDescriptor())) {
            throw QueryException.refreshNotPossibleWithoutCache(this);
        }
        if (shouldMaintainCache() && hasPartialAttributeExpressions()) {
            throw QueryException.cannotCachePartialObjects(this);
        }

        if (this.descriptor.isAggregateDescriptor()) {
            // Not allowed
            throw QueryException.aggregateObjectCannotBeDeletedOrWritten(this.descriptor, this);
        }

        if (hasAsOfClause() && (getSession().getAsOfClause() == null)) {
            if (shouldMaintainCache()) {
                throw QueryException.historicalQueriesMustPreserveGlobalCache();
            } else if (!getSession().getPlatform().isOracle() && !getSession().getProject().hasGenericHistorySupport()) {
                throw QueryException.historicalQueriesOnlySupportedOnOracle();
            }
        }

        // Validate and prepare partial attribute expressions.
        if (hasPartialAttributeExpressions()) {
            for (int index = 0; index < getPartialAttributeExpressions().size(); index++) {
                Expression expression = getPartialAttributeExpressions().get(index);

                // Search if any of the expression traverse a 1-m.
                while (expression.isQueryKeyExpression() && (!expression.isExpressionBuilder())) {
                    if (((QueryKeyExpression)expression).shouldQueryToManyRelationship()) {
                        getJoinedAttributeManager().setIsToManyJoinQuery(true);
                    }
                    expression = ((QueryKeyExpression)expression).getBaseExpression();
                }
            }
        }
        if (!shouldOuterJoinSubclasses()) {
            setShouldOuterJoinSubclasses(getMaxRows()>0 || getFirstResult()>0 || (this.descriptor != null &&
                    this.descriptor.hasInheritance() && (this.descriptor.getInheritancePolicy().shouldOuterJoinSubclasses()|| this.getExpressionBuilder().isTreatUsed()) ));
        }

        // Ensure the subclass call cache is initialized if a multiple table inheritance descriptor.
        // This must be initialized in the query before it is cloned, and never cloned.
        if (!shouldOuterJoinSubclasses() && this.descriptor.hasInheritance()
                && this.descriptor.getInheritancePolicy().requiresMultipleTableSubclassRead()) {
            getConcreteSubclassCalls();
            if (hasJoining()) {
                getConcreteSubclassJoinedMappingIndexes();
            }
        }

        // Ensure the subclass call cache is initialized if a table per class inheritance descriptor.
        // This must be initialized in the query before it is cloned, and never cloned.
        if (this.descriptor.hasTablePerClassPolicy()
                && (this.descriptor.getTablePerClassPolicy().getChildDescriptors().size() > 0)) {
            getConcreteSubclassQueries();
        }
    }

    /**
     * INTERNAL:
     * Prepare the receiver for execution in a session.
     */
    @Override
    protected void prepareForRemoteExecution() throws QueryException {
        super.prepareForRemoteExecution();
        checkPrePrepare(getSession());
        prepareQuery();
    }

    /**
     * PUBLIC:
     * Refresh the attributes of the object(s) resulting from the query.
     * If cascading is used the private parts of the objects will also be refreshed.
     */
    @Override
    public void refreshIdentityMapResult() {
        setShouldRefreshIdentityMapResult(true);
    }

    /**
     * PUBLIC:
     * Refresh the attributes of the object(s) resulting from the query.
     * If cascading is used the private parts of the objects will also be refreshed.
     */
    @Override
    public void refreshRemoteIdentityMapResult() {
        setShouldRefreshRemoteIdentityMapResult(true);
    }

    /**
     * INTERNAL:
     * All objects queried via a UnitOfWork get registered here.  If the query
     * went to the database.
     * <p>
     * Involves registering the query result individually and in totality, and
     * hence refreshing / conforming is done here.
     *
     * @param result may be collection (read all) or an object (read one),
     * or even a cursor.  If in transaction the shared cache will
     * be bypassed, meaning the result may not be originals from the parent
     * but raw database rows.
     * @param unitOfWork the unitOfWork the result is being registered in.
     * @param arguments the original arguments/parameters passed to the query
     * execution.  Used by conforming
     * @param buildDirectlyFromRows If in transaction must construct
     * a registered result from raw database rows.
     *
     * @return the final (conformed, refreshed, wrapped) UnitOfWork query result
     */
    public abstract Object registerResultInUnitOfWork(Object result, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, boolean buildDirectlyFromRows);

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by TopLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public void resetDistinct() {
        setDistinctState(UNCOMPUTED_DISTINCT);
    }

    /**
     * INTERNAL:
     * Additional fields can be added to a query.  This is used in m-m batch reading to bring back the key from the join table.
     */
    public void setAdditionalFields(List<Object> additionalFields) {
        this.additionalFields = additionalFields;
    }

    /**
     * PUBLIC:
     * Return if the cache should be checked.
     */
    public boolean shouldCheckCache() {
        return this.cacheUsage != DoNotCheckCache;
    }

    /**
     * PUBLIC:
     * Set the cache usage.
     * By default only primary key read object queries will first check the cache before accessing the database.
     * Any query can be configure to query against the cache completely, by key or ignore the cache check.
     * <p>Valid values are:
     * <ul>
     * <li> DoNotCheckCache - The query does not check the cache but accesses the database, the cache will still be maintain.
     * <li> CheckCacheByExactPrimaryKey - If the query is exactly and only on the object's primary key the cache will be checked.
     * <li> CheckCacheByPrimaryKey - If the query contains the primary key and possible other values the cache will be checked.
     * <li> CheckCacheThenDatabase - The whole cache will be checked to see if there is any object matching the query, if not the database will be accessed.
     * <li> CheckCacheOnly - The whole cache will be checked to see if there is any object matching the query, if not null or an empty collection is returned.
     * <li> ConformResultsAgainstUnitOfWork - The results will be checked against the changes within the unit of work and object no longer matching or deleted will be remove, matching new objects will also be added.
     * <li> shouldCheckDescriptorForCacheUsage - This setting functions like CheckCacheByPrimaryKey, except checks the appropriate descriptor's
     * shouldDisableCacheHits setting when querying on the cache.
      * </ul>
     */
    public void setCacheUsage(int cacheUsage) {
        this.cacheUsage = cacheUsage;
    }

    /**
     * INTERNAL:
     * Set the descriptor for the query.
     */
    @Override
    public void setDescriptor(ClassDescriptor descriptor) {
        // If the descriptor changed must unprepare as the SQL may change.
        if (this.descriptor != descriptor) {
            setIsPreparedKeepingSubclassData(false);
            this.descriptor = descriptor;
        }
        if (this.fetchGroup != null){
            this.fetchGroup = getExecutionFetchGroup(descriptor);
        }
        if (this.joinedAttributeManager != null){
            this.joinedAttributeManager.setDescriptor(descriptor);
        }
    }

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by TopLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public void setDistinctState(short distinctState) {
        this.distinctState = distinctState;
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    }

    /**
     * PUBLIC:
     * Set the example object of the query to be the newExampleObject.
     * The example object is used for Query By Example.
     * When doing a Query By Example, an instance of the desired object is created, and the fields are filled with
     * the values that are required in the result set.  From these values the corresponding expression is built
     * by EclipseLink, and the query is executed, returning the set of results.
     * <p>If a query already has a selection criteria this criteria and the generated
     * query by example criteria will be conjuncted.
     * <p>Once a query is executed you must make an explicit call to setExampleObject
     * if the example object is changed, so the query will know to prepare itself again.
     * <p>There is a caution to setting both a selection criteria and an example object:
     * Only in this case if you set the example object again after execution you must then also reset the selection criteria.
     * (This is because after execution the original criteria and Query By Example criteria were fused together,
     * and the former cannot be easily recovered from the now invalid result).
     * <p>
     * <b>Restrictions</b>:
     * <ul>
     * <li>Only attributes whose mappings are DirectToField, Aggregate (Embeddable), ObjectReference
     * (OneToOne) or Collection type OneToMany/ManyToMany are considered in a Query By Example object.  The behaviour when an example object has attribute values for other mappings types is <b>undefined</b>.
     * <ul><li>To ensure the example does not include any unsupported mappings the flag {@link org.eclipse.persistence.queries.QueryByExamplePolicy#setValidateExample}
     * should be set to true on the corresponding QueryByExamplePolicy to ensure no unsupported relationship types are used in the example.</li>
     * <li> For OneToMany and ManyToMany mappings the elements within the collections and the references attribute values will be added to the expression as disjuncts (OR)</li>
     * </ul></li>
     * </ul>
     */
    public void setExampleObject(Object newExampleObject) {
        if (!getQueryMechanism().isQueryByExampleMechanism()) {
            setQueryMechanism(new QueryByExampleMechanism(this, getSelectionCriteria()));
            ((QueryByExampleMechanism)getQueryMechanism()).setExampleObject(newExampleObject);
            setIsPrepared(false);
        } else {
            ((QueryByExampleMechanism)getQueryMechanism()).setExampleObject(newExampleObject);

            // Potentially force the query to be prepared again.  If shouldPrepare() is false
            // must use a slightly inferior check.
            if (isPrepared() || (!shouldPrepare() && ((QueryByExampleMechanism)getQueryMechanism()).isParsed())) {
                ((QueryByExampleMechanism)getQueryMechanism()).setIsParsed(false);
                setSelectionCriteria(null);
            }
        }
        if (newExampleObject != null) {
            setReferenceClass(newExampleObject.getClass());
        }
    }

    /**
     * PUBLIC:
     * Set the InMemoryQueryIndirectionPolicy for this query.
     */
    public void setInMemoryQueryIndirectionPolicy(InMemoryQueryIndirectionPolicy inMemoryQueryIndirectionPolicy) {
        // Bug2862302 Backwards compatibility.  This makes sure 9.0.3 and any older version project xml don't break.
        if (inMemoryQueryIndirectionPolicy != null) {
            this.inMemoryQueryIndirectionPolicy = inMemoryQueryIndirectionPolicy.getPolicy();
            inMemoryQueryIndirectionPolicy.setQuery(this);
        }
    }

    /**
     * PUBLIC:
     * Set the InMemoryQueryIndirectionPolicy for this query.
     */
    public void setInMemoryQueryIndirectionPolicyState(int inMemoryQueryIndirectionPolicy) {
        this.inMemoryQueryIndirectionPolicy = inMemoryQueryIndirectionPolicy;
    }

    /**
     * PUBLIC:
     * Sets whether this is a pessimistically locking query.
     * <ul>
     * <li>ObjectBuildingQuery.LOCK: SELECT .... FOR UPDATE issued.
     * <li>ObjectBuildingQuery.LOCK_NOWAIT: SELECT .... FOR UPDATE NO WAIT issued.
     * <li>ObjectBuildingQuery.NO_LOCK: no pessimistic locking.
     * <li>ObjectBuildingQuery.DEFAULT_LOCK_MODE (default) and you have a CMP descriptor:
     * fine grained locking will occur.
     * </ul>
     * <p>Fine Grained Locking: On execution the reference class
     * and those of all joined attributes will be checked.  If any of these have a
     * PessimisticLockingPolicy set on their descriptor, they will be locked in a
     * SELECT ... FOR UPDATE OF ... {NO WAIT}.  Issues fewer locks
     * and avoids setting the lock mode on each query.
     * <p>Example:<code>readAllQuery.setSelectionCriteria(employee.get("address").equal("Ottawa"));</code>
     * <ul><li>LOCK: all employees in Ottawa and all referenced Ottawa addresses will be locked.
     * <li>DEFAULT_LOCK_MODE: if address is a joined attribute, and only address has a pessimistic
     * locking policy, only referenced Ottawa addresses will be locked.
     * </ul>
     * @see org.eclipse.persistence.descriptors.PessimisticLockingPolicy
     */
    @Override
    public void setLockMode(short lockMode) {
        if ((lockMode == LOCK) || (lockMode == LOCK_NOWAIT)) {
            lockingClause = ForUpdateClause.newInstance(lockMode);
            setShouldRefreshIdentityMapResult(true);
        } else if (lockMode == NO_LOCK) {
            lockingClause = ForUpdateClause.newInstance(lockMode);
        } else {
            lockingClause = null;
            setIsPrePrepared(false);
        }
        setIsPrepared(false);
        setWasDefaultLockMode(false);
    }

    /**
     * INTERNAL:
     * returns the jakarta.persistence.LockModeType string value set on this query.
     */
    public String getLockModeType(){
        return this.lockModeType;
    }

    /**
     * INTERNAL:
     * Sets a jakarta.persistence.LockModeType to used with this queries execution.
     * The valid types are:
     *  - WRITE
     *  - READ
     *  - OPTIMISTIC
     *  - OPTIMISTIC_FORCE_INCREMENT
     *  - PESSIMISTIC_READ
     *  - PESSIMISTIC_WRITE
     *  - PESSIMISTIC_FORCE_INCREMENT
     *  - NONE
     * Setting a null type will do nothing.
     * @return returns a failure flag indicating that we were UNABLE to set the
     * lock mode because of validation. Callers to this method should check the
     * return value and throw the necessary exception.
     */
    public boolean setLockModeType(String lockModeType, AbstractSession session) {
        if (lockModeType != null) {
            OptimisticLockingPolicy lockingPolicy = session.getDescriptor(getReferenceClass()).getOptimisticLockingPolicy();

            if (lockingPolicy == null || !(lockingPolicy instanceof VersionLockingPolicy)) {
                if (! lockModeType.equals(PESSIMISTIC_READ) && ! lockModeType.equals(PESSIMISTIC_WRITE) && ! lockModeType.equals(NONE)) {
                    // Any locking mode other than PESSIMISTIC and NONE needs a
                    // version locking policy to be present, otherwise return a
                    // failure flag of true.
                    return true;
                }
            }

            this.lockModeType = lockModeType;
            setIsPrePrepared(false);
            setIsPrepared(false);
            setWasDefaultLockMode(false);
        }

        return false;
    }

    /**
     * INTERNAL:
     * Return the attributes that must be joined, but not fetched, that is,
     * do not trigger the value holder.
     */
    public void setNonFetchJoinAttributeExpressions(List<Expression> nonFetchJoinExpressions) {
        this.nonFetchJoinAttributeExpressions = nonFetchJoinExpressions;
    }

    /**
     * INTERNAL:
     * The locking clause contains a list of expressions representing which
     * objects are to be locked by the query.
     * <p>
     * Use for even finer grained control over what is and is not locked by
     * a particular query.
     */
    public void setLockingClause(ForUpdateClause clause) {
        if (clause.isForUpdateOfClause()) {
            this.lockingClause = clause;
            setIsPrePrepared(false);
        } else {
            setLockMode(clause.getLockMode());
        }
        setWasDefaultLockMode(false);
    }

    /**
     * INTERNAL:
     * Set the partial attributes to select.
     */
    public void setPartialAttributeExpressions(List<Expression> partialAttributeExpressions) {
        this.partialAttributeExpressions = partialAttributeExpressions;
    }

    @Override
    public void setEJBQLString(String ejbqlString) {
        super.setEJBQLString(ejbqlString);
        setIsPrePrepared(false);
    }

    /**
     * PUBLIC:
     * The QueryByExamplePolicy, is a useful to customize the query when Query By Example is used.
     * The policy will control what attributes should, or should not be included in the query.
     * When dealing with nulls, using special operations (notEqual, lessThan, like, etc.)
     * for comparison, or choosing to include certain attributes at all times, it is useful to modify
     * the policy accordingly.
     * <p>Once a query is executed you must make an explicit call to setQueryByExamplePolicy
     * when changing the policy, so the query will know to prepare itself again.
     * <p>There is a caution to setting both a selection criteria and an example object:
     * If you set the policy after execution you must also reset the selection criteria.
     * (This is because after execution the original criteria and Query By Example criteria are fused together,
     * and the former cannot be easily recovered).
     */
    public void setQueryByExamplePolicy(QueryByExamplePolicy queryByExamplePolicy) {
        if (!getQueryMechanism().isQueryByExampleMechanism()) {
            setQueryMechanism(new QueryByExampleMechanism(this, getSelectionCriteria()));
            ((QueryByExampleMechanism)getQueryMechanism()).setQueryByExamplePolicy(queryByExamplePolicy);
            setIsPrepared(false);
        } else {
            ((QueryByExampleMechanism)getQueryMechanism()).setQueryByExamplePolicy(queryByExamplePolicy);
            // Must allow the query to be prepared again.
            if (isPrepared() || (!shouldPrepare() && ((QueryByExampleMechanism)getQueryMechanism()).isParsed())) {
                ((QueryByExampleMechanism)getQueryMechanism()).setIsParsed(false);
                setSelectionCriteria(null);
                // setIsPrepared(false) triggered by previous.
            }
        }
        setIsPrePrepared(false);
    }

    /**
     * REQUIRED:
     * Set the reference class for the query.
     */
    @Override
    public void setReferenceClass(Class aClass) {
        if (referenceClass != aClass) {
            setIsPreparedKeepingSubclassData(false);
        }
        referenceClass = aClass;
    }

    /**
     * INTERNAL:
     * Set the reference class for the query.
     */
    @Override
    public void setReferenceClassName(String aClass) {
        if (this.referenceClassName != aClass) {
            setIsPreparedKeepingSubclassData(false);
        }
        this.referenceClassName = aClass;
    }


    /**
     * PUBLIC:
     * Set the Expression/where clause of the query.
     * The expression should be defined using the query's ExpressionBuilder.
     */
    @Override
    public void setSelectionCriteria(Expression expression) {
        super.setSelectionCriteria(expression);
        if ((expression != null) && (this.defaultBuilder != null) && (this.defaultBuilder.getQueryClass() == null)){
            // For flashback: Must make sure expression and defaultBuilder always in sync.
            ExpressionBuilder newBuilder = expression.getBuilder();
            if (newBuilder != this.defaultBuilder) {
                if (hasAsOfClause() && getAsOfClause().isUniversal()) {
                    newBuilder.asOf(this.defaultBuilder.getAsOfClause());
                }
                this.defaultBuilder = newBuilder;
            }
        }
    }

    /**
     * INTERNAL:
     * Set if the rows for the result of the query should also be returned using a complex query result.
     * @see ComplexQueryResult
     */
    public void setShouldIncludeData(boolean shouldIncludeData) {
        this.shouldIncludeData = shouldIncludeData;
        if (usesResultSetAccessOptimization() && shouldIncludeData) {
            // shouldIncludeData==true requires full row(s), ResultSetAccessOptimization purpose is to (sometimes) deliver incomplete row(s). These setting can't be used together.
            if (this.isResultSetAccessOptimizedQuery != null) {
                this.usesResultSetAccessOptimization = null;
                throw QueryException.resultSetAccessOptimizationIsNotPossible(this);
            } else {
                this.usesResultSetAccessOptimization = Boolean.FALSE;
            }
        }
    }

    /**
     * PUBLIC:
     * Return if cache should be checked.
     */
    public boolean shouldCheckCacheOnly() {
        return this.cacheUsage == CheckCacheOnly;
    }

    /**
     * PUBLIC:
     * Return whether the descriptor's disableCacheHits setting should be checked prior
     * to querying the cache.
     */
    public boolean shouldCheckDescriptorForCacheUsage() {
        return this.cacheUsage == UseDescriptorSetting;
    }

    /**
     * PUBLIC:
     * Should the results will be checked against the changes within the unit of work and object no longer matching or deleted will be remove, matching new objects will also be added..
     */
    public boolean shouldConformResultsInUnitOfWork() {
        return this.cacheUsage == ConformResultsInUnitOfWork;
    }

    /**
     * INTERNAL:
     * return true if this query should use a distinct
     */
    public boolean shouldDistinctBeUsed() {
        return getDistinctState() == USE_DISTINCT;
    }

    /**
     * INTERNAL:
     * Return if the rows for the result of the query should also be returned using a complex query result.
     * @see ComplexQueryResult
     */
    public boolean shouldIncludeData() {
        return shouldIncludeData;
    }

    /**
     * PUBLIC:
     * Return if an outer join should be used to read subclasses.
     * By default a separate query is done for each subclass when querying for
     * a root or branch inheritance class that has subclasses that span multiple tables.
     */
    public boolean shouldOuterJoinSubclasses() {
        if (shouldOuterJoinSubclasses == null) {
            return false;
        }
        return shouldOuterJoinSubclasses.booleanValue();
    }

    /**
     * PUBLIC:
     * Set if an outer join should be used to read subclasses.
     * By default a separate query is done for each subclass when querying for
     * a root or branch inheritance class that has subclasses that span multiple tables.
     */
    public void setShouldOuterJoinSubclasses(boolean shouldOuterJoinSubclasses) {
        this.shouldOuterJoinSubclasses = Boolean.valueOf(shouldOuterJoinSubclasses);
        setIsPrepared(false);
    }

    /**
     * INTERNAL:
     * Return if this is a full object query, not partial nor fetch group.
     */
    @Override
    public boolean shouldReadAllMappings() {
        return (!hasPartialAttributeExpressions()) && (this.fetchGroup == null);
    }

    /**
     * INTERNAL:
     * Check if the mapping is part of the partial attributes.
     */
    @Override
    public boolean shouldReadMapping(DatabaseMapping mapping, FetchGroup fetchGroup) {
        String attrName = mapping.getAttributeName();

        // bug 3659145 TODO - What is this bug ref? dclarke modified this next
        // if block
        if(fetchGroup  != null) {
            return fetchGroup.containsAttributeInternal(mapping.getAttributeName());
        }

        return isPartialAttribute(attrName);
    }

    /**
     * ADVANCED:
     * If a distinct has been set the DISTINCT clause will be printed.
     * This is used internally by EclipseLink for batch reading but may also be
     * used directly for advanced queries or report queries.
     */
    public void useDistinct() {
        setDistinctState(USE_DISTINCT);
    }

    /**
    * INTERNAL:
    * Indicates whether the query is cached as an expression query in descriptor's query manager.
    */
    public boolean isCachedExpressionQuery() {
        return this.isCachedExpressionQuery;
    }

    /**
    * INTERNAL:
    * Helper method that checks if clone has been locked with uow.
    */
    @Override
    public boolean isClonePessimisticLocked(Object clone, UnitOfWorkImpl uow) {
        return this.descriptor.hasPessimisticLockingPolicy() && uow.isPessimisticLocked(clone);
    }

    /**
     * INTERNAL:
     * Cache the locking policy isReferenceClassLocked check.
     */
    protected boolean isReferenceClassLocked() {
        if (isReferenceClassLocked == null) {
            isReferenceClassLocked = Boolean.valueOf(isLockQuery() && lockingClause.isReferenceClassLocked());
        }
        return isReferenceClassLocked.booleanValue();
    }

    /**
     * INTERNAL:
     * Helper method that records clone with uow if query is pessimistic locking.
     */
    @Override
    public void recordCloneForPessimisticLocking(Object clone, UnitOfWorkImpl uow) {
        if (isReferenceClassLocked()) {
            uow.addPessimisticLockedClone(clone);
        }
    }

    /**
     * ADVANCED:
     * Return if the query should be optimized to build directly from the result set.
     * This optimization follows an optimized path and can only be used for,
     * singleton primary key, direct mapped, simple type, no inheritance, uow isolated objects.
     */
    public boolean isResultSetOptimizedQuery() {
        return this.isResultSetOptimizedQuery;
    }

    /**
     * ADVANCED:
     * Return if the query result set access should be optimized.
     */
    public Boolean isResultSetAccessOptimizedQuery() {
        return this.isResultSetAccessOptimizedQuery;
    }

    /**
     * INTERNAL:
     * Return if the query uses ResultSet optimization.
     * Note that to be accurate it's required to be set by prepareResultSetAccessOptimization or checkResultSetAccessOptimization method.
     * It's always returns the same value as this.isResultSetOptimizedQuery.booleanValue (if not null).
     * Note that in this case if optimization is incompatible with other query settings then exception is thrown.
     * Otherwise - if the session demand optimization and it is possible - optimizes (returns true),
     * otherwise false.
     */
    @Override
    public boolean usesResultSetAccessOptimization() {
        return this.usesResultSetAccessOptimization != null && this.usesResultSetAccessOptimization;
    }

    /**
     * INTERNAL:
     * Sets usesResultSetAccessOptimization based on isResultSetAccessOptimizedQuery, session default and
     * query settings that could not be altered without re-preparing the query.
     * Called when the query is prepared or in case usesResultSetAccessOptimization hasn't been set yet.
     * Throws exception if isResultSetAccessOptimizedQuery==true cannot be accommodated because of a conflict with the query settings.
     * In case of isResultSetAccessOptimizedQuery hasn't been set and session default conflicting with the the query settings
     * the optimization is turned off.
     */
    protected void prepareResultSetAccessOptimization() {
        // if ResultSet optimization is used then ResultSet Access optimization is ignored.
        if (this.isResultSetOptimizedQuery) {
            return;
        }
        if (this.isResultSetAccessOptimizedQuery != null) {
            this.usesResultSetAccessOptimization = this.isResultSetAccessOptimizedQuery;
            if (this.usesResultSetAccessOptimization) {
                if (!supportsResultSetAccessOptimizationOnPrepare() || !supportsResultSetAccessOptimizationOnExecute()) {
                    this.usesResultSetAccessOptimization = null;
                    throw QueryException.resultSetAccessOptimizationIsNotPossible(this);
                }
            }
        } else {
            if (this.session.shouldOptimizeResultSetAccess() && supportsResultSetAccessOptimizationOnPrepare() && supportsResultSetAccessOptimizationOnExecute()) {
                this.usesResultSetAccessOptimization = Boolean.TRUE;
            } else {
                this.usesResultSetAccessOptimization = Boolean.FALSE;
            }
        }
    }

    /**
     * INTERNAL:
     */
    public void clearUsesResultSetAccessOptimization() {
        this.usesResultSetAccessOptimization = null;
    }

    /**
     * ADVANCED:
     * Set if the query should be optimized to build directly from the result set.
     * This optimization follows an optimized path and can only be used for,
     * singleton primary key, direct mapped, simple type, no inheritance, uow isolated objects.
     */
    public void setIsResultSetOptimizedQuery(boolean isResultSetOptimizedQuery) {
        this.isResultSetOptimizedQuery = isResultSetOptimizedQuery;
    }

    /**
     * ADVANCED:
     * Set if the query should be optimized to build directly from the result set.
     */
    public void setIsResultSetAccessOptimizedQuery(boolean isResultSetAccessOptimizedQuery) {
        if (this.isResultSetAccessOptimizedQuery == null || this.isResultSetAccessOptimizedQuery.booleanValue() != isResultSetOptimizedQuery) {
            this.isResultSetAccessOptimizedQuery = isResultSetAccessOptimizedQuery;
            this.usesResultSetAccessOptimization = null;
        }
    }

    /**
     * ADVANCED:
     * Clear the flag set by setIsResultSetOptimizedQuery method, allow to use default set on the session instead.
     */
    public void clearIsResultSetOptimizedQuery() {
        if (this.isResultSetAccessOptimizedQuery != null) {
            this.isResultSetAccessOptimizedQuery = null;
            this.usesResultSetAccessOptimization = null;
        }
    }

    /**
     * INTERNAL: Helper method to determine the default mode. If true and query has a pessimistic locking policy,
     * locking will be configured according to the pessimistic locking policy.
     */
    @Override
    public boolean isDefaultLock() {
        return (this.lockingClause == null) || wasDefaultLockMode();
    }

    /**
     * INTERNAL:
     * Return true if the query uses default properties.
     * This is used to determine if this query is cacheable.
     * i.e. does not use any properties that may conflict with another query
     * with the same JPQL or selection criteria.
     */
    @Override
    public boolean isDefaultPropertiesQuery() {
        return super.isDefaultPropertiesQuery()
            && (!this.isResultSetOptimizedQuery)
            && (this.isResultSetAccessOptimizedQuery == null || this.isResultSetAccessOptimizedQuery.equals(isResultSetAccessOptimizedQueryDefault))
            && (this.shouldUseSerializedObjectPolicy == shouldUseSerializedObjectPolicyDefault)
            && (isDefaultLock())
            && (!hasAdditionalFields())
            && (!hasPartialAttributeExpressions())
            && (!hasUnionExpressions())
            && (!hasNonFetchJoinedAttributeExpressions())
            && (this.fetchGroup == null)
            && (this.fetchGroupName == null)
            && (this.shouldUseDefaultFetchGroup);
    }

    /**
     * INTERNAL:
     * Checks to see if a builder has been set on the query.
     */
    public boolean hasDefaultBuilder(){
        return this.defaultBuilder != null;
    }

    /**
     * Return if a fetch group is set in the query.
     */
    public boolean hasFetchGroup() {
        return this.fetchGroup != null;
    }

    /**
     * Return the fetch group set in the query.
     * If a fetch group is not explicitly set in the query, default fetch group optionally defined in the descriptor
     * would be used, unless the user explicitly calls query.setShouldUseDefaultFetchGroup(false).
     * Note that the returned fetchGroup may be updated during preProcess.
     */
    public FetchGroup getFetchGroup() {
        return this.fetchGroup;
    }

    /**
     * Return the load group set in the query.
     */
    @Override
    public LoadGroup getLoadGroup() {
        return this.loadGroup;
    }

    /**
     * INTERNAL:
     * Returns FetchGroup that will be applied to the query.
     * Note that the returned fetchGroup may be updated during preProcess.
     */
    @Override
    public FetchGroup getExecutionFetchGroup() {
        return this.fetchGroup;
    }

    /**
     * INTERNAL:
     * Returns FetchGroup that will be applied to the query.
     * Note that the returned fetchGroup may be updated during preProcess.
     */
    @Override
    public FetchGroup getExecutionFetchGroup(ClassDescriptor descriptor) {
        if (this.fetchGroup != null && descriptor.hasInheritance()){
            return (FetchGroup) this.fetchGroup.findGroup(descriptor);
        }
        return this.fetchGroup;
    }

    /**
     * INTERNAL:
     * Indicates whether a FetchGroup will be applied to the query.
     */
    @Override
    public boolean hasExecutionFetchGroup() {
        return getExecutionFetchGroup() != null;
    }

    /**
     * Set a dynamic (use case) fetch group to the query.
     */
    public void setFetchGroup(FetchGroup newFetchGroup) {
        this.fetchGroup = newFetchGroup;
        this.fetchGroupName = null;
        setIsPrePrepared(false);
    }

    /**
     * Set a descriptor-level pre-defined named fetch group  to the query.
     */
    public void setFetchGroupName(String groupName) {
        //nullify the fetch group reference as one query can only has one fetch group.
        this.fetchGroup = null;
        this.fetchGroupName = groupName;
        setIsPrePrepared(false);
    }

    /**
     * Set a load group to the query.
     */
    public void setLoadGroup(LoadGroup loadGroup) {
        this.loadGroup = loadGroup;
    }

    /**
     * Return the fetch group name set in the query.
     */
    public String getFetchGroupName() {
        return this.fetchGroupName;
    }

    /**
     * Return false if the query does not use the default fetch group defined in the descriptor level.
     */
    public boolean shouldUseDefaultFetchGroup() {
        return this.shouldUseDefaultFetchGroup;
    }

    /**
     * Set false if the user does not want to use the default fetch group defined in the descriptor level.
     */
    public void setShouldUseDefaultFetchGroup(boolean shouldUseDefaultFetchGroup) {
        this.shouldUseDefaultFetchGroup = shouldUseDefaultFetchGroup;
        this.fetchGroup = null;
        this.fetchGroupName = null;
        // Force prepare again so executeFetchGroup is calculated
        setIsPrePrepared(false);
    }

    /**
     * INTERNAL:
     * Return the cache of concrete subclass calls.
     * This allow concrete subclasses calls to be prepared and cached for inheritance queries.
     */
    public Map<Class, DatabaseCall> getConcreteSubclassCalls() {
        if (concreteSubclassCalls == null) {
            concreteSubclassCalls = new ConcurrentHashMap(8);
        }
        return concreteSubclassCalls;
    }

    /**
     * INTERNAL:
     * Return the cache of concrete subclass queries.
     * This allow concrete subclasses calls to be prepared and cached for table per class inheritance and interface queries.
     */
    public Map<Class, DatabaseQuery> getConcreteSubclassQueries() {
        if (concreteSubclassQueries == null) {
            concreteSubclassQueries = new ConcurrentHashMap(8);
        }
        return concreteSubclassQueries;
    }

    /**
     * INTERNAL:
     * Return the cache of aggregate queries.
     * This allows aggregate query clones to be cached.
     */
    public Map<DatabaseMapping, ObjectLevelReadQuery> getAggregateQueries() {
        if (aggregateQueries == null) {
            aggregateQueries = new HashMap(8);
        }
        return aggregateQueries;
    }

    /**
     * INTERNAL:
     * Return the aggregate query clone for the mapping.
     */
    public ObjectLevelReadQuery getAggregateQuery(DatabaseMapping mapping) {
        if (this.aggregateQueries == null) {
            return null;
        }
        return this.aggregateQueries.get(mapping);
    }

    /**
     * INTERNAL:
     * Set the aggregate query clone for the mapping.
     */
    public void setAggregateQuery(DatabaseMapping mapping, ObjectLevelReadQuery query) {
        getAggregateQueries().put(mapping, query);
    }

    /**
     * INTERNAL:
     * Return the cache of concrete subclass joined mapping indexes.
     * This allow concrete subclasses calls to be prepared and cached for inheritance queries.
     */
    public Map<Class, Map<DatabaseMapping, Object>> getConcreteSubclassJoinedMappingIndexes() {
        if (concreteSubclassJoinedMappingIndexes == null) {
            concreteSubclassJoinedMappingIndexes = new ConcurrentHashMap(8);
        }
        return concreteSubclassJoinedMappingIndexes;
    }


    /**
     * INTERNAL:
     * Return if the query is known to be by primary key.
     */
    public boolean isPrimaryKeyQuery() {
        return false;
    }

    /**
     * INTERNAL:
     * Extends pessimistic lock scope.
     */
    public void extendPessimisticLockScope() {
        if(!shouldExtendPessimisticLockScope || getDescriptor() == null) {
            return;
        }
        int size = getDescriptor().getMappings().size();
        boolean isExtended = false;
        boolean isFurtherExtensionRequired = false;
        for(int i=0; i < size; i++) {
            DatabaseMapping mapping = getDescriptor().getMappings().get(i);
            if(mapping.isForeignReferenceMapping()) {
                ForeignReferenceMapping frMapping = (ForeignReferenceMapping)mapping;
                if(frMapping.shouldExtendPessimisticLockScope()) {
                    if(frMapping.shouldExtendPessimisticLockScopeInSourceQuery()) {
                        frMapping.extendPessimisticLockScopeInSourceQuery(this);
                        isExtended = true;
                    } else {
                        isFurtherExtensionRequired = true;
                    }
                }
            }
        }
        if(isExtended) {
            useDistinct();
        }
        if(!isFurtherExtensionRequired) {
            shouldExtendPessimisticLockScope = false;
        }
    }

    /**
     * Return the batch fetch policy for configuring batch fetching.
     */
    public BatchFetchPolicy getBatchFetchPolicy() {
        if (batchFetchPolicy == null) {
            batchFetchPolicy = new BatchFetchPolicy();
        }
        return batchFetchPolicy;
    }

    /**
     * Set the batch fetch policy for configuring batch fetching.
     */
    public void setBatchFetchPolicy(BatchFetchPolicy batchFetchPolicy) {
        this.batchFetchPolicy = batchFetchPolicy;
    }

    /**
     * INTERNAL:
     * Return all attributes specified for batch reading.
     */
    public List<Expression> getBatchReadAttributeExpressions() {
        return getBatchFetchPolicy().getAttributeExpressions();
    }

    /**
     * INTERNAL:
     * Set all attributes specified for batch reading.
     */
    public void setBatchReadAttributeExpressions(List<Expression> attributeExpressions) {
        if ((this.batchFetchPolicy == null) && (attributeExpressions.isEmpty())) {
            return;
        }
        getBatchFetchPolicy().setAttributeExpressions(attributeExpressions);
    }

    /**
     * INTERNAL:
     * Return true is this query has batching
     */
    public boolean hasBatchReadAttributes() {
        return (this.batchFetchPolicy != null) && (this.batchFetchPolicy.hasAttributes());
    }

    /**
     * INTERNAL:
     * Return if the attribute is specified for batch reading.
     */
    public boolean isAttributeBatchRead(ClassDescriptor mappingDescriptor, String attributeName) {
        if (this.batchFetchPolicy == null) {
            return false;
        }
        return this.batchFetchPolicy.isAttributeBatchRead(mappingDescriptor, attributeName);
    }

    /**
     * INTERNAL:
     * Used to optimize joining by pre-computing the nested join queries for the mappings.
     */
    public void computeBatchReadMappingQueries() {
        boolean initialized = false;
        if (getDescriptor().getObjectBuilder().hasBatchFetchedAttributes()) {
            // Only set the descriptor batched attributes if no batching has been set.
            // This avoid endless recursion if a recursive relationship is batched.
            // The batched mapping do not need to be processed up front,
            // this is just an optimization, and needed for IN batching.
            if (this.batchFetchPolicy == null) {
                this.batchFetchPolicy = new BatchFetchPolicy();
                if (getDescriptor().getObjectBuilder().hasInBatchFetchedAttribute()) {
                    this.batchFetchPolicy.setType(BatchFetchType.IN);
                }
                List<DatabaseMapping> batchedMappings = getDescriptor().getObjectBuilder().getBatchFetchedAttributes();
                this.batchFetchPolicy.setMappingQueries(new HashMap(batchedMappings.size()));
                initialized = true;
                int size = batchedMappings.size();
                for (int index = 0; index < size; index++) {
                    DatabaseMapping mapping = batchedMappings.get(index);
                    if ((mapping != null) && mapping.isForeignReferenceMapping()) {
                        // A nested query must be built to pass to the descriptor that looks like the real query execution would.
                        ReadQuery nestedQuery = ((ForeignReferenceMapping)mapping).prepareNestedBatchQuery(this);
                        // Register the nested query to be used by the mapping for all the objects.
                        this.batchFetchPolicy.getMappingQueries().put(mapping, nestedQuery);
                    }
                }
                this.batchFetchPolicy.setBatchedMappings(getDescriptor().getObjectBuilder().getBatchFetchedAttributes());
            }
        }
        if (hasBatchReadAttributes()) {
            List<Expression> batchReadAttributeExpressions = getBatchReadAttributeExpressions();
            this.batchFetchPolicy.setAttributes(new ArrayList(batchReadAttributeExpressions.size()));
            if (!initialized) {
                this.batchFetchPolicy.setMappingQueries(new HashMap(batchReadAttributeExpressions.size()));
            }
            computeNestedQueriesForBatchReadExpressions(batchReadAttributeExpressions);
        }
    }

    /**
     * INTERNAL:
     * Compute the cache batched attributes.
     * Used to recompute batched attributes for nested aggregate queries.
     */
    public void computeBatchReadAttributes() {
        List<Expression> batchReadAttributeExpressions = getBatchReadAttributeExpressions();
        this.batchFetchPolicy.setAttributes(new ArrayList(batchReadAttributeExpressions.size()));
        int size = batchReadAttributeExpressions.size();
        for (int index = 0; index < size; index++) {
            ObjectExpression objectExpression = (ObjectExpression)batchReadAttributeExpressions.get(index);

            // Expression may not have been initialized.
            ExpressionBuilder builder = objectExpression.getBuilder();
            if (builder.getSession() == null) {
                builder.setSession(getSession().getRootSession(null));
            }
            if (builder.getQueryClass() == null) {
                builder.setQueryClass(getReferenceClass());
            }

            // PERF: Cache join attribute names.
            ObjectExpression baseExpression = objectExpression;
            while (!baseExpression.getBaseExpression().isExpressionBuilder()) {
                baseExpression = (ObjectExpression)baseExpression.getBaseExpression();
            }
            this.batchFetchPolicy.getAttributes().add(baseExpression.getName());
        }
    }

    /**
     * INTERNAL:
     * This method is used when computing the nested queries for batch read mappings.
     * It recurses computing the nested mapping queries.
     */
    protected void computeNestedQueriesForBatchReadExpressions(List<Expression> batchReadExpressions) {
        int size = batchReadExpressions.size();
        for (int index = 0; index < size; index++) {
            ObjectExpression objectExpression = (ObjectExpression)batchReadExpressions.get(index);

            // Expression may not have been initialized.
            ExpressionBuilder builder = objectExpression.getBuilder();
            if (builder.getSession() == null) {
                builder.setSession(getSession().getRootSession(null));
            }
            if (builder.getQueryClass() == null) {
                builder.setQueryClass(getReferenceClass());
            }

            // PERF: Cache join attribute names.
            ObjectExpression baseExpression = objectExpression;
            while (!baseExpression.getBaseExpression().isExpressionBuilder()) {
                baseExpression = (ObjectExpression)baseExpression.getBaseExpression();
            }
            this.batchFetchPolicy.getAttributes().add(baseExpression.getName());

            DatabaseMapping mapping = baseExpression.getMapping();
            if ((mapping != null) && mapping.isAggregateObjectMapping()) {
                // Also prepare the nested aggregate queries, as aggregates do not have their own query.
                baseExpression = objectExpression.getFirstNonAggregateExpressionAfterExpressionBuilder(new ArrayList(2));
                mapping = baseExpression.getMapping();
            }
            if ((mapping != null) && mapping.isForeignReferenceMapping()) {
                if (!this.batchFetchPolicy.getMappingQueries().containsKey(mapping)) {
                    // A nested query must be built to pass to the descriptor that looks like the real query execution would.
                    ReadQuery nestedQuery = ((ForeignReferenceMapping)mapping).prepareNestedBatchQuery(this);
                    // Register the nested query to be used by the mapping for all the objects.
                    this.batchFetchPolicy.getMappingQueries().put(mapping, nestedQuery);
                }
            }
        }
    }

    /**
     * PUBLIC:
     * Specify the foreign-reference mapped attribute to be optimized in this query.
     * The query will execute normally, however when any of the batched parts is accessed,
     * the parts will all be read in a single query,
     * this allows all of the data required for the parts to be read in a single query instead of (n) queries.
     * This should be used when the application knows that it requires the part for all of the objects being read.
     * This can be used for one-to-one, one-to-many, many-to-many and direct collection mappings.
     *
     * The use of the expression allows for nested batch reading to be expressed.
     * <p>Example: query.addBatchReadAttribute("phoneNumbers")
     *
     * @see #addBatchReadAttribute(Expression)
     * @see #setBatchFetchType(BatchFetchType)
     * @see ObjectLevelReadQuery#addJoinedAttribute(String)
     */
    public void addBatchReadAttribute(String attributeName) {
        addBatchReadAttribute(getExpressionBuilder().get(attributeName));
    }

    /**
     * PUBLIC:
     * Specify the foreign-reference mapped attribute to be optimized in this query.
     * The query will execute normally, however when any of the batched parts is accessed,
     * the parts will all be read in a single query,
     * this allows all of the data required for the parts to be read in a single query instead of (n) queries.
     * This should be used when the application knows that it requires the part for all of the objects being read.
     * This can be used for one-to-one, one-to-many, many-to-many and direct collection mappings.
     *
     * The use of the expression allows for nested batch reading to be expressed.
     * <p>Example: query.addBatchReadAttribute(query.getExpressionBuilder().get("policies").get("claims"))
     *
     * @see #setBatchFetchType(BatchFetchType)
     * @see ObjectLevelReadQuery#addJoinedAttribute(String)
     */
    public void addBatchReadAttribute(Expression attributeExpression) {
        if (! getQueryMechanism().isExpressionQueryMechanism()){
            throw QueryException.batchReadingNotSupported(this);
        }
        getBatchReadAttributeExpressions().add(attributeExpression);
        setIsPrepared(false);
    }

    /**
     * PUBLIC:
     * Set the batch fetch type for the query.
     * This can be JOIN, EXISTS, or IN.
     * This defines the type of batch reading to use with the query.
     * The query must have defined batch read attributes to set its fetch type.
     *
     * @see #addBatchReadAttribute(Expression)
     */
    public void setBatchFetchType(BatchFetchType type) {
        getBatchFetchPolicy().setType(type);
        setIsPrepared(false);
    }

    /**
     * PUBLIC:
     * Set the batch fetch size for the query.
     * This is only relevant for the IN batch fetch type.
     * This defines the max number of keys for the IN clause.
     *
     * @see #setBatchFetchType(BatchFetchType)
     * @see #addBatchReadAttribute(Expression)
     */
    public void setBatchFetchSize(int size) {
        getBatchFetchPolicy().setSize(size);
        setIsPrepared(false);
    }

    /**
     * INTERNAL:
     * Return temporary map of batched objects.
     */
    @Override
    public Map<Object, Object> getBatchObjects() {
        return getBatchFetchPolicy().getBatchObjects();
    }

    /**
     * INTERNAL:
     * Set temporary map of batched objects.
     */
    @Override
    public void setBatchObjects(Map<Object, Object> batchObjects) {
        getBatchFetchPolicy().setBatchObjects(batchObjects);
    }

    @Override
    public String toString() {
        String str = super.toString();
        if(this.fetchGroup != null) {
            str += '\n' + this.fetchGroup.toString();
        } else if(this.fetchGroupName != null) {
            str += '\n' + "FetchGroup(" + this.fetchGroupName + ")";
        } else if(this.shouldUseDefaultFetchGroup) {
            if(this.descriptor != null && this.descriptor.hasFetchGroupManager()) {
                FetchGroup defaultFetchGroup = descriptor.getFetchGroupManager().getDefaultFetchGroup();
                if(defaultFetchGroup != null) {
                    str += '\n' + "Default " + defaultFetchGroup.toString();
                }
            }
        }
        return str;
    }

    /**
     * INTERNAL:
     * Indicates whether the query can use ResultSet optimization.
     * The method is called when the query is prepared,
     * so it should refer only to the attributes that cannot be altered without re-preparing the query.
     * If the query is a clone and the original has been already prepared
     * this method will be called to set a (transient and therefore set to null) usesResultSetAccessOptimization attribute.
     */
    public boolean supportsResultSetAccessOptimizationOnPrepare() {
        DatabaseCall call = getCall();
        return ((call != null) && call.getReturnsResultSet()) && // must return ResultSet
            (!hasJoining() || !this.joinedAttributeManager.isToManyJoin()) &&
            (!this.descriptor.hasInheritance() ||
                    !this.descriptor.getInheritancePolicy().hasClassExtractor() &&  // ClassExtractor requires the whole row
                    (shouldOuterJoinSubclasses() || !this.descriptor.getInheritancePolicy().requiresMultipleTableSubclassRead() || this.descriptor.getInheritancePolicy().hasView())) &&  // don't know how to handle select class type call - ResultSet optimization breaks it.
            (this.batchFetchPolicy == null || !this.batchFetchPolicy.isIN());  // batchFetchPolicy.isIN() requires all rows up front - can't support it
    }

    /**
     * INTERNAL:
     * Indicates whether the query can use ResultSet optimization.
     * Note that the session must be already set.
     * The method is called when the query is executed,
     * so it should refer only to the attributes that can be altered without re-preparing the query.
     */
    public boolean supportsResultSetAccessOptimizationOnExecute() {
        return !this.session.isConcurrent() && !this.shouldIncludeData; // doesn't make sense to use ResultSetAccessOptimization if the whole row is required
    }

    /**
     * INTERNAL:
     * Indicates whether the query should use SerializedObjectPolicy if descriptor has it.
     */
    @Override
    public boolean shouldUseSerializedObjectPolicy() {
        return this.shouldUseSerializedObjectPolicy;
    }

    /**
     * INTERNAL:
     * Set a flag that indicates whether the query should use SerializedObjectPolicy if descriptor has it.
     */
    public void setShouldUseSerializedObjectPolicy(boolean shouldUseSerializedObjectPolicy) {
        if (this.shouldUseSerializedObjectPolicy != shouldUseSerializedObjectPolicy) {
            if (shouldUseSerializedObjectPolicy && this.fetchGroup != null) {
                // currently SOP is incompatible with fetch groups
                return;
            }
            this.shouldUseSerializedObjectPolicy = shouldUseSerializedObjectPolicy;
            setIsPrepared(false);
        }
    }
}
