/*
 * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     04/01/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 2)
//     09/09/2011-2.3.1 Guy Pelletier
//       - 356197: Add new VPD type to MultitenantType
//     01/06/2011-2.3 Guy Pelletier
//       - 371453: JPA Multi-Tenancy in Bidirectional OneToOne Relation throws ArrayIndexOutOfBoundsException
package org.eclipse.persistence.queries;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.InvalidObject;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.indirection.ProxyIndirectionPolicy;
import org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.ResultSetRecord;
import org.eclipse.persistence.internal.sessions.SimpleResultSetRecord;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.internal.sessions.remote.RemoteSessionController;
import org.eclipse.persistence.internal.sessions.remote.Transporter;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.remote.DistributedSession;
import org.eclipse.persistence.tools.profiler.QueryMonitor;

/**
 * <p><b>Purpose</b>:
 * Concrete class for all read queries involving a single object.
 *
 * <p><b>Responsibilities</b>:
 * Return a single object for the query.
 * Implements the inheritance feature when dealing with abstract descriptors.
 *
 * @author Yvon Lavoie
 * @since TOPLink/Java 1.0
 */
public class ReadObjectQuery extends ObjectLevelReadQuery {
    /** Object that can be used in place of a selection criteria. */
    protected transient Object selectionObject;

    /** Key that can be used in place of a selection criteria. */
    protected Object selectionId;

    /** Can be used to refresh a specific non-cached instance from the database. */
    protected boolean shouldLoadResultIntoSelectionObject = false;

    /**
     * PUBLIC:
     * Return a new read object query.
     * A reference class must be specified before execution.
     * It is better to provide the class and expression builder on construction to esnure a single expression builder is used.
     * If no selection criteria is specified this will reads the first object found in the database.
     */
    public ReadObjectQuery() {
        super();
    }

    /**
     * PUBLIC:
     * Return a new read object query.
     * By default, the query has no selection criteria. Executing this query without
     * selection criteria will always result in a database access to read the first
     * instance of the specified Class found in the database. This is true no
     * matter how cache usage is configured and even if an instance of the
     * specified Class exists in the cache.
     * Executing a query with selection criteria allows you to avoid a database
     * access if the selected instance is in the cache. For this reason, you may whish to use a ReadObjectQuery constructor that takes selection criteria, such as: {@link #ReadObjectQuery(Class, Call)}, {@link #ReadObjectQuery(Class, Expression)}, {@link #ReadObjectQuery(Class, ExpressionBuilder)}, {@link #ReadObjectQuery(ExpressionBuilder)}, {@link #ReadObjectQuery(Object)}, or {@link #ReadObjectQuery(Object, QueryByExamplePolicy)}.
     */
    public ReadObjectQuery(Class classToRead) {
        this();
        this.referenceClass = classToRead;
    }

    /**
     * PUBLIC:
     * Return a new read object query for the class and the selection criteria.
     */
    public ReadObjectQuery(Class classToRead, Expression selectionCriteria) {
        this();
        this.referenceClass = classToRead;
        setSelectionCriteria(selectionCriteria);
    }

    /**
     * PUBLIC:
     * Return a new read object query for the class.
     * The expression builder must be used for all associated expressions used with the query.
     */
    public ReadObjectQuery(Class classToRead, ExpressionBuilder builder) {
        this();
        this.defaultBuilder = builder;
        this.referenceClass = classToRead;
    }

    /**
     * PUBLIC:
     * Return a new read object query.
     * The call represents a database interaction such as SQL, Stored Procedure.
     */
    public ReadObjectQuery(Class classToRead, Call call) {
        this();
        this.referenceClass = classToRead;
        setCall(call);
    }

    /**
     * PUBLIC:
     * Return a new read object query.
     * The call represents a database interaction such as SQL, Stored Procedure.
     */
    public ReadObjectQuery(Call call) {
        this();
        setCall(call);
    }

    /**
     * PUBLIC:
     * Return a query to read the object with the same primary key as the provided object.
     * Note: This is not a query by example object, only the primary key will be used for the selection criteria.
     */
    public ReadObjectQuery(Object objectToRead) {
        this();
        setSelectionObject(objectToRead);
    }

    /**
     * PUBLIC:
     * Return a query by example query to find an object matching the attributes of the example object.
     */
    public ReadObjectQuery(Object exampleObject, QueryByExamplePolicy policy) {
        this();
        setExampleObject(exampleObject);
        setQueryByExamplePolicy(policy);
    }

    /**
     * PUBLIC:
     * The expression builder should be provide on creation to ensure only one is used.
     */
    public ReadObjectQuery(ExpressionBuilder builder) {
        this();
        this.defaultBuilder = builder;
    }

    /**
     * INTERNAL:
     * <P> This method is called by the object builder when building an original.
     * It will cause the original to be cached in the query results if the query
     * is set to do so.
     */
    @Override
    public void cacheResult(Object object) {
        Object cachableObject = object;
        if (object == null) {
            this.temporaryCachedQueryResults = InvalidObject.instance();
        } else {
            if (this.shouldUseWrapperPolicy) {
                cachableObject = this.session.wrapObject(object);
            }
            this.temporaryCachedQueryResults = cachableObject;
        }
    }


    /**
     * PUBLIC:
     * The cache will be checked only if the query contains exactly the primary key.
     * Queries can be configured to use the cache at several levels.
     * Other caching option are available.
     * @see #setCacheUsage(int)
     */
    public void checkCacheByExactPrimaryKey() {
        setCacheUsage(CheckCacheByExactPrimaryKey);
    }

    /**
     * PUBLIC:
     * This is the default, the cache will be checked only if the query contains the primary key.
     * Queries can be configured to use the cache at several levels.
     * Other caching option are available.
     * @see #setCacheUsage(int)
     */
    public void checkCacheByPrimaryKey() {
        setCacheUsage(CheckCacheByPrimaryKey);
    }

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

    /**
     * INTERNAL:
     * Ensure that the descriptor has been set.
     */
    @Override
    public void checkDescriptor(AbstractSession session) throws QueryException {
        if (this.descriptor == null) {
            if (getReferenceClass() == null) {
                throw QueryException.referenceClassMissing(this);
            }
            ClassDescriptor referenceDescriptor;
            //Bug#3947714  In case getSelectionObject() is proxy
            if (getSelectionObject() != null && session.getProject().hasProxyIndirection()) {
                referenceDescriptor = session.getDescriptor(getSelectionObject());
            } else {
                referenceDescriptor = session.getDescriptor(getReferenceClass());
            }
            if (referenceDescriptor == null) {
                throw QueryException.descriptorIsMissing(getReferenceClass(), this);
            }
            setDescriptor(referenceDescriptor);
        }
    }

    /**
     * INTERNAL:
     * The cache check is done before the prepare as a hit will not require the work to be done.
     */
    @Override
    protected Object checkEarlyReturnLocal(AbstractSession session, AbstractRecord translationRow) {
        if (shouldCheckCache() && shouldMaintainCache() && (!shouldRefreshIdentityMapResult() && (!shouldRetrieveBypassCache()))
                && (!(session.isRemoteSession() && (shouldRefreshRemoteIdentityMapResult() || this.descriptor.shouldDisableCacheHitsOnRemote())))
                && (!(shouldCheckDescriptorForCacheUsage() && this.descriptor.shouldDisableCacheHits())) && (!this.descriptor.isDescriptorForInterface())) {
            Object cachedObject = getQueryMechanism().checkCacheForObject(translationRow, session);
            this.isCacheCheckComplete = true;

            // Optimization: If find deleted object by exact primary
            // key expression or selection object/key just abort.
            if (cachedObject == InvalidObject.instance) {
                return cachedObject;
            }
            if (cachedObject != null) {
                if (shouldLoadResultIntoSelectionObject()) {
                    ObjectBuilder builder = this.descriptor.getObjectBuilder();
                    builder.copyInto(cachedObject, getSelectionObject());
                    //put this object into the cache.  This may cause some loss of identity
                    session.getIdentityMapAccessorInstance().putInIdentityMap(getSelectionObject());
                    cachedObject = getSelectionObject();
                }

                // check locking.  If clone has not been locked, do not early return cached object
                if (isLockQuery() && (session.isUnitOfWork() && !((UnitOfWorkImpl)session).isPessimisticLocked(cachedObject))) {
                    return null;
                }
                if (QueryMonitor.shouldMonitor()) {
                    QueryMonitor.incrementReadObjectHits(this);
                }
                session.incrementProfile(SessionProfiler.CacheHits, this);
            } else {
                if (!session.isUnitOfWork()) {
                    if (QueryMonitor.shouldMonitor()) {
                        QueryMonitor.incrementReadObjectMisses(this);
                    }
                    session.incrementProfile(SessionProfiler.CacheMisses, this);
                }
            }
            if (shouldUseWrapperPolicy()) {
                cachedObject = this.descriptor.getObjectBuilder().wrapObject(cachedObject, session);
            }
            return cachedObject;
        } else {
            if (!session.isUnitOfWork()) {
                if (QueryMonitor.shouldMonitor()) {
                    QueryMonitor.incrementReadObjectMisses(this);
                }
                session.incrementProfile(SessionProfiler.CacheMisses, this);
            }
            return null;
        }
    }

    /**
     * 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 will never be {@code null}.
     */
    @Override
    protected Boolean checkCustomQueryFlag(final AbstractSession session, final AbstractRecord translationRow) {
        // #436871 - Use local copy to avoid NPE from concurrent modification.
        Boolean useCustomQuery = isCustomQueryUsed;
        if (useCustomQuery != null) {
            return useCustomQuery;
        }
        // Check if user defined a custom query in the query manager.
        if (!this.isUserDefined) {
            if (!isCallQuery()
                    // By default all descriptors have a custom ("static") read-object query.
                    // This allows the read-object query and SQL to be prepare once.
                    && this.descriptor.getQueryManager().hasReadObjectQuery()) {
                // If the query require special SQL generation or execution do not use the static read object query.
                // PERF: the read-object query should always be static to ensure no regeneration of SQL.
                if ((!hasJoining() || !this.joinedAttributeManager.hasJoinedAttributeExpressions())
                        && (!hasPartialAttributeExpressions()) && (redirector == null) && !doNotRedirect
                        && (!hasAsOfClause()) && (!hasNonDefaultFetchGroup())
                        && (this.shouldUseSerializedObjectPolicy == shouldUseSerializedObjectPolicyDefault)
                        && this.wasDefaultLockMode && (shouldBindAllParameters == null) && (this.hintString == null)) {
                    if ((this.selectionId != null) || (this.selectionObject != null)) {// Must be primary key.
                        return Boolean.TRUE;
                    } else {
                        Expression selectionCriteria = getSelectionCriteria();
                        if (selectionCriteria != null) {
                            AbstractRecord primaryKeyRow =
                                    this.descriptor.getObjectBuilder().extractPrimaryKeyRowFromExpression(
                                            selectionCriteria, translationRow, session);
                            // Only execute the query if the selection criteria has the primary key fields set
                            if (primaryKeyRow != null) {
                                return Boolean.TRUE;
                            }
                        }
                    }
                }
            }
        }
        return useCustomQuery;
    }

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

    /**
     * INTERNAL:
     * Conform the result in the UnitOfWork.
     */
    protected Object conformResult(Object result, UnitOfWorkImpl unitOfWork, AbstractRecord databaseRow, boolean buildDirectlyFromRows) {
        // Note that if the object does not conform even though other objects might exist on the database null is returned.
        // Note that new objects is checked before the read is executed so does not have to be re-checked.
        // Must unwrap as the built object is always wrapped.
        // Note the object is unwrapped on the parent which it belongs to, as we
        // do not want to trigger a registration just yet.
        Object clone = null;
        if (buildDirectlyFromRows) {
            clone = buildObject((AbstractRecord)result);
        } else {
            clone = registerIndividualResult(
                    this.descriptor.getObjectBuilder().unwrapObject(result, unitOfWork.getParent()),
                    null, unitOfWork, null, null);
        }
        Expression selectionCriteria = getSelectionCriteria();
        if ((selectionCriteria != null) && (this.selectionId == null) && (this.selectionObject == null)) {
            ExpressionBuilder builder = selectionCriteria.getBuilder();
            builder.setSession(unitOfWork.getRootSession(null));
            builder.setQueryClass(getReferenceClass());
        }

        clone = conformIndividualResult(clone, unitOfWork, databaseRow, selectionCriteria, null);
        if (clone == null) {
            return clone;
        }

        if (shouldUseWrapperPolicy()) {
            return this.descriptor.getObjectBuilder().wrapObject(clone, unitOfWork);
        } else {
            return clone;
        }
    }

    /**
     * PUBLIC:
     * Do not refesh/load into the selection object, this is the default.
     * This property allows for the selection object of the query to be refreshed or put into the TopLink cache.
     * By default on a read or refresh the object in the cache is refreshed and returned or a new object is built from the database,
     * in some cases such as EJB BMP it is desirable to refresh or load into the object passed into the read object query.
     * <p>Note: This forces the selection object into the cache a replaces any existing object that may already be there,
     * this is a strict violation of object identity and other objects can still be refering to the old object.
     */
    public void dontLoadResultIntoSelectionObject() {
        setShouldLoadResultIntoSelectionObject(false);
    }

    /**
     * INTERNAL:
     * Execute the query. If there are cached results return those.
     * This must override the super to support result caching.
     *
     * @param session the session in which the receiver will be executed.
     * @return An object or vector, the result of executing the query.
     * @exception DatabaseException - an error has occurred on the database
     */
    @Override
    public Object execute(AbstractSession session, AbstractRecord row) throws DatabaseException {
        if (shouldCacheQueryResults()) {
            if (shouldConformResultsInUnitOfWork()) {
                throw QueryException.cannotConformAndCacheQueryResults(this);
            }
            if (isPrepared()) {// only prepared queries can have cached results.
                Object result = getQueryResults(session, row, true);
                // Bug6138532 - if result is "cached no results", return null immediately
                if (result == InvalidObject.instance) {
                    return null;
                }
                if (result != null) {
                    if (session.isUnitOfWork()) {
                        result = ((UnitOfWorkImpl)session).registerExistingObject(result);
                    }
                    return result;
                }
            }
        }
        return super.execute(session, row);
    }

    /**
     * INTERNAL:
     * Execute the query.
     * Do a cache lookup and build object from row if required.
     * @exception  DatabaseException - an error has occurred on the database
     * @return object - the first object found or null if none.
     */
    @Override
    protected Object executeObjectLevelReadQuery() throws DatabaseException {
        if (this.descriptor.isDescriptorForInterface()  || this.descriptor.hasTablePerClassPolicy()) {
            Object returnValue = this.descriptor.getInterfacePolicy().selectOneObjectUsingMultipleTableSubclassRead(this);

            if (this.descriptor.hasTablePerClassPolicy() && (!this.descriptor.isAbstract()) && (returnValue == null)) {
                // let it fall through to query the root.
            } else {
                this.executionTime = System.currentTimeMillis();
                return returnValue;
            }
        }

        boolean shouldSetRowsForJoins = hasJoining() && this.joinedAttributeManager.isToManyJoin();
        AbstractSession session = getSession();
        Object result = null;
        AbstractRecord row = null;

        Object sopObject = getTranslationRow().getSopObject();
        boolean useOptimization = false;
        if (sopObject == null) {
            useOptimization = usesResultSetAccessOptimization();
        }

        if (useOptimization) {
            DatabaseCall call = ((DatasourceCallQueryMechanism)this.queryMechanism).selectResultSet();
            this.executionTime = System.currentTimeMillis();
            boolean exceptionOccured = false;
            ResultSet resultSet = call.getResult();
            DatabaseAccessor dbAccessor = (DatabaseAccessor)getAccessor();
            try {
                if (resultSet.next()) {
                    ResultSetMetaData metaData = call.getResult().getMetaData();
                    boolean useSimple = this.descriptor.getObjectBuilder().isSimple();
                    DatabasePlatform platform = dbAccessor.getPlatform();
                    boolean optimizeData = platform.shouldOptimizeDataConversion();
                    if (useSimple) {
                        row = new SimpleResultSetRecord(call.getFields(), call.getFieldsArray(), resultSet, metaData, dbAccessor, getExecutionSession(), platform, optimizeData);
                        if (this.descriptor.isDescriptorTypeAggregate()) {
                            // Aggregate Collection may have an unmapped primary key referencing the owner, the corresponding field will not be used when the object is populated and therefore may not be cleared.
                            ((SimpleResultSetRecord)row).setShouldKeepValues(true);
                        }
                    } else {
                        row = new ResultSetRecord(call.getFields(), call.getFieldsArray(), resultSet, metaData, dbAccessor, getExecutionSession(), platform, optimizeData);
                    }
                    if (session.isUnitOfWork()) {
                        result = registerResultInUnitOfWork(row, (UnitOfWorkImpl)session, this.translationRow, true);
                    } else {
                        result = buildObject(row);
                    }

                    if (!useSimple && this.descriptor.getObjectBuilder().shouldKeepRow()) {
                        if (((ResultSetRecord)row).hasResultSet()) {
                            // ResultSet has not been fully triggered - that means the cached object was used.
                            // Yet the row still may be cached in a value holder (see loadBatchReadAttributes and loadJoinedAttributes methods).
                            // Remove ResultSet to avoid attempt to trigger it (already closed) when pk or fk values (already extracted) accessed when the value holder is instantiated.
                            ((ResultSetRecord)row).removeResultSet();
                        } else {
                            ((ResultSetRecord)row).removeNonIndirectionValues();
                        }
                    }
                }
            } catch (SQLException exception) {
                exceptionOccured = true;
                DatabaseException commException = dbAccessor.processExceptionForCommError(session, exception, call);
                if (commException != null) {
                    throw commException;
                }
                throw DatabaseException.sqlException(exception, call, getAccessor(), session, false);
            } finally {
                try {
                    if (resultSet != null) {
                        resultSet.close();
                    }
                    if (dbAccessor != null) {
                        if (call.getStatement() != null) {
                            dbAccessor.releaseStatement(call.getStatement(), call.getSQLString(), call, session);
                        }
                    }
                    if (call.hasAllocatedConnection()) {
                        getExecutionSession().releaseConnectionAfterCall(this);
                    }
                } catch (RuntimeException cleanupException) {
                    if (!exceptionOccured) {
                        throw cleanupException;
                    }
                } catch (SQLException cleanupSQLException) {
                    if (!exceptionOccured) {
                        throw DatabaseException.sqlException(cleanupSQLException, call, dbAccessor, session, false);
                    }
                }
            }
        } else {
            if (sopObject != null) {
                row = new DatabaseRecord(0);
                row.setSopObject(sopObject);
            } else {
                // If using 1-m joins, must select all rows.
                if (shouldSetRowsForJoins) {
                    List rows = getQueryMechanism().selectAllRows();
                    if (rows.size() > 0) {
                        row = (AbstractRecord)rows.get(0);
                    }
                    getJoinedAttributeManager().setDataResults(rows, session);
                } else {
                    row = getQueryMechanism().selectOneRow();
                }
            }

            this.executionTime = System.currentTimeMillis();
            if (row != null) {
                if (session.isUnitOfWork()) {
                    result = registerResultInUnitOfWork(row, (UnitOfWorkImpl)session, this.translationRow, true);
                } else {
                    result = buildObject(row);
                }
                if (sopObject != null) {
                    // remove sopObject so it's not stuck in a value holder.
                    row.setSopObject(null);
                }
            }
        }
        if ((result == null) && shouldCacheQueryResults()) {
            cacheResult(null);
        }
        if ((result == null) && this.shouldRefreshIdentityMapResult) {
            // bug5955326, should invalidate the shared cached if refreshed object no longer exists.
            if (this.selectionId != null) {
                session.getParentIdentityMapSession(this.descriptor, true, true).getIdentityMapAccessor().invalidateObject(this.selectionId, this.referenceClass);
            } else if (this.selectionObject != null) {
                session.getParentIdentityMapSession(this.descriptor, true, true).getIdentityMapAccessor().invalidateObject(this.selectionObject);
            }
        }

        if (this.shouldIncludeData && (sopObject == null)) {
            ComplexQueryResult complexResult = new ComplexQueryResult();
            complexResult.setResult(result);
            complexResult.setData(row);
            return complexResult;
        }

        return result;
    }

    /**
     * INTERNAL:
     * Execute the query building the objects directly from the database result-set.
     * @exception  DatabaseException - an error has occurred on the database
     * @return object - the first object found or null if none.
     */
    @Override
    protected Object executeObjectLevelReadQueryFromResultSet() throws DatabaseException {
        AbstractSession session = this.session;
        DatabasePlatform platform = session.getPlatform();
        DatabaseCall call = ((DatasourceCallQueryMechanism)this.queryMechanism).selectResultSet();
        Statement statement = call.getStatement();
        ResultSet resultSet = call.getResult();
        DatabaseAccessor accessor = (DatabaseAccessor)((List<Accessor>)this.accessors).get(0);
        boolean exceptionOccured = false;
        try {
            if (!resultSet.next()) {
                return null;
            }
            ResultSetMetaData metaData = resultSet.getMetaData();
            return this.descriptor.getObjectBuilder().buildObjectFromResultSet(this, null, resultSet, session, accessor, metaData, platform, call.getFields(), call.getFieldsArray());
        } catch (SQLException exception) {
            exceptionOccured = true;
            DatabaseException commException = accessor.processExceptionForCommError(session, exception, call);
            if (commException != null) {
                throw commException;
            }
            throw DatabaseException.sqlException(exception, call, accessor, session, false);
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    accessor.releaseStatement(statement, call.getSQLString(), call, session);
                }
                if (accessor != null) {
                    session.releaseReadConnection(accessor);
                }
            } catch (SQLException exception) {
                if (!exceptionOccured) {
                    //in the case of an external connection pool the connection may be null after the statement release
                    // if it is null we will be unable to check the connection for a comm error and
                    //therefore must return as if it was not a comm error.
                    DatabaseException commException = accessor.processExceptionForCommError(session, exception, call);
                    if (commException != null) {
                        throw commException;
                    }
                    throw DatabaseException.sqlException(exception, call, accessor, session, false);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Extract the correct query result from the transporter.
     */
    @Override
    public Object extractRemoteResult(Transporter transporter) {
        return ((DistributedSession)getSession()).getObjectCorrespondingTo(transporter.getObject(), transporter.getObjectDescriptors(), new IdentityHashMap(), this);
    }

    /**
     * INTERNAL:
     * Returns the specific default redirector for this query type.  There are numerous default query redirectors.
     * See ClassDescriptor for their types.
     */
    @Override
    protected QueryRedirector getDefaultRedirector(){
        return descriptor.getDefaultReadObjectQueryRedirector();
    }

    /**
     * PUBLIC:
     * Return the selection object of the query.
     * This can be used instead of a where clause expression for single object primary key queries.
     * The selection object given should have a primary key defined,
     * this primary key will be used to query the database instance of the same object.
     * This is a basic form of query by example where only the primary key is required,
     * it can be used for simple query forms, or testing.
     */
    public Object getSelectionObject() {
        return selectionObject;
    }

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

    /**
     * INTERNAL:
     * Return if the query is by primary key.
     */
    @Override
    public boolean isPrimaryKeyQuery() {
        return (this.selectionId != null) || (this.selectionObject != null);
    }

    /**
     * PUBLIC:
     * Allow for the selection object of the query to be refreshed or put into the EclipseLink cache.
     * By default on a read or refresh the object in the cache is refreshed and returned or a new object is built from the database,
     * in some cases such as EJB BMP it is desirable to refresh or load into the object passed into the read object query.
     * <p>Note: This forces the selection object into the cache a replaces any existing object that may already be there,
     * this is a strict violation of object identity and other objects can still be referring to the old object.
     */
    public void loadResultIntoSelectionObject() {
        setShouldLoadResultIntoSelectionObject(true);
    }

    /**
     * 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.isReadObjectQuery()) {
            ReadObjectQuery readQuery = (ReadObjectQuery)query;
            this.selectionId = readQuery.selectionId;
            this.selectionObject = readQuery.selectionObject;
            this.shouldLoadResultIntoSelectionObject = readQuery.shouldLoadResultIntoSelectionObject;
        }
    }

    /**
     * INTERNAL:
     * Prepare the receiver for execution in a session.
     */
    @Override
    protected void prepare() throws QueryException {
        if (prepareFromCachedQuery()) {
            return;
        }
        super.prepare();

        if ((this.selectionId != null) || (this.selectionObject != null)) {
            // The expression is set in the prepare as params.
            setSelectionCriteria(this.descriptor.getObjectBuilder().getPrimaryKeyExpression());
            setExpressionBuilder(getSelectionCriteria().getBuilder());
            extendPessimisticLockScope();
            // For bug 2989998 the translation row is required to be set at this point.
            if (!shouldPrepare()) {
                if (this.selectionId != null) {
                    // Row must come from the key.
                    setTranslationRow(this.descriptor.getObjectBuilder().buildRowFromPrimaryKeyValues(this.selectionId, this.session));
                } else {//(getSelectionObject() != null)
                    setTranslationRow(this.descriptor.getObjectBuilder().buildRowForTranslation(this.selectionObject, this.session));
                }
            }
        }

        if (this.descriptor.isDescriptorForInterface()) {
            return;
        }

        // PERF: Disable cache check if not a primary key query.
        if (isExpressionQuery()) {
            Expression selectionCriteria = getSelectionCriteria();
            if (selectionCriteria != null) {
                if (((this.cacheUsage == CheckCacheByPrimaryKey)
                                && (!this.descriptor.getObjectBuilder().isPrimaryKeyExpression(false, selectionCriteria, this.session)))
                        || ((this.cacheUsage == CheckCacheByExactPrimaryKey)
                                && (!this.descriptor.getObjectBuilder().isPrimaryKeyExpression(true, selectionCriteria, this.session)))) {
                    this.cacheUsage = DoNotCheckCache;
                }
            }
        }

        // If using 1-m joining select all rows.
        if ((this.joinedAttributeManager != null) && this.joinedAttributeManager.isToManyJoin()) {
            getQueryMechanism().prepareSelectAllRows();
        } else {
            getQueryMechanism().prepareSelectOneRow();
        }

        // should be called after prepareSelectRow so that the call knows whether it returns ResultSet
        prepareResultSetAccessOptimization();
    }

    /**
     * INTERNAL:
     * Set the properties needed to be cascaded into the custom query including the translation row.
     * This is used only for primary key queries, as the descriptor query manager
     * stores a predefined query for this query to avoid having to re-prepare and allow for customization.
     */
    @Override
    protected void prepareCustomQuery(DatabaseQuery customQuery) {
        super.prepareCustomQuery(customQuery);
        ReadObjectQuery customReadQuery = (ReadObjectQuery)customQuery;
        customReadQuery.shouldRefreshIdentityMapResult = this.shouldRefreshIdentityMapResult;
        customReadQuery.cascadePolicy = this.cascadePolicy;
        customReadQuery.shouldMaintainCache = this.shouldMaintainCache;
        customReadQuery.shouldUseWrapperPolicy = this.shouldUseWrapperPolicy;
        // CR... was missing some values, execution could cause infinite loop.
        customReadQuery.queryId = this.queryId;
        customReadQuery.executionTime = this.executionTime;
        customReadQuery.shouldLoadResultIntoSelectionObject = this.shouldLoadResultIntoSelectionObject;
        AbstractRecord primaryKeyRow;
        if (this.selectionObject != null) {
            // CR#... Must also set the selection object as may be loading into the object (refresh)
            customReadQuery.selectionObject = this.selectionObject;
            // The translation/primary key row will be set in prepareForExecution.
        } else if (this.selectionId != null) {
            customReadQuery.selectionId = this.selectionId;
        } else {
            // The primary key row must be used.
            primaryKeyRow = customQuery.getDescriptor().getObjectBuilder().extractPrimaryKeyRowFromExpression(getSelectionCriteria(), customQuery.getTranslationRow(), customReadQuery.getSession());
            customReadQuery.setTranslationRow(primaryKeyRow);
        }
    }

    /**
     * INTERNAL:
     * Prepare the receiver for execution in a session.
     */
    @Override
    public void prepareForExecution() throws QueryException {
        super.prepareForExecution();

        // For bug 2989998 the translation row now sometimes set earlier in prepare.
        if (shouldPrepare()) {
            if (this.selectionId != null) {
                // Row must come from the key.
                this.translationRow = this.descriptor.getObjectBuilder().buildRowFromPrimaryKeyValues(this.selectionId, getSession());
            } else if (this.selectionObject != null) {
                // The expression is set in the prepare as params.
                this.translationRow = this.descriptor.getObjectBuilder().buildRowForTranslation(this.selectionObject, getSession());
            }
        }

        // If we have tenant discriminator fields we need to add them to the
        // database row when doing a primary key query.
        // Modifying the translation row here will modify it on the original
        // query which is not good (will append the tenant field to the sql call
        // for subsequent queries) The translation row must be cloned to isolate
        // this.
        if (getDescriptor().hasMultitenantPolicy()) {
            this.translationRow = this.translationRow.clone();
            getDescriptor().getMultitenantPolicy().addFieldsToRow(this.translationRow, getSession());
        }
    }

    /**
     * INTERNAL:
     * Prepare the receiver for execution in a session.
     */
    @Override
    protected void prePrepare() throws QueryException {
        super.prePrepare();
        //Bug#3947714  In case getSelectionObject() is proxy
        if (getSelectionObject() != null && getSession().getProject().hasProxyIndirection()) {
            setSelectionObject(ProxyIndirectionPolicy.getValueFromProxy(getSelectionObject()));
        }
    }

    /**
     * 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
     */
    @Override
    public Object registerResultInUnitOfWork(Object result, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, boolean buildDirectlyFromRows) {
        if (result == null) {
            return null;
        }
        if (unitOfWork.hasCloneMapping() // PERF: Avoid conforming empty uow.
                && (shouldConformResultsInUnitOfWork() || this.descriptor.shouldAlwaysConformResultsInUnitOfWork())) {
            return conformResult(result, unitOfWork, arguments, buildDirectlyFromRows);
        }
        Object clone = null;
        if (buildDirectlyFromRows) {
            clone = buildObject((AbstractRecord)result);
        } else {
            clone = registerIndividualResult(result, null, unitOfWork, null, null);
        }

        if (shouldUseWrapperPolicy()) {
            clone = this.descriptor.getObjectBuilder().wrapObject(clone, unitOfWork);
        }
        return clone;
    }

    @Override
    protected Object remoteExecute() {
        // Do a cache lookup.
        checkDescriptor(session);
        // As the selection object is transient, compute the key.
        if (getSelectionObject() != null) {
            // Must be checked separately as the expression and row is not yet set.
            setSelectionId(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(getSelectionObject(), session));
        }

        Object cacheHit = checkEarlyReturn(getSession(), getTranslationRow());
        if ((cacheHit != null) || shouldCheckCacheOnly()) {
            if (cacheHit == InvalidObject.instance) {
                return null;
            }
            return cacheHit;
        }

        return super.remoteExecute();
    }

    /**
     * INTERNAL:
     * replace the value holders in the specified result object(s)
     */
    @Override
    public Map replaceValueHoldersIn(Object object, RemoteSessionController controller) {
        return controller.replaceValueHoldersIn(object);
    }

    /**
     * INTERNAL:
     * Return the primary key stored in this query
     *
     * @return the selection id of this ReadObjectQuery
     */
    @Override
    protected Object getQueryPrimaryKey(){
        return getSelectionId();
    }

    /**
     * PUBLIC:
     * Return Id of the object to be selected by the query.
     */
    public Object getSelectionId() {
        return this.selectionId;
    }

    /**
     * INTERNAL:
     * Clear the selection id and object.
     * This is done after cloning queries to prepare them in inheritance.
     */
    public void clearSelectionId() {
        this.selectionId = null;
        this.selectionObject = null;
    }

    /**
     * PUBLIC:
     * The Id of the object to be selected by the query.
     * This will generate a query by primary key.
     * This can be used instead of an Expression, SQL, or JPQL, or example object.
     * The Id is the Id value for a singleton primary key,
     * for a composite it is an instance of CacheId.
     * @see CacheId
     */
    public void setSelectionId(Object id) {
        this.selectionId = id;
    }

    /**
     * PUBLIC:
     * Used to set the where clause of the query.
     * This can be used instead of a where clause expression for single object primary key queries.
     * The selection object given should have a primary key defined,
     * this primary key will be used to query the database instance of the same object.
     * This is a basic form of query by example where only the primary key is required,
     * it can be used for simple query forms, or testing.
     */
    public void setSelectionObject(Object selectionObject) {
        if (selectionObject == null) {
            throw QueryException.selectionObjectCannotBeNull(this);
        }
        setSelectionId(null);
        // Check if the query needs to be unprepared.
        if ((this.selectionObject == null) || (this.selectionObject.getClass() != selectionObject.getClass())) {
            setIsPrepared(false);
        }
        setReferenceClass(selectionObject.getClass());
        this.selectionObject = selectionObject;
    }

    /**
     * PUBLIC:
     * Allow for the selection object of the query to be refreshed or put into the EclipseLink cache.
     * By default on a read or refresh the object in the cache is refreshed and returned or a new object is built from the database,
     * in some cases such as EJB BMP it is desirable to refresh or load into the object passed into the read object query.
     * <p>Note: This forces the selection object into the cache a replaces any existing object that may already be there,
     * this is a strict violation of object identity and other objects can still be referring to the old object.
     */
    public void setShouldLoadResultIntoSelectionObject(boolean shouldLoadResultIntoSelectionObject) {
        this.shouldLoadResultIntoSelectionObject = shouldLoadResultIntoSelectionObject;
    }

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

    /**
     * PUBLIC:
     * Return if cache should be checked.
     */
    public boolean shouldCheckCacheByPrimaryKey() {
        return (this.cacheUsage == CheckCacheByPrimaryKey) || (this.cacheUsage == UseDescriptorSetting);
    }

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

    /**
     * PUBLIC:
     * return true if the result should be loaded into the passed in selection Object
     */
    public boolean shouldLoadResultIntoSelectionObject() {
        return shouldLoadResultIntoSelectionObject;
    }

    /**
     * INTERNAL:
     * Return if the query has an non-default fetch group defined for itself.
     */
    protected boolean hasNonDefaultFetchGroup() {
        return this.descriptor.hasFetchGroupManager() && ((this.fetchGroup != null) || (this.fetchGroupName != null)
                || (!this.shouldUseDefaultFetchGroup && (this.descriptor.getFetchGroupManager().getDefaultFetchGroup() != null)));

    }
}
