// 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.*;

import java.sql.*;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Pattern;
import org.mariadb.jdbc.client.ColumnDecoder;
import org.mariadb.jdbc.client.Completion;
import org.mariadb.jdbc.client.result.CompleteResult;
import org.mariadb.jdbc.client.result.Result;
import org.mariadb.jdbc.client.util.Parameters;
import org.mariadb.jdbc.export.ExceptionFactory;
import org.mariadb.jdbc.message.ClientMessage;
import org.mariadb.jdbc.message.client.BulkExecutePacket;
import org.mariadb.jdbc.message.client.ExecutePacket;
import org.mariadb.jdbc.message.client.PrepareExecutePacket;
import org.mariadb.jdbc.message.client.PreparePacket;
import org.mariadb.jdbc.message.server.OkPacket;
import org.mariadb.jdbc.message.server.PrepareResultPacket;
import org.mariadb.jdbc.util.ParameterList;

/**
 * Server prepare statement. command will generate COM_STMT_PREPARE + COM_STMT_EXECUTE (+
 * COM_STMT_CLOSE)
 */
public class ServerPreparedStatement extends BasePreparedStatement {
  private static final Pattern PREPARABLE_STATEMENT_PATTERN =
      Pattern.compile("^(SELECT|UPDATE|INSERT|DELETE|REPLACE|DO|CALL)", Pattern.CASE_INSENSITIVE);
  private final boolean canCachePrepStmts;
  /**
   * Server prepare statement constructor
   *
   * @param sql command
   * @param con connection
   * @param lock thread safe lock
   * @param canUseServerTimeout can server use timeout
   * @param canUseServerMaxRows can server use max rows
   * @param canCachePrepStmts can server cache prepared statement
   * @param autoGeneratedKeys must command return automatically generated keys
   * @param resultSetType resultset type
   * @param resultSetConcurrency resultset concurrency
   * @param defaultFetchSize default fetch size
   * @throws SQLException if prepare fails
   */
  public ServerPreparedStatement(
      String sql,
      Connection con,
      ReentrantLock lock,
      boolean canUseServerTimeout,
      boolean canUseServerMaxRows,
      boolean canCachePrepStmts,
      int autoGeneratedKeys,
      int resultSetType,
      int resultSetConcurrency,
      int defaultFetchSize)
      throws SQLException {
    super(
        sql,
        con,
        lock,
        canUseServerTimeout,
        canUseServerMaxRows,
        autoGeneratedKeys,
        resultSetType,
        resultSetConcurrency,
        defaultFetchSize);
    this.canCachePrepStmts = canCachePrepStmts;
    prepareResult = canCachePrepStmts ? con.getContext().getPrepareCache().get(sql, this) : null;
    if (prepareResult == null && !PREPARABLE_STATEMENT_PATTERN.matcher(sql).find()) {
      con.getClient().execute(new PreparePacket(sql), this, true);
    }
    parameters = new ParameterList();
  }

  /**
   * Execute command with parameters
   *
   * @throws SQLException if any error occurs
   */
  protected void executeInternal() throws SQLException {
    checkNotClosed();
    validParameters();
    lock.lock();
    String cmd = escapeTimeout(sql);
    if (prepareResult == null)
      if (canCachePrepStmts) prepareResult = con.getContext().getPrepareCache().get(cmd, this);
    try {
      if (prepareResult == null && con.getContext().permitPipeline()) {
        executePipeline(cmd);
      } else {
        executeStandard(cmd);
      }
    } finally {
      localInfileInputStream = null;
      lock.unlock();
    }
  }

  /**
   * Send COM_STMT_PREPARE + COM_STMT_EXECUTE, then read for the 2 answers
   *
   * @param cmd command
   * @throws SQLException if IOException / Command error
   */
  private void executePipeline(String cmd) throws SQLException {
    // server is 10.2+, permitting to execute last prepare with (-1) statement id.
    // Server send prepare, followed by execute, in one exchange.
    try {
      List<Completion> res =
          con.getClient()
              .execute(
                  new PrepareExecutePacket(cmd, parameters, this, localInfileInputStream),
                  this,
                  fetchSize,
                  maxRows,
                  resultSetConcurrency,
                  resultSetType,
                  closeOnCompletion,
                  false);
      results = res.subList(1, res.size());
    } catch (SQLException ex) {
      results = null;
      throw ex;
    }
  }

  private void executeStandard(String cmd) throws SQLException {
    // send COM_STMT_PREPARE
    if (prepareResult == null) {
      if (canCachePrepStmts) prepareResult = con.getContext().getPrepareCache().get(cmd, this);
      if (prepareResult == null) {
        con.getClient().execute(new PreparePacket(cmd), this, true);
      }
    }
    validParameters();
    // send COM_STMT_EXECUTE
    ExecutePacket execute =
        new ExecutePacket(prepareResult, parameters, cmd, this, localInfileInputStream);
    results =
        con.getClient()
            .execute(
                execute,
                this,
                fetchSize,
                maxRows,
                resultSetConcurrency,
                resultSetType,
                closeOnCompletion,
                false);
  }

  private void executeInternalPreparedBatch() throws SQLException {
    checkNotClosed();
    String cmd = escapeTimeout(sql);
    if (batchParameters.size() > 1 && con.getContext().hasServerCapability(STMT_BULK_OPERATIONS)) {

      // ensure pipelining is possible (no LOAD DATA/XML INFILE commands)
      boolean possibleLoadLocal = con.getContext().hasClientCapability(LOCAL_FILES);
      if (possibleLoadLocal) {
        String sqlUpper = sql.toUpperCase(Locale.ROOT);
        possibleLoadLocal =
            sqlUpper.contains(" LOCAL ")
                && sqlUpper.contains("LOAD")
                && sqlUpper.contains(" INFILE");
      }

      if (!possibleLoadLocal) {
        if (con.getContext().getConf().useBulkStmts()
            && autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS) {
          executeBatchBulk(cmd);
        } else {
          executeBatchPipeline(cmd);
        }
        return;
      }
    }
    executeBatchStandard(cmd);
  }

  /**
   * Send COM_STMT_PREPARE + X * COM_STMT_BULK_EXECUTE, then read for the all answers
   *
   * @param cmd command
   * @throws SQLException if IOException / Command error
   */
  private void executeBatchBulk(String cmd) throws SQLException {
    List<Completion> res;
    if (prepareResult == null && canCachePrepStmts)
      prepareResult = con.getContext().getPrepareCache().get(cmd, this);
    try {
      if (prepareResult == null) {
        ClientMessage[] packets;
        packets =
            new ClientMessage[] {
              new PreparePacket(cmd), new BulkExecutePacket(null, batchParameters, cmd, this)
            };
        res =
            con.getClient()
                .executePipeline(
                    packets,
                    this,
                    0,
                    maxRows,
                    ResultSet.CONCUR_READ_ONLY,
                    ResultSet.TYPE_FORWARD_ONLY,
                    closeOnCompletion,
                    false);

        // in case of failover, prepare is done in failover, skipping prepare result
        if (res.get(0) instanceof PrepareResultPacket) {
          results = res.subList(1, res.size());
        } else {
          results = res;
        }
      } else {
        results =
            con.getClient()
                .execute(
                    new BulkExecutePacket(prepareResult, batchParameters, cmd, this),
                    this,
                    0,
                    maxRows,
                    ResultSet.CONCUR_READ_ONLY,
                    ResultSet.TYPE_FORWARD_ONLY,
                    closeOnCompletion,
                    false);
      }

    } catch (SQLException bue) {
      results = null;
      throw exceptionFactory()
          .createBatchUpdate(Collections.emptyList(), batchParameters.size(), bue);
    }
  }

  /**
   * Send COM_STMT_PREPARE + X * COM_STMT_EXECUTE, then read for the all answers
   *
   * @param cmd command
   * @throws SQLException if Command error
   */
  private void executeBatchPipeline(String cmd) throws SQLException {
    if (prepareResult == null && canCachePrepStmts)
      prepareResult = con.getContext().getPrepareCache().get(cmd, this);
    // server is 10.2+, permitting to execute last prepare with (-1) statement id.
    // Server send prepare, followed by execute, in one exchange.
    int maxCmd = 250;
    List<Completion> res = new ArrayList<>();
    try {
      int index = 0;
      if (prepareResult == null) {
        res.addAll(executeBunchPrepare(cmd, index, maxCmd));
        index += maxCmd;
      }
      while (index < batchParameters.size()) {
        res.addAll(executeBunch(cmd, index, maxCmd));
        index += maxCmd;
      }
      results = res;

    } catch (SQLException bue) {
      results = null;
      throw exceptionFactory().createBatchUpdate(res, batchParameters.size(), bue);
    }
  }

  private List<Completion> executeBunch(String cmd, int index, int maxCmd) throws SQLException {
    int maxCmdToSend = Math.min(batchParameters.size() - index, maxCmd);
    ClientMessage[] packets = new ClientMessage[maxCmdToSend];
    for (int i = index; i < index + maxCmdToSend; i++) {
      packets[i - index] =
          new ExecutePacket(
              prepareResult, batchParameters.get(i), cmd, this, localInfileInputStream);
    }
    return con.getClient()
        .executePipeline(
            packets,
            this,
            0,
            maxRows,
            ResultSet.CONCUR_READ_ONLY,
            ResultSet.TYPE_FORWARD_ONLY,
            closeOnCompletion,
            false);
  }

  private List<Completion> executeBunchPrepare(String cmd, int index, int maxCmd)
      throws SQLException {
    int maxCmdToSend = Math.min(batchParameters.size() - index, maxCmd);
    ClientMessage[] packets = new ClientMessage[maxCmdToSend + 1];
    packets[0] = new PreparePacket(cmd);
    for (int i = index; i < index + maxCmdToSend; i++) {
      packets[i + 1 - index] =
          new ExecutePacket(null, batchParameters.get(i), cmd, this, localInfileInputStream);
    }
    List<Completion> res =
        con.getClient()
            .executePipeline(
                packets,
                this,
                0,
                maxRows,
                ResultSet.CONCUR_READ_ONLY,
                ResultSet.TYPE_FORWARD_ONLY,
                closeOnCompletion,
                false);
    // in case of failover, prepare is done in failover, skipping prepare result
    if (res.get(0) instanceof PrepareResultPacket) {
      return res.subList(1, res.size());
    } else {
      return res;
    }
  }

  /**
   * Send COM_STMT_PREPARE + read answer, then Send a COM_STMT_EXECUTE + read answer * n time
   *
   * @param cmd command
   * @throws SQLException if IOException / Command error
   */
  private void executeBatchStandard(String cmd) throws SQLException {
    // send COM_STMT_PREPARE
    List<Completion> tmpResults = new ArrayList<>();
    SQLException error = null;
    for (Parameters batchParameter : batchParameters) {
      // prepare is in loop, because if connection fail, prepare is reset, and need to be re
      // prepared
      if (prepareResult == null) {
        if (canCachePrepStmts) prepareResult = con.getContext().getPrepareCache().get(cmd, this);
        if (prepareResult == null) {
          con.getClient().execute(new PreparePacket(cmd), this, false);
        }
      }
      try {
        ExecutePacket execute =
            new ExecutePacket(prepareResult, batchParameter, cmd, this, localInfileInputStream);
        tmpResults.addAll(con.getClient().execute(execute, this, false));
      } catch (SQLException e) {
        if (error == null) error = e;
      }
    }

    if (error != null) {
      throw exceptionFactory().createBatchUpdate(tmpResults, batchParameters.size(), error);
    }
    this.results = tmpResults;
  }

  /**
   * Executes the SQL statement in this <code>PreparedStatement</code> object, which may be any kind
   * of SQL statement. Some prepared statements return multiple results; the <code>execute</code>
   * method handles these complex statements as well as the simpler form of statements handled by
   * the methods <code>executeQuery</code> and <code>executeUpdate</code>.
   *
   * <p>The <code>execute</code> method returns a <code>boolean</code> to indicate the form of the
   * first result. You must call either the method <code>getResultSet</code> or <code>getUpdateCount
   * </code> to retrieve the result; you must call <code>getMoreResults</code> to move to any
   * subsequent result(s).
   *
   * @return <code>true</code> if the first result is a <code>ResultSet</code> object; <code>false
   *     </code> if the first result is an update count or there is no result
   * @throws SQLException if a database access error occurs; this method is called on a closed
   *     <code>PreparedStatement</code> or an argument is supplied to 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 Statement#execute
   * @see Statement#getResultSet
   * @see Statement#getUpdateCount
   * @see Statement#getMoreResults
   */
  @Override
  public boolean execute() throws SQLException {
    executeInternal();
    handleParameterOutput();
    if (results.size() > 0) {
      currResult = results.remove(0);
      return currResult instanceof Result;
    }
    return false;
  }

  @Override
  public void setMaxRows(int max) throws SQLException {
    super.setMaxRows(max);
    if (canUseServerMaxRows && prepareResult != null) {
      prepareResult.decrementUse(con.getClient(), this);
      prepareResult = null;
    }
  }

  @Override
  public void setLargeMaxRows(long max) throws SQLException {
    super.setLargeMaxRows(max);
    if (canUseServerMaxRows && prepareResult != null) {
      prepareResult.decrementUse(con.getClient(), this);
      prepareResult = null;
    }
  }

  @Override
  public void setQueryTimeout(int seconds) throws SQLException {
    super.setQueryTimeout(seconds);
    if (canUseServerTimeout && prepareResult != null) {
      prepareResult.decrementUse(con.getClient(), this);
      prepareResult = null;
    }
  }

  /**
   * Executes the SQL query in this <code>PreparedStatement</code> object and returns the <code>
   * ResultSet</code> object generated by the query.
   *
   * @return a <code>ResultSet</code> object that contains the data produced by the query; never
   *     <code>null</code>
   * @throws SQLException if a database access error occurs; this method is called on a closed
   *     <code>PreparedStatement</code> or the SQL statement does not return a <code>ResultSet
   *     </code> object
   * @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 ResultSet executeQuery() throws SQLException {
    executeInternal();
    handleParameterOutput();
    if (results.size() > 0) {
      currResult = results.remove(0);
      if (currResult instanceof Result) return (Result) currResult;
    }
    return new CompleteResult(new ColumnDecoder[0], new byte[0][], con.getContext());
  }

  /**
   * Executes the SQL statement in this <code>PreparedStatement</code> object, which must be 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>PreparedStatement</code> or the SQL statement returns a <code>ResultSet</code> object
   * @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() throws SQLException {
    return (int) executeLargeUpdate();
  }

  /**
   * Executes the SQL statement in this <code>PreparedStatement</code> object, which must be 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.
   *
   * <p>This method should be used when the returned row count may exceed {@link Integer#MAX_VALUE}.
   *
   * <p>The default implementation will throw {@code UnsupportedOperationException}
   *
   * @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>PreparedStatement</code> or the SQL statement returns a <code>ResultSet</code> object
   * @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.8
   */
  @Override
  public long executeLargeUpdate() throws SQLException {
    executeInternal();
    handleParameterOutput();
    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();
  }

  /**
   * Handle output parameter result-set (only for CallableStatement)
   *
   * @throws SQLException if any error occurs
   */
  protected void handleParameterOutput() throws SQLException {}

  /**
   * Adds a set of parameters to this <code>PreparedStatement</code> object's batch of commands.
   *
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>PreparedStatement</code>
   * @see Statement#addBatch
   * @since 1.2
   */
  @Override
  public void addBatch() throws SQLException {
    validParameters();
    if (batchParameters == null) batchParameters = new ArrayList<>();
    batchParameters.add(parameters);
    parameters = parameters.clone();
  }

  /**
   * Validated that all parameters have been set.
   *
   * @throws SQLException if number of parameters doesn't correspond to expected number
   */
  protected void validParameters() throws SQLException {
    if (prepareResult != null) {
      for (int i = 0; i < prepareResult.getParameters().length; i++) {
        if (!parameters.containsKey(i)) {
          throw exceptionFactory()
              .create("Parameter at position " + (i + 1) + " is not set", "07004");
        }
      }
    } else {

      if (batchParameters != null
          && !batchParameters.isEmpty()
          && parameters.size() < batchParameters.get(0).size()) {
        // ensure batch parameters set same number
        throw exceptionFactory()
            .create(
                "batch set of parameters differ from previous set. All parameters must be set",
                "07004");
      }

      // ensure all parameters are set
      for (int i = 0; i < parameters.size(); i++) {
        if (!parameters.containsKey(i)) {
          throw exceptionFactory()
              .create("Parameter at position " + (i + 1) + " is not set", "07004");
        }
      }
    }
  }

  /**
   * Retrieves a <code>ResultSetMetaData</code> object that contains information about the columns
   * of the <code>ResultSet</code> object that will be returned when this <code>PreparedStatement
   * </code> object is executed.
   *
   * <p>Because a <code>PreparedStatement</code> object is precompiled, it is possible to know about
   * the <code>ResultSet</code> object that it will return without having to execute it.
   * Consequently, it is possible to invoke the method <code>getMetaData</code> on a <code>
   * PreparedStatement</code> object rather than waiting to execute it and then invoking the <code>
   * ResultSet.getMetaData</code> method on the <code>ResultSet</code> object that is returned.
   *
   * <p><B>NOTE:</B> Using this method may be expensive for some drivers due to the lack of
   * underlying DBMS support.
   *
   * @return the description of a <code>ResultSet</code> object's columns or <code>null</code> if
   *     the driver cannot return a <code>ResultSetMetaData</code> object
   * @throws SQLException 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 ResultSetMetaData getMetaData() throws SQLException {

    // send COM_STMT_PREPARE
    if (prepareResult == null) {
      con.getClient().execute(new PreparePacket(escapeTimeout(sql)), this, true);
    }

    return new org.mariadb.jdbc.client.result.ResultSetMetaData(
        exceptionFactory(), prepareResult.getColumns(), con.getContext().getConf(), false);
  }

  /**
   * Retrieves the number, types and properties of this <code>PreparedStatement</code> object's
   * parameters.
   *
   * @return a <code>ParameterMetaData</code> object that contains information about the number,
   *     types and properties for each parameter marker of this <code>PreparedStatement</code>
   *     object
   * @throws SQLException if a database access error occurs or this method is called on a closed
   *     <code>PreparedStatement</code>
   * @see ParameterMetaData
   * @since 1.4
   */
  @Override
  public java.sql.ParameterMetaData getParameterMetaData() throws SQLException {
    // send COM_STMT_PREPARE
    if (prepareResult == null) {
      con.getClient().execute(new PreparePacket(escapeTimeout(sql)), this, true);
    }

    return new ParameterMetaData(exceptionFactory(), prepareResult.getParameters());
  }

  @Override
  public int[] executeBatch() throws SQLException {
    checkNotClosed();
    if (batchParameters == null || batchParameters.isEmpty()) return new int[0];
    lock.lock();
    try {
      executeInternalPreparedBatch();

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

    } finally {
      localInfileInputStream = null;
      batchParameters.clear();
      lock.unlock();
    }
  }

  @Override
  public long[] executeLargeBatch() throws SQLException {
    checkNotClosed();
    if (batchParameters == null || batchParameters.isEmpty()) return new long[0];
    lock.lock();
    try {
      executeInternalPreparedBatch();

      long[] updates = new long[batchParameters.size()];
      if (results.size() != updates.length) {
        for (int i = 0; i < updates.length; i++) {
          updates[i] = Statement.SUCCESS_NO_INFO;
        }
      } else {
        for (int i = 0; i < updates.length; i++) {
          if (results.get(i) instanceof OkPacket) {
            updates[i] = ((OkPacket) results.get(i)).getAffectedRows();
          } else {
            updates[i] = org.mariadb.jdbc.Statement.SUCCESS_NO_INFO;
          }
        }
      }

      currResult = results.remove(0);
      return updates;

    } finally {
      batchParameters.clear();
      lock.unlock();
    }
  }

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

  @Override
  public void close() throws SQLException {
    if (prepareResult != null) {
      prepareResult.decrementUse(con.getClient(), this);
      prepareResult = null;
    }
    con.fireStatementClosed(this);
    super.close();
  }

  /**
   * reset prepare statement in case of a failover. (Command need then to be re-prepared on server)
   */
  public void reset() {
    lock.lock();
    try {
      prepareResult = null;
    } finally {
      lock.unlock();
    }
  }

  @Override
  public String toString() {
    return "ServerPreparedStatement{" + super.toString() + '}';
  }
}
