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

com.scalar.db.sql.statement.UpdateStatement Maven / Gradle / Ivy

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

import com.google.common.collect.ImmutableList;
import com.scalar.db.sql.AndPredicateList;
import com.scalar.db.sql.Assignment;
import com.scalar.db.sql.BindMarker;
import com.scalar.db.sql.NamedBindMarker;
import com.scalar.db.sql.OrPredicateList;
import com.scalar.db.sql.PositionalBindMarker;
import com.scalar.db.sql.Predicate;
import com.scalar.db.sql.TableRef;
import com.scalar.db.sql.Value;
import com.scalar.db.sql.common.SqlError;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

@Immutable
public class UpdateStatement
    implements DmlStatement,
        BindableStatement,
        NamespaceNameOmittable {

  public final TableRef table;
  @Nullable public final String alias;
  public final ImmutableList assignments;
  public final ImmutableList andPredicateLists; // for DNF, empty when using CNF
  public final ImmutableList orPredicateLists; // for CNF, empty when using DNF

  private UpdateStatement(
      TableRef table,
      @Nullable String alias,
      ImmutableList assignments,
      ImmutableList andPredicateLists,
      ImmutableList orPredicateLists) {
    this.table = Objects.requireNonNull(table);
    this.alias = alias;
    this.assignments = Objects.requireNonNull(assignments);
    this.andPredicateLists = Objects.requireNonNull(andPredicateLists);
    this.orPredicateLists = Objects.requireNonNull(orPredicateLists);
  }

  @Override
  public UpdateStatement bind(List positionalValues) {
    Iterator positionalValueIterator = positionalValues.iterator();
    return create(
        table,
        alias,
        bindAssignments(assignments, positionalValueIterator),
        StatementUtils.bindPredicateLists(andPredicateLists, positionalValueIterator),
        StatementUtils.bindPredicateLists(orPredicateLists, positionalValueIterator));
  }

  @Override
  public UpdateStatement bind(Map namedValues) {
    return create(
        table,
        alias,
        bindAssignments(assignments, namedValues),
        StatementUtils.bindPredicateLists(andPredicateLists, namedValues),
        StatementUtils.bindPredicateLists(orPredicateLists, namedValues));
  }

  private ImmutableList bindAssignments(
      ImmutableList assignments, Iterator positionalValueIterator) {
    ImmutableList.Builder builder = ImmutableList.builder();
    assignments.forEach(
        a -> {
          if (positionalValueIterator.hasNext() && a.value instanceof BindMarker) {
            if (a.value instanceof NamedBindMarker) {
              throw new IllegalArgumentException(
                  SqlError.NAMED_BIND_MARKER_NOT_ALLOWED.buildMessage());
            }
            builder.add(a.replaceValue(positionalValueIterator.next()));
          } else {
            builder.add(a);
          }
        });
    return builder.build();
  }

  private ImmutableList bindAssignments(
      ImmutableList assignments, Map namedValues) {
    ImmutableList.Builder builder = ImmutableList.builder();
    assignments.forEach(
        a -> {
          if (a.value instanceof BindMarker) {
            if (a.value instanceof PositionalBindMarker) {
              throw new IllegalArgumentException(
                  SqlError.POSITIONAL_BIND_MARKER_NOT_ALLOWED.buildMessage());
            }
            String name = ((NamedBindMarker) a.value).name;
            if (namedValues.containsKey(name)) {
              builder.add(a.replaceValue(namedValues.get(name)));
            } else {
              builder.add(a);
            }
          } else {
            builder.add(a);
          }
        });
    return builder.build();
  }

  @Override
  public String toSql() {
    StringBuilder builder = new StringBuilder("UPDATE ");
    StatementUtils.appendTable(builder, table);

    if (alias != null) {
      builder.append(" AS ");
      StatementUtils.appendObjectName(builder, alias);
    }

    builder.append(" SET ");

    boolean first = true;
    for (Assignment assignment : assignments) {
      if (!first) {
        builder.append(',');
      } else {
        first = false;
      }
      StatementUtils.appendColumn(builder, assignment.column);
      builder.append('=');
      StatementUtils.appendTerm(builder, assignment.value);
    }

    StatementUtils.appendWhere(builder, andPredicateLists, orPredicateLists);

    return builder.toString();
  }

  @Override
  public  R accept(StatementVisitor visitor, C context) {
    return visitor.visit(this, context);
  }

  @Override
  public  R accept(DmlStatementVisitor visitor, C context) {
    return visitor.visit(this, context);
  }

  @Override
  public boolean namespaceNameOmitted() {
    return table.namespaceName == null;
  }

  @Override
  public UpdateStatement setNamespaceNameIfOmitted(String namespaceName) {
    if (namespaceNameOmitted()) {
      return create(
          TableRef.of(namespaceName, table.tableName),
          alias,
          assignments,
          andPredicateLists,
          orPredicateLists);
    }
    return this;
  }

  @Override
  public String toString() {
    return toSql();
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof UpdateStatement)) {
      return false;
    }
    UpdateStatement that = (UpdateStatement) o;
    return Objects.equals(table, that.table)
        && Objects.equals(assignments, that.assignments)
        && Objects.equals(andPredicateLists, that.andPredicateLists)
        && Objects.equals(orPredicateLists, that.orPredicateLists);
  }

  @Override
  public int hashCode() {
    return Objects.hash(table, assignments, andPredicateLists, orPredicateLists);
  }

  public static UpdateStatement create(
      TableRef table,
      @Nullable String alias,
      ImmutableList assignments,
      ImmutableList predicates) {
    return create(
        table,
        alias,
        assignments,
        predicates.isEmpty()
            ? ImmutableList.of()
            : ImmutableList.of(AndPredicateList.predicates(predicates).build()),
        ImmutableList.of());
  }

  public static UpdateStatement create(
      TableRef table,
      @Nullable String alias,
      ImmutableList assignments,
      ImmutableList andPredicateLists,
      ImmutableList orPredicateLists) {
    if (!andPredicateLists.isEmpty() && !orPredicateLists.isEmpty()) {
      throw new IllegalArgumentException(
          "Either andPredicateLists or orPredicateLists can be used");
    }
    return new UpdateStatement(table, alias, assignments, andPredicateLists, orPredicateLists);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy