All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scalar.db.sql.PreparedStatement Maven / Gradle / Ivy

There is a newer version: 3.14.0
Show newest version
package com.scalar.db.sql;

import com.google.common.annotations.VisibleForTesting;
import com.scalar.db.sql.common.SqlError;
import com.scalar.db.sql.exception.SqlException;
import com.scalar.db.sql.exception.TransactionRetryableException;
import com.scalar.db.sql.exception.UnknownTransactionStatusException;
import com.scalar.db.sql.statement.BindableStatement;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;

/** A statement with bind parameters that has been pre-parsed. */
@NotThreadSafe
public class PreparedStatement {

  private final SqlSession sqlSession;
  @Nullable private final String sql;
  @Nullable private final BindableStatement bindableStatement;

  private final ArrayList positionalValues = new ArrayList<>();
  private final Map namedValues = new HashMap<>();

  PreparedStatement(SqlSession sqlSession, String sql) {
    this.sqlSession = Objects.requireNonNull(sqlSession);
    this.sql = Objects.requireNonNull(sql);
    bindableStatement = null;
  }

  PreparedStatement(SqlSession sqlSession, BindableStatement bindableStatement) {
    this.sqlSession = Objects.requireNonNull(sqlSession);
    sql = null;
    this.bindableStatement = Objects.requireNonNull(bindableStatement);
  }

  /**
   * Sets the i-th parameter to the specified {@link Value}.
   *
   * @param i the position of the bind marker
   * @param value a value to bind
   * @return this object
   */
  public PreparedStatement set(int i, Value value) {
    if (!namedValues.isEmpty()) {
      throw new IllegalStateException(SqlError.MIXED_POSITIONAL_AND_NAMED_VALUES.buildMessage());
    }

    if (i == positionalValues.size()) {
      positionalValues.add(value);
    } else {
      ensurePositionalValuesSize(i + 1);
      positionalValues.set(i, value);
    }
    return this;
  }

  private void ensurePositionalValuesSize(int size) {
    if (positionalValues.size() >= size) {
      return;
    }

    positionalValues.ensureCapacity(size);
    while (positionalValues.size() < size) {
      positionalValues.add(positionalValues.size(), null);
    }
  }

  /**
   * Sets the i-th parameter to the specified Boolean value.
   *
   * @param i the position of the bind marker
   * @param value a Boolean value to bind
   * @return this object
   */
  public PreparedStatement setBoolean(int i, boolean value) {
    return set(i, Value.ofBoolean(value));
  }

  /**
   * Sets the i-th parameter to the specified Int value.
   *
   * @param i the position of the bind marker
   * @param value an Int value to bind
   * @return this object
   */
  public PreparedStatement setInt(int i, int value) {
    return set(i, Value.ofInt(value));
  }

  /**
   * Sets the i-th parameter to the specified BigIng value.
   *
   * @param i the position of the bind marker
   * @param value a BigIng value to bind
   * @return this object
   */
  public PreparedStatement setBigInt(int i, long value) {
    return set(i, Value.ofBigInt(value));
  }

  /**
   * Sets the i-th parameter to the specified Float value.
   *
   * @param i the position of the bind marker
   * @param value a Float value to bind
   * @return this object
   */
  public PreparedStatement setFloat(int i, float value) {
    return set(i, Value.ofFloat(value));
  }

  /**
   * Sets the i-th parameter to the specified Double value.
   *
   * @param i the position of the bind marker
   * @param value a Double value to bind
   * @return this object
   */
  public PreparedStatement setDouble(int i, double value) {
    return set(i, Value.ofDouble(value));
  }

  /**
   * Sets the i-th parameter to the specified Text value.
   *
   * @param i the position of the bind marker
   * @param value a Text value to bind
   * @return this object
   */
  public PreparedStatement setText(int i, @Nullable String value) {
    if (value == null) {
      return set(i, Value.ofNull());
    }
    return set(i, Value.ofText(value));
  }

  /**
   * Sets the i-th parameter to the specified Blob value.
   *
   * @param i the position of the bind marker
   * @param value a Blob value to bind
   * @return this object
   */
  public PreparedStatement setBlob(int i, @Nullable ByteBuffer value) {
    if (value == null) {
      return set(i, Value.ofNull());
    }
    return set(i, Value.ofBlob(value));
  }

  /**
   * Sets the i-th parameter to the specified Blob value.
   *
   * @param i the position of the bind marker
   * @param value a Blob value to bind
   * @return this object
   */
  public PreparedStatement setBlob(int i, @Nullable byte[] value) {
    if (value == null) {
      return set(i, Value.ofNull());
    }
    return set(i, Value.ofBlob(value));
  }

  /**
   * Sets the i-th parameter to a null value.
   *
   * @param i the position of the bind marker
   * @return this object
   */
  public PreparedStatement setNull(int i) {
    return set(i, Value.ofNull());
  }

  /**
   * Sets the parameter for all occurrences of name to the specified {@link Value}.
   *
   * @param name the name of the bind marker
   * @param value a value to bind
   * @return this object
   */
  public PreparedStatement set(String name, Value value) {
    if (!positionalValues.isEmpty()) {
      throw new IllegalStateException(SqlError.MIXED_POSITIONAL_AND_NAMED_VALUES.buildMessage());
    }

    namedValues.put(name, value);
    return this;
  }

  /**
   * Sets the parameter for all occurrences of name to the specified Boolean value.
   *
   * @param name the name of the bind marker
   * @param value a Boolean value to bind
   * @return this object
   */
  public PreparedStatement setBoolean(String name, boolean value) {
    return set(name, Value.ofBoolean(value));
  }

  /**
   * Sets the parameter for all occurrences of name to the specified Int value.
   *
   * @param name the name of the bind marker
   * @param value an Int value to bind
   * @return this object
   */
  public PreparedStatement setInt(String name, int value) {
    return set(name, Value.ofInt(value));
  }

  /**
   * Sets the parameter for all occurrences of name to the specified BigInt value.
   *
   * @param name the name of the bind marker
   * @param value a BigInt value to bind
   * @return this object
   */
  public PreparedStatement setBigInt(String name, long value) {
    return set(name, Value.ofBigInt(value));
  }

  /**
   * Sets the parameter for all occurrences of name to the specified Float value.
   *
   * @param name the name of the bind marker
   * @param value a Float value to bind
   * @return this object
   */
  public PreparedStatement setFloat(String name, float value) {
    return set(name, Value.ofFloat(value));
  }

  /**
   * Sets the parameter for all occurrences of name to the specified Double value.
   *
   * @param name the name of the bind marker
   * @param value a Double value to bind
   * @return this object
   */
  public PreparedStatement setDouble(String name, double value) {
    return set(name, Value.ofDouble(value));
  }

  /**
   * Sets the parameter for all occurrences of name to the specified Text value.
   *
   * @param name the name of the bind marker
   * @param value a Text value to bind
   * @return this object
   */
  public PreparedStatement setText(String name, @Nullable String value) {
    if (value == null) {
      return set(name, Value.ofNull());
    }
    return set(name, Value.ofText(value));
  }

  /**
   * Sets the parameter for all occurrences of name to the specified Blob value.
   *
   * @param name the name of the bind marker
   * @param value a Blob value to bind
   * @return this object
   */
  public PreparedStatement setBlob(String name, @Nullable ByteBuffer value) {
    if (value == null) {
      return set(name, Value.ofNull());
    }
    return set(name, Value.ofBlob(value));
  }

  /**
   * Sets the parameter for all occurrences of name to the specified Blob value.
   *
   * @param name the name of the bind marker
   * @param value a Blob value to bind
   * @return this object
   */
  public PreparedStatement setBlob(String name, @Nullable byte[] value) {
    if (value == null) {
      return set(name, Value.ofNull());
    }
    return set(name, Value.ofBlob(value));
  }

  /**
   * Sets the parameter for all occurrences of name to a null value.
   *
   * @param name the name of the bind marker
   * @return this object
   */
  public PreparedStatement setNull(String name) {
    return set(name, Value.ofNull());
  }

  /** Clears the parameters. */
  public void clearParameters() {
    positionalValues.clear();
    namedValues.clear();
  }

  /**
   * Executes the statement in this {@code PreparedStatement} object.
   *
   * @return a {@link ResultSet} object that contains the data produced by the query
   * @throws TransactionRetryableException if the transaction operation execution fails due to
   *     retryable faults (e.g., a transaction conflict). You can retry the transaction from the
   *     beginning.
   * @throws UnknownTransactionStatusException if the transaction status (committed or aborted) is
   *     unknown when executing the COMMIT statement
   * @throws SqlException if the transaction operation execution fails due to transient or
   *     nontransient faults. You can try retrying the transaction from the beginning, but the
   *     transaction may still fail if the cause is nontranient
   */
  public ResultSet execute() {
    if (!positionalValues.isEmpty()) {
      if (sql != null) {
        return sqlSession.execute(sql, positionalValues);
      } else {
        assert bindableStatement != null;
        return sqlSession.execute(bindableStatement, positionalValues);
      }
    } else if (!namedValues.isEmpty()) {
      if (sql != null) {
        return sqlSession.execute(sql, namedValues);
      } else {
        assert bindableStatement != null;
        return sqlSession.execute(bindableStatement, namedValues);
      }
    } else {
      if (sql != null) {
        return sqlSession.execute(sql);
      } else {
        assert bindableStatement != null;
        return sqlSession.execute(bindableStatement);
      }
    }
  }

  @VisibleForTesting
  SqlSession getSqlSession() {
    return sqlSession;
  }

  @VisibleForTesting
  @Nullable
  String getSql() {
    return sql;
  }

  @VisibleForTesting
  @Nullable
  BindableStatement getBindableStatement() {
    return bindableStatement;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy