/*
 * Copyright (c) 1998, 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
//     10/29/2010-2.2 Michael O'Brien
//       - 325167: Make reserved # bind parameter char generic to enable native SQL pass through
//     05/24/2011-2.3 Guy Pelletier
//       - 345962: Join fetch query when using tenant discriminator column fails.
//     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
//     11/10/2014-2.6 Dmitry Kornilov
//       - 450818: Column names with hash mark => "java.sql.SQLException: Invalid column index"
package org.eclipse.persistence.internal.databaseaccess;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.expressions.ParameterExpression;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.queries.DatabaseQueryMechanism;
import org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.structures.ObjectRelationalDatabaseField;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DatabaseQuery;

/**
 * INTERNAL:
 * <b>Purpose</b>: Used as an abstraction of a datasource invocation.
 *
 * @author James Sutherland
 * @since OracleAS TopLink 10<i>g</i> (10.0.3)
 */
public abstract class DatasourceCall implements Call {
    // Back reference to query, unfortunately required for events.
    protected transient DatabaseQuery query;

    // The parameters (values) are ordered as they appear in the call.
    protected List parameters;

    // The parameter types determine if the parameter is a modify, translation or literal type.
    protected List<Integer> parameterTypes;
    public static final Integer LITERAL = 1;
    public static final Integer MODIFY = 2;
    public static final Integer TRANSLATION = 3;
    public static final Integer CUSTOM_MODIFY = 4;
    public static final Integer OUT = 5;
    public static final Integer INOUT = 6;
    public static final Integer IN = 7;
    public static final Integer OUT_CURSOR = 8;
    public static final Integer INLINE = 9;

    // Store if the call has been prepared.
    protected boolean isPrepared;

    /** Allow connection unwrapping to be configured. */
    protected boolean isNativeConnectionRequired;

    //Eclipselink Bug 217745 indicates whether or not the token(#,?) needs to be processed if they are in the quotes.
    protected boolean shouldProcessTokenInQuotes;

    // Type of call.
    protected int returnType;
    protected static final int NO_RETURN = 1;
    protected static final int RETURN_ONE_ROW = 2;
    protected static final int RETURN_MANY_ROWS = 3;
    protected static final int RETURN_CURSOR = 4;
    protected static final int EXECUTE_UPDATE = 5;

    protected DatasourceCall() {
        this.isPrepared = false;
        this.shouldProcessTokenInQuotes = true;
    }

    /**
     * The parameters are the values in order of occurrence in the SQL statement.
     * This is lazy initialized to conserve space on calls that have no parameters.
     */
    public List getParameters() {
        if (parameters == null) {
            parameters = new ArrayList();
        }
        return parameters;
    }

    /**
     * The parameter types determine if the parameter is a modify, translation or literal type.
     */
    public List<Integer> getParameterTypes() {
        if (parameterTypes == null) {
            parameterTypes = new ArrayList<>();
        }
        return parameterTypes;
    }

    /**
     * The parameters are the values in order of occurrence in the SQL statement.
     */
    public void setParameters(List parameters) {
        this.parameters = parameters;
    }

    /**
     * The parameter types determine if the parameter is a modify, translation or literal type.
     */
    public void setParameterTypes(List<Integer> parameterTypes) {
        this.parameterTypes = parameterTypes;
    }

    /**
     * The parameters are the values in order of occurrence in call.
     * This is lazy initialized to conserve space on calls that have no parameters.
     */
    public boolean hasParameters() {
        return (parameters != null) && (!getParameters().isEmpty());
    }

    /**
     * The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
     */
    public boolean areManyRowsReturned() {
        return this.returnType == RETURN_MANY_ROWS;
    }

    public static boolean isOutputParameterType(Integer parameterType) {
        return (parameterType == OUT) || (parameterType == INOUT) || (parameterType == OUT_CURSOR);
    }

    /**
     * Bound calls can have the SQL pre generated.
     */
    public boolean isPrepared() {
        return isPrepared;
    }

    /**
     * Bound calls can have the SQL pre generated.
     */
    public void setIsPrepared(boolean isPrepared) {
        this.isPrepared = isPrepared;
    }

    /**
     * Return the appropriate mechanism,
     * with the call added as necessary.
     */
    @Override
    public DatabaseQueryMechanism buildNewQueryMechanism(DatabaseQuery query) {
        return new DatasourceCallQueryMechanism(query, this);
    }

    /**
     * Return the appropriate mechanism,
     * with the call added as necessary.
     */
    @Override
    public DatabaseQueryMechanism buildQueryMechanism(DatabaseQuery query, DatabaseQueryMechanism mechanism) {
        if (mechanism.isCallQueryMechanism() && (mechanism instanceof DatasourceCallQueryMechanism)) {
            // Must also add the call singleton...
            DatasourceCallQueryMechanism callMechanism = ((DatasourceCallQueryMechanism)mechanism);
            if (!callMechanism.hasMultipleCalls()) {
                callMechanism.addCall(callMechanism.getCall());
                callMechanism.setCall(null);
            }
            callMechanism.addCall(this);
            return mechanism;
        } else {
            return buildNewQueryMechanism(query);
        }
    }

    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException exception) {
            //Do nothing
        }

        return null;
    }

    /**
     * Return the SQL string for logging purposes.
     */
    @Override
    public abstract String getLogString(Accessor accessor);

    /**
     * Back reference to query, unfortunately required for events.
     */
    public DatabaseQuery getQuery() {
        return query;
    }

    /**
     * The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
     */
    public int getReturnType() {
        return returnType;
    }

    /**
     * The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
     */
    public boolean isCursorReturned() {
        return this.returnType == RETURN_CURSOR;
    }

    /**
     * Returns true if this call returns from a statement.execute call.
     */
    public boolean isExecuteUpdate() {
        return this.returnType == EXECUTE_UPDATE;
    }

    /**
     * Return whether all the results of the call have been returned.
     */
    @Override
    public boolean isFinished() {
        return !isCursorReturned() && !isExecuteUpdate();
    }

    /**
     * The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
     */
    @Override
    public boolean isNothingReturned() {
        return this.returnType == NO_RETURN;
    }

    /**
     * The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
     */
    @Override
    public boolean isOneRowReturned() {
        return this.returnType == RETURN_ONE_ROW;
    }

    public boolean isSQLCall() {
        return false;
    }

    public boolean isStoredPLSQLFunctionCall() {
        return false;
    }

    public boolean isStoredPLSQLProcedureCall() {
        return false;
    }

    public boolean isStoredFunctionCall() {
        return false;
    }

    public boolean isStoredProcedureCall() {
        return false;
    }

    public boolean isJPQLCall() {
        return false;
    }

    public boolean isEISInteraction() {
        return false;
    }

    public boolean isQueryStringCall() {
        return false;
    }

    /**
     * Allow pre-printing of the query/SQL string for fully bound calls, to save from reprinting.
     */
    public void prepare(AbstractSession session) {
        setIsPrepared(true);
    }

    /**
     * Cursor return is used for cursored streams.
     */
    public void returnCursor() {
        setReturnType(RETURN_CURSOR);
    }

    /**
     * Indicates that this call will return a boolean value from an execute()
     * call.
     */
    public void setExecuteUpdate() {
        setReturnType(EXECUTE_UPDATE);
    }

    /**
     * Return if the call's return type has been set.
     */
    public boolean isReturnSet() {
        return this.returnType != 0;
    }

    /**
     * Many rows are returned for read-all queries.
     */
    public void returnManyRows() {
        setReturnType(RETURN_MANY_ROWS);
    }

    /**
     * No return is used for modify calls like insert / update / delete.
     */
    public void returnNothing() {
        setReturnType(NO_RETURN);
    }

    /**
     * One row is returned for read-object queries.
     */
    public void returnOneRow() {
        setReturnType(RETURN_ONE_ROW);
    }

    /**
     * Back reference to query, unfortunately required for events.
     */
    public void setQuery(DatabaseQuery query) {
        this.query = query;
    }

    /**
     * The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
     */
    public void setReturnType(int returnType) {
        this.returnType = returnType;
    }

    /**
     * Allow the call to translate from the translation for predefined calls.
     */
    public void translate(AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session) {
        //do nothing by default.
    }

    /**
     * Return the query string of the call.
     * This must be overwritten by subclasses that support query language translation (SQLCall, XQueryCall).
     */
    public String getQueryString() {
        return "";
    }

    /**
     * Set the query string of the call.
     * This must be overwritten by subclasses that support query language translation (SQLCall, XQueryCall).
     */
    public void setQueryString(String queryString) {
        // Nothing by default.
    }

    /**
     * INTERNAL:
     * Parse the query string for # markers for custom query based on a query language.
     * This is used by SQLCall and XQuery call, but can be reused by other query languages.
     */
    public void translateCustomQuery() {
        if (this.shouldProcessTokenInQuotes) {
            if (getQueryString().indexOf(this.query.getParameterDelimiter()) == -1) {
                if (this.getQuery().shouldBindAllParameters() && getQueryString().indexOf('?') == -1) {
                    return;
                }
                translatePureSQLCustomQuery();
                return;
            }
        } else {
            if (!hasArgumentMark(getQueryString(), this.query.getParameterDelimiterChar(), '\'')
                    || !hasArgumentMark(getQueryString(), this.query.getParameterDelimiterChar(), '\"')
                    || !hasArgumentMark(getQueryString(), this.query.getParameterDelimiterChar(), '`')) {
                if (this.getQuery().shouldBindAllParameters() && !hasArgumentMark(getQueryString(),'?', '\'')) {
                    return;
                }
                translatePureSQLCustomQuery();
                return;
            }
        }

        int lastIndex = 0;
        String queryString = getQueryString();
        Writer writer = new CharArrayWriter(queryString.length() + 50);
        try {
            // ** This method is heavily optimized do not touch anything unless you "know" what your doing.
            while (lastIndex != -1) {
                int poundIndex = queryString.indexOf(this.query.getParameterDelimiterChar(), lastIndex);
                String token;
                if (poundIndex == -1) {
                    token = queryString.substring(lastIndex, queryString.length());
                    lastIndex = -1;
                } else {
                    if(this.shouldProcessTokenInQuotes){//Always process token no matter whether the quotes around it or not.
                        token = queryString.substring(lastIndex, poundIndex);
                    }else{
                        boolean hasPairedQuoteBeforePound = true;
                        int quotePairIndex=poundIndex;

                        do{
                            quotePairIndex=queryString.lastIndexOf('\'',quotePairIndex-1);
                            if(quotePairIndex!=-1 && quotePairIndex > lastIndex){
                                hasPairedQuoteBeforePound = !hasPairedQuoteBeforePound;
                            } else {
                               break;
                            }
                        }while(true);

                        int endQuoteIndex = -1;
                        if(!hasPairedQuoteBeforePound){//There is begin quote, so search end quote.
                            endQuoteIndex = queryString.indexOf('\'', poundIndex+1);
                        }
                        if(endQuoteIndex!=-1){//There is quote around pound.
                            token = queryString.substring(lastIndex, endQuoteIndex+1);
                            poundIndex=-1;
                            lastIndex = endQuoteIndex + 1;
                        } else { //No quote around pound,
                            token = queryString.substring(lastIndex, poundIndex);
                            lastIndex = poundIndex + 1;
                        }
                    }
                }
                writer.write(token);
                if (poundIndex != -1) {
                    int wordEndIndex = poundIndex + 1;
                    while ((wordEndIndex < queryString.length()) && (whitespace().indexOf(queryString.charAt(wordEndIndex)) == -1)) {
                        wordEndIndex = wordEndIndex + 1;
                    }

                    // Check for ## which means field from modify row.
                    if (queryString.charAt(poundIndex + 1) == this.query.getParameterDelimiterChar()) {
                        // Check for ### which means OUT parameter type.
                        if (queryString.charAt(poundIndex + 2) == this.query.getParameterDelimiterChar()) {
                            // Check for #### which means INOUT parameter type.
                            if (queryString.charAt(poundIndex + 3) == this.query.getParameterDelimiterChar()) {
                                String fieldName = queryString.substring(poundIndex + 4, wordEndIndex);
                                DatabaseField field = createField(fieldName);
                                appendInOut(writer, field);
                            } else {
                                String fieldName = queryString.substring(poundIndex + 3, wordEndIndex);
                                DatabaseField field = createField(fieldName);
                                appendOut(writer, field);
                            }
                        } else {
                            String fieldName = queryString.substring(poundIndex + 2, wordEndIndex);
                            DatabaseField field = createField(fieldName);
                            appendModify(writer, field);
                        }
                    } else {
                        String fieldName = queryString.substring(poundIndex + 1, wordEndIndex);
                        DatabaseField field = createField(fieldName);
                        appendIn(writer, field);
                    }
                    lastIndex = wordEndIndex;
                }
            }
            setQueryString(writer.toString());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
    }

    /**
     * INTERNAL:
     * Parse the query string for ? markers for custom query based on a query language.
     * This is used by SQLCall and XQuery call, but can be reused by other query languages.
     */
    public void translatePureSQLCustomQuery() {
        int lastIndex = 0;
        String queryString = getQueryString();
        int parameterIndex = 1; // this is the parameter index
        Writer writer = new CharArrayWriter(queryString.length() + 50);
        try {
            // ** This method is heavily optimized do not touch anything unless you "know" what your doing.
            while (lastIndex != -1) {
                int markIndex = queryString.indexOf('?', lastIndex);
                String token;
                if (markIndex == -1) { // did not find question mark then we are done looking
                    token = queryString.substring(lastIndex, queryString.length()); //write rest of sql
                    lastIndex = -1;
                } else {
                    if(this.shouldProcessTokenInQuotes){
                        token = queryString.substring(lastIndex, markIndex);
                        lastIndex = markIndex + 1;
                    }else{
                        boolean hasPairedQuoteBeforeMark = true;
                        int quotePairIndex=markIndex;
                        do{
                            quotePairIndex=queryString.lastIndexOf('\'',quotePairIndex-1);
                            if(quotePairIndex!=-1 && quotePairIndex > lastIndex){
                                hasPairedQuoteBeforeMark = !hasPairedQuoteBeforeMark;
                            } else {
                               break;
                            }
                        }while(true);

                        int endQuoteIndex = -1;
                        if(!hasPairedQuoteBeforeMark){//There is begin quote, so search end quote.
                            endQuoteIndex = queryString.indexOf('\'', markIndex+1);
                        }
                        if(endQuoteIndex!=-1){//There is quote around mark.
                            token = queryString.substring(lastIndex, endQuoteIndex+1);
                            markIndex=-1;
                            lastIndex = endQuoteIndex + 1;
                        }else{
                            //if no quote around the mark, write the rest of sql.
                            token = queryString.substring(lastIndex, markIndex);
                            lastIndex = markIndex + 1;
                        }
                    }
                }
                writer.write(token);
                if (markIndex != -1) {  // found the question mark now find the named token
                    int wordEndIndex = markIndex + 1;
                    while ((wordEndIndex < queryString.length()) && (whitespace().indexOf(queryString.charAt(wordEndIndex)) == -1)) {
                        wordEndIndex = wordEndIndex + 1;
                    }
                    if (wordEndIndex > markIndex + 1){ //found a 'name' for this token (may be positional)
                        String fieldName = queryString.substring(markIndex + 1, wordEndIndex);
                        DatabaseField field = createField(fieldName);
                        appendIn(writer, field);
                        lastIndex = wordEndIndex;
                    }else{
                        DatabaseField field = createField(String.valueOf(parameterIndex));
                        parameterIndex++;
                        appendIn(writer, field);
                    }
                }
            }
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        setQueryString(writer.toString());
    }

    /**
     * INTERNAL:
     * Create a new Database Field
     * This method can be overridden by subclasses to return other field types
     */
    protected DatabaseField createField(String fieldName) {
        return new DatabaseField(fieldName);
    }

    /**
     * INTERNAL:
     * All values are printed as ? to allow for parameter binding or translation during the execute of the call.
     */
    public void appendLiteral(Writer writer, Object literal) {
        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().add(literal);
        getParameterTypes().add(LITERAL);
    }

    /**
     * INTERNAL:
     * All values are printed as ? to allow for parameter binding or translation during the execute of the call.
     */
    public void appendTranslation(Writer writer, DatabaseField modifyField) {
        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().add(modifyField);
        getParameterTypes().add(TRANSLATION);
    }

    /**
     * INTERNAL:
     * All values are printed as ? to allow for parameter binding or translation during the execute of the call.
     */
    public void appendModify(Writer writer, DatabaseField modifyField) {
        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().add(modifyField);
        getParameterTypes().add(MODIFY);
    }

    /**
     * INTERNAL:
     * All values are printed as ? to allow for parameter binding or translation during the execute of the call.
     */
    public void appendIn(Writer writer, DatabaseField field) {
        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().add(field);
        getParameterTypes().add(IN);
    }

    /**
     * INTERNAL:
     * All values are printed as ? to allow for parameter binding or translation during the execute of the call.
     */
    public void appendInOut(Writer writer, DatabaseField inoutField) {
        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        Object[] inOut = { inoutField, inoutField };
        getParameters().add(inOut);
        getParameterTypes().add(INOUT);
    }

    /**
     * INTERNAL:
     * All values are printed as ? to allow for parameter binding or translation during the execute of the call.
     */
    public void appendOut(Writer writer, DatabaseField outField) {
        try {
            writer.write(argumentMarker());
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().add(outField);
        getParameterTypes().add(OUT);
    }

    /**
     * Add the parameter.
     * If using binding bind the parameter otherwise let the platform print it.
     * The platform may also decide to bind the value.
     */
    public void appendParameter(Writer writer, Object parameter, AbstractSession session) {
        session.getDatasourcePlatform().appendParameter(this, writer, parameter);
    }

    /**
     * INTERNAL:
     * Return the character to use for the argument marker.
     * ? is used in SQL, however other query languages such as XQuery need to use other markers.
     */
    protected char argumentMarker() {
        return '?';
    }

    /**
     * INTERNAL:
     * Return the characters that represent non-arguments names.
     */
    protected String whitespace() {
        return ",); \n\t:";
    }

    /**
     * INTERNAL:
     * Allow the call to translate from the translation for predefined calls.
     */
    public void translateQueryString(AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session) {
        //has a '?'
        if ((this.parameters == null) || getParameters().isEmpty()) {
            //has no parameters
            return;
        }
        if (getQueryString().indexOf(argumentMarker()) == -1) {
            return;
        }

        int lastIndex = 0;
        int parameterIndex = 0;
        String queryString = getQueryString();
        Writer writer = new CharArrayWriter(queryString.length() + 50);
        try {
            // PERF: This method is heavily optimized do not touch anything unless you know "very well" what your doing.
            // Must translate field parameters and may get new bound parameters for large data.
            List parameterFields = getParameters();
            List<Integer> parameterTypes = getParameterTypes();
            setParameters(new ArrayList(parameterFields.size()));
            while (lastIndex != -1) {
                int tokenIndex = queryString.indexOf(argumentMarker(), lastIndex);
                String token;
                if (tokenIndex == -1) {
                    token = queryString.substring(lastIndex, queryString.length());
                    lastIndex = -1;
                } else {
                    if (this.shouldProcessTokenInQuotes) {
                        token = queryString.substring(lastIndex, tokenIndex);
                    } else {
                        boolean hasPairedQuoteBeforeMark = true;
                        int quotePairIndex = tokenIndex;
                        do {
                            quotePairIndex = queryString.lastIndexOf('\'', quotePairIndex - 1);
                            if (quotePairIndex != -1 && quotePairIndex > lastIndex){
                                hasPairedQuoteBeforeMark = !hasPairedQuoteBeforeMark;
                            } else {
                                break;
                            }
                        } while (true);

                        int endQuoteIndex = -1;
                        if (!hasPairedQuoteBeforeMark) { // there is a begin quote, so search for end quote.
                            endQuoteIndex = queryString.indexOf('\'', tokenIndex + 1);
                        }
                        if (endQuoteIndex != -1) { // there is a quote around the mark.
                            token = queryString.substring(lastIndex, endQuoteIndex + 1);
                            tokenIndex = -1;
                            lastIndex = endQuoteIndex + 1;
                        } else {
                            // if no quote around the mark, write the rest of sql.
                            token = queryString.substring(lastIndex, tokenIndex);
                            lastIndex = tokenIndex + 1;
                        }
                    }
                }
                writer.write(token);
                if (tokenIndex != -1) {
                    // Process next parameter.
                    Integer parameterType = parameterTypes.get(parameterIndex);
                    Object parameter = parameterFields.get(parameterIndex);
                    if (parameterType == MODIFY) {
                        DatabaseField field = (DatabaseField)parameter;
                        Object value = modifyRow.get(field);
                        appendParameter(writer, value, session);
                    } else if (parameterType == CUSTOM_MODIFY) {
                        DatabaseField field = (DatabaseField)parameter;
                        Object value = modifyRow.get(field);
                        if (value != null) {
                            value = session.getDatasourcePlatform().getCustomModifyValueForCall(this, value, field, false);
                            //Bug#5200826 needs use unwrapped connection.
                            if ((value instanceof BindCallCustomParameter) && ((BindCallCustomParameter)value).shouldUseUnwrappedConnection()){
                                this.isNativeConnectionRequired=true;
                            }
                        }
                        appendParameter(writer, value, session);
                    } else if (parameterType == TRANSLATION) {
                        Object value = null;
                        // Parameter expressions are used for nesting and correct mapping conversion of the value.
                        if (parameter instanceof ParameterExpression) {
                            value = ((ParameterExpression)parameter).getValue(translationRow, getQuery(), session);
                        } else {
                            DatabaseField field = (DatabaseField)parameter;
                            value = translationRow.get(field);
                            // Must check for the modify row as well for custom SQL compatibility as only one # is required.
                            if ((value == null) && (modifyRow != null)) {
                                value = modifyRow.get(field);
                            }
                        }
                        appendParameter(writer, value, session);
                    } else if (parameterType == LITERAL) {
                        if (parameter instanceof DatabaseField) {
                            parameter = null;
                        }
                        appendParameter(writer, parameter, session);
                    } else if (parameterType == IN) {
                        Object value = getValueForInParameter(parameter, translationRow, modifyRow, session, false);
                        appendParameter(writer, value, session);
                    } else if (parameterType == INOUT) {
                        Object value = getValueForInOutParameter(parameter, translationRow, modifyRow, session);
                        appendParameter(writer, value, session);
                    } else if (parameterType == INLINE) {
                        writer.write((String)parameter);
                    } else if (parameterType == OUT || parameterType == OUT_CURSOR) {
                        if (parameter instanceof DatabaseField) {
                            parameter = null;
                        }
                        appendParameter(writer, parameter, session);
                    }
                    lastIndex = tokenIndex + 1;
                    parameterIndex++;
                }
            }

            setQueryString(writer.toString());

        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
    }

    /**
     * INTERNAL:
     * Returns value for IN parameter. Called by translate and translateSQLString methods.
     * In case shouldBind==true tries to return a DatabaseField with type instead of null,
     * returns null only in case no DatabaseField with type was found (case sensitive).
     */
    protected Object getValueForInParameter(Object parameter, AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session, boolean shouldBind) {
        Object value = parameter;
        DatabaseField field = null;
        boolean isNull = false;

        // Parameter expressions are used for nesting and correct mapping conversion of the value.
        if (parameter instanceof ParameterExpression) {
            value = ((ParameterExpression)parameter).getValue(translationRow, getQuery(), session);
            field = ((ParameterExpression)parameter).getField();
        } else if (parameter instanceof DatabaseField) {
            field = (DatabaseField)parameter;
            value = translationRow.get(field);
            // Must check for the modify row as well for custom SQL compatibility as only one # is required.
            if (modifyRow != null) {
                if (value == null) {
                    value = modifyRow.get(field);
                }
                if (value != null) {
                    DatabaseField modifyField = modifyRow.getField(field);
                    if (modifyField != null) {
                        if (session.getDatasourcePlatform().shouldUseCustomModifyForCall(modifyField)) {
                            value = session.getDatasourcePlatform().getCustomModifyValueForCall(this, value, modifyField, shouldBind);
                        }
                    }
                }
            }
            if (value == null && shouldBind) {
                isNull = true;
                if ((field.getType() != null) ||(field.getSqlType()!= DatabaseField.NULL_SQL_TYPE)){
                    value = field;
                } else if (modifyRow != null) {
                    DatabaseField modifyField = modifyRow.getField(field);
                    if ((modifyField != null) && (modifyField.getType() != null)) {
                        value = modifyField;
                    }
                }
                if (value == null) {
                    DatabaseField translationField = translationRow.getField(field);
                    if (translationField == null){
                        session.log(SessionLog.WARNING, SessionLog.SQL, "named_argument_not_found_in_query_parameters", new Object[]{field});
                    }
                    if ((translationField != null) && (translationField.getType() != null)) {
                        value = translationField;
                    }
                }
            } else {
                if (parameter instanceof ObjectRelationalDatabaseField){
                    value = new InParameterForCallableStatement(value, (DatabaseField)parameter);
                }
            }
        }
        if ((value == null || isNull) && this.query.hasNullableArguments() && this.query.getNullableArguments().contains(field)) {
            return this;
        }
        return value;
    }

    /**
     * INTERNAL:
     * Returns value for INOUT parameter. Called by translate and translateSQLString methods.
     */
    protected Object getValueForInOutParameter(Object parameter, AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session) {
        // parameter ts an array of two Objects: inParameter and outParameter
        Object inParameter = ((Object[])parameter)[0];
        Object inValue = getValueForInParameter(inParameter, translationRow, modifyRow, session, true);
        Object outParameter = ((Object[])parameter)[1];
        return createInOutParameter(inValue, outParameter, session);
    }

    /**
     * INTERNAL:
     * Returns INOUT parameter. Called by getValueForInOutParameter method.
     * Descendants may override this method.
     */
    protected Object createInOutParameter(Object inValue, Object outParameter, AbstractSession session) {
        Object[] inOut = { inValue, outParameter };
        return inOut;
    }

    /**
     * Return true if the specific mark is existing and not quoted around.
     *
     * @param string    string to search
     * @param mark      mark to find
     * @param quote     quote char (usually ' or ")
     */
    private boolean hasArgumentMark(String string, char mark, char quote){
        int quoteIndex = -1;
        int lastEndQuoteIndex = -1;

        do{
            int markIndex=string.indexOf(mark,lastEndQuoteIndex+1);
            if(markIndex==-1){
                return false; //no mark at all.
            }
            quoteIndex = string.lastIndexOf(quote, markIndex);
            if(quoteIndex==-1){//no quote before the mark
                return true;
            }else{//has quote before the mark
                boolean hasPairedQuoteBeforeMark = false;
                while(quoteIndex!=-1 && quoteIndex >= lastEndQuoteIndex){
                    if((quoteIndex=string.lastIndexOf(quote, quoteIndex-1))!=-1){
                        hasPairedQuoteBeforeMark = !hasPairedQuoteBeforeMark;
                    }
                }
                if(hasPairedQuoteBeforeMark){//if there is paired quotes before the mark.
                    return true;
                }else{//might have quotes around the mark, need further check.
                    lastEndQuoteIndex = string.indexOf(quote, markIndex+1);
                    if(lastEndQuoteIndex==-1){
                        return true;//no end quote around the mark.
                    }
                }
            }
            //Upon to here, the current mark is positioning between quotes
            //we need search for the next mark.
        }while(true);
    }

    /**
     * Set if the call requires usage of a native (unwrapped) JDBC connection.
     * This may be required for some Oracle JDBC support when a wrapping DataSource is used.
     */
    public void setIsNativeConnectionRequired(boolean isNativeConnectionRequired) {
        this.isNativeConnectionRequired = isNativeConnectionRequired;
    }

    /**
     * Return if the call requires usage of a native (unwrapped) JDBC connection.
     * This may be required for some Oracle JDBC support when a wrapping DataSource is used.
     */
    public boolean isNativeConnectionRequired() {
        return isNativeConnectionRequired;
    }

    /**
     * INTERNAL:
     * This method is used to correct parameterTypes which are compared to static values using == equality, which changes
     * during serialization/deserialization.
     */
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        if (parameterTypes !=null) {
            List<Integer> newParameterTypes = new ArrayList<>(parameterTypes.size());
            for (Integer type: parameterTypes){
                if (LITERAL.equals(type)) {
                    newParameterTypes.add(LITERAL);
                } else if (MODIFY.equals(type)) {
                    newParameterTypes.add(MODIFY);
                } else if (TRANSLATION.equals(type)) {
                    newParameterTypes.add(TRANSLATION);
                } else if (CUSTOM_MODIFY.equals(type)) {
                    newParameterTypes.add(CUSTOM_MODIFY);
                } else if (OUT.equals(type)) {
                    newParameterTypes.add(OUT);
                } else if (INOUT.equals(type)) {
                    newParameterTypes.add(INOUT);
                } else if (IN.equals(type)) {
                    newParameterTypes.add(IN);
                } else if (OUT_CURSOR.equals(type)) {
                    newParameterTypes.add(OUT_CURSOR);
                }
            }
            parameterTypes = newParameterTypes;
        }
    }
}
