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

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     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
//     07/13/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     08/24/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     09/13/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     09/27/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
package org.eclipse.persistence.internal.jpa;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType;
import jakarta.persistence.LockTimeoutException;
import jakarta.persistence.Parameter;
import jakarta.persistence.ParameterMode;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.QueryTimeoutException;
import jakarta.persistence.StoredProcedureQuery;
import jakarta.persistence.TemporalType;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.internal.databaseaccess.*;
import org.eclipse.persistence.internal.helper.DatabaseField;
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.logging.SessionLog;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ResultSetMappingQuery;
import org.eclipse.persistence.queries.SQLResultSetMapping;
import org.eclipse.persistence.queries.StoredProcedureCall;

/**
 * Concrete JPA query class. The JPA query wraps a StoredProcesureQuery which
 * is executed.
 */
public class StoredProcedureQueryImpl extends QueryImpl implements StoredProcedureQuery {
    protected boolean hasMoreResults;

    // Call will be returned from an execute. From it you can get the result set.
    protected DatabaseCall executeCall;
    protected Statement executeStatement;
    protected int executeResultSetIndex = -1;

    // If the procedure returns output cursor(s), we'll use them to satisfy
    // getResultList and getSingleResult calls so keep track of our index.
    protected int outputCursorIndex = -1;
    protected boolean isOutputCursorResultSet = false;

    /**
     * Base constructor for StoredProcedureQueryImpl. Initializes basic variables.
     */
    protected StoredProcedureQueryImpl(EntityManagerImpl entityManager) {
        super(entityManager);
    }

    /**
     * Create an StoredProcedureQueryImpl with a DatabaseQuery.
     */
    public StoredProcedureQueryImpl(DatabaseQuery query, EntityManagerImpl entityManager) {
        super(query, entityManager);
    }

    /**
     * Create an StoredProcedureQueryImpl with a query name.
     */
    public StoredProcedureQueryImpl(String name, EntityManagerImpl entityManager) {
        super(entityManager);
        this.queryName = name;
    }

    /**
     * Build the given result set into a list objects. Assumes there is an
     * execute call available and therefore should not be called unless an
     * execute statement was issued by the user.
     */
    protected List buildResultRecords(ResultSet resultSet) {
        try {
            AbstractSession session = (AbstractSession) getActiveSession();
            DatabaseAccessor accessor = (DatabaseAccessor) executeCall.getQuery().getAccessor();

            executeCall.setFields(null);
            executeCall.matchFieldOrder(resultSet, accessor, session);
            ResultSetMetaData metaData = resultSet.getMetaData();

            List result =  new Vector();
            while (resultSet.next()) {
                result.add(accessor.fetchRow(executeCall.getFields(), executeCall.getFieldsArray(), resultSet, metaData, session));
            }

            // The result set must be closed in case the statement is cached and not closed.
            resultSet.close();

            return result;
        } catch (Exception e) {
            setRollbackOnly();
            throw new PersistenceException(e);
        }
    }

    /**
     * Build a ResultSetMappingQuery from a sql result set mapping name and a
     * stored procedure call.
     *
     * This is called from a named stored procedure that employs result set
     * mapping name(s) which should be available from the session.
     */
    public static DatabaseQuery buildResultSetMappingNameQuery(List<String> resultSetMappingNames, StoredProcedureCall call) {
        ResultSetMappingQuery query = new ResultSetMappingQuery();
        call.setReturnMultipleResultSetCollections(call.hasMultipleResultSets() && ! call.isMultipleCursorOutputProcedure());
        query.setCall(call);
        query.setIsUserDefined(true);
        query.setSQLResultSetMappingNames(resultSetMappingNames);
        return query;
    }

    /**
     * Build a ResultSetMappingQuery from a sql result set mapping name and a
     * stored procedure call.
     *
     * This is called from a named stored procedure that employs result set
     * mapping name(s) which should be available from the session.
     */
    public static DatabaseQuery buildResultSetMappingNameQuery(List<String> resultSetMappingNames, StoredProcedureCall call, Map<String, Object> hints, ClassLoader classLoader, AbstractSession session) {
        // apply any query hints
        DatabaseQuery hintQuery = applyHints(hints, buildResultSetMappingNameQuery(resultSetMappingNames, call) , classLoader, session);

        // apply any query arguments
        applyArguments(call, hintQuery);

        return hintQuery;
    }

    /**
     * Build a ResultSetMappingQuery from the sql result set mappings given
     *  a stored procedure call.
     *
     * This is called from a named stored procedure query that employs result
     * class name(s). The resultSetMappings are build from these class name(s)
     * and are not available from the session.
     */
    public static DatabaseQuery buildResultSetMappingQuery(List<SQLResultSetMapping> resultSetMappings, StoredProcedureCall call) {
        ResultSetMappingQuery query = new ResultSetMappingQuery();
        call.setReturnMultipleResultSetCollections(call.hasMultipleResultSets() && ! call.isMultipleCursorOutputProcedure());
        query.setCall(call);
        query.setIsUserDefined(true);
        query.setSQLResultSetMappings(resultSetMappings);
        return query;
    }

    /**
     * Build a ResultSetMappingQuery from the sql result set mappings given
     *  a stored procedure call.
     *
     * This is called from a named stored procedure query that employs result
     * class name(s). The resultSetMappings are build from these class name(s)
     * and are not available from the session.
     */
    public static DatabaseQuery buildResultSetMappingQuery(List<SQLResultSetMapping> resultSetMappings, StoredProcedureCall call, Map<String, Object> hints, ClassLoader classLoader, AbstractSession session) {
        // apply any query hints
        DatabaseQuery hintQuery = applyHints(hints, buildResultSetMappingQuery(resultSetMappings, call), classLoader, session);

        // apply any query arguments
        applyArguments(call, hintQuery);

        return hintQuery;
    }

    /**
     * Build a ReadAllQuery from a class and stored procedure call.
     */
    public static DatabaseQuery buildStoredProcedureQuery(Class resultClass, StoredProcedureCall call, Map<String, Object> hints, ClassLoader classLoader, AbstractSession session) {
        DatabaseQuery query = new ReadAllQuery(resultClass);
        query.setCall(call);
        query.setIsUserDefined(true);

        // apply any query hints
        query = applyHints(hints, query, classLoader, session);

        // apply any query arguments
        applyArguments(call, query);

        return query;
    }

    /**
     * Build a DataReadQuery with the stored procedure call given.
     */
    public static DatabaseQuery buildStoredProcedureQuery(StoredProcedureCall call, Map<String, Object> hints, ClassLoader classLoader, AbstractSession session) {
        DataReadQuery query = new DataReadQuery();
        query.setResultType(DataReadQuery.AUTO);

        query.setCall(call);
        query.setIsUserDefined(true);

        // apply any query hints
        DatabaseQuery hintQuery = applyHints(hints, query, classLoader, session);

        // apply any query arguments
        applyArguments(call, hintQuery);

        return hintQuery;
    }

    /**
     * Build a ResultSetMappingQuery from a sql result set mapping name and a
     * stored procedure call.
     */
    public static DatabaseQuery buildStoredProcedureQuery(String sqlResultSetMappingName, StoredProcedureCall call, Map<String, Object> hints, ClassLoader classLoader, AbstractSession session) {
        ResultSetMappingQuery query = new ResultSetMappingQuery();
        query.setSQLResultSetMappingName(sqlResultSetMappingName);
        query.setCall(call);
        query.setIsUserDefined(true);

        // apply any query hints
        DatabaseQuery hintQuery = applyHints(hints, query, classLoader, session);

        // apply any query arguments
        applyArguments(call, hintQuery);

        return hintQuery;
    }

    /**
     * Call this method to close any open connections to the database.
     */
    @Override
    public void close() {
        if (executeCall != null) {
            DatabaseQuery query = executeCall.getQuery();
            AbstractSession session = query.getSession();

            // Release the accessors acquired for the query.
            for (Accessor accessor : query.getAccessors()) {
                session.releaseReadConnection(accessor);
            }

            try {
                if (executeStatement != null) {
                    DatabaseAccessor accessor = (DatabaseAccessor) query.getAccessor();
                    accessor.releaseStatement(executeStatement, query.getSQLString(), executeCall, session);
                }
            } catch (SQLException exception) {
                // Catch the exception and log a message.
                session.log(SessionLog.WARNING, SessionLog.CONNECTION, "exception_caught_closing_statement", exception);
            }
        }

        executeCall = null;
        executeStatement = null;
    }

    /**
     * Returns true if the first result corresponds to a result set, and false
     * if it is an update count or if there are no results other than through
     * INOUT and OUT parameters, if any.
     * @return true if first result corresponds to result set
     * @throws QueryTimeoutException if the query execution exceeds the query
     * timeout value set 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
     */
    @Override
    public boolean execute() {
        try {
            entityManager.verifyOpen();

            if (! getDatabaseQueryInternal().isResultSetMappingQuery()) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_execute"));
            }

            getResultSetMappingQuery().setIsExecuteCall(true);
            executeCall = (DatabaseCall) executeReadQuery();
            executeStatement = executeCall.getStatement();

            // Add this query to the entity manager open queries list.
            // The query will be closed in the following cases:
            // Within a transaction:
            //  - on commit
            //  - on rollback
            // Outside of a transaction:
            //  - em close
            // Other safeguards, we will close the query if/when
            //  - we hit the end of the results.
            //  - this query is garbage collected (finalize method)
            //
            // Deferring closing the call avoids having to go through all the
            // results now (and building all the result objects) and things
            // remain on a as needed basis from the statement.
            entityManager.addOpenQuery(this);

            hasMoreResults = executeCall.getExecuteReturnValue();

            // If execute returned false but we have output cursors then return
            // true and build the results from the output cursors.
            if (!hasMoreResults && getCall().hasOutputCursors()) {
                hasMoreResults = true;
                outputCursorIndex = 0;
                isOutputCursorResultSet = true;
            }

            return hasMoreResults;
        } catch (LockTimeoutException exception) {
            throw exception;
        } catch (PersistenceException exception) {
            setRollbackOnly();
            throw exception;
        } catch (IllegalStateException e){
            setRollbackOnly();
            throw e;
        } catch (RuntimeException exception) {
            setRollbackOnly();
            throw new PersistenceException(exception);
        }
    }

    /**
     * Execute an update or delete statement (from a stored procedure query).
     * @return the number of entities updated or deleted
     */
    @Override
    public int executeUpdate() {
        try {
            // Need to throw TransactionRequiredException if there is no active transaction
            entityManager.checkForTransaction(true);

            // Legacy: we could have a data read query or a read all query, so
            // clearly we shouldn't be executing an update on it. As of JPA 2.1
            // API we always create a result set mapping query to interact with
            // a stored procedure.
            // Also if the result set mapping query has result set mappings
            // defined, then it's clearly expecting result sets and we can be
            // preemptive in throwing an exception.
            if (! getDatabaseQueryInternal().isResultSetMappingQuery() || getResultSetMappingQuery().hasResultSetMappings()) {
                throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_execute_update"));
            }

            // If the return value is true indicating a result set then throw an exception.
            if (execute()) {
                if (getActiveSession().getPlatform().isJDBCExecuteCompliant()) {
                    throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_execute_update"));
                } else {
                    return getUpdateCount();
                }
            } else {
                return getUpdateCount();
            }
        } catch (LockTimeoutException exception) {
            throw exception;
        } catch (PersistenceException e) {
            setRollbackOnly();
            throw e;
        } catch (IllegalStateException e){
            setRollbackOnly();
            throw e;
        } catch (RuntimeException exception) {
            setRollbackOnly();
            throw new PersistenceException(exception);
        } finally {
            close(); // Close the connection once we're done.
        }
    }

    /**
     * Finalize method in case the query is not closed.
     */
    @Override
    public void finalize() {
        close();
    }

    /**
     * Return the stored procedure call associated with this query.
     */
    protected StoredProcedureCall getCall() {
        return (StoredProcedureCall) getDatabaseQueryInternal().getCall();
    }

    /**
     * Return the internal map of parameters.
     */
    @Override
    protected Map<String, Parameter<?>> getInternalParameters() {
        if (parameters == null) {
            parameters = new HashMap<String, Parameter<?>>();

            int index = 0;

            for (Object parameter : getCall().getParameters()) {
                Integer parameterType = getCall().getParameterTypes().get(index);
                String argumentName = getCall().getProcedureArgumentNames().get(index);

                DatabaseField field = null;

                if (parameterType == DatasourceCall.INOUT) {
                    field = (DatabaseField) ((Object[]) parameter)[0];
                } else if (parameterType == DatasourceCall.IN) {
                    field = (DatabaseField) parameter;
                } else if (parameterType == DatasourceCall.OUT || parameterType == DatasourceCall.OUT_CURSOR) {
                    if (parameter instanceof OutputParameterForCallableStatement) {
                        field = ((OutputParameterForCallableStatement) parameter).getOutputField();
                    } else {
                        field = (DatabaseField) parameter;
                    }
                }

                // If field is not null (one we care about) then add it, otherwise continue.
                if (field != null) {
                    // If the argument name is null then it is a positional parameter.
                    if (argumentName == null) {
                        parameters.put(field.getName(), new ParameterExpressionImpl(null, field.getType(), Integer.parseInt(field.getName())));
                    } else {
                        parameters.put(field.getName(), new ParameterExpressionImpl(null, field.getType(), field.getName()));
                    }
                }

                ++index;
            }
        }

        return parameters;
    }

    /**
     * Used to retrieve the values passed back from the procedure through INOUT
     * and OUT parameters. For portability, all results corresponding to result
     * sets and update counts must be retrieved before the values of output
     * parameters.
     * @param position parameter position
     * @return the result that is passed back through the parameter
     * @throws IllegalArgumentException if the position does not correspond to a
     * parameter of the query or is not an INOUT or OUT parameter
     */
    @Override
    public Object getOutputParameterValue(int position) {
        entityManager.verifyOpen();

        if (isValidCallableStatement()) {
            try {
                Object obj = executeCall.getOutputParameterValue((CallableStatement) executeStatement, position - 1, entityManager.getAbstractSession());

                if (obj instanceof ResultSet) {
                    // If a result set is returned we have to build the objects.
                    return getResultSetMappingQuery().buildObjectsFromRecords(buildResultRecords((ResultSet) obj), ++executeResultSetIndex);
                } else {
                    return obj;
                }
            } catch (Exception exception) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa21_invalid_parameter_position", new Object[] { position, exception.getMessage() }), exception);
            }
        }

        return null;
    }

    /**
     * Used to retrieve the values passed back from the procedure through INOUT
     * and OUT parameters. For portability, all results corresponding to result
     * sets and update counts must be retrieved before the values of output
     * parameters.
     * @param parameterName name of the parameter as registered or specified in
     *        metadata
     * @return the result that is passed back through the parameter
     * @throws IllegalArgumentException if the parameter name does not
     * correspond to a parameter of the query or is not an INOUT or OUT parameter
     */
    @Override
    public Object getOutputParameterValue(String parameterName) {
        entityManager.verifyOpen();

        if (isValidCallableStatement()) {
            try {
                Object obj = executeCall.getOutputParameterValue((CallableStatement) executeStatement, parameterName, entityManager.getAbstractSession());

                if (obj instanceof ResultSet) {
                    // If a result set is returned we have to build the objects.
                    return getResultSetMappingQuery().buildObjectsFromRecords(buildResultRecords((ResultSet) obj), ++executeResultSetIndex);
                }
                return obj;
            } catch (Exception exception) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa21_invalid_parameter_name", new Object[] { parameterName, exception.getMessage() }), exception);
            }
        }

        return null;
    }

    private boolean hasPositionalParameters() {
        for (Parameter parameter: this.getParameters()) {
            if (parameter.getName() != null) {
                return false;
            }
        }
        return true;
    }

    /**
     * Execute the query and return the query results as a List.
     * @return a list of the results
     */
    @Override
    public List getResultList() {
        // bug51411440: need to throw IllegalStateException if query
        // executed on closed em
        this.entityManager.verifyOpenWithSetRollbackOnly();
        try {
            // If there is no execute statement, the user has not called
            // execute and is simply calling getResultList directly on the query.
            if (executeStatement == null) {
                // If it's not a result set mapping query (as of JPA 2.1 we
                // always create a result set mapping query to interact with a
                // stored procedure) then throw an exception.
                if (! getDatabaseQueryInternal().isResultSetMappingQuery()) {
                    throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_get_result_list"));
                }

                // If the return value is false indicating no result set then throw an exception.
                if (execute()) {
                    return getResultList();
                } else {
                    throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_get_result_list"));
                }
            } else {
                if (hasMoreResults()) {
                    if (isOutputCursorResultSet) {
                        // Return result set list for the current outputCursorIndex.
                        List results = null;
                        if (hasPositionalParameters()) {
                            results = (List) getOutputParameterValue(getCall().getOutputCursors().get(outputCursorIndex++).getIndex() + 1);
                        } else {
                            results = (List) getOutputParameterValue(getCall().getOutputCursors().get(outputCursorIndex++).getName());
                        }

                        // Update the hasMoreResults flag.
                        hasMoreResults = (outputCursorIndex < getCall().getOutputCursors().size());

                        return results;
                    } else {
                        // Build the result records first.
                        List result = buildResultRecords(executeStatement.getResultSet());

                        // Move the result pointer.
                        moveResultPointer();

                        return getResultSetMappingQuery().buildObjectsFromRecords(result, ++executeResultSetIndex);
                    }
                } else {
                    return null;
                }
            }
        } catch (LockTimeoutException e) {
            throw e;
        } catch (PersistenceException e) {
            setRollbackOnly();
            throw e;
        } catch (IllegalStateException e) {
            setRollbackOnly();
            throw e;
        } catch (Exception e) {
            setRollbackOnly();
            throw new PersistenceException(e);
        }
    }

    /**
     * Return the ResultSetMappingQuery for this stored procedure query.
     * NOTE: Methods assumes associated database query is a ResultSetMappingQuery.
     */
    protected ResultSetMappingQuery getResultSetMappingQuery() {
        if (executeCall != null) {
            return (ResultSetMappingQuery) executeCall.getQuery();
        } else {
            return (ResultSetMappingQuery) getDatabaseQuery();
        }
    }

    /**
     * Execute the query and return the single query result.
     * @return a single result object.
     */
    @Override
    public Object getSingleResult() {
        // bug51411440: need to throw IllegalStateException if query
        // executed on closed em
        this.entityManager.verifyOpenWithSetRollbackOnly();
        try {
            // If there is no execute statement, the user has not called
            // execute and is simply calling getSingleResult directly on the query.
            if (executeStatement == null) {
                // If it's not a result set mapping query (as of JPA 2.1 we
                // always create a result set mapping query to interact with a
                // stored procedure) then throw an exception.
                if (! getDatabaseQueryInternal().isResultSetMappingQuery()) {
                    throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_get_single_result"));
                }

                // If the return value is true indicating a result set then
                // build and return the single result.
                if (execute()) {
                    return getSingleResult();
                } else {
                    throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_get_result_list"));
                }
            } else {
                if (hasMoreResults()) {
                    // Build the result records first.
                    List results;

                    if (isOutputCursorResultSet) {
                        // Return result set list for the current outputCursorIndex.
                        if (hasPositionalParameters()) {
                            results = (List) getOutputParameterValue(getCall().getOutputCursors().get(outputCursorIndex++).getIndex() + 1);
                        } else {
                            results = (List) getOutputParameterValue(getCall().getOutputCursors().get(outputCursorIndex++).getName());
                        }

                        // Update the hasMoreResults flag.
                        hasMoreResults = (outputCursorIndex < getCall().getOutputCursors().size());
                    } else {
                        // Build the result records first.
                        List result = buildResultRecords(executeStatement.getResultSet());

                        // Move the result pointer.
                        moveResultPointer();

                        results = getResultSetMappingQuery().buildObjectsFromRecords(result, ++executeResultSetIndex);
                    }

                    if (results.size() > 1) {
                        throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", null));
                    } else if (results.isEmpty()) {
                        throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
                    }

                    // TODO: if hasMoreResults is true, we 'could' and maybe should throw an exception here.

                    return results.get(0);
                } else {
                    return null;
                }
            }
        } catch (LockTimeoutException e) {
            throw e;
        } catch (PersistenceException e) {
            setRollbackOnly();
            throw e;
        } catch (IllegalStateException e) {
            setRollbackOnly();
            throw e;
        } catch (Exception e) {
            setRollbackOnly();
            throw new PersistenceException(e);
        } finally {
            close(); // Close the connection once we're done.
        }
    }

    /**
     * Returns the update count or -1 if there is no pending result
     * or if the next result is not an update count.
     * @return update count or -1 if there is no pending result or
     * if the next result is not an update count
     * @throws QueryTimeoutException if the query execution exceeds
     * the query timeout value set 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
     */
    @Override
    public int getUpdateCount() {
        entityManager.verifyOpenWithSetRollbackOnly();

        if (executeStatement != null) {
            try {
                int updateCount = executeStatement.getUpdateCount();

                // Moving the result pointer when -1 is reached doesn't seem
                // to be an issue for the jbdc driver, however as a safeguard,
                // once -1 is reached don't bother trying to move the pointer
                // as there is no need to do so.
                if (updateCount > -1) {
                    moveResultPointer();
                }
                return updateCount;
            } catch (SQLException e) {
                throw getDetailedException(DatabaseException.sqlException(e, executeCall, executeCall.getQuery().getAccessor(), executeCall.getQuery().getSession(), false));
            }
        }

        return -1;
    }

    /**
     * Returns true if the next result corresponds to a result set, and false if
     * it is an update count or if there are no results other than through INOUT
     * and OUT parameters, if any.
     *
     * @return true if next result corresponds to result set
     * @throws QueryTimeoutException if the query execution exceeds the query
     * timeout value set 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
     */
    @Override
    public boolean hasMoreResults() {
        entityManager.verifyOpen();

        return hasMoreResults;
    }

    /**
     * Returns true if the execute statement for this query is 1) not null (i.e.
     * query has been executed and 2) is an instance of callable statement,
     * meaning there are out parameters associated with it.
     */
    protected boolean isValidCallableStatement() {
        if (executeStatement == null) {
            throw new IllegalStateException(ExceptionLocalization.buildMessage("jpa21_invalid_call_on_un_executed_query"));
        }

        if (! (executeStatement instanceof CallableStatement)) {
            throw new IllegalStateException(ExceptionLocalization.buildMessage("jpa21_invalid_call_with_no_output_parameters"));
        }

        return true;
    }

    /**
     * INTERNAL:
     * Move the pointer up and update our has more results flag.
     * Once there are no result sets left, this will always return false.
     */
    private void moveResultPointer() {
        try {
            hasMoreResults = executeStatement.getMoreResults();
        } catch (SQLException e) {
            // swallow it.
            hasMoreResults = false;
        }
    }

    /**
     * Register a positional parameter. All positional parameters must be
     * registered.
     *
     * @param position parameter position
     * @param type type of the parameter
     * @param mode parameter mode
     * @return the same query instance
     */
    @Override
    public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) {
        entityManager.verifyOpenWithSetRollbackOnly();
        StoredProcedureCall call = (StoredProcedureCall) getDatabaseQuery().getCall();

        if (mode.equals(ParameterMode.IN)) {
            call.addUnamedArgument(String.valueOf(position), type);
        } else if (mode.equals(ParameterMode.OUT)) {
            call.addUnamedOutputArgument(String.valueOf(position), type);
        } else if (mode.equals(ParameterMode.INOUT)) {
            call.addUnamedInOutputArgument(String.valueOf(position), String.valueOf(position), type);
        } else if (mode.equals(ParameterMode.REF_CURSOR)) {
            call.useUnnamedCursorOutputAsResultSet(position);
        }

        // Force a re-calculate of the parameters.
        this.parameters = null;

        return this;
    }

    /**
     * Register a named parameter. When using parameter names, all parameters
     * must be registered in the order in which they occur in the parameter list
     * of the stored procedure.
     *
     * @param parameterName name of the parameter as registered or
     *        specified in metadata
     * @param type type of the parameter
     * @param mode parameter mode
     * @return the same query instance
     */
    @Override
    public StoredProcedureQuery registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) {
        entityManager.verifyOpenWithSetRollbackOnly();
        StoredProcedureCall call = (StoredProcedureCall) getDatabaseQuery().getCall();

        if (mode.equals(ParameterMode.IN)) {
            call.addNamedArgument(parameterName, parameterName, type);
        } else if (mode.equals(ParameterMode.OUT)) {
            call.addNamedOutputArgument(parameterName, parameterName, type);
        } else if (mode.equals(ParameterMode.INOUT)) {
            call.addNamedInOutputArgument(parameterName, parameterName, parameterName, type);
        } else if (mode.equals(ParameterMode.REF_CURSOR)) {
            call.useNamedCursorOutputAsResultSet(parameterName);
        }

        // Force a re-calculate of the parameters.
        this.parameters = null;

        return this;
    }

    /**
     * Set the position of the first result to retrieve.
     *
     * @param startPosition
     *            position of the first result, numbered from 0
     * @return the same query instance
     */
    @Override
    public StoredProcedureQueryImpl setFirstResult(int startPosition) {
        throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_not_supported", new Object[]{"setFirstResult", "StoredProcedureQuery"}));
    }

    /**
     * Set the flush mode type to be used for the query execution.
     * The flush mode type applies to the query regardless of the
     * flush mode type in use for the entity manager.
     * @param flushMode flush mode
     * @return the same query instance
     */
    @Override
    public StoredProcedureQueryImpl setFlushMode(FlushModeType flushMode) {
        return (StoredProcedureQueryImpl) super.setFlushMode(flushMode);
    }

    /**
     * Set a query property or hint. The hints elements may be used to specify
     * query properties and hints. Properties defined by this specification must
     * be observed by the provider. Vendor-specific hints that are not
     * recognized by a provider must be silently ignored. Portable applications
     * should not rely on the standard timeout hint. Depending on the database
     * in use, this hint may or may not be observed.
     *
     * @param hintName name of the property or hint
     * @param value value for the property or hint
     * @return the same query instance
     * @throws IllegalArgumentException if the second argument is not valid for
     * the implementation
     */
    @Override
    public StoredProcedureQuery setHint(String hintName, Object value) {
        try {
            entityManager.verifyOpen();
            setHintInternal(hintName, value);
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * 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
     */
    @Override
    public StoredProcedureQueryImpl setLockMode(LockModeType lockMode) {
        return (StoredProcedureQueryImpl) super.setLockMode(lockMode);
    }

    /**
     * Set the maximum number of results to retrieve.
     *
     * @param maxResult
     * @return the same query instance
     */
    @Override
    public StoredProcedureQueryImpl setMaxResults(int maxResult) {
        throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_not_supported", new Object[]{"setMaxResults", "StoredProcedureQuery"}));
    }

    /**
     * Bind an instance of java.util.Calendar to a positional parameter.
     *
     * @param position
     * @param value
     * @param temporalType
     * @return the same query instance
     * @throws IllegalArgumentException if position does not correspond to a
     * positional parameter of the query or if the value argument is of
     * incorrect type
     */
    @Override
    public StoredProcedureQuery setParameter(int position, Calendar value, TemporalType temporalType) {
        entityManager.verifyOpenWithSetRollbackOnly();
        return setParameter(position, convertTemporalType(value, temporalType));
    }

    /**
     * Bind an instance of java.util.Date to a positional parameter.
     *
     * @param position
     * @param value
     * @param temporalType
     * @return the same query instance
     * @throws IllegalArgumentException if position does not correspond to a
     * positional parameter of the query or if the value argument is of
     * incorrect type
     */
    @Override
    public StoredProcedureQuery setParameter(int position, Date value, TemporalType temporalType) {
        entityManager.verifyOpenWithSetRollbackOnly();
        return setParameter(position, convertTemporalType(value, temporalType));
    }

    /**
     * Bind an argument to a positional parameter.
     *
     * @param position
     * @param value
     * @return the same query instance
     * @throws IllegalArgumentException if position does not correspond to a
     * positional parameter of the query or if the argument is of incorrect type
     */
    @Override
    public StoredProcedureQuery setParameter(int position, Object value) {
        try {
            entityManager.verifyOpen();
            setParameterInternal(position, value);
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * Bind an instance of java.util.Calendar to a Parameter object.
     *
     * @param param
     * @param value
     * @param temporalType
     * @return the same query instance
     * @throws IllegalArgumentException if the parameter does not correspond to
     * a parameter of the query
     */
    @Override
    public StoredProcedureQuery setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NULL_PARAMETER_PASSED_TO_SET_PARAMETER"));
        }
        //bug 402686: type validation
        String position = getParameterId(param);
        ParameterExpressionImpl parameter = (ParameterExpressionImpl) this.getInternalParameters().get(position);
        if (parameter == null ) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { param.toString(), this.databaseQuery }));
        }
        if (!parameter.getParameterType().equals(param.getParameterType())) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { position, param.getParameterType() }));
        }
        return this.setParameter(position, value, temporalType);
    }

    /**
     * Bind an instance of java.util.Date to a Parameter object.
     *
     * @param param
     * @param value
     * @param temporalType
     * @return the same query instance
     * @throws IllegalArgumentException if the parameter does not correspond to
     * a parameter of the query
     */
    @Override
    public StoredProcedureQuery setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NULL_PARAMETER_PASSED_TO_SET_PARAMETER"));
        }
        //bug 402686: type validation
        String position = getParameterId(param);
        ParameterExpressionImpl parameter = (ParameterExpressionImpl) this.getInternalParameters().get(position);
        if (parameter == null ) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { param.toString(), this.databaseQuery }));
        }
        if (!parameter.getParameterType().equals(param.getParameterType())) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { position, param.getParameterType() }));
        }
        return this.setParameter(position, value, temporalType);
    }

    /**
     * Bind the value of a Parameter object.
     *
     * @param param
     * @param value
     * @return the same query instance
     * @throws IllegalArgumentException if the parameter does not correspond to
     * a parameter of the query
     */
    @Override
    public <T> StoredProcedureQuery setParameter(Parameter<T> param, T value) {
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NULL_PARAMETER_PASSED_TO_SET_PARAMETER"));
        }
        //bug 402686: type validation
        String position = getParameterId(param);
        ParameterExpressionImpl parameter = (ParameterExpressionImpl) this.getInternalParameters().get(position);
        if (parameter == null ) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { param.toString(), this.databaseQuery }));
        }
        if (!parameter.getParameterType().equals(param.getParameterType())) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { position, param.getParameterType() }));
        }
        return this.setParameter(position, value);
    }

    /**
     * Bind an instance of java.util.Calendar to a named parameter.
     *
     * @param name
     * @param value
     * @param temporalType
     * @return the same query instance
     * @throws IllegalArgumentException if the parameter name does not
     * correspond to a parameter of the query or if the value argument is of
     * incorrect type
     */
    @Override
    public StoredProcedureQuery setParameter(String name, Calendar value, TemporalType temporalType) {
        entityManager.verifyOpenWithSetRollbackOnly();
        return setParameter(name, convertTemporalType(value, temporalType));
    }

    /**
     * Bind an instance of java.util.Date to a named parameter.
     *
     * @param name
     * @param value
     * @param temporalType
     * @return the same query instance
     * @throws IllegalArgumentException if the parameter name does not
     * correspond to a parameter of the query or if the value argument is of
     * incorrect type
     */
    @Override
    public StoredProcedureQuery setParameter(String name, Date value, TemporalType temporalType) {
        entityManager.verifyOpenWithSetRollbackOnly();
        return setParameter(name, convertTemporalType(value, temporalType));
    }

    /**
     * Bind an argument to a named parameter.
     *
     * @param name
     * @param value
     * @return the same query instance
     * @throws IllegalArgumentException if the parameter name does not
     * correspond to a parameter of the query or if the argument is of incorrect
     * type
     */
    @Override
    public StoredProcedureQuery setParameter(String name, Object value) {
        try {
            entityManager.verifyOpen();
            setParameterInternal(name, value, false);
            return this;
        } catch (RuntimeException e) {
            setRollbackOnly();
            throw e;
        }
    }

    /**
     * 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
     */
    @Override
    protected void setParameterInternal(String name, Object value, boolean isIndex) {
        Parameter parameter = this.getInternalParameters().get(name);
        StoredProcedureCall call = (StoredProcedureCall) getDatabaseQuery().getCall();
        if (parameter == null) {
            if (isIndex) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-index", new Object[] { name, call.getProcedureName() }));
            } else {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-name", new Object[] { name, call.getProcedureName() }));
            }
        }
        if (!isValidActualParameter(value, parameter.getParameterType())) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-incorrect-parameter-type", new Object[] { name, value.getClass(), parameter.getParameterType(), call.getProcedureName() }));
        }
        this.parameterValues.put(name, value);
    }
}

