// 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 static org.mariadb.jdbc.util.constants.Capabilities.LOCAL_FILES;

import java.io.InputStream;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.locks.ReentrantLock;
import org.mariadb.jdbc.client.ColumnDecoder;
import org.mariadb.jdbc.client.Completion;
import org.mariadb.jdbc.client.DataType;
import org.mariadb.jdbc.client.result.CompleteResult;
import org.mariadb.jdbc.client.result.Result;
import org.mariadb.jdbc.export.ExceptionFactory;
import org.mariadb.jdbc.message.client.QueryPacket;
import org.mariadb.jdbc.message.server.OkPacket;
import org.mariadb.jdbc.util.NativeSql;
import org.mariadb.jdbc.util.constants.ColumnFlags;
import org.mariadb.jdbc.util.constants.ServerStatus;

/** Statement implementation */
public class Statement implements java.sql.Statement {

  private List<String> batchQueries;

  /** result-set type */
  protected final int resultSetType;
  /** concurrency */
  protected final int resultSetConcurrency;
  /** thread safe locker */
  protected final ReentrantLock lock;
  /** can use server query timeout */
  protected final boolean canUseServerTimeout;
  /** can use server row limitation */
  protected final boolean canUseServerMaxRows;
  /** connection */
  protected final Connection con;
  /** required query timeout */
  protected int queryTimeout;
  /** maximum row number */
  protected long maxRows;
  /** fetch size */
  protected int fetchSize;
  /** automatic generated keys result required */
  protected int autoGeneratedKeys;
  /** close statement on resultset completion */
  protected boolean closeOnCompletion;
  /** closed flag */
  protected boolean closed;
  /** escape processing */
  protected boolean escape;
  /** last execution results */
  protected List<Completion> results;
  /** current results */
  protected Completion currResult;
  /** streaming load data infile data */
  protected InputStream localInfileInputStream;

  /**
   * Constructor
   *
   * @param con connection
   * @param lock thread safe locker
   * @param canUseServerTimeout can use server timeout
   * @param canUseServerMaxRows can use server row number limitation
   * @param autoGeneratedKeys automatic generated keys result required
   * @param resultSetType result-set type
   * @param resultSetConcurrency concurrency
   * @param defaultFetchSize fetch size
   */
  public Statement(
      Connection con,
      ReentrantLock lock,
      boolean canUseServerTimeout,
      boolean canUseServerMaxRows,
      int autoGeneratedKeys,
      int resultSetType,
      int resultSetConcurrency,
      int defaultFetchSize) {
    this.con = con;
    this.lock = lock;
    this.resultSetConcurrency = resultSetConcurrency;
    this.resultSetType = resultSetType;
    this.autoGeneratedKeys = autoGeneratedKeys;
    this.canUseServerTimeout = canUseServerTimeout;
    this.canUseServerMaxRows = canUseServerMaxRows;
    this.fetchSize = defaultFetchSize;
  }

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

  /**
   * Set current local infile stream
   *
   * @param inputStream stream
   * @throws SQLException if statement is already closed
   */
  public void setLocalInfileInputStream(InputStream inputStream) throws SQLException {
    checkNotClosed();
    localInfileInputStream = inputStream;
  }

  /**
   * Executes the given SQL statement, which returns a single <code>ResultSet</code> object.
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql an SQL statement to be sent to the database, typically a static SQL <code>SELECT
   *     </code> statement
   * @return a <code>ResultSet</code> object that contains the data produced by the given query;
   *     never <code>null</code>
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the given SQL statement produces anything other than a single
   *     <code>ResultSet</code> object, the method is called on a <code>PreparedStatement</code> or
   *     <code>CallableStatement</code>
   * @throws java.sql.SQLTimeoutException when the driver has determined that the timeout value that
   *     was specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   */
  @Override
  public ResultSet executeQuery(String sql) throws SQLException {
    executeInternal(sql, Statement.NO_GENERATED_KEYS);
    currResult = results.remove(0);
    if (currResult instanceof Result) return (Result) currResult;
    return new CompleteResult(new ColumnDecoder[0], new byte[0][], con.getContext());
  }

  /**
   * Executes the given SQL statement, which may be an <code>INSERT</code>, <code>UPDATE</code>, or
   * <code>DELETE</code> statement or an SQL statement that returns nothing, such as an SQL DDL
   * statement.
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>,
   *     <code>UPDATE</code> or <code>DELETE</code>; or an SQL statement that returns nothing, such
   *     as a DDL statement.
   * @return either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0
   *     for SQL statements that return nothing
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the given SQL statement produces a <code>ResultSet</code> object,
   *     the method is called on a <code>PreparedStatement</code> or <code>CallableStatement</code>
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   */
  @Override
  public int executeUpdate(String sql) throws SQLException {
    return executeUpdate(sql, Statement.NO_GENERATED_KEYS);
  }

  /**
   * Releases this <code>Statement</code> object's database and JDBC resources immediately instead
   * of waiting for this to happen when it is automatically closed. It is generally good practice to
   * release resources as soon as you are finished with them to avoid tying up database resources.
   *
   * <p>Calling the method <code>close</code> on a <code>Statement</code> object that is already
   * closed has no effect.
   *
   * <p><B>Note:</B>When a <code>Statement</code> object is closed, its current <code>ResultSet
   * </code> object, if one exists, is also closed.
   *
   * @throws SQLException if a database access error occurs
   */
  @Override
  public void close() throws SQLException {
    if (!closed) {
      closed = true;

      if (currResult != null && currResult instanceof Result) {
        ((Result) currResult).closeFromStmtClose(lock);
      }

      // close result-set
      if (results != null && !results.isEmpty()) {
        for (Completion completion : results) {
          if (completion instanceof Result) {
            ((Result) completion).closeFromStmtClose(lock);
          }
        }
      }
    }
  }

  /**
   * Abort current command result if streaming. result-set will be incomplete and closed, but ensure
   * connection state
   */
  public void abort() {
    lock.lock();
    try {
      if (!closed) {
        closed = true;

        if (currResult != null && currResult instanceof Result) {
          ((Result) currResult).abort();
        }

        // close result-set
        if (results != null) {
          for (Completion completion : results) {
            if (completion instanceof Result) {
              ((Result) completion).abort();
            }
          }
        }
      }
    } finally {
      lock.unlock();
    }
  }

  /**
   * Retrieves the maximum number of bytes that can be returned for character and binary column
   * values in a <code>ResultSet</code> object produced by this <code>Statement</code> object. This
   * limit applies only to <code>BINARY</code>, <code>VARBINARY</code>, <code>LONGVARBINARY</code>,
   * <code>CHAR</code>, <code>VARCHAR</code>, <code>NCHAR</code>, <code>NVARCHAR</code>, <code>
   * LONGNVARCHAR</code> and <code>LONGVARCHAR</code> columns. If the limit is exceeded, the excess
   * data is silently discarded.
   *
   * @return the current column size limit for columns storing character and binary values; zero
   *     means there is no limit
   * @see #setMaxFieldSize
   */
  @Override
  public int getMaxFieldSize() {
    return 0;
  }

  /**
   * NOT SUPPORTED.
   *
   * @see #getMaxFieldSize
   */
  @Override
  public void setMaxFieldSize(int max) {}

  /**
   * Retrieves the maximum number of rows that a <code>ResultSet</code> object produced by this
   * <code>Statement</code> object can contain. If this limit is exceeded, the excess rows are
   * silently dropped.
   *
   * @return the current maximum number of rows for a <code>ResultSet</code> object produced by this
   *     <code>Statement</code> object; zero means there is no limit
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @see #setMaxRows
   */
  @Override
  public int getMaxRows() throws SQLException {
    checkNotClosed();
    return (int) maxRows;
  }

  /**
   * Sets the limit for the maximum number of rows that any <code>ResultSet</code> object generated
   * by this <code>Statement</code> object can contain to the given number. If the limit is
   * exceeded, the excess rows are silently dropped.
   *
   * @param max the new max rows limit; zero means there is no limit
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code> or the condition {@code max >= 0} is not satisfied
   * @see #getMaxRows
   */
  @Override
  public void setMaxRows(int max) throws SQLException {
    checkNotClosed();
    if (max < 0) {
      throw exceptionFactory().create("max rows cannot be negative : asked for " + max, "42000");
    }
    maxRows = max;
  }

  /**
   * Sets escape processing on or off. If escape scanning is on (the default), the driver will do
   * escape substitution before sending the SQL statement to the database.
   *
   * <p>The {@code Connection} and {@code DataSource} property {@code escapeProcessing} may be used
   * to change the default escape processing behavior. A value of true (the default) enables escape
   * Processing for all {@code Statement} objects. A value of false disables escape processing for
   * all {@code Statement} objects. The {@code setEscapeProcessing} method may be used to specify
   * the escape processing behavior for an individual {@code Statement} object.
   *
   * <p>Note: Since prepared statements have usually been parsed prior to making this call,
   * disabling escape processing for <code>PreparedStatements</code> objects will have no effect.
   *
   * @param enable <code>true</code> to enable escape processing; <code>false</code> to disable it
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   */
  @Override
  public void setEscapeProcessing(boolean enable) throws SQLException {
    checkNotClosed();
    this.escape = enable;
  }

  /**
   * Retrieves the number of seconds the driver will wait for a <code>Statement</code> object to
   * execute. If the limit is exceeded, a <code>SQLException</code> is thrown.
   *
   * @return the current query timeout limit in seconds; zero means there is no limit
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @see #setQueryTimeout
   */
  @Override
  public int getQueryTimeout() throws SQLException {
    checkNotClosed();
    return queryTimeout;
  }

  /**
   * Sets the number of seconds the driver will wait for a <code>Statement</code> object to execute
   * to the given number of seconds. By default, there is no limit on the amount of time allowed for
   * a running statement to complete. If the limit is exceeded, an <code>SQLTimeoutException</code>
   * is thrown. A JDBC driver must apply this limit to the <code>execute</code>, <code>executeQuery
   * </code> and <code>executeUpdate</code> methods.
   *
   * <p><strong>Note:</strong> JDBC driver implementations may also apply this limit to {@code
   * ResultSet} methods (consult your driver vendor documentation for details).
   *
   * <p><strong>Note:</strong> In the case of {@code Statement} batching, it is implementation
   * defined whether the time-out is applied to individual SQL commands added via the {@code
   * addBatch} method or to the entire batch of SQL commands invoked by the {@code executeBatch}
   * method (consult your driver vendor documentation for details).
   *
   * @param seconds the new query timeout limit in seconds; zero means there is no limit
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code> or the condition {@code seconds >= 0} is not satisfied
   * @see #getQueryTimeout
   */
  @Override
  public void setQueryTimeout(int seconds) throws SQLException {
    if (seconds < 0) {
      throw exceptionFactory()
          .create("Query timeout cannot be negative : asked for " + seconds, "42000");
    }
    this.queryTimeout = seconds;
  }

  /**
   * Cancels this <code>Statement</code> object if both the DBMS and driver support aborting an SQL
   * statement. This method can be used by one thread to cancel a statement that is being executed
   * by another thread.
   *
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   */
  @Override
  public void cancel() throws SQLException {
    checkNotClosed();
    boolean locked = lock.tryLock();
    // if any query is active, lock is set.
    // this avoids trying to execute a KILL QUERY if no query is running.
    if (!locked) {
      con.cancelCurrentQuery();
    } else {
      lock.unlock();
    }
  }

  /**
   * Retrieves the first warning reported by calls on this <code>Statement</code> object. Subsequent
   * <code>Statement</code> object warnings will be chained to this <code>SQLWarning</code> object.
   *
   * <p>The warning chain is automatically cleared each time a statement is (re)executed. This
   * method may not be called on a closed <code>Statement</code> object; doing so will cause an
   * <code>SQLException</code> to be thrown.
   *
   * <p><B>Note:</B> If you are processing a <code>ResultSet</code> object, any warnings associated
   * with reads on that <code>ResultSet</code> object will be chained on it rather than on the
   * <code>Statement</code> object that produced it.
   *
   * @return the first <code>SQLWarning</code> object or <code>null</code> if there are no warnings
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   */
  @Override
  public SQLWarning getWarnings() throws SQLException {
    return con.getWarnings();
  }

  /**
   * Clears all the warnings reported on this <code>Statement</code> object. After a call to this
   * method, the method <code>getWarnings</code> will return <code>null</code> until a new warning
   * is reported for this <code>Statement</code> object.
   */
  @Override
  public void clearWarnings() {
    con.getContext().setWarning(0);
  }

  /**
   * Sets the SQL cursor name to the given <code>String</code>, which will be used by subsequent
   * <code>Statement</code> object <code>execute</code> methods. This name can then be used in SQL
   * positioned update or delete statements to identify the current row in the <code>ResultSet
   * </code> object generated by this statement. If the database does not support positioned
   * update/delete, this method is a noop. To ensure that a cursor has the proper isolation level to
   * support updates, the cursor's <code>SELECT</code> statement should have the form <code>
   * SELECT FOR UPDATE</code>. If <code>FOR UPDATE</code> is not present, positioned updates may
   * fail.
   *
   * <p><B>Note:</B> By definition, the execution of positioned updates and deletes must be done by
   * a different <code>Statement</code> object than the one that generated the <code>ResultSet
   * </code> object being used for positioning. Also, cursor names must be unique within a
   * connection.
   *
   * @param name the new cursor name, which must be unique within a connection
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   */
  @Override
  public void setCursorName(String name) throws SQLException {
    throw exceptionFactory().notSupported("Cursors are not supported");
  }

  /**
   * Executes the given SQL statement, which may return multiple results. In some (uncommon)
   * situations, a single SQL statement may return multiple result sets and/or update counts.
   * Normally you can ignore this unless you are (1) executing a stored procedure that you know may
   * return multiple results or (2) you are dynamically executing an unknown SQL string.
   *
   * <p>The <code>execute</code> method executes an SQL statement and indicates the form of the
   * first result. You must then use the methods <code>getResultSet</code> or <code>getUpdateCount
   * </code> to retrieve the result, and <code>getMoreResults</code> to move to any subsequent
   * result(s).
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql any SQL statement
   * @return <code>true</code> if the first result is a <code>ResultSet</code> object; <code>false
   *     </code> if it is an update count or there are no results
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the method is called on a <code>PreparedStatement</code> or <code>
   *     CallableStatement</code>
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   * @see #getResultSet
   * @see #getUpdateCount
   * @see #getMoreResults
   */
  @Override
  public boolean execute(String sql) throws SQLException {
    return execute(sql, Statement.NO_GENERATED_KEYS);
  }

  /**
   * Retrieves the current result as a <code>ResultSet</code> object. This method should be called
   * only once per result.
   *
   * @return the current result as a <code>ResultSet</code> object or <code>null</code> if the
   *     result is an update count or there are no more results
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @see #execute
   */
  @Override
  public ResultSet getResultSet() throws SQLException {
    checkNotClosed();
    if (currResult instanceof Result) {
      return (Result) currResult;
    }
    return null;
  }

  /**
   * Retrieves the current result as an update count; if the result is a <code>ResultSet</code>
   * object or there are no more results, -1 is returned. This method should be called only once per
   * result.
   *
   * @return the current result as an update count; -1 if the current result is a <code>ResultSet
   *     </code> object or there are no more results
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @see #execute
   */
  @Override
  public int getUpdateCount() throws SQLException {
    checkNotClosed();
    if (currResult instanceof OkPacket) {
      return (int) ((OkPacket) currResult).getAffectedRows();
    }
    return -1;
  }

  /**
   * Moves to this <code>Statement</code> object's next result, returns <code>true</code> if it is a
   * <code>ResultSet</code> object, and implicitly closes any current <code>ResultSet</code>
   * object(s) obtained with the method <code>getResultSet</code>.
   *
   * <p>There are no more results when the following is true:
   *
   * <PRE>{@code
   * // stmt is a Statement object
   * ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))
   * }</PRE>
   *
   * @return <code>true</code> if the next result is a <code>ResultSet</code> object; <code>false
   *     </code> if it is an update count or there are no more results
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @see #execute
   */
  @Override
  public boolean getMoreResults() throws SQLException {
    return getMoreResults(Statement.CLOSE_CURRENT_RESULT);
  }

  /**
   * Retrieves the direction for fetching rows from database tables that is the default for result
   * sets generated from this <code>Statement</code> object. If this <code>Statement</code> object
   * has not set a fetch direction by calling the method <code>setFetchDirection</code>, the return
   * value is implementation-specific.
   *
   * @return the default fetch direction for result sets generated from this <code>Statement</code>
   *     object
   * @see #setFetchDirection
   * @since 1.2
   */
  @Override
  public int getFetchDirection() {
    return ResultSet.FETCH_FORWARD;
  }

  /**
   * Gives the driver a hint as to the direction in which rows will be processed in <code>ResultSet
   * </code> objects created using this <code>Statement</code> object. The default value is <code>
   * ResultSet.FETCH_FORWARD</code>.
   *
   * <p>Note that this method sets the default fetch direction for result sets generated by this
   * <code>Statement</code> object. Each result set has its own methods for getting and setting its
   * own fetch direction.
   *
   * @param direction the initial direction for processing rows
   */
  @Override
  public void setFetchDirection(int direction) {
    // not supported
  }

  /**
   * Retrieves the number of result set rows that is the default fetch size for <code>ResultSet
   * </code> objects generated from this <code>Statement</code> object. If this <code>Statement
   * </code> object has not set a fetch size by calling the method <code>setFetchSize</code>, the
   * return value is implementation-specific.
   *
   * @return the default fetch size for result sets generated from this <code>Statement</code>
   *     object
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @see #setFetchSize
   */
  @Override
  public int getFetchSize() throws SQLException {
    checkNotClosed();
    return this.fetchSize;
  }

  /**
   * Gives the JDBC driver a hint as to the number of rows that should be fetched from the database
   * when more rows are needed for <code>ResultSet</code> objects generated by this <code>Statement
   * </code>. If the value specified is zero, then the hint is ignored. The default value is zero.
   *
   * @param rows the number of rows to fetch
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code> or the condition {@code rows >= 0} is not satisfied.
   * @see #getFetchSize
   * @since 1.2
   */
  @Override
  public void setFetchSize(int rows) throws SQLException {
    if (rows < 0) {
      throw exceptionFactory().create("invalid fetch size");
    }
    this.fetchSize = rows;
  }

  /**
   * Retrieves the result set concurrency for <code>ResultSet</code> objects generated by this
   * <code>Statement</code> object.
   *
   * @return either <code>ResultSet.CONCUR_READ_ONLY</code> or <code>ResultSet.CONCUR_UPDATABLE
   *     </code>
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   */
  @Override
  public int getResultSetConcurrency() throws SQLException {
    checkNotClosed();
    return this.resultSetConcurrency;
  }

  /**
   * Retrieves the result set type for <code>ResultSet</code> objects generated by this <code>
   * Statement</code> object.
   *
   * @return one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, <code>
   *     ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
   * @since 1.2
   */
  @Override
  public int getResultSetType() {
    return this.resultSetType;
  }

  /**
   * Adds the given SQL command to the current list of commands for this <code>Statement</code>
   * object. The commands in this list can be executed as a batch by calling the method <code>
   * executeBatch</code>.
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql typically this is an SQL <code>INSERT</code> or <code>UPDATE</code> statement
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the driver does not support batch updates, the method is called on
   *     a <code>PreparedStatement</code> or <code>CallableStatement</code>
   * @see #executeBatch
   * @see DatabaseMetaData#supportsBatchUpdates
   */
  @Override
  public void addBatch(String sql) throws SQLException {
    if (sql == null) {
      throw exceptionFactory().create("null cannot be set to addBatch(String sql)");
    }
    if (batchQueries == null) batchQueries = new ArrayList<>();
    batchQueries.add(escape ? NativeSql.parse(sql, con.getContext()) : sql);
  }

  /**
   * Empties this <code>Statement</code> object's current list of SQL commands.
   *
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code> or the driver does not support batch updates
   * @see #addBatch
   * @see DatabaseMetaData#supportsBatchUpdates
   * @since 1.2
   */
  @Override
  public void clearBatch() throws SQLException {
    checkNotClosed();
    if (batchQueries == null) {
      batchQueries = new ArrayList<>();
    } else {
      batchQueries.clear();
    }
  }

  /**
   * Submits a batch of commands to the database for execution and if all commands execute
   * successfully, returns an array of update counts. The <code>int</code> elements of the array
   * that is returned are ordered to correspond to the commands in the batch, which are ordered
   * according to the order in which they were added to the batch. The elements in the array
   * returned by the method <code>executeBatch</code> may be one of the following:
   *
   * <OL>
   *   <LI>A number greater than or equal to zero -- indicates that the command was processed
   *       successfully and is an update count giving the number of rows in the database that were
   *       affected by the command's execution
   *   <LI>A value of <code>SUCCESS_NO_INFO</code> -- indicates that the command was processed
   *       successfully but that the number of rows affected is unknown
   *       <p>If one of the commands in a batch update fails to execute properly, this method throws
   *       a <code>BatchUpdateException</code>, and a JDBC driver may or may not continue to process
   *       the remaining commands in the batch. However, the driver's behavior must be consistent
   *       with a particular DBMS, either always continuing to process commands or never continuing
   *       to process commands. If the driver continues processing after a failure, the array
   *       returned by the method <code>BatchUpdateException.getUpdateCounts</code> will contain as
   *       many elements as there are commands in the batch, and at least one of the elements will
   *       be the following:
   *   <LI>A value of <code>EXECUTE_FAILED</code> -- indicates that the command failed to execute
   *       successfully and occurs only if a driver continues to process commands after a command
   *       fails
   * </OL>
   *
   * <p>The possible implementations and return values have been modified in the Java 2 SDK,
   * Standard Edition, version 1.3 to accommodate the option of continuing to process commands in a
   * batch update after a <code>BatchUpdateException</code> object has been thrown.
   *
   * @return an array of update counts containing one element for each command in the batch. The
   *     elements of the array are ordered according to the order in which commands were added to
   *     the batch.
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code> or the driver does not support batch statements. Throws {@link
   *     BatchUpdateException} (a subclass of <code>SQLException</code>) if one of the commands sent
   *     to the database fails to execute properly or attempts to return a result set.
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   * @see #addBatch
   * @see DatabaseMetaData#supportsBatchUpdates
   * @since 1.2
   */
  @Override
  public int[] executeBatch() throws SQLException {
    checkNotClosed();
    if (batchQueries == null || batchQueries.isEmpty()) return new int[0];
    lock.lock();
    try {
      // ensure pipelining is possible (no LOAD DATA/XML INFILE commands)
      boolean possibleLoadLocal = con.getContext().hasClientCapability(LOCAL_FILES);
      if (possibleLoadLocal) {
        possibleLoadLocal = false;
        for (int i = 0; i < batchQueries.size(); i++) {
          String sql = batchQueries.get(i).toUpperCase(Locale.ROOT);
          if (sql.contains(" LOCAL ") && sql.contains("LOAD") && sql.contains(" INFILE")) {
            possibleLoadLocal = true;
            break;
          }
        }
      }

      List<Completion> res =
          possibleLoadLocal ? executeInternalBatchStandard() : executeInternalBatchPipeline();

      results = res;

      int[] updates = new int[res.size()];
      for (int i = 0; i < res.size(); i++) {
        if (res.get(i) instanceof OkPacket) {
          updates[i] = (int) ((OkPacket) res.get(i)).getAffectedRows();
        } else {
          updates[i] = org.mariadb.jdbc.Statement.SUCCESS_NO_INFO;
        }
      }
      currResult = results.remove(0);
      batchQueries.clear();
      return updates;

    } finally {
      lock.unlock();
    }
  }

  /**
   * Retrieves the <code>Connection</code> object that produced this <code>Statement</code> object.
   *
   * @return the connection that produced this statement
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @since 1.2
   */
  @Override
  public Connection getConnection() throws SQLException {
    checkNotClosed();
    return con;
  }

  /**
   * Moves to this <code>Statement</code> object's next result, deals with any current <code>
   * ResultSet</code> object(s) according to the instructions specified by the given flag, and
   * returns <code>true</code> if the next result is a <code>ResultSet</code> object.
   *
   * <p>There are no more results when the following is true:
   *
   * <PRE>{@code
   * // stmt is a Statement object
   * ((stmt.getMoreResults(current) == false) && (stmt.getUpdateCount() == -1))
   * }</PRE>
   *
   * @param current one of the following <code>Statement</code> constants indicating what should
   *     happen to current <code>ResultSet</code> objects obtained using the method <code>
   *     getResultSet</code>: <code>Statement.CLOSE_CURRENT_RESULT</code>, <code>
   *     Statement.KEEP_CURRENT_RESULT</code>, or <code>Statement.CLOSE_ALL_RESULTS</code>
   * @return <code>true</code> if the next result is a <code>ResultSet</code> object; <code>false
   *     </code> if it is an update count or there are no more results
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code> or the argument supplied is not one of the following: <code>
   *     Statement.CLOSE_CURRENT_RESULT</code>, <code>Statement.KEEP_CURRENT_RESULT</code> or <code>
   *     Statement.CLOSE_ALL_RESULTS</code>
   * @throws SQLFeatureNotSupportedException if <code>DatabaseMetaData.supportsMultipleOpenResults
   *     </code> returns <code>false</code> and either <code>Statement.KEEP_CURRENT_RESULT</code> or
   *     <code>Statement.CLOSE_ALL_RESULTS</code> are supplied as the argument.
   * @see #execute
   * @since 1.4
   */
  @Override
  public boolean getMoreResults(int current) throws SQLException {
    checkNotClosed();
    if (currResult instanceof ResultSet) {
      lock.lock();
      try {
        Result result = (Result) currResult;
        if (current == java.sql.Statement.CLOSE_CURRENT_RESULT) {
          result.close();
        } else {
          result.fetchRemaining();
        }
        if (result.streaming()
            && (con.getContext().getServerStatus() & ServerStatus.MORE_RESULTS_EXISTS) > 0) {
          con.getClient()
              .readStreamingResults(
                  results,
                  fetchSize,
                  maxRows,
                  resultSetConcurrency,
                  resultSetType,
                  closeOnCompletion);
        }
      } finally {
        lock.unlock();
      }
    }

    if (results.size() > 0) {
      currResult = results.remove(0);
      return (currResult instanceof Result);
    }
    currResult = null;
    return false;
  }

  /**
   * Permit to streaming result to fetch remaining results.
   *
   * @throws SQLException if socket error occurs.
   */
  public void fetchRemaining() throws SQLException {
    if (currResult != null && currResult instanceof ResultSet) {
      Result result = (Result) currResult;
      result.fetchRemaining();
      if (result.streaming()
          && (con.getContext().getServerStatus() & ServerStatus.MORE_RESULTS_EXISTS) > 0) {
        con.getClient()
            .readStreamingResults(
                results, 0, 0L, resultSetConcurrency, resultSetType, closeOnCompletion);
      }
    }
  }

  /**
   * Retrieves any auto-generated keys created as a result of executing this <code>Statement</code>
   * object. If this <code>Statement</code> object did not generate any keys, an empty <code>
   * ResultSet</code> object is returned.
   *
   * <p><B>Note:</B>If the columns which represent the auto-generated keys were not specified, the
   * JDBC driver implementation will determine the columns which best represent the auto-generated
   * keys.
   *
   * @return a <code>ResultSet</code> object containing the auto-generated key(s) generated by the
   *     execution of this <code>Statement</code> object
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>Statement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @since 1.4
   */
  @Override
  public ResultSet getGeneratedKeys() throws SQLException {
    checkNotClosed();
    if (autoGeneratedKeys != java.sql.Statement.RETURN_GENERATED_KEYS) {
      throw new SQLException(
          "Cannot return generated keys: query was not set with Statement.RETURN_GENERATED_KEYS");
    }

    if (currResult instanceof OkPacket) {

      OkPacket ok = ((OkPacket) currResult);
      if (ok.getLastInsertId() != 0) {
        List<String[]> insertIds = new ArrayList<>();
        insertIds.add(new String[] {String.valueOf(ok.getLastInsertId())});
        for (Completion result : results) {
          if (result instanceof OkPacket) {
            insertIds.add(new String[] {String.valueOf(((OkPacket) result).getLastInsertId())});
          }
        }
        String[][] ids = insertIds.toArray(new String[0][]);
        return CompleteResult.createResultSet(
            "insert_id",
            DataType.BIGINT,
            ids,
            con.getContext(),
            ColumnFlags.AUTO_INCREMENT | ColumnFlags.UNSIGNED);
      }
    }

    return new CompleteResult(new ColumnDecoder[0], new byte[0][], con.getContext());
  }

  /**
   * Executes the given SQL statement and signals the driver with the given flag about whether the
   * auto-generated keys produced by this <code>Statement</code> object should be made available for
   * retrieval. The driver will ignore the flag if the SQL statement is not an <code>INSERT</code>
   * statement, or an SQL statement able to return auto-generated keys (the list of such statements
   * is vendor-specific).
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>,
   *     <code>UPDATE</code> or <code>DELETE</code>; or an SQL statement that returns nothing, such
   *     as a DDL statement.
   * @param autoGeneratedKeys a flag indicating whether auto-generated keys should be made available
   *     for retrieval; one of the following constants: <code>Statement.RETURN_GENERATED_KEYS</code>
   *     <code>Statement.NO_GENERATED_KEYS</code>
   * @return either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0
   *     for SQL statements that return nothing
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the given SQL statement returns a <code>ResultSet</code> object,
   *     the given constant is not one of those allowed, the method is called on a <code>
   *     PreparedStatement</code> or <code>CallableStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method with a
   *     constant of Statement.RETURN_GENERATED_KEYS
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   * @since 1.4
   */
  @Override
  public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
    executeInternal(sql, autoGeneratedKeys);

    currResult = results.remove(0);
    if (currResult instanceof Result) {
      throw exceptionFactory()
          .create("the given SQL statement produces an unexpected ResultSet object", "HY000");
    }
    return (int) ((OkPacket) currResult).getAffectedRows();
  }

  private void executeInternal(String sql, int autoGeneratedKeys) throws SQLException {
    checkNotClosed();
    lock.lock();
    try {
      this.autoGeneratedKeys = autoGeneratedKeys;
      String cmd = escapeTimeout(sql);
      results =
          con.getClient()
              .execute(
                  new QueryPacket(cmd, localInfileInputStream),
                  this,
                  fetchSize,
                  maxRows,
                  resultSetConcurrency,
                  resultSetType,
                  closeOnCompletion,
                  false);
    } finally {
      localInfileInputStream = null;
      lock.unlock();
    }
  }

  /**
   * Executes the given SQL statement and signals the driver that the auto-generated keys indicated
   * in the given array should be made available for retrieval. This array contains the indexes of
   * the columns in the target table that contain the auto-generated keys that should be made
   * available. The driver will ignore the array if the SQL statement is not an <code>INSERT</code>
   * statement, or an SQL statement able to return auto-generated keys (the list of such statements
   * is vendor-specific).
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>,
   *     <code>UPDATE</code> or <code>DELETE</code>; or an SQL statement that returns nothing, such
   *     as a DDL statement.
   * @param columnIndexes an array of column indexes indicating the columns that should be returned
   *     from the inserted row
   * @return either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0
   *     for SQL statements that return nothing
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the SQL statement returns a <code>ResultSet</code> object,the
   *     second argument supplied to this method is not an <code>int</code> array whose elements are
   *     valid column indexes, the method is called on a <code>PreparedStatement</code> or <code>
   *     CallableStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   * @since 1.4
   */
  @Override
  public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
    return executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
  }

  /**
   * Executes the given SQL statement and signals the driver that the auto-generated keys indicated
   * in the given array should be made available for retrieval. This array contains the names of the
   * columns in the target table that contain the auto-generated keys that should be made available.
   * The driver will ignore the array if the SQL statement is not an <code>INSERT</code> statement,
   * or an SQL statement able to return auto-generated keys (the list of such statements is
   * vendor-specific).
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>,
   *     <code>UPDATE</code> or <code>DELETE</code>; or an SQL statement that returns nothing, such
   *     as a DDL statement.
   * @param columnNames an array of the names of the columns that should be returned from the
   *     inserted row
   * @return either the row count for <code>INSERT</code>, <code>UPDATE</code>, or <code>DELETE
   *     </code> statements, or 0 for SQL statements that return nothing
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the SQL statement returns a <code>ResultSet</code> object, the
   *     second argument supplied to this method is not a <code>String</code> array whose elements
   *     are valid column names, the method is called on a <code>PreparedStatement</code> or <code>
   *     CallableStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   * @since 1.4
   */
  @Override
  public int executeUpdate(String sql, String[] columnNames) throws SQLException {
    return executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
  }

  /**
   * Executes the given SQL statement, which may return multiple results, and signals the driver
   * that any auto-generated keys should be made available for retrieval. The driver will ignore
   * this signal if the SQL statement is not an <code>INSERT</code> statement, or an SQL statement
   * able to return auto-generated keys (the list of such statements is vendor-specific).
   *
   * <p>In some (uncommon) situations, a single SQL statement may return multiple result sets and/or
   * update counts. Normally you can ignore this unless you are (1) executing a stored procedure
   * that you know may return multiple results or (2) you are dynamically executing an unknown SQL
   * string.
   *
   * <p>The <code>execute</code> method executes an SQL statement and indicates the form of the
   * first result. You must then use the methods <code>getResultSet</code> or <code>getUpdateCount
   * </code> to retrieve the result, and <code>getMoreResults</code> to move to any subsequent
   * result(s).
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql any SQL statement
   * @param autoGeneratedKeys a constant indicating whether auto-generated keys should be made
   *     available for retrieval using the method <code>getGeneratedKeys</code>; one of the
   *     following constants: <code>Statement.RETURN_GENERATED_KEYS</code> or <code>
   *     Statement.NO_GENERATED_KEYS</code>
   * @return <code>true</code> if the first result is a <code>ResultSet</code> object; <code>false
   *     </code> if it is an update count or there are no results
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the second parameter supplied to this method is not <code>
   *     Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>, the
   *     method is called on a <code>PreparedStatement</code> or <code>CallableStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method with a
   *     constant of Statement.RETURN_GENERATED_KEYS
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   * @see #getResultSet
   * @see #getUpdateCount
   * @see #getMoreResults
   * @see #getGeneratedKeys
   * @since 1.4
   */
  @Override
  public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
    executeInternal(sql, autoGeneratedKeys);

    currResult = results.remove(0);
    return currResult instanceof Result;
  }

  /**
   * Build sql command to execute :
   *
   * <ul>
   *   <li>Execute escape substitution if needed
   *   <li>add query timeout prefix if server permits it
   *   <li>add max row limit prefix if server permits it
   * </ul>
   *
   * @param sql sql command
   * @return sql command to execute
   * @throws SQLException if fails to escape sql
   */
  protected String escapeTimeout(final String sql) throws SQLException {
    String escapedSql = escape ? NativeSql.parse(sql, con.getContext()) : sql;
    if (queryTimeout != 0 && canUseServerTimeout) {
      if (canUseServerMaxRows && maxRows > 0) {
        return "SET STATEMENT max_statement_time="
            + queryTimeout
            + ", SQL_SELECT_LIMIT="
            + maxRows
            + " FOR "
            + escapedSql;
      }
      return "SET STATEMENT max_statement_time=" + queryTimeout + " FOR " + escapedSql;
    }
    if (canUseServerMaxRows && maxRows > 0) {
      return "SET STATEMENT SQL_SELECT_LIMIT=" + maxRows + " FOR " + escapedSql;
    }
    return escapedSql;
  }

  /**
   * Executes the given SQL statement, which may return multiple results, and signals the driver
   * that the auto-generated keys indicated in the given array should be made available for
   * retrieval. This array contains the indexes of the columns in the target table that contain the
   * auto-generated keys that should be made available. The driver will ignore the array if the SQL
   * statement is not an <code>INSERT</code> statement, or an SQL statement able to return
   * auto-generated keys (the list of such statements is vendor-specific).
   *
   * <p>Under some (uncommon) situations, a single SQL statement may return multiple result sets
   * and/or update counts. Normally you can ignore this unless you are (1) executing a stored
   * procedure that you know may return multiple results or (2) you are dynamically executing an
   * unknown SQL string.
   *
   * <p>The <code>execute</code> method executes an SQL statement and indicates the form of the
   * first result. You must then use the methods <code>getResultSet</code> or <code>getUpdateCount
   * </code> to retrieve the result, and <code>getMoreResults</code> to move to any subsequent
   * result(s).
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql any SQL statement
   * @param columnIndexes an array of the indexes of the columns in the inserted row that should be
   *     made available for retrieval by a call to the method <code>getGeneratedKeys</code>
   * @return <code>true</code> if the first result is a <code>ResultSet</code> object; <code>false
   *     </code> if it is an update count or there are no results
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>, the elements in the <code>int</code> array passed to this method
   *     are not valid column indexes, the method is called on a <code>PreparedStatement</code> or
   *     <code>CallableStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   * @see #getResultSet
   * @see #getUpdateCount
   * @see #getMoreResults
   * @since 1.4
   */
  @Override
  public boolean execute(String sql, int[] columnIndexes) throws SQLException {
    return execute(sql, Statement.RETURN_GENERATED_KEYS);
  }

  /**
   * Executes the given SQL statement, which may return multiple results, and signals the driver
   * that the auto-generated keys indicated in the given array should be made available for
   * retrieval. This array contains the names of the columns in the target table that contain the
   * auto-generated keys that should be made available. The driver will ignore the array if the SQL
   * statement is not an <code>INSERT</code> statement, or an SQL statement able to return
   * auto-generated keys (the list of such statements is vendor-specific).
   *
   * <p>In some (uncommon) situations, a single SQL statement may return multiple result sets and/or
   * update counts. Normally you can ignore this unless you are (1) executing a stored procedure
   * that you know may return multiple results or (2) you are dynamically executing an unknown SQL
   * string.
   *
   * <p>The <code>execute</code> method executes an SQL statement and indicates the form of the
   * first result. You must then use the methods <code>getResultSet</code> or <code>getUpdateCount
   * </code> to retrieve the result, and <code>getMoreResults</code> to move to any subsequent
   * result(s).
   *
   * <p><strong>Note:</strong>This method cannot be called on a <code>PreparedStatement</code> or
   * <code>CallableStatement</code>.
   *
   * @param sql any SQL statement
   * @param columnNames an array of the names of the columns in the inserted row that should be made
   *     available for retrieval by a call to the method <code>getGeneratedKeys</code>
   * @return <code>true</code> if the next result is a <code>ResultSet</code> object; <code>false
   *     </code> if it is an update count or there are no more results
   * @throws SQLException if a database access error occurs, this method is called on a closed
   *     <code>Statement</code>,the elements of the <code>String</code> array passed to this method
   *     are not valid column names, the method is called on a <code>PreparedStatement</code> or
   *     <code>CallableStatement</code>
   * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
   * @throws SQLTimeoutException when the driver has determined that the timeout value that was
   *     specified by the {@code setQueryTimeout} method has been exceeded and has at least
   *     attempted to cancel the currently running {@code Statement}
   * @see #getResultSet
   * @see #getUpdateCount
   * @see #getMoreResults
   * @see #getGeneratedKeys
   * @since 1.4
   */
  @Override
  public boolean execute(String sql, String[] columnNames) throws SQLException {
    return execute(sql, Statement.RETURN_GENERATED_KEYS);
  }

  /**
   * Retrieves the result set holdability for <code>ResultSet</code> objects generated by this
   * <code>Statement</code> object.
   *
   * @return either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>
   *     ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
   * @since 1.4
   */
  @Override
  public int getResultSetHoldability() {
    return ResultSet.HOLD_CURSORS_OVER_COMMIT;
  }

  /**
   * Retrieves whether this <code>Statement</code> object has been closed. A <code>Statement</code>
   * is closed if the method close has been called on it, or if it is automatically closed.
   *
   * @return true if this <code>Statement</code> object is closed; false if it is still open
   */
  @Override
  public boolean isClosed() {
    return closed;
  }

  /**
   * Returns a value indicating whether the <code>Statement</code> is poolable or not.
   *
   * @return <code>true</code> if the <code>Statement</code> is poolable; <code>false</code>
   *     otherwise
   * @throws SQLException if this method is called on a closed <code>Statement</code>
   * @see java.sql.Statement#setPoolable(boolean) setPoolable(boolean)
   */
  @Override
  public boolean isPoolable() throws SQLException {
    checkNotClosed();
    return false;
  }

  /**
   * Requests that a <code>Statement</code> be pooled or not pooled. The value specified is a hint
   * to the statement pool implementation indicating whether the application wants the statement to
   * be pooled. It is up to the statement pool manager whether the hint is used.
   *
   * <p>The poolable value of a statement is applicable to both internal statement caches
   * implemented by the driver and external statement caches implemented by application servers and
   * other applications.
   *
   * <p>By default, a <code>Statement</code> is not poolable when created, and a <code>
   * PreparedStatement</code> and <code>CallableStatement</code> are poolable when created.
   *
   * @param poolable requests that the statement be pooled if true and that the statement not be
   *     pooled if false
   * @throws SQLException if this method is called on a closed <code>Statement</code>
   */
  @Override
  public void setPoolable(boolean poolable) throws SQLException {
    checkNotClosed();
  }

  /**
   * Specifies that this {@code Statement} will be closed when all its dependent result sets are
   * closed. If execution of the {@code Statement} does not produce any result sets, this method has
   * no effect.
   *
   * <p><strong>Note:</strong> Multiple calls to {@code closeOnCompletion} do not toggle the effect
   * on this {@code Statement}. However, a call to {@code closeOnCompletion} does affect both the
   * subsequent execution of statements, and statements that currently have open, dependent, result
   * sets.
   *
   * @throws SQLException if this method is called on a closed {@code Statement}
   */
  @Override
  public void closeOnCompletion() throws SQLException {
    checkNotClosed();
    this.closeOnCompletion = true;
  }

  /**
   * Returns a value indicating whether this {@code Statement} will be closed when all its dependent
   * result sets are closed.
   *
   * @return {@code true} if the {@code Statement} will be closed when all of its dependent result
   *     sets are closed; {@code false} otherwise
   * @throws SQLException if this method is called on a closed {@code Statement}
   */
  @Override
  public boolean isCloseOnCompletion() throws SQLException {
    checkNotClosed();
    return closeOnCompletion;
  }

  /**
   * Returns an object that implements the given interface to allow access to non-standard methods,
   * or standard methods not exposed by the proxy.
   *
   * <p>If the receiver implements the interface then the result is the receiver or a proxy for the
   * receiver. If the receiver is a wrapper and the wrapped object implements the interface then the
   * result is the wrapped object or a proxy for the wrapped object. Otherwise, return the result of
   * calling <code>unwrap</code> recursively on the wrapped object or a proxy for that result. If
   * the receiver is not a wrapper and does not implement the interface, then an <code>SQLException
   * </code> is thrown.
   *
   * @param iface A Class defining an interface that the result must implement.
   * @return an object that implements the interface. Maybe a proxy for the actual implementing
   *     object.
   * @throws SQLException If no object found that implements the interface
   */
  @Override
  @SuppressWarnings("unchecked")
  public <T> T unwrap(Class<T> iface) throws SQLException {
    if (isWrapperFor(iface)) {
      return (T) this;
    }
    throw exceptionFactory()
        .create("The receiver is not a wrapper and does not implement the interface", "42000");
  }

  /**
   * Returns true if this either implements the interface argument or is directly or indirectly a
   * wrapper for an object that does. Returns false otherwise. If this implements the interface then
   * return true, else if this is a wrapper then return the result of recursively calling <code>
   * isWrapperFor</code> on the wrapped object. If this does not implement the interface and is not
   * a wrapper, return false. This method should be implemented as a low-cost operation compared to
   * <code>unwrap</code> so that callers can use this method to avoid expensive <code>unwrap</code>
   * calls that may fail. If this method returns true then calling <code>unwrap</code> with the same
   * argument should succeed.
   *
   * @param iface a Class defining an interface.
   * @return true if this implements the interface or directly or indirectly wraps an object that
   *     does.
   */
  @Override
  public boolean isWrapperFor(Class<?> iface) {
    if (iface == null) return false;
    return iface.isInstance(this);
  }

  /**
   * Check if statement is closed, and throw exception if so.
   *
   * @throws SQLException if statement close
   */
  protected void checkNotClosed() throws SQLException {
    if (closed) {
      throw exceptionFactory().create("Cannot do an operation on a closed statement");
    }
  }

  /**
   * Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL
   * statement that returns nothing, such as an SQL DDL statement. This method should be used when
   * the returned row count may exceed Integer.MAX_VALUE.
   *
   * @param sql sql command
   * @return update counts
   * @throws SQLException if any error occur during execution
   */
  @Override
  public long executeLargeUpdate(String sql) throws SQLException {
    return executeLargeUpdate(sql, Statement.NO_GENERATED_KEYS);
  }

  /**
   * Identical to executeLargeUpdate(String sql), with a flag that indicate that autoGeneratedKeys
   * (primary key fields with "auto_increment") generated id's must be retrieved.
   *
   * <p>Those id's will be available using getGeneratedKeys() method.
   *
   * @param sql sql command
   * @param autoGeneratedKeys a flag indicating whether auto-generated keys should be made available
   *     for retrieval; one of the following constants: Statement.RETURN_GENERATED_KEYS
   *     Statement.NO_GENERATED_KEYS
   * @return update counts
   * @throws SQLException if any error occur during execution
   */
  @Override
  public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
    executeInternal(sql, autoGeneratedKeys);
    currResult = results.remove(0);
    if (currResult instanceof Result) {
      throw exceptionFactory()
          .create("the given SQL statement produces an unexpected ResultSet object", "HY000");
    }
    return ((OkPacket) currResult).getAffectedRows();
  }

  /**
   * Identical to executeLargeUpdate(String sql, int autoGeneratedKeys) with autoGeneratedKeys =
   * Statement.RETURN_GENERATED_KEYS set.
   *
   * @param sql sql command
   * @param columnIndexes column Indexes
   * @return update counts
   * @throws SQLException if any error occur during execution
   */
  @Override
  public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
    return executeLargeUpdate(sql, java.sql.Statement.RETURN_GENERATED_KEYS);
  }

  /**
   * Identical to executeLargeUpdate(String sql, int autoGeneratedKeys) with autoGeneratedKeys =
   * Statement.RETURN_GENERATED_KEYS set.
   *
   * @param sql sql command
   * @param columnNames columns names
   * @return update counts
   * @throws SQLException if any error occur during execution
   */
  @Override
  public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
    return executeLargeUpdate(sql, java.sql.Statement.RETURN_GENERATED_KEYS);
  }

  /**
   * Retrieves the maximum number of rows that a ResultSet object produced by this Statement object
   * can contain. If this limit is exceeded, the excess rows are silently dropped.
   *
   * @throws SQLException if this method is called on a closed Statement
   * @return the current maximum number of rows for a ResultSet object produced by this Statement
   *     object; zero means there is no limit
   */
  @Override
  public long getLargeMaxRows() throws SQLException {
    checkNotClosed();
    return maxRows;
  }

  /**
   * Sets the limit for the maximum number of rows that any ResultSet object generated by this
   * Statement object can contain to the given number. If the limit is exceeded, the excess rows are
   * silently dropped.
   *
   * @param max the new max rows limit; zero means there is no limit
   * @throws SQLException if the condition max &gt;= 0 is not satisfied
   */
  @Override
  public void setLargeMaxRows(long max) throws SQLException {
    checkNotClosed();
    if (max < 0) {
      throw exceptionFactory().create("max rows cannot be negative : asked for " + max, "42000");
    }
    maxRows = max;
  }

  /**
   * Retrieves the current result as an update count; if the result is a ResultSet object or there
   * are no more results, -1 is returned.
   *
   * @throws SQLException if this method is called on a closed Statement
   * @return last update count
   */
  @Override
  public long getLargeUpdateCount() throws SQLException {
    checkNotClosed();
    if (currResult instanceof OkPacket) {
      return (int) ((OkPacket) currResult).getAffectedRows();
    }
    return -1;
  }

  /**
   * Execute batch, like executeBatch(), with returning results with long[]. For when row count may
   * exceed Integer.MAX_VALUE.
   *
   * @return an array of update counts (one element for each command in the batch)
   * @throws SQLException if a database error occur.
   */
  @Override
  public long[] executeLargeBatch() throws SQLException {
    checkNotClosed();
    if (batchQueries == null || batchQueries.isEmpty()) return new long[0];

    lock.lock();
    try {
      // ensure pipelining is possible (no LOAD DATA/XML INFILE commands)
      boolean possibleLoadLocal = con.getContext().hasClientCapability(LOCAL_FILES);
      if (possibleLoadLocal) {
        for (int i = 0; i < batchQueries.size(); i++) {
          String sql = batchQueries.get(i).toUpperCase(Locale.ROOT);
          if (sql.contains(" LOCAL ") && sql.contains("LOAD") && sql.contains(" INFILE")) {
            break;
          }
        }
        possibleLoadLocal = false;
      }

      List<Completion> res =
          possibleLoadLocal ? executeInternalBatchStandard() : executeInternalBatchPipeline();

      results = res;
      long[] updates = new long[res.size()];
      for (int i = 0; i < res.size(); i++) {
        updates[i] = ((OkPacket) res.get(i)).getAffectedRows();
      }
      currResult = results.remove(0);
      batchQueries.clear();
      return updates;

    } finally {
      lock.unlock();
    }
  }

  /**
   * Execute batch pipelining commands (sending all client message, then reading results) (batches
   * cannot contain results-set, so cannot fill receiving socket buffer while sending buffer is
   * full)
   *
   * @return results
   * @throws SQLException if any error occurs
   */
  public List<Completion> executeInternalBatchPipeline() throws SQLException {
    QueryPacket[] packets = new QueryPacket[batchQueries.size()];
    for (int i = 0; i < batchQueries.size(); i++) {
      String sql = batchQueries.get(i);
      packets[i] = new QueryPacket(sql);
    }
    return con.getClient()
        .executePipeline(
            packets,
            this,
            0,
            0L,
            ResultSet.CONCUR_READ_ONLY,
            ResultSet.TYPE_FORWARD_ONLY,
            closeOnCompletion,
            false);
  }

  /**
   * basic implementation Send batch query per query.
   *
   * @return results
   * @throws SQLException if any error occurs
   */
  public List<Completion> executeInternalBatchStandard() throws SQLException {
    List<Completion> results = new ArrayList<>();
    try {
      for (String batchQuery : batchQueries) {
        results.addAll(
            con.getClient()
                .execute(
                    new QueryPacket(batchQuery, localInfileInputStream),
                    this,
                    0,
                    0L,
                    ResultSet.CONCUR_READ_ONLY,
                    ResultSet.TYPE_FORWARD_ONLY,
                    closeOnCompletion,
                    false));
      }
      return results;
    } catch (SQLException sqle) {
      int[] updateCounts = new int[batchQueries.size()];
      for (int i = 0; i < Math.min(results.size(), updateCounts.length); i++) {
        Completion completion = results.get(i);
        updateCounts[i] =
            completion instanceof OkPacket ? (int) ((OkPacket) completion).getAffectedRows() : 0;
      }
      throw new BatchUpdateException(
          sqle.getMessage(), sqle.getSQLState(), sqle.getErrorCode(), updateCounts, sqle);
    } finally {
      localInfileInputStream = null;
    }
  }
}
