/*
 * 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<Expression> joinedAttributes = getJoinedAttributeManager().getJoinedAttributeExpressions();
            List<Expression> 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<Expression> orderBys = getOrderByExpressions();
            List<Expression> 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) {
            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<Expression> 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<DatabaseField> 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<String> 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<DatabaseField> 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 == 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;
    }

    /**
     * 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 = 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 = isLockQuery() && lockingClause.isReferenceClassLocked();
        }
        return isReferenceClassLocked;
    }

    /**
     * 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 != 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);
        }
    }
}
