// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (c) 2012-2014 Monty Program Ab
// Copyright (c) 2015-2021 MariaDB Corporation Ab

package org.mariadb.jdbc;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.sql.Date;
import java.sql.ParameterMetaData;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import org.mariadb.jdbc.client.ColumnDecoder;
import org.mariadb.jdbc.client.util.Parameters;
import org.mariadb.jdbc.codec.*;
import org.mariadb.jdbc.export.ExceptionFactory;
import org.mariadb.jdbc.export.Prepare;
import org.mariadb.jdbc.plugin.Codec;
import org.mariadb.jdbc.plugin.codec.*;
import org.mariadb.jdbc.util.ParameterList;

/** Common methods for prepare statement, for client and server prepare statement. */
public abstract class BasePreparedStatement extends Statement implements PreparedStatement {

  /** parameters */
  protected Parameters parameters;

  /** batching parameters */
  protected List<Parameters> batchParameters;

  /** prepare statement sql command */
  protected final String sql;

  /** PREPARE command result */
  protected Prepare prepareResult = null;

  /**
   * Constructor
   *
   * @param sql sql command
   * @param con connection
   * @param lock thread safe lock
   * @param canUseServerTimeout indicate if server can support server timeout
   * @param canUseServerMaxRows indicate if server can support max rows
   * @param autoGeneratedKeys indicate if automatif generated key retrival is required
   * @param resultSetType resultset type
   * @param resultSetConcurrency resultset concurrency
   * @param defaultFetchSize default fetch size
   */
  public BasePreparedStatement(
      String sql,
      Connection con,
      ReentrantLock lock,
      boolean canUseServerTimeout,
      boolean canUseServerMaxRows,
      int autoGeneratedKeys,
      int resultSetType,
      int resultSetConcurrency,
      int defaultFetchSize) {
    super(
        con,
        lock,
        canUseServerTimeout,
        canUseServerMaxRows,
        autoGeneratedKeys,
        resultSetType,
        resultSetConcurrency,
        defaultFetchSize);
    this.sql = sql;
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder("sql:'" + sql + "'");
    sb.append(", parameters:[");
    for (int i = 0; i < parameters.size(); i++) {
      org.mariadb.jdbc.client.util.Parameter param = parameters.get(i);
      if (param == null) {
        sb.append("null");
      } else {
        sb.append(param.bestEffortStringValue(con.getContext()));
      }
      if (i != parameters.size() - 1) {
        sb.append(",");
      }
    }
    sb.append("]");
    return sb.toString();
  }

  /**
   * Set PREPARE result
   *
   * @param prepareResult prepare result
   */
  public void setPrepareResult(Prepare prepareResult) {
    this.prepareResult = prepareResult;
  }

  /**
   * Get cached metadata list
   *
   * @return metadata list
   */
  public ColumnDecoder[] getMeta() {
    return this.prepareResult.getColumns();
  }

  /**
   * update cached metadata list
   *
   * @param ci metadata columns
   */
  public void updateMeta(ColumnDecoder[] ci) {
    this.prepareResult.setColumns(ci);
  }

  public abstract boolean execute() throws SQLException;

  public abstract ResultSet executeQuery() throws SQLException;

  public abstract int executeUpdate() throws SQLException;

  public abstract long executeLargeUpdate() throws SQLException;

  public abstract void addBatch() throws SQLException;

  public abstract ResultSetMetaData getMetaData() throws SQLException;

  public abstract ParameterMetaData getParameterMetaData() throws SQLException;

  /**
   * Set all parameters
   *
   * @param parameters parameters
   */
  public void setParameters(Parameters parameters) {
    this.parameters = parameters;
  }

  /**
   * Set parameter
   *
   * @param index parameter index
   * @param param parameter
   */
  public void setParameter(int index, org.mariadb.jdbc.client.util.Parameter param) {
    parameters.set(index, param);
  }

  @Override
  public abstract int[] executeBatch() throws SQLException;

  @Override
  public abstract long[] executeLargeBatch() throws SQLException;

  // ***************************************************************************************************
  // methods inherited from Statement that are disabled
  // ***************************************************************************************************

  @Override
  public void addBatch(String sql) throws SQLException {
    throw exceptionFactory().create("addBatch(String sql) cannot be called on preparedStatement");
  }

  @Override
  public boolean execute(String sql) throws SQLException {
    throw exceptionFactory().create("execute(String sql) cannot be called on preparedStatement");
  }

  @Override
  public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
    throw exceptionFactory()
        .create("execute(String sql, int autoGeneratedKeys) cannot be called on preparedStatement");
  }

  @Override
  public boolean execute(String sql, int[] columnIndexes) throws SQLException {
    throw exceptionFactory()
        .create("execute(String sql, int[] columnIndexes) cannot be called on preparedStatement");
  }

  @Override
  public boolean execute(String sql, String[] columnNames) throws SQLException {
    throw exceptionFactory()
        .create("execute(String sql, String[] columnNames) cannot be called on preparedStatement");
  }

  @Override
  public ResultSet executeQuery(String sql) throws SQLException {
    throw exceptionFactory()
        .create("executeQuery(String sql) cannot be called on preparedStatement");
  }

  @Override
  public int executeUpdate(String sql) throws SQLException {
    throw exceptionFactory()
        .create("executeUpdate(String sql) cannot be called on preparedStatement");
  }

  @Override
  public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
    throw exceptionFactory()
        .create(
            "executeUpdate(String sql, int autoGeneratedKeys) cannot be called on"
                + " preparedStatement");
  }

  @Override
  public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
    throw exceptionFactory()
        .create(
            "executeUpdate(String sql, int[] columnIndexes) cannot be called on preparedStatement");
  }

  @Override
  public int executeUpdate(String sql, String[] columnNames) throws SQLException {
    throw exceptionFactory()
        .create(
            "executeUpdate(String sql, String[] columnNames) cannot be called on"
                + " preparedStatement");
  }

  @Override
  public long executeLargeUpdate(String sql) throws SQLException {
    throw exceptionFactory()
        .create("executeLargeUpdate(String sql) cannot be called on preparedStatement");
  }

  @Override
  public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
    throw exceptionFactory()
        .create(
            "executeLargeUpdate(String sql, int autoGeneratedKeys) cannot be called on"
                + " preparedStatement");
  }

  @Override
  public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
    throw exceptionFactory()
        .create(
            "executeLargeUpdate(String sql, int[] columnIndexes) cannot be called on"
                + " preparedStatement");
  }

  @Override
  public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
    throw exceptionFactory()
        .create(
            "executeLargeUpdate(String sql, String[] columnNames) cannot be called on"
                + " preparedStatement");
  }

  // ***************************************************************************************************
  // Setters
  // ***************************************************************************************************

  private void checkIndex(int index) throws SQLException {
    if (index <= 0) {
      throw exceptionFactory().create(String.format("wrong parameter index %s", index));
    }
  }

  /**
   * Sets the designated parameter to SQL <code>NULL</code>.
   *
   * <p><B>Note:</B> You must specify the parameter's SQL type.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if <code>sqlType</code> is a <code>ARRAY</code>, <code>
   *     BLOB</code>, <code>CLOB</code>, <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>
   *     NCHAR</code>, <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>, <code>
   *     REF</code>, <code>ROWID</code>, <code>SQLXML</code> or <code>STRUCT</code> data type and
   *     the JDBC driver does not support this data type
   */
  @Override
  public void setNull(int parameterIndex, int sqlType) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, Parameter.NULL_PARAMETER);
  }

  /**
   * Sets the designated parameter to the given Java <code>boolean</code> value. The driver converts
   * this to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setBoolean(int parameterIndex, boolean x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new NonNullParameter<>(BooleanCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given Java <code>byte</code> value. The driver converts
   * this to an SQL <code>TINYINT</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setByte(int parameterIndex, byte x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new NonNullParameter<>(ByteCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given Java <code>short</code> value. The driver converts
   * this to an SQL <code>SMALLINT</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setShort(int parameterIndex, short x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new NonNullParameter<>(ShortCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given Java <code>int</code> value. The driver converts
   * this to an SQL <code>INTEGER</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setInt(int parameterIndex, int x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new NonNullParameter<>(IntCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given Java <code>long</code> value. The driver converts
   * this to an SQL <code>BIGINT</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setLong(int parameterIndex, long x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new NonNullParameter<>(LongCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given Java <code>float</code> value. The driver converts
   * this to an SQL <code>REAL</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setFloat(int parameterIndex, float x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new NonNullParameter<>(FloatCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given Java <code>double</code> value. The driver converts
   * this to an SQL <code>DOUBLE</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setDouble(int parameterIndex, double x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new NonNullParameter<>(DoubleCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given <code>java.math.BigDecimal</code> value. The driver
   * converts this to an SQL <code>NUMERIC</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(BigDecimalCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given Java <code>String</code> value. The driver converts
   * this to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value (depending on the
   * argument's size relative to the driver's limits on <code>VARCHAR</code> values) when it sends
   * it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setString(int parameterIndex, String x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StringCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given Java array of bytes. The driver converts this to an
   * SQL <code>VARBINARY</code> or <code>LONGVARBINARY</code> (depending on the argument's size
   * relative to the driver's limits on <code>VARBINARY</code> values) when it sends it to the
   * database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setBytes(int parameterIndex, byte[] x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ByteArrayCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Date</code> value using the default
   * time zone of the virtual machine that is running the application. The driver converts this to
   * an SQL <code>DATE</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setDate(int parameterIndex, Date x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(DateCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Time</code> value. The driver
   * converts this to an SQL <code>TIME</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setTime(int parameterIndex, Time x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(TimeCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value. The driver
   * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(TimestampCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given input stream, which will have the specified number
   * of bytes. When a very large ASCII value is input to a <code>LONGVARCHAR</code> parameter, it
   * may be more practical to send it via a <code>java.io.InputStream</code>. Data will be read from
   * the stream as needed until end-of-file is reached. The JDBC driver will do any necessary
   * conversion from ASCII to the database char format.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the Java input stream that contains the ASCII parameter value
   * @param length the number of bytes in the stream
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, (long) length));
  }

  /**
   * Sets the designated parameter to the given input stream, which will have the specified number
   * of bytes.
   *
   * <p>When a very large Unicode value is input to a <code>LONGVARCHAR</code> parameter, it may be
   * more practical to send it via a <code>java.io.InputStream</code> object. The data will be read
   * from the stream as needed until end-of-file is reached. The JDBC driver will do any necessary
   * conversion from Unicode to the database char format.
   *
   * <p>The byte format of the Unicode stream must be a Java UTF-8, as defined in the Java Virtual
   * Machine Specification.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x a <code>java.io.InputStream</code> object that contains the Unicode parameter value
   * @param length the number of bytes in the stream
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @deprecated Use {@code setCharacterStream}
   */
  @Override
  @Deprecated
  public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, (long) length));
  }

  /**
   * Sets the designated parameter to the given input stream, which will have the specified number
   * of bytes. When a very large binary value is input to a <code>LONGVARBINARY</code> parameter, it
   * may be more practical to send it via a <code>java.io.InputStream</code> object. The data will
   * be read from the stream as needed until end-of-file is reached.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the java input stream which contains the binary parameter value
   * @param length the number of bytes in the stream
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   */
  @Override
  public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, (long) length));
  }

  /**
   * Clears the current parameter values immediately.
   *
   * <p>In general, parameter values remain in force for repeated use of a statement. Setting a
   * parameter value automatically clears its previous value. However, in some cases it is useful to
   * immediately release the resources used by the current parameter values; this can be done by
   * calling the method <code>clearParameters</code>.
   *
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>PreparedStatement</code>
   */
  @Override
  public void clearParameters() throws SQLException {
    checkNotClosed();
    parameters = new ParameterList();
  }

  /**
   * Sets the value of the designated parameter with the given object.
   *
   * <p>This method is similar to {@link #setObject(int parameterIndex, Object x, int targetSqlType,
   * int scaleOrLength)}, except that it assumes a scale of zero.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value
   * @param targetSqlType the SQL type (as defined in java.sql.Types) to be sent to the database
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed
   *     PreparedStatement
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support the specified
   *     targetSqlType
   * @see Types
   */
  @Override
  public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
    setInternalObject(parameterIndex, x, targetSqlType, null);
  }

  /**
   * Sets the value of the designated parameter using the given object.
   *
   * <p>The JDBC specification specifies a standard mapping from Java <code>Object</code> types to
   * SQL types. The given argument will be converted to the corresponding SQL type before being sent
   * to the database.
   *
   * <p>Note that this method may be used to pass datatabase- specific abstract data types, by using
   * a driver-specific Java type.
   *
   * <p>If the object is of a class implementing the interface <code>SQLData</code>, the JDBC driver
   * should call the method <code>SQLData.writeSQL</code> to write it to the SQL data stream. If, on
   * the other hand, the object is of a class implementing <code>Ref</code>, <code>Blob</code>,
   * <code>Clob</code>, <code>NClob</code>, <code>Struct</code>, <code>java.net.URL</code>, <code>
   * RowId</code>, <code>SQLXML</code> or <code>Array</code>, the driver should pass it to the
   * database as a value of the corresponding SQL type.
   *
   * <p><b>Note:</b> Not all databases allow for a non-typed Null to be sent to the backend. For
   * maximum portability, the <code>setNull</code> or the <code>
   * setObject(int parameterIndex, Object x, int sqlType)</code> method should be used instead of
   * <code>setObject(int parameterIndex, Object x)</code>.
   *
   * <p><b>Note:</b> This method throws an exception if there is an ambiguity, for example, if the
   * object is of a class implementing more than one of the interfaces named above.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs; this method is called on a closed <code>
   *     PreparedStatement</code> or the type of the given object is ambiguous
   */
  @Override
  public void setObject(int parameterIndex, Object x) throws SQLException {
    setInternalObject(parameterIndex, x, null, null);
  }

  /**
   * Sets the designated parameter to the given <code>Reader</code> object, which is the given
   * number of characters long. When a very large UNICODE value is input to a <code>LONGVARCHAR
   * </code> parameter, it may be more practical to send it via a <code>java.io.Reader</code>
   * object. The data will be read from the stream as needed until end-of-file is reached. The JDBC
   * driver will do any necessary conversion from UNICODE to the database char format.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param reader the <code>java.io.Reader</code> object that contains the Unicode data
   * @param length the number of characters in the stream
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @since 1.2
   */
  @Override
  public void setCharacterStream(int parameterIndex, Reader reader, int length)
      throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(
        parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, reader, (long) length));
  }

  /**
   * Sets the designated parameter to the given <code>REF(&lt;structured-type&gt;)</code> value. The
   * driver converts this to an SQL <code>REF</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x an SQL <code>REF</code> value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.2
   */
  @Override
  public void setRef(int parameterIndex, Ref x) throws SQLException {
    throw exceptionFactory().notSupported("REF parameter are not supported");
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Blob</code> object. The driver
   * converts this to an SQL <code>BLOB</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.2
   */
  @Override
  public void setBlob(int parameterIndex, Blob x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(BlobCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Clob</code> object. The driver
   * converts this to an SQL <code>CLOB</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.2
   */
  @Override
  public void setClob(int parameterIndex, Clob x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ClobCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Array</code> object. The driver
   * converts this to an SQL <code>ARRAY</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x an <code>Array</code> object that maps an SQL <code>ARRAY</code> value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.2
   */
  @Override
  public void setArray(int parameterIndex, Array x) throws SQLException {
    throw exceptionFactory().notSupported("Array parameter are not supported");
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Date</code> value, using the given
   * <code>Calendar</code> object. The driver uses the <code>Calendar</code> object to construct an
   * SQL <code>DATE</code> value, which the driver then sends to the database. With a <code>Calendar
   * </code> object, the driver can calculate the date taking into account a custom timezone. If no
   * <code>Calendar</code> object is specified, the driver uses the default timezone, which is that
   * of the virtual machine running the application.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @param cal the <code>Calendar</code> object the driver will use to construct the date
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @since 1.2
   */
  @Override
  public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new ParameterWithCal<>(DateCodec.INSTANCE, x, cal));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Time</code> value, using the given
   * <code>Calendar</code> object. The driver uses the <code>Calendar</code> object to construct an
   * SQL <code>TIME</code> value, which the driver then sends to the database. With a <code>Calendar
   * </code> object, the driver can calculate the time taking into account a custom timezone. If no
   * <code>Calendar</code> object is specified, the driver uses the default timezone, which is that
   * of the virtual machine running the application.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @param cal the <code>Calendar</code> object the driver will use to construct the time
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @since 1.2
   */
  @Override
  public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new ParameterWithCal<>(TimeCodec.INSTANCE, x, cal));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value, using the
   * given <code>Calendar</code> object. The driver uses the <code>Calendar</code> object to
   * construct an SQL <code>TIMESTAMP</code> value, which the driver then sends to the database.
   * With a <code>Calendar</code> object, the driver can calculate the timestamp taking into account
   * a custom timezone. If no <code>Calendar</code> object is specified, the driver uses the default
   * timezone, which is that of the virtual machine running the application.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @param cal the <code>Calendar</code> object the driver will use to construct the timestamp
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @since 1.2
   */
  @Override
  public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new ParameterWithCal<>(TimestampCodec.INSTANCE, x, cal));
  }

  /**
   * Sets the designated parameter to SQL <code>NULL</code>. This version of the method <code>
   * setNull</code> should be used for user-defined types and REF type parameters. Examples of
   * user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and named array types.
   *
   * <p><B>Note:</B> To be portable, applications must give the SQL type code and the
   * fully-qualified SQL type name when specifying a NULL user-defined or REF parameter. In the case
   * of a user-defined type the name is the type name of the parameter itself. For a REF parameter,
   * the name is the type name of the referenced type. If a JDBC driver does not need the type code
   * or type name information, it may ignore it.
   *
   * <p>Although it is intended for user-defined and Ref parameters, this method may be used to set
   * a null parameter of any JDBC type. If the parameter does not have a user-defined or REF type,
   * the given typeName is ignored.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param sqlType a value from <code>java.sql.Types</code>
   * @param typeName the fully-qualified name of an SQL user-defined type; ignored if the parameter
   *     is not a user-defined type or REF
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if <code>sqlType</code> is a <code>ARRAY</code>, <code>
   *     BLOB</code>, <code>CLOB</code>, <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>
   *     NCHAR</code>, <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>, <code>
   *     REF</code>, <code>ROWID</code>, <code>SQLXML</code> or <code>STRUCT</code> data type and
   *     the JDBC driver does not support this data type or if the JDBC driver does not support this
   *     method
   * @since 1.2
   */
  @Override
  public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, Parameter.NULL_PARAMETER);
  }

  /**
   * Sets the designated parameter to the given <code>java.net.URL</code> value. The driver converts
   * this to an SQL <code>DATALINK</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the <code>java.net.URL</code> object to be set
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.4
   */
  @Override
  public void setURL(int parameterIndex, URL x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StringCodec.INSTANCE, x.toString()));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The driver
   * converts this to an SQL <code>ROWID</code> value when it sends it to the database
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setRowId(int parameterIndex, RowId x) throws SQLException {
    throw exceptionFactory().notSupported("RowId parameter are not supported");
  }

  /**
   * Sets the designated parameter to the given <code>String</code> object. The driver converts this
   * to an SQL <code>NCHAR</code> or <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
   * (depending on the argument's size relative to the driver's limits on <code>NVARCHAR</code>
   * values) when it sends it to the database.
   *
   * @param parameterIndex of the first parameter is 1, the second is 2, ...
   * @param value the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if the driver does not support national character sets; if the driver can detect
   *     that a data conversion error could occur; if a database access error occurs; or this method
   *     is called on a closed <code>PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setNString(int parameterIndex, String value) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StringCodec.INSTANCE, value));
  }

  /**
   * Sets the designated parameter to a <code>Reader</code> object. The <code>Reader</code> reads
   * the data till end-of-file is reached. The driver does the necessary conversion from Java
   * character format to the national character set in the database.
   *
   * @param parameterIndex of the first parameter is 1, the second is 2, ...
   * @param value the parameter value
   * @param length the number of characters in the parameter data.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if the driver does not support national character sets; if the driver can detect
   *     that a data conversion error could occur; if a database access error occurs; or this method
   *     is called on a closed <code>PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setNCharacterStream(int parameterIndex, Reader value, long length)
      throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, value, length));
  }

  /**
   * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this
   * to an SQL <code>NCLOB</code> value when it sends it to the database.
   *
   * @param parameterIndex of the first parameter is 1, the second is 2, ...
   * @param value the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if the driver does not support national character sets; if the driver can detect
   *     that a data conversion error could occur; if a database access error occurs; or this method
   *     is called on a closed <code>PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setNClob(int parameterIndex, NClob value) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ClobCodec.INSTANCE, value));
  }

  /**
   * Sets the designated parameter to a <code>Reader</code> object. The reader must contain the
   * number of characters specified by length otherwise a <code>SQLException</code> will be
   * generated when the <code>PreparedStatement</code> is executed. This method differs from the
   * <code>setCharacterStream (int, Reader, int)</code> method because it informs the driver that
   * the parameter value should be sent to the server as a <code>CLOB</code>. When the <code>
   * setCharacterStream</code> method is used, the driver may have to do extra work to determine
   * whether the parameter data should be sent to the server as a <code>LONGVARCHAR</code> or a
   * <code>CLOB</code>
   *
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param reader An object that contains the data to set the parameter value to.
   * @param length the number of characters in the parameter data.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs; this method is called on a closed <code>
   *     PreparedStatement</code> or if the length specified is less than zero.
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, reader, length));
  }

  /**
   * Sets the designated parameter to a <code>InputStream</code> object. The inputstream must
   * contain the number of characters specified by length otherwise a <code>SQLException</code> will
   * be generated when the <code>PreparedStatement</code> is executed. This method differs from the
   * <code>setBinaryStream (int, InputStream, int)</code> method because it informs the driver that
   * the parameter value should be sent to the server as a <code>BLOB</code>. When the <code>
   * setBinaryStream</code> method is used, the driver may have to do extra work to determine
   * whether the parameter data should be sent to the server as a <code>LONGVARBINARY</code> or a
   * <code>BLOB</code>
   *
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param inputStream An object that contains the data to set the parameter value to.
   * @param length the number of bytes in the parameter data.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs; this method is called on a closed <code>
   *     PreparedStatement</code>; if the length specified is less than zero or if the number of
   *     bytes in the inputstream does not match the specified length.
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setBlob(int parameterIndex, InputStream inputStream, long length)
      throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, inputStream, length));
  }

  /**
   * Sets the designated parameter to a <code>Reader</code> object. The reader must contain the
   * number of characters specified by length otherwise a <code>SQLException</code> will be
   * generated when the <code>PreparedStatement</code> is executed. This method differs from the
   * <code>setCharacterStream (int, Reader, int)</code> method because it informs the driver that
   * the parameter value should be sent to the server as a <code>NCLOB</code>. When the <code>
   * setCharacterStream</code> method is used, the driver may have to do extra work to determine
   * whether the parameter data should be sent to the server as a <code>LONGNVARCHAR</code> or a
   * <code>NCLOB</code>
   *
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param reader An object that contains the data to set the parameter value to.
   * @param length the number of characters in the parameter data.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if the length specified is less than zero; if the driver does not support
   *     national character sets; if the driver can detect that a data conversion error could occur;
   *     if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, reader, length));
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object. The driver
   * converts this to an SQL <code>XML</code> value when it sends it to the database.
   *
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs; this method is called on a closed <code>
   *     PreparedStatement</code> or the <code>java.xml.transform.Result</code>, <code>Writer</code>
   *     or <code>OutputStream</code> has not been closed for the <code>SQLXML</code> object
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
    throw exceptionFactory().notSupported("SQLXML parameter are not supported");
  }

  private ExceptionFactory exceptionFactory() {
    return con.getExceptionFactory().of(this);
  }

  /**
   * Sets the value of the designated parameter with the given object.
   *
   * <p>If the second argument is an <code>InputStream</code> then the stream must contain the
   * number of bytes specified by scaleOrLength. If the second argument is a <code>Reader</code>
   * then the reader must contain the number of characters specified by scaleOrLength. If these
   * conditions are not true the driver will generate a <code>SQLException</code> when the prepared
   * statement is executed.
   *
   * <p>The given Java object will be converted to the given targetSqlType before being sent to the
   * database.
   *
   * <p>If the object has a custom mapping (is of a class implementing the interface <code>SQLData
   * </code>), the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it to
   * the SQL data stream. If, on the other hand, the object is of a class implementing <code>Ref
   * </code>, <code>Blob</code>, <code>Clob</code>, <code>NClob</code>, <code>Struct</code>, <code>
   * java.net.URL</code>, or <code>Array</code>, the driver should pass it to the database as a
   * value of the corresponding SQL type.
   *
   * <p>Note that this method may be used to pass database-specific abstract data types.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value
   * @param targetSqlType the SQL type (as defined in java.sql.Types) to be sent to the database.
   *     The scale argument may further qualify this type.
   * @param scaleOrLength for <code>java.sql.Types.DECIMAL</code> or <code>
   *     java.sql.Types.NUMERIC types</code>, this is the number of digits after the decimal point.
   *     For Java Object types <code>InputStream</code> and <code>Reader</code>, this is the length
   *     of the data in the stream or reader. For all other types, this value will be ignored.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs; this method is called on a closed <code>
   *     PreparedStatement</code> or if the Java Object specified by x is an InputStream or Reader
   *     object and the value of the scale parameter is less than zero
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support the specified
   *     targetSqlType
   * @see Types
   */
  @Override
  public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength)
      throws SQLException {
    setInternalObject(parameterIndex, x, targetSqlType, (long) scaleOrLength);
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  private void setInternalObject(
      int parameterIndex, Object obj, Integer targetSqlType, Long scaleOrLength)
      throws SQLException {
    checkIndex(parameterIndex);
    if (obj == null) {
      parameters.set(parameterIndex - 1, Parameter.NULL_PARAMETER);
      return;
    }

    if (targetSqlType != null) {
      // target type is defined.
      // in case of not corresponding data type, converting
      switch (targetSqlType) {
        case Types.ARRAY:
        case Types.DATALINK:
        case Types.JAVA_OBJECT:
        case Types.REF:
        case Types.ROWID:
        case Types.SQLXML:
        case Types.STRUCT:
          throw exceptionFactory().notSupported("Type not supported");
        default:
          break;
      }

      if (obj instanceof String || obj instanceof Character) {
        if (targetSqlType == Types.BLOB) {
          throw exceptionFactory()
              .create(
                  String.format(
                      "Cannot convert a %s to a Blob",
                      obj instanceof String ? "string" : "character"));
        }
        String str = obj instanceof String ? (String) obj : ((Character) obj).toString();
        try {
          switch (targetSqlType) {
            case Types.BIT:
            case Types.BOOLEAN:
              setBoolean(parameterIndex, !("false".equalsIgnoreCase(str) || "0".equals(str)));
              return;
            case Types.TINYINT:
              setByte(parameterIndex, Byte.parseByte(str));
              return;
            case Types.SMALLINT:
              setShort(parameterIndex, Short.parseShort(str));
              return;
            case Types.INTEGER:
              setInt(parameterIndex, Integer.parseInt(str));
              return;
            case Types.DOUBLE:
            case Types.FLOAT:
              setDouble(parameterIndex, Double.valueOf(str));
              return;
            case Types.REAL:
              setFloat(parameterIndex, Float.valueOf(str));
              return;
            case Types.BIGINT:
              setLong(parameterIndex, Long.valueOf(str));
              return;
            case Types.DECIMAL:
            case Types.NUMERIC:
              setBigDecimal(parameterIndex, new BigDecimal(str));
              return;
            case Types.CLOB:
            case Types.NCLOB:
            case Types.CHAR:
            case Types.VARCHAR:
            case Types.LONGVARCHAR:
            case Types.NCHAR:
            case Types.NVARCHAR:
            case Types.LONGNVARCHAR:
              setString(parameterIndex, str);
              return;
            case Types.TIMESTAMP:
              if (str.startsWith("0000-00-00")) {
                setTimestamp(parameterIndex, null);
              } else {
                setTimestamp(parameterIndex, Timestamp.valueOf(str));
              }
              return;
            case Types.TIME:
              setTime(parameterIndex, Time.valueOf((String) obj));
              return;
            default:
              throw exceptionFactory()
                  .create(String.format("Could not convert [%s] to %s", str, targetSqlType));
          }
        } catch (IllegalArgumentException e) {
          throw exceptionFactory()
              .create(
                  String.format("Could not convert [%s] to java.sql.Type %s", str, targetSqlType),
                  "HY000",
                  e);
        }
      } else if (obj instanceof Number) {
        Number bd = (Number) obj;
        switch (targetSqlType) {
          case Types.TINYINT:
            setByte(parameterIndex, bd.byteValue());
            return;
          case Types.SMALLINT:
            setShort(parameterIndex, bd.shortValue());
            return;
          case Types.INTEGER:
            setInt(parameterIndex, bd.intValue());
            return;
          case Types.BIGINT:
            setLong(parameterIndex, bd.longValue());
            return;
          case Types.FLOAT:
          case Types.DOUBLE:
            setDouble(parameterIndex, bd.doubleValue());
            return;
          case Types.REAL:
            setFloat(parameterIndex, bd.floatValue());
            return;
          case Types.DECIMAL:
          case Types.NUMERIC:
            if (obj instanceof BigDecimal) {
              setBigDecimal(parameterIndex, (BigDecimal) obj);
            } else if (obj instanceof Double || obj instanceof Float) {
              setDouble(parameterIndex, bd.doubleValue());
            } else {
              setLong(parameterIndex, bd.longValue());
            }
            return;
          case Types.BIT:
            setBoolean(parameterIndex, bd.shortValue() != 0);
            return;
          case Types.CHAR:
          case Types.VARCHAR:
            setString(parameterIndex, bd.toString());
            return;
          default:
            throw exceptionFactory()
                .create(String.format("Could not convert [%s] to %s", bd, targetSqlType));
        }
      } else if (obj instanceof byte[]) {
        if (targetSqlType == Types.BINARY
            || targetSqlType == Types.VARBINARY
            || targetSqlType == Types.LONGVARBINARY) {
          setBytes(parameterIndex, (byte[]) obj);
          return;
        } else if (targetSqlType == Types.BLOB) {
          setBlob(parameterIndex, new MariaDbBlob((byte[]) obj));
        } else {
          throw exceptionFactory()
              .create("Can only convert a byte[] to BINARY, VARBINARY, LONGVARBINARY or BLOB type");
        }
      }
    }

    // in case parameter still not set, defaulting to object type
    for (Codec<?> codec : con.getContext().getConf().codecs()) {
      if (codec.canEncode(obj)) {
        Parameter p = new Parameter(codec, obj, scaleOrLength);
        parameters.set(parameterIndex - 1, p);
        return;
      }
    }

    throw new SQLException(String.format("Type %s not supported type", obj.getClass().getName()));
  }

  /**
   * Sets the designated parameter to the given input stream, which will have the specified number
   * of bytes. When a very large ASCII value is input to a <code>LONGVARCHAR</code> parameter, it
   * may be more practical to send it via a <code>java.io.InputStream</code>. Data will be read from
   * the stream as needed until end-of-file is reached. The JDBC driver will do any necessary
   * conversion from ASCII to the database char format.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the Java input stream that contains the ASCII parameter value
   * @param length the number of bytes in the stream
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @since 1.6
   */
  @Override
  public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, length));
  }

  /**
   * Sets the designated parameter to the given input stream, which will have the specified number
   * of bytes. When a very large binary value is input to a <code>LONGVARBINARY</code> parameter, it
   * may be more practical to send it via a <code>java.io.InputStream</code> object. The data will
   * be read from the stream as needed until end-of-file is reached.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the java input stream which contains the binary parameter value
   * @param length the number of bytes in the stream
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @since 1.6
   */
  @Override
  public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, length));
  }

  /**
   * Sets the designated parameter to the given <code>Reader</code> object, which is the given
   * number of characters long. When a very large UNICODE value is input to a <code>LONGVARCHAR
   * </code> parameter, it may be more practical to send it via a <code>java.io.Reader</code>
   * object. The data will be read from the stream as needed until end-of-file is reached. The JDBC
   * driver will do any necessary conversion from UNICODE to the database char format.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param reader the <code>java.io.Reader</code> object that contains the Unicode data
   * @param length the number of characters in the stream
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @since 1.6
   */
  @Override
  public void setCharacterStream(int parameterIndex, Reader reader, long length)
      throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, reader, length));
  }

  /**
   * Sets the designated parameter to the given input stream. When a very large ASCII value is input
   * to a <code>LONGVARCHAR</code> parameter, it may be more practical to send it via a <code>
   * java.io.InputStream</code>. Data will be read from the stream as needed until end-of-file is
   * reached. The JDBC driver will do any necessary conversion from ASCII to the database char
   * format.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * <p><B>Note:</B> Consult your JDBC driver documentation to determine if it might be more
   * efficient to use a version of <code>setAsciiStream</code> which takes a length parameter.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the Java input stream that contains the ASCII parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given input stream. When a very large binary value is
   * input to a <code>LONGVARBINARY</code> parameter, it may be more practical to send it via a
   * <code>java.io.InputStream</code> object. The data will be read from the stream as needed until
   * end-of-file is reached.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * <p><B>Note:</B> Consult your JDBC driver documentation to determine if it might be more
   * efficient to use a version of <code>setBinaryStream</code> which takes a length parameter.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the java input stream which contains the binary parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x));
  }

  /**
   * Sets the designated parameter to the given <code>Reader</code> object. When a very large
   * UNICODE value is input to a <code>LONGVARCHAR</code> parameter, it may be more practical to
   * send it via a <code>java.io.Reader</code> object. The data will be read from the stream as
   * needed until end-of-file is reached. The JDBC driver will do any necessary conversion from
   * UNICODE to the database char format.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * <p><B>Note:</B> Consult your JDBC driver documentation to determine if it might be more
   * efficient to use a version of <code>setCharacterStream</code> which takes a length parameter.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param reader the <code>java.io.Reader</code> object that contains the Unicode data
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed <code>
   *     PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, reader));
  }

  /**
   * Sets the designated parameter to a <code>Reader</code> object. The <code>Reader</code> reads
   * the data till end-of-file is reached. The driver does the necessary conversion from Java
   * character format to the national character set in the database.
   *
   * <p><B>Note:</B> This stream object can either be a standard Java stream object or your own
   * subclass that implements the standard interface.
   *
   * <p><B>Note:</B> Consult your JDBC driver documentation to determine if it might be more
   * efficient to use a version of <code>setNCharacterStream</code> which takes a length parameter.
   *
   * @param parameterIndex of the first parameter is 1, the second is 2, ...
   * @param value the parameter value
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if the driver does not support national character sets; if the driver can detect
   *     that a data conversion error could occur; if a database access error occurs; or this method
   *     is called on a closed <code>PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, value));
  }

  /**
   * Sets the designated parameter to a <code>Reader</code> object. This method differs from the
   * <code>setCharacterStream (int, Reader)</code> method because it informs the driver that the
   * parameter value should be sent to the server as a <code>CLOB</code>. When the <code>
   * setCharacterStream</code> method is used, the driver may have to do extra work to determine
   * whether the parameter data should be sent to the server as a <code>LONGVARCHAR</code> or a
   * <code>CLOB</code>
   *
   * <p><B>Note:</B> Consult your JDBC driver documentation to determine if it might be more
   * efficient to use a version of <code>setClob</code> which takes a length parameter.
   *
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param reader An object that contains the data to set the parameter value to.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs; this method is called on a closed <code>
   *     PreparedStatement</code>or if parameterIndex does not correspond to a parameter marker in
   *     the SQL statement
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setClob(int parameterIndex, Reader reader) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, reader));
  }

  /**
   * Sets the designated parameter to a <code>InputStream</code> object. This method differs from
   * the <code>setBinaryStream (int, InputStream)</code> method because it informs the driver that
   * the parameter value should be sent to the server as a <code>BLOB</code>. When the <code>
   * setBinaryStream</code> method is used, the driver may have to do extra work to determine
   * whether the parameter data should be sent to the server as a <code>LONGVARBINARY</code> or a
   * <code>BLOB</code>
   *
   * <p><B>Note:</B> Consult your JDBC driver documentation to determine if it might be more
   * efficient to use a version of <code>setBlob</code> which takes a length parameter.
   *
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param inputStream An object that contains the data to set the parameter value to.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs; this method is called on a closed <code>
   *     PreparedStatement</code> or if parameterIndex does not correspond to a parameter marker in
   *     the SQL statement,
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(StreamCodec.INSTANCE, inputStream));
  }

  /**
   * Sets the designated parameter to a <code>Reader</code> object. This method differs from the
   * <code>setCharacterStream (int, Reader)</code> method because it informs the driver that the
   * parameter value should be sent to the server as a <code>NCLOB</code>. When the <code>
   * setCharacterStream</code> method is used, the driver may have to do extra work to determine
   * whether the parameter data should be sent to the server as a <code>LONGNVARCHAR</code> or a
   * <code>NCLOB</code>
   *
   * <p><B>Note:</B> Consult your JDBC driver documentation to determine if it might be more
   * efficient to use a version of <code>setNClob</code> which takes a length parameter.
   *
   * @param parameterIndex index of the first parameter is 1, the second is 2, ...
   * @param reader An object that contains the data to set the parameter value to.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if the driver does not support national character sets; if the driver can detect
   *     that a data conversion error could occur; if a database access error occurs or this method
   *     is called on a closed <code>PreparedStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.6
   */
  @Override
  public void setNClob(int parameterIndex, Reader reader) throws SQLException {
    checkIndex(parameterIndex);
    parameters.set(parameterIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, reader));
  }

  /**
   * Sets the value of the designated parameter with the given object.
   *
   * <p>If the second argument is an {@code InputStream} then the stream must contain the number of
   * bytes specified by scaleOrLength. If the second argument is a {@code Reader} then the reader
   * must contain the number of characters specified by scaleOrLength. If these conditions are not
   * true the driver will generate a {@code SQLException} when the prepared statement is executed.
   *
   * <p>The given Java object will be converted to the given targetSqlType before being sent to the
   * database.
   *
   * <p>If the object has a custom mapping (is of a class implementing the interface {@code
   * SQLData}), the JDBC driver should call the method {@code SQLData.writeSQL} to write it to the
   * SQL data stream. If, on the other hand, the object is of a class implementing {@code Ref},
   * {@code Blob}, {@code Clob}, {@code NClob}, {@code Struct}, {@code java.net.URL}, or {@code
   * Array}, the driver should pass it to the database as a value of the corresponding SQL type.
   *
   * <p>Note that this method may be used to pass database-specific abstract data types.
   *
   * <p>The default implementation will throw {@code SQLFeatureNotSupportedException}
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value
   * @param targetSqlType the SQL type to be sent to the database. The scale argument may further
   *     qualify this type.
   * @param scaleOrLength for {@code java.sql.JDBCType.DECIMAL} or {@code java.sql.JDBCType.NUMERIC
   *     types}, this is the number of digits after the decimal point. For Java Object types {@code
   *     InputStream} and {@code Reader}, this is the length of the data in the stream or reader.
   *     For all other types, this value will be ignored.
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed {@code
   *     PreparedStatement} or if the Java Object specified by x is an InputStream or Reader object
   *     and the value of the scale parameter is less than zero
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support the specified
   *     targetSqlType
   * @see JDBCType
   * @see SQLType
   * @since 1.8
   */
  @Override
  public void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength)
      throws SQLException {
    setInternalObject(
        parameterIndex,
        x,
        targetSqlType == null ? null : targetSqlType.getVendorTypeNumber(),
        (long) scaleOrLength);
  }

  /**
   * Sets the value of the designated parameter with the given object.
   *
   * <p>This method is similar to {@link #setObject(int parameterIndex, Object x, SQLType
   * targetSqlType, int scaleOrLength)}, except that it assumes a scale of zero.
   *
   * <p>The default implementation will throw {@code SQLFeatureNotSupportedException}
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value
   * @param targetSqlType the SQL type to be sent to the database
   * @throws SQLException if parameterIndex does not correspond to a parameter marker in the SQL
   *     statement; if a database access error occurs or this method is called on a closed {@code
   *     PreparedStatement}
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support the specified
   *     targetSqlType
   * @see JDBCType
   * @see SQLType
   * @since 1.8
   */
  @Override
  public void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException {
    setInternalObject(
        parameterIndex,
        x,
        targetSqlType == null ? null : targetSqlType.getVendorTypeNumber(),
        null);
  }
}
