// 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.client.result;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.mariadb.jdbc.BasePreparedStatement;
import org.mariadb.jdbc.Connection;
import org.mariadb.jdbc.Statement;
import org.mariadb.jdbc.client.Column;
import org.mariadb.jdbc.client.ColumnDecoder;
import org.mariadb.jdbc.client.Context;
import org.mariadb.jdbc.client.result.rowdecoder.BinaryRowDecoder;
import org.mariadb.jdbc.codec.*;
import org.mariadb.jdbc.plugin.Codec;
import org.mariadb.jdbc.plugin.codec.*;
import org.mariadb.jdbc.util.ParameterList;

/** Updatable result implementation */
public class UpdatableResult extends CompleteResult {
  private static final int STATE_STANDARD = 0;
  private static final int STATE_UPDATE = 1;
  private static final int STATE_UPDATED = 2;
  private static final int STATE_INSERT = 3;
  private static final int STATE_INSERTED = 4;

  private String database;
  private String table;
  private boolean canInsert;
  private boolean canUpdate;
  private String sqlStateError = "HY000";
  private boolean isAutoincrementPk;
  private int savedRowPointer;
  private String changeError;
  private int state = STATE_STANDARD;
  private ParameterList parameters;
  private String[] primaryCols;

  /**
   * Constructor
   *
   * @param stmt statement that initiate this result
   * @param binaryProtocol are rows binary encoded
   * @param maxRows maximum rows
   * @param metadataList columns metadata
   * @param reader packet reader
   * @param context connection context
   * @param resultSetType result-set type
   * @param closeOnCompletion close on completion
   * @param traceEnable must network exchanges be logged
   * @throws IOException if any socket error occurs
   * @throws SQLException for other kind of error
   */
  public UpdatableResult(
      Statement stmt,
      boolean binaryProtocol,
      long maxRows,
      ColumnDecoder[] metadataList,
      org.mariadb.jdbc.client.socket.Reader reader,
      Context context,
      int resultSetType,
      boolean closeOnCompletion,
      boolean traceEnable)
      throws IOException, SQLException {
    super(
        stmt,
        binaryProtocol,
        maxRows,
        metadataList,
        reader,
        context,
        resultSetType,
        closeOnCompletion,
        traceEnable);
    checkIfUpdatable();
    parameters = new ParameterList(metadataList.length);
  }

  private void checkIfUpdatable() throws SQLException {
    isAutoincrementPk = false;
    canInsert = true;
    canUpdate = true;

    // check that resultSet concern one table and database exactly
    database = null;
    table = null;
    for (Column columnDefinition : metadataList) {
      if (columnDefinition.getTable().isEmpty()) {
        cannotUpdateInsertRow(
            "The result-set contains fields without without any database/table information");
        sqlStateError = "0A000";
        return;
      }

      if (database != null && !database.equals(columnDefinition.getSchema())) {
        cannotUpdateInsertRow("The result-set contains more than one database");
        sqlStateError = "0A000";
        return;
      }
      database = columnDefinition.getSchema();

      if (table != null && !table.equals(columnDefinition.getTable())) {
        cannotUpdateInsertRow("The result-set contains fields on different tables");
        sqlStateError = "0A000";
        return;
      }
      table = columnDefinition.getTable();
    }

    // check that listed column contain primary field
    for (Column col : metadataList) {
      if (col.isPrimaryKey()) {
        isAutoincrementPk = col.isAutoIncrement();
        if (isAutoincrementPk) {
          primaryCols = new String[] {col.getColumnName()};
          return;
        }
      }
    }

    // check that table contains a generated primary field
    // to check if insert are still possible
    ResultSet rs =
        statement
            .getConnection()
            .createStatement()
            .executeQuery("SHOW COLUMNS FROM `" + database + "`.`" + table + "`");
    List<String> primaryColumns = new ArrayList<>();
    while (rs.next()) {
      if ("PRI".equals(rs.getString("Key"))) {
        primaryColumns.add(rs.getString("Field"));
        boolean keyPresent = false;
        for (Column col : metadataList) {
          if (rs.getString("Field").equals(col.getColumnName())) {
            keyPresent = true;
          }
        }
        boolean canBeNull = "YES".equals(rs.getString("Null"));
        boolean hasDefault = rs.getString("Default") != null;
        boolean generated = rs.getString("Extra") != null && !rs.getString("Extra").isEmpty();
        isAutoincrementPk =
            rs.getString("Extra") != null && rs.getString("Extra").contains("auto_increment");
        if (!keyPresent && !canBeNull && !hasDefault && !generated) {
          canInsert = false;
          changeError =
              String.format("primary field `%s` is not present in query", rs.getString("Field"));
        }
        if (!keyPresent) {
          canUpdate = false;
          changeError =
              String.format(
                  "Cannot update rows, since primary field %s is not present in query",
                  rs.getString("Field"));
        }
      }
    }

    if (primaryColumns.isEmpty()) {
      canUpdate = false;
      changeError = "Cannot update rows, since no primary field is present in query";
    } else {
      primaryCols = primaryColumns.toArray(new String[0]);
    }
  }

  private void cannotUpdateInsertRow(String reason) {
    changeError = reason;
    canUpdate = false;
    canInsert = false;
  }

  private void checkUpdatable(int position) throws SQLException {
    if (position <= 0 || position > metadataList.length) {
      throw exceptionFactory.create("No such column: " + position, "22023");
    }

    if (state == STATE_STANDARD || state == STATE_UPDATED) {
      state = STATE_UPDATE;
    }
    if (state == STATE_UPDATE) {
      if (rowPointer <= BEFORE_FIRST_POS) {
        throw new SQLDataException("Current position is before the first row", "22023");
      }
      if (rowPointer >= dataSize) {
        throw new SQLDataException("Current position is after the last row", "22023");
      }
      if (!canUpdate) {
        throw exceptionFactory.create("ResultSet cannot be updated. " + changeError, sqlStateError);
      }
    }
  }

  @Override
  public boolean rowUpdated() {
    return state == STATE_UPDATED;
  }

  @Override
  public boolean rowInserted() {
    return state == STATE_INSERTED;
  }

  @Override
  public boolean rowDeleted() {
    return false;
  }

  @Override
  public void updateNull(int columnIndex) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, Parameter.NULL_PARAMETER);
  }

  @Override
  public void updateBoolean(int columnIndex, boolean x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(BooleanCodec.INSTANCE, x));
  }

  @Override
  public void updateByte(int columnIndex, byte x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ByteCodec.INSTANCE, x));
  }

  @Override
  public void updateShort(int columnIndex, short x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ShortCodec.INSTANCE, x));
  }

  @Override
  public void updateInt(int columnIndex, int x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(IntCodec.INSTANCE, x));
  }

  @Override
  public void updateLong(int columnIndex, long x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(LongCodec.INSTANCE, x));
  }

  @Override
  public void updateFloat(int columnIndex, float x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(FloatCodec.INSTANCE, x));
  }

  @Override
  public void updateDouble(int columnIndex, double x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(DoubleCodec.INSTANCE, x));
  }

  @Override
  public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(BigDecimalCodec.INSTANCE, x));
  }

  @Override
  public void updateString(int columnIndex, String x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StringCodec.INSTANCE, x));
  }

  @Override
  public void updateBytes(int columnIndex, byte[] x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ByteArrayCodec.INSTANCE, x));
  }

  @Override
  public void updateDate(int columnIndex, Date x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(DateCodec.INSTANCE, x));
  }

  @Override
  public void updateTime(int columnIndex, Time x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(TimeCodec.INSTANCE, x));
  }

  @Override
  public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(TimestampCodec.INSTANCE, x));
  }

  @Override
  public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, (long) length));
  }

  @Override
  public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, (long) length));
  }

  @Override
  public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, x, (long) length));
  }

  @Override
  public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException {
    updateInternalObject(columnIndex, x, (long) scaleOrLength);
  }

  @Override
  public void updateObject(int columnIndex, Object x) throws SQLException {
    updateInternalObject(columnIndex, x, null);
  }

  @Override
  public void updateNull(String columnLabel) throws SQLException {
    updateNull(findColumn(columnLabel));
  }

  @Override
  public void updateBoolean(String columnLabel, boolean x) throws SQLException {
    updateBoolean(findColumn(columnLabel), x);
  }

  @Override
  public void updateByte(String columnLabel, byte x) throws SQLException {
    updateByte(findColumn(columnLabel), x);
  }

  @Override
  public void updateShort(String columnLabel, short x) throws SQLException {
    updateShort(findColumn(columnLabel), x);
  }

  @Override
  public void updateInt(String columnLabel, int x) throws SQLException {
    updateInt(findColumn(columnLabel), x);
  }

  @Override
  public void updateLong(String columnLabel, long x) throws SQLException {
    updateLong(findColumn(columnLabel), x);
  }

  @Override
  public void updateFloat(String columnLabel, float x) throws SQLException {
    updateFloat(findColumn(columnLabel), x);
  }

  @Override
  public void updateDouble(String columnLabel, double x) throws SQLException {
    updateDouble(findColumn(columnLabel), x);
  }

  @Override
  public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {
    updateBigDecimal(findColumn(columnLabel), x);
  }

  @Override
  public void updateString(String columnLabel, String x) throws SQLException {
    updateString(findColumn(columnLabel), x);
  }

  @Override
  public void updateBytes(String columnLabel, byte[] x) throws SQLException {
    updateBytes(findColumn(columnLabel), x);
  }

  @Override
  public void updateDate(String columnLabel, Date x) throws SQLException {
    updateDate(findColumn(columnLabel), x);
  }

  @Override
  public void updateTime(String columnLabel, Time x) throws SQLException {
    updateTime(findColumn(columnLabel), x);
  }

  @Override
  public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException {
    updateTimestamp(findColumn(columnLabel), x);
  }

  @Override
  public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException {
    updateAsciiStream(findColumn(columnLabel), x, length);
  }

  @Override
  public void updateBinaryStream(String columnLabel, InputStream x, int length)
      throws SQLException {
    updateBinaryStream(findColumn(columnLabel), x, length);
  }

  @Override
  public void updateCharacterStream(String columnLabel, Reader reader, int length)
      throws SQLException {
    updateCharacterStream(findColumn(columnLabel), reader, length);
  }

  @Override
  public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException {
    updateObject(findColumn(columnLabel), x, scaleOrLength);
  }

  @Override
  public void updateObject(String columnLabel, Object x) throws SQLException {
    updateObject(findColumn(columnLabel), x);
  }

  @Override
  public void insertRow() throws SQLException {
    if (state == STATE_INSERT || state == STATE_INSERTED) {

      // Create query will all field with WHERE clause contain primary field.
      // if field are not updated, value DEFAULT will be set
      // (if field has no default, then insert will throw an exception that will be return to
      // user)

      String insertSql = buildInsertQuery();
      try (PreparedStatement insertPreparedStatement =
          ((Connection) statement.getConnection())
              .prepareInternal(
                  insertSql,
                  Statement.RETURN_GENERATED_KEYS,
                  ResultSet.TYPE_FORWARD_ONLY,
                  ResultSet.CONCUR_READ_ONLY,
                  rowDecoder instanceof BinaryRowDecoder)) {

        int paramPos = 0;
        for (int pos = 0; pos < metadataList.length; pos++) {
          Column colInfo = metadataList[pos];
          org.mariadb.jdbc.client.util.Parameter param =
              parameters.size() > pos ? parameters.get(pos) : null;
          if (param != null) {
            ((BasePreparedStatement) insertPreparedStatement).setParameter(paramPos++, param);
          } else if (!Arrays.asList(primaryCols).contains(colInfo.getColumnName())
              && !colInfo.hasDefault()) {
            ((BasePreparedStatement) insertPreparedStatement)
                .setParameter(paramPos++, Parameter.NULL_PARAMETER);
          }
        }
        ResultSet insertRs = insertPreparedStatement.executeQuery();
        if (context.getVersion().isMariaDBServer()
            && context.getVersion().versionGreaterOrEqual(10, 5, 1)) {
          if (insertRs.next()) {
            byte[] rowByte = ((Result) insertRs).getCurrentRowData();
            addRowData(rowByte);
          }
        } else if (isAutoincrementPk) {
          // primary is auto_increment (only one field)
          ResultSet rsKey = insertPreparedStatement.getGeneratedKeys();
          if (rsKey.next()) {
            try (PreparedStatement refreshPreparedStatement = prepareRefreshStmt()) {
              refreshPreparedStatement.setObject(1, rsKey.getObject(1));
              Result rs = (Result) refreshPreparedStatement.executeQuery();
              // update row data only if not deleted externally
              if (rs.next()) {
                addRowData(rs.getCurrentRowData());
              }
            }
          }
        } else {
          addRowData(refreshRawData());
        }
      }
      parameters = new ParameterList(parameters.size());
      state = STATE_INSERTED;
    }
  }

  /**
   * Build insert query
   *
   * @return insert sql
   * @throws SQLException exception
   */
  private String buildInsertQuery() throws SQLException {
    StringBuilder insertSql = new StringBuilder("INSERT `" + database + "`.`" + table + "` ( ");
    StringBuilder valueClause = new StringBuilder();
    StringBuilder returningClause = new StringBuilder();

    boolean firstParam = true;

    for (int pos = 0; pos < metadataList.length; pos++) {
      Column colInfo = metadataList[pos];

      if (pos != 0) {
        returningClause.append(", ");
      }
      returningClause.append("`").append(colInfo.getColumnName()).append("`");

      org.mariadb.jdbc.client.util.Parameter param =
          parameters.size() > pos ? parameters.get(pos) : null;
      if (param != null) {
        if (!firstParam) {
          insertSql.append(",");
          valueClause.append(", ");
        }
        insertSql.append("`").append(colInfo.getColumnName()).append("`");
        valueClause.append("?");
        firstParam = false;
      } else {
        if (Arrays.asList(primaryCols).contains(colInfo.getColumnName())) {
          boolean isAutoIncrement =
              colInfo.isAutoIncrement() || (primaryCols.length == 1 && isAutoincrementPk);
          if (isAutoIncrement || colInfo.hasDefault()) {
            if (!isAutoIncrement
                && (!context.getVersion().isMariaDBServer()
                    || !context.getVersion().versionGreaterOrEqual(10, 5, 1))) {
              // driver cannot know generated default value like uuid().
              // but for server 10.5+, will use RETURNING to know primary key
              throw exceptionFactory.create(
                  String.format(
                      "Cannot call insertRow() not setting value for primary key %s "
                          + "with default value before server 10.5",
                      colInfo.getColumnName()));
            }
          } else {
            throw exceptionFactory.create(
                String.format(
                    "Cannot call insertRow() not setting value for primary key %s",
                    colInfo.getColumnName()));
          }
        } else if (!colInfo.hasDefault()) {
          if (!firstParam) {
            insertSql.append(",");
            valueClause.append(", ");
          }
          firstParam = false;
          insertSql.append("`").append(colInfo.getColumnName()).append("`");
          valueClause.append("?");
        }
      }
    }
    insertSql.append(") VALUES (").append(valueClause).append(")");
    if (context.getVersion().isMariaDBServer()
        && context.getVersion().versionGreaterOrEqual(10, 5, 1)) {
      insertSql.append(" RETURNING ").append(returningClause);
    }
    return insertSql.toString();
  }

  private String refreshStmt() {
    // Construct SELECT query according to column metadata, with WHERE part containing primary
    // fields
    StringBuilder selectSql = new StringBuilder("SELECT ");
    StringBuilder whereClause = new StringBuilder(" WHERE ");

    boolean firstPrimary = true;
    for (int pos = 0; pos < metadataList.length; pos++) {
      Column colInfo = metadataList[pos];
      if (pos != 0) {
        selectSql.append(",");
      }
      selectSql.append("`").append(colInfo.getColumnName()).append("`");

      if (Arrays.asList(primaryCols).contains(colInfo.getColumnName())) {
        if (!firstPrimary) {
          whereClause.append("AND ");
        }
        firstPrimary = false;
        whereClause.append("`").append(colInfo.getColumnName()).append("` = ? ");
      }
    }
    selectSql
        .append(" FROM `")
        .append(database)
        .append("`.`")
        .append(table)
        .append("`")
        .append(whereClause);
    return selectSql.toString();
  }

  private PreparedStatement prepareRefreshStmt() throws SQLException {
    // row's raw bytes must be encoded according to current resultSet type
    // so use Server or Client PrepareStatement accordingly
    return ((Connection) statement.getConnection())
        .prepareInternal(
            refreshStmt(),
            Statement.RETURN_GENERATED_KEYS,
            ResultSet.TYPE_FORWARD_ONLY,
            ResultSet.CONCUR_READ_ONLY,
            rowDecoder instanceof BinaryRowDecoder);
  }

  private byte[] refreshRawData() throws SQLException {
    int fieldsPrimaryIndex = 0;
    try (PreparedStatement refreshPreparedStatement = prepareRefreshStmt()) {

      for (int pos = 0; pos < metadataList.length; pos++) {
        Column colInfo = metadataList[pos];
        if (Arrays.asList(primaryCols).contains(colInfo.getColumnName())) {
          if ((state != STATE_STANDARD) && parameters.size() > pos && parameters.get(pos) != null) {
            // Row has just been updated using updateRow() methods.
            // updateRow might have changed primary key, so must use the new value.
            org.mariadb.jdbc.client.util.Parameter value = parameters.get(pos);
            ((BasePreparedStatement) refreshPreparedStatement)
                .setParameter(fieldsPrimaryIndex++, value);
          } else {
            refreshPreparedStatement.setObject(++fieldsPrimaryIndex, getObject(pos + 1));
          }
        }
      }

      Result rs = (Result) refreshPreparedStatement.executeQuery();
      rs.next();
      return rs.getCurrentRowData();
    }
  }

  private String updateQuery() {
    StringBuilder updateSql = new StringBuilder("UPDATE `" + database + "`.`" + table + "` SET ");
    StringBuilder whereClause = new StringBuilder(" WHERE ");

    boolean firstUpdate = true;

    for (int pos = 0; pos < primaryCols.length; pos++) {
      String key = primaryCols[pos];
      if (pos != 0) {
        whereClause.append("AND ");
      }
      whereClause.append("`").append(key).append("` = ? ");
    }

    for (int pos = 0; pos < metadataList.length; pos++) {
      Column colInfo = metadataList[pos];

      if (parameters.size() > pos && parameters.get(pos) != null) {
        if (!firstUpdate) {
          updateSql.append(",");
        }
        firstUpdate = false;
        updateSql.append("`").append(colInfo.getColumnName()).append("` = ? ");
      }
    }
    if (firstUpdate) return null;
    return updateSql.append(whereClause).toString();
  }

  @Override
  public void updateRow() throws SQLException {

    if (state == STATE_INSERT) {
      throw exceptionFactory.create("Cannot call updateRow() when inserting a new row");
    }

    if (rowPointer < 0) {
      throw exceptionFactory.create("Current position is before the first row", "22023");
    }

    if (rowPointer >= dataSize) {
      throw exceptionFactory.create("Current position is after the last row", "22023");
    }

    if (state == STATE_UPDATE || state == STATE_UPDATED) {

      // state is STATE_UPDATE, meaning that at least one field is modified, update query can be
      // run.
      // Construct UPDATE query according to modified field only
      String updateQuery = updateQuery();
      if (updateQuery != null) {
        try (PreparedStatement preparedStatement =
            ((Connection) statement.getConnection())
                .prepareInternal(
                    updateQuery,
                    Statement.RETURN_GENERATED_KEYS,
                    ResultSet.TYPE_FORWARD_ONLY,
                    ResultSet.CONCUR_READ_ONLY,
                    rowDecoder instanceof BinaryRowDecoder)) {

          int fieldsIndex = 0;
          for (int pos = 0; pos < metadataList.length; pos++) {
            if (parameters.size() > pos) {
              org.mariadb.jdbc.client.util.Parameter param = parameters.get(pos);
              if (param != null) {
                ((BasePreparedStatement) preparedStatement).setParameter(fieldsIndex++, param);
              }
            }
          }

          for (int pos = 0; pos < metadataList.length; pos++) {
            Column colInfo = metadataList[pos];
            if (Arrays.asList(primaryCols).contains(colInfo.getColumnName())) {
              preparedStatement.setObject(++fieldsIndex, getObject(pos + 1));
            }
          }

          preparedStatement.execute();
        }
        refreshRow();
      }
      parameters = new ParameterList(parameters.size());
      state = STATE_UPDATED;
    }
  }

  @Override
  public void deleteRow() throws SQLException {

    if (state == STATE_INSERT) {
      throw exceptionFactory.create("Cannot call deleteRow() when inserting a new row");
    }
    if (!canUpdate) {
      throw exceptionFactory.create("ResultSet cannot be updated. " + changeError, sqlStateError);
    }
    if (rowPointer < 0) {
      throw new SQLDataException("Current position is before the first row", "22023");
    }
    if (rowPointer >= dataSize) {
      throw new SQLDataException("Current position is after the last row", "22023");
    }

    // Create query with WHERE clause contain primary field.
    StringBuilder deleteSql =
        new StringBuilder("DELETE FROM `" + database + "`.`" + table + "` WHERE ");
    boolean firstPrimary = true;
    for (Column colInfo : metadataList) {
      if (Arrays.asList(primaryCols).contains(colInfo.getColumnName())) {
        if (!firstPrimary) {
          deleteSql.append("AND ");
        }
        firstPrimary = false;
        deleteSql.append("`").append(colInfo.getColumnName()).append("` = ? ");
      }
    }

    try (PreparedStatement deletePreparedStatement =
        ((Connection) statement.getConnection())
            .prepareInternal(
                deleteSql.toString(),
                Statement.RETURN_GENERATED_KEYS,
                ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY,
                false)) {

      int fieldsPrimaryIndex = 1;
      for (int pos = 0; pos < metadataList.length; pos++) {
        Column colInfo = metadataList[pos];
        if (Arrays.asList(primaryCols).contains(colInfo.getColumnName())) {
          deletePreparedStatement.setObject(fieldsPrimaryIndex++, getObject(pos + 1));
        }
      }

      deletePreparedStatement.executeUpdate();

      // remove data
      System.arraycopy(data, rowPointer + 1, data, rowPointer, dataSize - 1 - rowPointer);
      data[dataSize - 1] = null;
      dataSize--;
      previous();
    }
  }

  @Override
  public void refreshRow() throws SQLException {
    if (state == STATE_INSERT) {
      throw exceptionFactory.create("Cannot call refreshRow() when inserting a new row");
    }
    if (rowPointer < 0) {
      throw exceptionFactory.create("Current position is before the first row", "22023");
    }
    if (rowPointer >= data.length) {
      throw exceptionFactory.create("Current position is after the last row", "22023");
    }
    if (canUpdate) {
      updateRowData(refreshRawData());
    }
  }

  @Override
  public void cancelRowUpdates() {
    parameters = new ParameterList(parameters.size());
    state = STATE_STANDARD;
  }

  @Override
  public void moveToInsertRow() throws SQLException {
    if (!canInsert) {
      throw exceptionFactory.create("No row can be inserted. " + changeError, sqlStateError);
    }
    parameters = new ParameterList(parameters.size());
    state = STATE_INSERT;
    savedRowPointer = rowPointer;
  }

  @Override
  public void moveToCurrentRow() {
    state = STATE_STANDARD;
    resetToRowPointer();
  }

  @Override
  public void updateBlob(int columnIndex, Blob x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(BlobCodec.INSTANCE, x));
  }

  @Override
  public void updateBlob(String columnLabel, Blob x) throws SQLException {
    updateBlob(findColumn(columnLabel), x);
  }

  @Override
  public void updateClob(int columnIndex, Clob x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ClobCodec.INSTANCE, x));
  }

  @Override
  public void updateClob(String columnLabel, Clob x) throws SQLException {
    updateClob(findColumn(columnLabel), x);
  }

  @Override
  public void updateNString(int columnIndex, String nString) throws SQLException {
    updateString(columnIndex, nString);
  }

  @Override
  public void updateNString(String columnLabel, String nString) throws SQLException {
    updateString(columnLabel, nString);
  }

  @Override
  public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
    updateClob(columnIndex, nClob);
  }

  @Override
  public void updateNClob(String columnLabel, NClob nClob) throws SQLException {
    updateClob(columnLabel, nClob);
  }

  @Override
  public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
    updateCharacterStream(columnIndex, x, length);
  }

  @Override
  public void updateNCharacterStream(String columnLabel, Reader reader, long length)
      throws SQLException {
    updateCharacterStream(columnLabel, reader, length);
  }

  @Override
  public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, length));
  }

  @Override
  public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, length));
  }

  @Override
  public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, x, length));
  }

  @Override
  public void updateAsciiStream(String columnLabel, InputStream x, long length)
      throws SQLException {
    updateAsciiStream(findColumn(columnLabel), x, length);
  }

  @Override
  public void updateBinaryStream(String columnLabel, InputStream x, long length)
      throws SQLException {
    updateBinaryStream(findColumn(columnLabel), x, length);
  }

  @Override
  public void updateCharacterStream(String columnLabel, Reader reader, long length)
      throws SQLException {
    updateCharacterStream(findColumn(columnLabel), reader, length);
  }

  @Override
  public void updateBlob(int columnIndex, InputStream x, long length) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x, length));
  }

  @Override
  public void updateBlob(String columnLabel, InputStream inputStream, long length)
      throws SQLException {
    updateBlob(findColumn(columnLabel), inputStream, length);
  }

  @Override
  public void updateClob(int columnIndex, Reader x, long length) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, x, length));
  }

  @Override
  public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
    updateClob(findColumn(columnLabel), reader, length);
  }

  @Override
  public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
    updateClob(columnIndex, reader, length);
  }

  @Override
  public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
    updateClob(columnLabel, reader, length);
  }

  @Override
  public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
    updateCharacterStream(columnIndex, x);
  }

  @Override
  public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
    updateCharacterStream(columnLabel, reader);
  }

  @Override
  public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x));
  }

  @Override
  public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x));
  }

  @Override
  public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, x));
  }

  @Override
  public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
    updateAsciiStream(findColumn(columnLabel), x);
  }

  @Override
  public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
    updateBinaryStream(findColumn(columnLabel), x);
  }

  @Override
  public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
    updateCharacterStream(findColumn(columnLabel), reader);
  }

  @Override
  public void updateBlob(int columnIndex, InputStream x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(StreamCodec.INSTANCE, x));
  }

  @Override
  public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
    updateBlob(findColumn(columnLabel), inputStream);
  }

  @Override
  public void updateClob(int columnIndex, Reader x) throws SQLException {
    checkUpdatable(columnIndex);
    parameters.set(columnIndex - 1, new Parameter<>(ReaderCodec.INSTANCE, x));
  }

  @Override
  public void updateClob(String columnLabel, Reader reader) throws SQLException {
    updateClob(findColumn(columnLabel), reader);
  }

  @Override
  public void updateNClob(int columnIndex, Reader reader) throws SQLException {
    updateClob(columnIndex, reader);
  }

  @Override
  public void updateNClob(String columnLabel, Reader reader) throws SQLException {
    updateClob(columnLabel, reader);
  }

  @Override
  public void updateObject(int columnIndex, Object x, SQLType targetSqlType, int scaleOrLength)
      throws SQLException {
    updateInternalObject(columnIndex, x, (long) scaleOrLength);
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  private void updateInternalObject(int columnIndex, Object x, Long scaleOrLength)
      throws SQLException {
    checkUpdatable(columnIndex);
    if (x == null) {
      parameters.set(columnIndex - 1, Parameter.NULL_PARAMETER);
      return;
    }

    for (Codec<?> codec : context.getConf().codecs()) {
      if (codec.canEncode(x)) {
        Parameter p = new Parameter(codec, x, scaleOrLength);
        parameters.set(columnIndex - 1, p);
        return;
      }
    }

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

  @Override
  public void updateObject(String columnLabel, Object x, SQLType targetSqlType, int scaleOrLength)
      throws SQLException {
    updateObject(findColumn(columnLabel), x, targetSqlType, scaleOrLength);
  }

  @Override
  public void updateObject(int columnIndex, Object x, SQLType targetSqlType) throws SQLException {
    updateInternalObject(columnIndex, x, null);
  }

  @Override
  public void updateObject(String columnLabel, Object x, SQLType targetSqlType)
      throws SQLException {
    updateObject(findColumn(columnLabel), x, targetSqlType);
  }

  @Override
  public int getConcurrency() {
    return CONCUR_UPDATABLE;
  }

  private void resetToRowPointer() {
    rowPointer = savedRowPointer;
    if (rowPointer != BEFORE_FIRST_POS && rowPointer < dataSize - 1) {
      setRow(data[rowPointer]);
    } else {
      // all data are reads and pointer is after last
      setNullRowBuf();
    }
    savedRowPointer = -1;
  }

  @Override
  public void beforeFirst() throws SQLException {
    if (state == STATE_INSERT) {
      resetToRowPointer();
    }
    state = STATE_STANDARD;
    super.beforeFirst();
  }

  @Override
  public boolean first() throws SQLException {
    if (state == STATE_INSERT) {
      resetToRowPointer();
    }
    state = STATE_STANDARD;
    return super.first();
  }

  @Override
  public boolean last() throws SQLException {
    if (state == STATE_INSERT) {
      resetToRowPointer();
    }
    state = STATE_STANDARD;
    return super.last();
  }

  @Override
  public void afterLast() throws SQLException {
    if (state == STATE_INSERT) {
      resetToRowPointer();
    }
    state = STATE_STANDARD;
    super.afterLast();
  }

  @Override
  public boolean absolute(int row) throws SQLException {
    if (state == STATE_INSERT) {
      resetToRowPointer();
    }
    state = STATE_STANDARD;
    return super.absolute(row);
  }

  @Override
  public boolean relative(int rows) throws SQLException {
    if (state == STATE_INSERT) {
      resetToRowPointer();
    }
    state = STATE_STANDARD;
    return super.relative(rows);
  }

  @Override
  public boolean next() throws SQLException {
    if (state == STATE_INSERT) {
      resetToRowPointer();
    }
    state = STATE_STANDARD;
    return super.next();
  }

  @Override
  public boolean previous() throws SQLException {
    if (state == STATE_INSERT) {
      resetToRowPointer();
    }
    state = STATE_STANDARD;
    return super.previous();
  }
}
