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

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     Zoltan NAGY & tware - updated support for MaxRows
//     11/01/2010-2.2 Guy Pelletier
//       - 322916: getParameter on Query throws NPE
//     11/09/2010-2.1 Michael O'Brien
//       - 329089: PERF: EJBQueryImpl.setParamenterInternal() move indexOf check inside non-native block
//     02/08/2012-2.4 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     06/20/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     08/24/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     11/05/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     08/11/2012-2.5 Guy Pelletier
//       - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.
package org.eclipse.persistence.internal.jpa;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.LockTimeoutException;
import jakarta.persistence.NoResultException;
import jakarta.persistence.NonUniqueResultException;
import jakarta.persistence.Parameter;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.PessimisticLockException;
import jakarta.persistence.Query;
import jakarta.persistence.QueryTimeoutException;
import jakarta.persistence.TemporalType;
import jakarta.persistence.TransactionRequiredException;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.internal.helper.BasicTypeHelperImpl;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.jpa.querydef.ParameterExpressionImpl;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLargument;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DataModifyQuery;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DatabaseQuery.ParameterType;
import org.eclipse.persistence.queries.ModifyQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Session;

/**
 * Concrete JPA query class. The JPA query wraps a DatabaseQuery which is
 * executed.
 */
public class QueryImpl {

    public static final int UNDEFINED = -1;

    /**
     * Wrapped native query. The query may be {@link #isShared}
     */
    protected DatabaseQuery databaseQuery = null;

    protected EntityManagerImpl entityManager = null;
    protected String queryName = null;
    protected Map<String, Object> parameterValues = null;
    protected Map<String, Parameter<?>> parameters;
    protected int firstResultIndex = UNDEFINED;
    protected int maxResults = UNDEFINED;

    protected LockModeType lockMode = null;

    /**
     * Stores if the wrapped query is shared, and requires cloning before being
     * changed.
     */
    protected boolean isShared;

    /**
     * Base constructor for EJBQueryImpl. Initializes basic variables.
     */
    protected QueryImpl(EntityManagerImpl entityManager) {
        this.parameterValues = new HashMap<String, Object>();
        this.entityManager = entityManager;
        this.isShared = true;
    }

    /**
     * Create an EJBQueryImpl with a DatabaseQuery.
     */
    public QueryImpl(DatabaseQuery query, EntityManagerImpl entityManager) {
        this(entityManager);
        this.databaseQuery = query;
    }

    /**
     * This method should be called to close any left over open connection to
     * the database (if there is one).
     */
    public void close() {
        // Currently nothing to do at this level. Connections are not left open.
    }

    /**
     * INTERNAL:
     * Change the internal query to data modify query.
     */
    protected void setAsDataModifyQuery() {
        DataModifyQuery query = new DataModifyQuery();
        query.setIsUserDefined(this.databaseQuery.isUserDefined());
        // By default, do not batch user native queries, as row count must be returned.
        query.setIsBatchExecutionSupported(false);
        query.copyFromQuery(this.databaseQuery);
        // Need to clone call, in case was executed as read.
        query.setDatasourceCall((Call) this.databaseQuery.getDatasourceCall().clone());
        this.databaseQuery = query;
    }

    /**
     * Internal method to change the wrapped query to a DataModifyQuery if
     * necessary. When created, the query is created as a DataReadQuery as it is
     * unknown if it is a SELECT or UPDATE. Note that this prevents the original
     * named query from every being prepared.
     */
    protected void setAsSQLModifyQuery() {
        if (getDatabaseQueryInternal().isDataReadQuery()) {
            setAsDataModifyQuery();
        }
    }

    /**
     * Internal method to change the wrapped query to a DataReadQuery if
     * necessary. This should never occur, but could possibly if the same query
     * was executed as executeUpdate() then as getResultList(). Note that the
     * initial conversion to modify would loose any read settings that had been
     * set.
     */
    protected void setAsSQLReadQuery() {
        if (getDatabaseQueryInternal().isDataModifyQuery()) {
            DataReadQuery query = new DataReadQuery();
            query.setResultType(DataReadQuery.AUTO);
            query.setIsUserDefined(databaseQuery.isUserDefined());
            query.copyFromQuery(this.databaseQuery);
            this.databaseQuery = query;
        }
    }

    /**
     * Execute a ReadQuery by assigning the stored parameter values and running
     * it in the database
     *
     * @return the results of the query execution
     */
    protected Object executeReadQuery() {
        List<Object> parameterValues = processParameters();
        // TODO: the following performFlush() call is a temporary workaround for
        // bug 4752493:
        // CTS: INMEMORY QUERYING IN EJBQUERY BROKEN DUE TO CHANGE TO USE
        // REPORTQUERY.
        // Ideally we should only flush in case the selectionExpression can't be
        // conformed in memory.
        // There are two alternative ways to implement that:
        // 1. Try running the query with conformInUOW flag first - if it fails
        // with
        // QueryException.cannotConformExpression then flush and run the query
        // again -
        // now without conforming.
        // 2. Implement a new isComformable method on Expression which would
        // determine whether the expression
        // could be conformed in memory, flush only in case it returns false.
        // Note that doesConform method currently implemented on Expression
        // requires object(s) to be confirmed as parameter(s).
        // The new isComformable method should not take any objects as
        // parameters,
        // it should return false if there could be such an object that
        // passed to doesConform causes it to throw
        // QueryException.cannotConformExpression -
        // and true otherwise.
        boolean shouldResetConformResultsInUnitOfWork = false;
        DatabaseQuery query = getDatabaseQueryInternal();
        boolean isObjectLevelReadQuery = query.isObjectLevelReadQuery();
        if (isFlushModeAUTO() && (!isObjectLevelReadQuery || !((ObjectLevelReadQuery)query).isReadOnly())) {
            performPreQueryFlush();
            if (isObjectLevelReadQuery) {
                if (((ObjectLevelReadQuery)query).shouldConformResultsInUnitOfWork()) {
                    cloneSharedQuery();
                    query = getDatabaseQueryInternal();
                    ((ObjectLevelReadQuery)query).setCacheUsage(ObjectLevelReadQuery.UseDescriptorSetting);
                    shouldResetConformResultsInUnitOfWork = true;
                }
            }
        }

        // Set a pessimistic locking on the query if specified.
        if (this.lockMode != null && !this.lockMode.equals(LockModeType.NONE)) {
            // We need to throw TransactionRequiredException if there is no
            // active transaction
            this.entityManager.checkForTransaction(true);

            // The lock mode setters and getters validate the query type
            // so should be safe to make the casting.
            cloneSharedQuery();
            query = getDatabaseQueryInternal();

            // Set the lock mode (the session is passed in to do some validation
            // checks)
            // If the return value from the set returns true, it indicates that
            // we were unable to set the lock mode.
            if (((ObjectLevelReadQuery)query).setLockModeType(lockMode.name(), (AbstractSession) getActiveSession())) {
                throw new PersistenceException(ExceptionLocalization.buildMessage("ejb30-wrong-lock_called_without_version_locking-index", null));
            }
        }

        Session session = getActiveSession();
        try {
            // in case it's a user-defined query
            if (query.isUserDefined()) {
                // and there is an active transaction
                if (this.entityManager.checkForTransaction(false) != null) {
                    // verify whether uow has begun early transaction
                    if (session.isUnitOfWork() && !((UnitOfWorkImpl)session).wasTransactionBegunPrematurely()) {
                        // uow begins early transaction in case it hasn't
                        // already begun.
                        // TODO: This is not good, it means that no SQL queries
                        // can ever use the cache,
                        // using isUserDefined to mean an SQL query is also
                        // wrong.
                        ((UnitOfWorkImpl)session).beginEarlyTransaction();
                    }
                }
            }

            // Execute the query and return the result.
            return session.executeQuery(query, parameterValues);
        } catch (DatabaseException e) {
            throw getDetailedException(e);
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        } finally {
            this.lockMode = null;

            if (shouldResetConformResultsInUnitOfWork) {
                ((ObjectLevelReadQuery)query).conformResultsInUnitOfWork();
            }
        }
    }

    /**
     * Execute an update or delete statement.
     *
     * @return the number of entities updated or deleted
     */
    public int executeUpdate() {
        // bug51411440: need to throw IllegalStateException if query
        // executed on closed em
        this.entityManager.verifyOpenWithSetRollbackOnly();
        try {
            setAsSQLModifyQuery();
            // bug:4294241, only allow modify queries - UpdateAllQuery preferred
            if (!(getDatabaseQueryInternal() instanceof ModifyQuery)) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_execute_update"));
            }

            // need to throw TransactionRequiredException if there is no active
            // transaction
            entityManager.checkForTransaction(true);

            // fix for bug:4288845, did not add the parameters to the query
            List<Object> parameterValues = processParameters();
            if (isFlushModeAUTO()) {
                performPreQueryFlush();
            }
            Integer changedRows = (Integer) getActiveSession().executeQuery(databaseQuery, parameterValues);
            return changedRows;
        } catch (PersistenceException exception) {
            setRollbackOnly();
            throw exception;
        } catch (IllegalStateException exception) {
            setRollbackOnly();
            throw exception;
        }catch (RuntimeException exception) {
            setRollbackOnly();
            throw new PersistenceException(exception);
        }
    }

    /**
     * Return the wrapped {@link DatabaseQuery} ensuring that if it
     * {@link #isShared} it is cloned before returning to prevent corruption of
     * the query cache.
     *
     * @see #getDatabaseQueryInternal()
     */
    public DatabaseQuery getDatabaseQuery() {
        cloneSharedQuery();
        return getDatabaseQueryInternal();
    }

    /**
     * INTERNAL: Return the cached database query for this EJBQueryImpl. If the
     * query is a named query and it has not yet been looked up, the query will
     * be looked up and stored as the cached query.
     */
    public DatabaseQuery getDatabaseQueryInternal() {
        if ((this.queryName != null) && (this.databaseQuery == null)) {
            // Always ask for the query from the active session. Table per
            // tenant multitenant entity queries may be isolated per EM meaning
            // those queries will not have been initialized (and made available)
            // from their parent session.
            this.databaseQuery = this.entityManager.getActiveSessionIfExists().getQuery(this.queryName);
            // need error checking and appropriate exception for non-existing query
            if (this.databaseQuery != null) {
                if (!this.databaseQuery.isPrepared()) {
                    // prepare the query before cloning, this ensures we do not
                    // have to continually prepare on each usage
                    try {
                        this.databaseQuery.checkPrepare(this.entityManager.getActiveSessionIfExists(), new DatabaseRecord());
                    } catch(RuntimeException re){
                        throw new IllegalArgumentException(re);
                    }
                }
                if (this.databaseQuery.isObjectLevelReadQuery() && ((ObjectLevelReadQuery)this.databaseQuery).getLockModeType() != null){
                    this.lockMode = LockModeType.valueOf(((ObjectLevelReadQuery)this.databaseQuery).getLockModeType());
                }
                if (this.databaseQuery.isReadQuery()){
                    this.maxResults = ((ReadQuery)this.databaseQuery).getInternalMax();
                    // Bug 501272
                    // Do not reset a Query's uninitialized first result index, unless the parameter is greater than 0 (default for ReadQuery).
                    int queryFirstResult = ((ReadQuery)this.databaseQuery).getFirstResult();
                    if ((this.firstResultIndex != UNDEFINED) || (this.firstResultIndex == UNDEFINED && queryFirstResult > 0)) {
                        this.firstResultIndex = queryFirstResult;
                    }
                }
            } else {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("unable_to_find_named_query", new Object[] { this.queryName }));
            }

        }

        return this.databaseQuery;
    }

    /**
     * Given a DatabaseException, this method will determine if we should
     * throw a different more specific exception like a lock timeout exception.
     */
    protected RuntimeException getDetailedException(DatabaseException e) {
        // If we catch a database exception as a result of executing a
        // pessimistic locking query we need to ask the platform which
        // JPA 2.0 locking exception we should throw. It will be either
        // be a PessimisticLockException or a LockTimeoutException (if
        // the query was executed using a wait timeout value)
        if (this.lockMode != null && this.lockMode.name().contains(ObjectLevelReadQuery.PESSIMISTIC_)) {
            // ask the platform if it is a lock timeout
            if (getActiveSession().getPlatform().isLockTimeoutException(e)) {
                return new LockTimeoutException(e);
            } else {
                return new PessimisticLockException(e);
            }
        } else {
            setRollbackOnly();
            return new PersistenceException(e);
        }
    }

    /**
     * Return the entityManager this query is tied to.
     */
    public JpaEntityManager getEntityManager() {
        return entityManager;
    }

    /**
     * Return the internal map of parameters.
     */
    protected Map<String, Parameter<?>> getInternalParameters() {
        if (this.parameters == null) {
            this.parameters = new HashMap<String, Parameter<?>>();
            DatabaseQuery query = getDatabaseQueryInternal(); // Retrieve named
                                                              // query
            int count = 0;
            if (query.getArguments() != null && !query.getArguments().isEmpty()) {
                boolean checkParameterType = query.getArgumentParameterTypes().size() == query.getArguments().size();
                for (String argName : query.getArguments()) {
                    Parameter<?> param = null;
                    ParameterType type = null;
                    if (checkParameterType){
                        type = query.getArgumentParameterTypes().get(count);
                    }
                    if (type == ParameterType.POSITIONAL){
                        Integer position = Integer.parseInt(argName);
                        param = new ParameterExpressionImpl(null, query.getArgumentTypes().get(count), position);
                    } else {
                        param = new ParameterExpressionImpl(null, query.getArgumentTypes().get(count), argName);
                    }
                    this.parameters.put(argName, param);
                    ++count;
                }
            }

        }

        return this.parameters;
    }

    /**
     * Get the current lock mode for the query.
     *
     * @return lock mode
     * @throws IllegalStateException
     *             if not a Java Persistence query language SELECT query
     */
    public LockModeType getLockMode() {
        entityManager.verifyOpen();

        if (!getDatabaseQueryInternal().isObjectLevelReadQuery()) {
            throw new IllegalStateException(ExceptionLocalization.buildMessage("invalid_lock_query", null));
        }

        return this.lockMode;
    }

    /**
     * Execute the query and return the query results as a List.
     *
     * @return a list of the results
     */
    public List getResultList() {
        // bug51411440: need to throw IllegalStateException if query
        // executed on closed em
        this.entityManager.verifyOpenWithSetRollbackOnly();
        try {
            setAsSQLReadQuery();
            propagateResultProperties();
            // bug:4297903, check container policy class and throw exception if
            // its not the right type
            DatabaseQuery query = getDatabaseQueryInternal();
            if (query.isReadAllQuery()) {
                Class containerClass = ((ReadAllQuery) query).getContainerPolicy().getContainerClass();
                if (!Helper.classImplementsInterface(containerClass, ClassConstants.List_Class)) {
                    throw QueryException.invalidContainerClass(containerClass, ClassConstants.List_Class);
                }
            } else if (query.isReadObjectQuery()) {
                List<Object> resultList = new ArrayList<>();
                Object result = executeReadQuery();
                if (result != null) {
                    resultList.add(result);
                }
                return resultList;
            } else if (!query.isReadQuery()) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_result_list"));
            }
            return (List) executeReadQuery();
        } catch (LockTimeoutException exception) {
            throw exception;
        } catch (PersistenceException exception) {
            setRollbackOnly();
            throw exception;
        } catch (IllegalStateException exception) {
            setRollbackOnly();
            throw exception;
        } catch (RuntimeException exception) {
            setRollbackOnly();
            throw new PersistenceException(exception);
        }
    }

    /**
     * Execute a SELECT query that returns a single untyped result.
     *
     * @return the result
     * @throws NoResultException if there is no result
     * @throws NonUniqueResultException if more than one result
     * @throws IllegalStateException if called for a Java Persistence query
     *         language UPDATE or DELETE statement
     * @throws QueryTimeoutException if the query execution exceeds the query
     *         timeout value set and only the statement is rolled back
     * @throws TransactionRequiredException if a lock mode other than NONE has
     *         been been set and there is no transaction or the persistence
     *         context has not been joined to the transaction
     * @throws PessimisticLockException if pessimistic locking fails and the
     *         transaction is rolled back
     * @throws LockTimeoutException if pessimistic locking fails and only the
     *         statement is rolled back
     * @throws PersistenceException if the query execution exceeds the query
     *         timeout value set and the transaction is rolled back
     */
    public Object getSingleResult() {
        boolean rollbackOnException = true;
        // bug51411440: need to throw IllegalStateException if query
        // executed on closed em
        this.entityManager.verifyOpenWithSetRollbackOnly();
        try {
            setAsSQLReadQuery();
            propagateResultProperties();
            // This API is used to return non-List results, so no other validation is done.
            // It could be Cursor or other Collection or Map type.
            if (!(getDatabaseQueryInternal().isReadQuery())) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_single_result"));
            }
            Object result = executeReadQuery();
            if (result instanceof List) {
                List results = (List) result;
                if (results.isEmpty()) {
                    rollbackOnException = false;
                    throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
                } else if (results.size() > 1) {
                    rollbackOnException = false;
                    throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", null));
                }
                return results.get(0);
            } else {
                if (result == null) {
                    rollbackOnException = false;
                    throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
                }
                return result;
            }
        } catch (LockTimeoutException exception) {
            throw exception;
        } catch (PersistenceException exception) {
            if (rollbackOnException) {
                setRollbackOnly();
            }
            throw exception;
        } catch (IllegalStateException exception) {
            setRollbackOnly();
            throw exception;
        } catch (RuntimeException exception) {
            setRollbackOnly();
            throw new PersistenceException(exception);
        }
    }

    /**
     * Internal method to add the parameters values to the query prior to
     * execution. Returns a list of parameter values in the order the parameters
     * are defined for the databaseQuery.
     */
    protected List<Object> processParameters() {
        DatabaseQuery query = getDatabaseQueryInternal();
        List<String> arguments = query.getArguments();
        if (arguments.isEmpty()) {
            // This occurs for native queries, as the query does not know of its arguments.
            // This may have issues, it is better if the query set its arguments
            // when parsing the SQL.

            arguments = new ArrayList<>(this.parameterValues.keySet());
            query.setArguments(arguments);
        }
        // now create parameterValues in the same order as the argument list
        int size = arguments.size();
        List<Object> parameterValues = new ArrayList<Object>(size);
        for (int index = 0; index < size; index++) {
            String name = arguments.get(index);
            Object parameter = this.parameterValues.get(name);
            if ((parameter != null) || this.parameterValues.containsKey(name)) {
                parameterValues.add(parameter);
            } else if (query.hasNullableArguments() && query.getNullableArguments().contains(new DatabaseField(name))) {
                parameterValues.add(null);
            } else {
                // Error: missing actual parameter value
                throw new IllegalStateException(ExceptionLocalization.buildMessage("missing_parameter_value", new Object[] { name }));
            }
        }
        return parameterValues;
    }

    /**
     * Replace the cached query with the given query.
     */
    public void setDatabaseQuery(DatabaseQuery query) {
        databaseQuery = query;
    }

    /**
     * Set the position of the first result to retrieve.
     *
     * @param startPosition
     *            position of the first result, numbered from 0
     * @return the same query instance
     */
    public QueryImpl setFirstResult(int startPosition) {
        try {
            entityManager.verifyOpen();
            setFirstResultInternal(startPosition);
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * @see jakarta.persistence.Query#getFirstResult()
     * @since Java Persistence API 2.0
     */
    public int getFirstResult() {
        entityManager.verifyOpenWithSetRollbackOnly();
        if (this.firstResultIndex == UNDEFINED) {
            return 0;
        }
        return this.firstResultIndex;
    }

    /**
     * Set the flush mode type to be used for the query execution.
     *
     * @param flushMode
     */
    public QueryImpl setFlushMode(FlushModeType flushMode) {
        try {
            entityManager.verifyOpen();
            if (flushMode == null) {
                getDatabaseQueryInternal().setFlushOnExecute(null);
            } else {
                cloneSharedQuery();
                getDatabaseQueryInternal().setFlushOnExecute(flushMode == FlushModeType.AUTO);
            }
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * Set the position of the first result to retrieve.
     *
     * @param startPosition
     *            position of the first result, numbered from 0.
     */
    protected void setFirstResultInternal(int startPosition) {
        if (startPosition < 0) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("negative_start_position", null));
        }
        // bug 362804
        firstResultIndex = startPosition;
    }

    /**
     * Define the query arguments based on the procedure call.
     */
    protected static void applyArguments(StoredProcedureCall call, DatabaseQuery query) {
        if (call instanceof PLSQLStoredProcedureCall) {
            PLSQLStoredProcedureCall plsqlCall = (PLSQLStoredProcedureCall)call;
            for (int index = 0; index < plsqlCall.getArguments().size(); index++) {
                PLSQLargument argument = plsqlCall.getArguments().get(index);
                int type = argument.direction;
                if ((type == StoredProcedureCall.IN) || (type == StoredProcedureCall.INOUT)) {
                    if (call.hasOptionalArguments()) {
                        query.addArgument(argument.name, Object.class, call.getOptionalArguments().contains(new DatabaseField(argument.name)));
                    } else {
                        query.addArgument(argument.name);
                    }
                }
            }
        } else {
            for (int index = 0; index < call.getParameters().size(); index++) {
                int type = call.getParameterTypes().get(index);
                if ((type == StoredProcedureCall.IN) || (type == StoredProcedureCall.INOUT)) {
                    Object value = call.getParameters().get(index);
                    DatabaseField parameter = null;
                    if (value instanceof Object[]) {
                        parameter = (DatabaseField) ((Object[])value)[0];
                    } else {
                        parameter = (DatabaseField)call.getParameters().get(index);
                    }
                    if (call.hasOptionalArguments()) {
                        query.addArgument(parameter.getName(), Object.class, call.getOptionalArguments().contains(parameter));
                    } else {
                        query.addArgument(parameter.getName());
                    }
                }
            }
        }
    }

    /**
     * Set implementation-specific hints.
     *
     * @param hints
     *            a list of hints to be applied to the query
     * @param query
     *            the query to apply the hints to
     */
    protected static DatabaseQuery applyHints(Map<String, Object> hints, DatabaseQuery query, ClassLoader classLoader, AbstractSession session) {
        return QueryHintsHandler.apply(hints, query, classLoader, session);
    }


    /**
     * Return the identifier of this parameter.  This will be the name if it is set, else it will be the position
     * @param param
     * @return
     */
    public static String getParameterId(Parameter param){
        Integer id= param.getPosition();
        if (id == null ){
            return String.valueOf(((ParameterExpressionImpl)param).getInternalName());
        }
        return String.valueOf(id);
    }

    /**
     * Return a boolean indicating whether a value has been bound to the
     * parameter.
     *
     * @param param
     *            parameter object
     * @return boolean indicating whether parameter has been bound
     */
    public boolean isBound(Parameter<?> param) {
        entityManager.verifyOpenWithSetRollbackOnly();
        if (param == null)
            return false;
        return this.parameterValues.containsKey(getParameterId(param));
    }

    /**
     * Spec. 3.5.2: "FlushMode.AUTO is set on the Query object, or if the flush
     * mode setting for the persistence context is AUTO (the default) and a
     * flush mode setting has not been specified for the Query object, the
     * persistence provider is responsible for ensuring that all updates to the
     * state of all entities in the persistence context which could potentially
     * affect the result of the query are visible to the processing of the
     * query."
     */
    protected boolean isFlushModeAUTO() {
        if (getDatabaseQueryInternal().getFlushOnExecute() != null) {
            return getDatabaseQueryInternal().getFlushOnExecute();
        } else {
            return entityManager.isFlushModeAUTO();
        }
    }

    /**
     * Set an implementation-specific hint. If the hint name is not recognized,
     * it is silently ignored.
     *
     * @throws IllegalArgumentException
     *             if the second argument is not valid for the implementation.
     */
    protected void setHintInternal(String hintName, Object value) {
        cloneSharedQuery();
        ClassLoader loader = getEntityManager().getAbstractSession().getLoader();
        DatabaseQuery hintQuery = QueryHintsHandler.apply(hintName, value, getDatabaseQueryInternal(), loader, (AbstractSession) getActiveSession());
        if (hintQuery != null) {
            setDatabaseQuery(hintQuery);
        }
    }

    /**
     * Set the lock mode type to be used for the query execution.
     *
     * @param lockMode
     * @throws IllegalStateException
     *             if not a Java Persistence query language SELECT query
     */
    public QueryImpl setLockMode(LockModeType lockMode) {
        try {
            entityManager.verifyOpen();

            if (!getDatabaseQueryInternal().isObjectLevelReadQuery()) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("invalid_lock_query", null));
            }

            this.lockMode = lockMode;
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * If the query was from the jpql parse cache it must be cloned before being
     * modified.
     */
    protected void cloneSharedQuery() {
        DatabaseQuery query = getDatabaseQueryInternal();
        if (this.isShared) {
            // Clone to allow setting of hints or other properties without
            // corrupting original query.
            query = (DatabaseQuery) databaseQuery.clone();
            setDatabaseQuery(query);
            this.isShared = false;
        }
    }

    /**
     * Convert the given object to the class represented by the given temporal
     * type.
     *
     * @return an object representing the given TemporalType.
     */
    protected Object convertTemporalType(Object value, TemporalType type) {
        ConversionManager conversionManager = getEntityManager().getActiveSession().getDatasourcePlatform().getConversionManager();
        if (type == TemporalType.TIME) {
            return conversionManager.convertObject(value, ClassConstants.TIME);
        } else if (type == TemporalType.TIMESTAMP) {
            return conversionManager.convertObject(value, ClassConstants.TIMESTAMP);
        } else if (type == TemporalType.DATE) {
            return conversionManager.convertObject(value, ClassConstants.SQLDATE);
        }
        return value;
    }

    /**
     * Set the maximum number of results to retrieve.
     *
     * @param maxResult
     * @return the same query instance
     */
    public QueryImpl setMaxResults(int maxResult) {
        try {
            entityManager.verifyOpen();
            setMaxResultsInternal(maxResult);
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * @see jakarta.persistence.Query#getMaxResults()
     * @since Java Persistence API 2.0
     */
    public int getMaxResults() {
        entityManager.verifyOpenWithSetRollbackOnly();
        if (this.maxResults == UNDEFINED) {
            return Integer.MAX_VALUE;
        }
        return this.maxResults;
    }

    /**
     * @see jakarta.persistence.Query#getMaxResults()
     * @since Java Persistence API 2.0
     */
    public int getMaxResultsInternal() {
        return this.maxResults;
    }

    /**
     * Set the maximum number of results to retrieve.
     *
     * @param maxResult
     */
    public void setMaxResultsInternal(int maxResult) {
        if (maxResult < 0) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("negative_max_result", null));
        }
        if (maxResult == Integer.MAX_VALUE) {
            this.maxResults = UNDEFINED;
        } else {
            this.maxResults = maxResult;
        }
    }

    /**
     * Configure the firstResult, maxRows and lock mode in the EclipseLink
     * ReadQuery.
     */
    protected void propagateResultProperties() {
        DatabaseQuery databaseQuery = getDatabaseQueryInternal();
        if (databaseQuery.isReadQuery()) {
            ReadQuery readQuery = (ReadQuery) databaseQuery;
            if (maxResults >= 0) {
                cloneSharedQuery();
                readQuery = (ReadQuery) getDatabaseQueryInternal();
                int maxRows = maxResults + ((firstResultIndex >= 0) ? firstResultIndex : 0);
                readQuery.setMaxRows(maxRows);
            }
            if (firstResultIndex > UNDEFINED) {
                cloneSharedQuery();
                readQuery = (ReadQuery) getDatabaseQueryInternal();
                readQuery.setFirstResult(firstResultIndex);
            }
        }
    }

    /**
     * Bind an argument to a positional parameter.
     *
     * @param position
     * @param value
     */
    protected void setParameterInternal(int position, Object value) {
        setParameterInternal(String.valueOf(position), value, true);
    }

    /**
     * Bind an argument to a named or indexed parameter.
     *
     * @param name
     *            the parameter name
     * @param value
     *            to bind
     * @param isIndex
     *            defines if index or named
     */
    protected void setParameterInternal(String name, Object value, boolean isIndex) {
        DatabaseQuery query = getDatabaseQueryInternal();
        if (query.getQueryMechanism().isJPQLCallQueryMechanism()) { // only non native queries
            int index = query.getArguments().indexOf(name);
            if (index == -1) {
                if (isIndex) {
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-index", new Object[] { name, query.getEJBQLString() }));
                } else {
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-name", new Object[] { name, query.getEJBQLString() }));
                }
            }
            Class type = query.getArgumentTypes().get(index);
            if (!isValidActualParameter(value, type)) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-incorrect-parameter-type", new Object[] { name, value.getClass(), query.getArgumentTypes().get(index), query.getEJBQLString() }));
            }
        } else {
            // native queries start a 1 not 0.
            if (isIndex && name.equals("0")) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-index", new Object[] { name, query.getSQLString() }));
            }
        }
        this.parameterValues.put(name, value);
    }

    protected boolean isValidActualParameter(Object value, Class parameterType) {
        if (value == null) {
            return true;
        } else {
            return BasicTypeHelperImpl.getInstance().isAssignableFrom(parameterType, value.getClass());
        }
    }

    protected Session getActiveSession() {
        DatabaseQuery query = getDatabaseQueryInternal();
        // PERF: If read-only query, avoid creating unit of work and JTA transaction.
        if (query.isObjectLevelReadQuery() && ((ObjectLevelReadQuery) query).isReadOnly()) {
            return this.entityManager.getReadOnlySession();
        }
        return this.entityManager.getActiveSession();
    }

    protected void performPreQueryFlush() {
        if (this.entityManager.shouldFlushBeforeQuery()) {
            this.entityManager.flush();
        }
    }

    protected void setRollbackOnly() {
        entityManager.setRollbackOnly();
    }

    protected void throwNoResultException(String message) {
        throw new NoResultException(message);
    }

    protected void throwNonUniqueResultException(String message) {
        throw new NonUniqueResultException(message);
    }

    /**
     * @see Query#getFlushMode()
     * @since Java Persistence 2.0
     */
    public FlushModeType getFlushMode() {
        try {
            entityManager.verifyOpen();
            Boolean flushOnExecute = getDatabaseQueryInternal().getFlushOnExecute();
            if ((flushOnExecute == null) || flushOnExecute)
                return FlushModeType.AUTO;
            return FlushModeType.COMMIT;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * @see Query#getHints()
     * @since Java Persistence 2.0
     */
    public Map<String, Object> getHints() {
        entityManager.verifyOpenWithSetRollbackOnly();
        return (Map<String, Object>) getDatabaseQueryInternal().getProperty(QueryHintsHandler.QUERY_HINT_PROPERTY);
    }

    /**
     * @see Query#getParameter(String, Class)
     * @since Java Persistence 2.0
     */
    public <T> Parameter<T> getParameter(String name, Class<T> type) {
        //don't rollback transaction on error
        entityManager.verifyOpen();
        Parameter param = getInternalParameters().get(name);
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { name, this.databaseQuery }));
        } else if (param.getParameterType() != null && type != null && !type.isAssignableFrom(param.getParameterType())){
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { name, type }));
        }
        return param;
    }

    /**
     * @see Query#getParameter(int, Class)
     * @since Java Persistence 2.0
     */
    public <T> Parameter<T> getParameter(int position, Class<T> type) {
        //don't rollback transaction on error
        entityManager.verifyOpen();
        Parameter param = getInternalParameters().get(String.valueOf(position));
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_INDEX", new Object[] { position, this.databaseQuery }));
        } else if (param.getParameterType() != null && type != null && !type.isAssignableFrom(param.getParameterType())){
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { position, type }));
        }
        return param;
    }

    /**
     * @see Query#getParameter(String, Class)
     * @since Java Persistence 2.0
     */
    public Parameter<?> getParameter(String name) {
        //don't rollback transaction on error
        entityManager.verifyOpen();
        Parameter<?> param = getInternalParameters().get(name);
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { name, this.databaseQuery }));
        }
        return param;
    }

    /**
     * @see Query#getParameter(int, Class)
     * @since Java Persistence 2.0
     */
    public Parameter<?> getParameter(int position) {
        //don't rollback transaction on error
        entityManager.verifyOpen();
        Parameter<?> param = getInternalParameters().get(String.valueOf(position));
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_INDEX", new Object[] { position, this.databaseQuery }));
        }
        return param;
    }

    /**
     * @see Query#getParameterValue(Parameter)
     * @since Java Persistence 2.0
     */
    public <T> T getParameterValue(Parameter<T> param) {
        if (param == null)
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("PARAMETER_NILL_NOT_FOUND"));

        ParameterExpressionImpl<T> parameter = (ParameterExpressionImpl<T>) this.getInternalParameters().get(getParameterId(param));
        if (parameter == null || !parameter.getParameterType().equals(param.getParameterType())) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { param.toString(), this.databaseQuery }));
        }

        return (T) this.getParameterValue(getParameterId(param));
    }

    /**
     * Return the value bound to the named parameter.
     *
     * @param name
     * @return parameter value
     * @throws IllegalStateException
     *             if the parameter has not been been bound
     */
    public Object getParameterValue(String name) {
        entityManager.verifyOpen();//don't rollback transaction
        if (!getInternalParameters().containsKey(name)) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { name, this.databaseQuery }));
        }
        if (!this.parameterValues.containsKey(name)) { // must check for
            // key. get() would
            // return negative
            // for value == null.
            throw new IllegalStateException(ExceptionLocalization.buildMessage("NO_VALUE_BOUND", new Object[] { name }));
        }
        return this.parameterValues.get(name);
    }

    /**
     * Return the value bound to the positional parameter.
     *
     * @param position
     * @return parameter value
     * @throws IllegalStateException
     *             if the parameter has not been been bound
     */
    public Object getParameterValue(int position) {
        entityManager.verifyOpen();//don't rollback transaction
        String param = String.valueOf(position);

        if (!getInternalParameters().containsKey(param)) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("position_param_not_found", new Object[] { position }));
        }

        if (!this.parameterValues.containsKey(param)) {
            throw new IllegalStateException(ExceptionLocalization.buildMessage("position_bound_param_not_found", new Object[] { position }));
        }

        return this.parameterValues.get(param);
    }

    /**
     * @see Query#getParameters()
     * @since Java Persistence 2.0
     */
    public Set<Parameter<?>> getParameters() {
        entityManager.verifyOpen();//don't rollback transaction
        return new HashSet<>(getInternalParameters().values());
    }

    /**
     * @since Java Persistence 2.0
     */
    public Set<String> getSupportedHints() {
        return QueryHintsHandler.getSupportedHints();
    }

    /**
     * Unwrap the query into the JPA implementation classes/interfaces or the
     * underlying native EclipseLink query.
     *
     * @see Query#unwrap(Class)
     * @since Java Persistence 2.0
     */
    public <T> T unwrap(Class<T> cls) {
        if (cls.isAssignableFrom(this.getClass())) {
            // unwraps any proxy to Query, JPAQuery or EJBQueryImpl
            return (T) this;
        }
        if (cls.isAssignableFrom(getDatabaseQueryInternal().getClass())) {
            return (T) getDatabaseQueryInternal();
        }

        throw new PersistenceException(ExceptionLocalization.buildMessage("unable_to_unwrap_jpa", new String[]{Query.class.getName(), cls.getName()}));
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "(" + this.databaseQuery + ")";
    }
}

