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

com.scalar.db.sql.statement.StatementUtils 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.BindMarker;
import com.scalar.db.sql.ColumnRef;
import com.scalar.db.sql.JoinPredicate;
import com.scalar.db.sql.LikePredicate;
import com.scalar.db.sql.Literal;
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.PredicateList;
import com.scalar.db.sql.TableRef;
import com.scalar.db.sql.Term;
import com.scalar.db.sql.Value;
import com.scalar.db.sql.common.SqlError;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public final class StatementUtils {

  private StatementUtils() {}

  @SuppressWarnings("unchecked")
  public static  ImmutableList bindPredicateLists(
      ImmutableList predicateLists, Iterator positionalValueIterator) {
    ImmutableList.Builder builder = ImmutableList.builder();
    predicateLists.forEach(
        predicateList -> {
          ImmutableList.Builder predicateBuilder = ImmutableList.builder();
          predicateList
              .getPredicates()
              .forEach(p -> predicateBuilder.add(bindPredicate(p, positionalValueIterator)));
          if (predicateList instanceof AndPredicateList) {
            ((ImmutableList.Builder) builder)
                .add(AndPredicateList.predicates(predicateBuilder.build()).build());
          } else {
            assert predicateList instanceof OrPredicateList;
            ((ImmutableList.Builder) builder)
                .add(OrPredicateList.predicates(predicateBuilder.build()).build());
          }
        });
    return builder.build();
  }

  private static Predicate bindPredicate(
      Predicate predicate, Iterator positionalValueIterator) {
    if (predicate instanceof LikePredicate) {
      return bindLikePredicate((LikePredicate) predicate, positionalValueIterator);
    }

    if (positionalValueIterator.hasNext() && predicate.value instanceof BindMarker) {
      if (predicate.value instanceof NamedBindMarker) {
        throw new IllegalArgumentException(SqlError.NAMED_BIND_MARKER_NOT_ALLOWED.buildMessage());
      }
      return predicate.replaceValue(positionalValueIterator.next());
    } else {
      return predicate;
    }
  }

  private static LikePredicate bindLikePredicate(
      LikePredicate predicate, Iterator positionalValueIterator) {
    if (positionalValueIterator.hasNext() && predicate.value instanceof BindMarker) {
      if (predicate.value instanceof NamedBindMarker) {
        throw new IllegalArgumentException(SqlError.NAMED_BIND_MARKER_NOT_ALLOWED.buildMessage());
      }
      Value value = positionalValueIterator.next();
      if (positionalValueIterator.hasNext() && predicate.escape instanceof BindMarker) {
        if (predicate.escape instanceof NamedBindMarker) {
          throw new IllegalArgumentException(SqlError.NAMED_BIND_MARKER_NOT_ALLOWED.buildMessage());
        }
        Value escape = positionalValueIterator.next();
        return predicate.replaceValueAndEscape(value, escape);
      }
      return predicate.replaceValue(value);
    } else if (positionalValueIterator.hasNext() && predicate.escape instanceof BindMarker) {
      if (predicate.escape instanceof NamedBindMarker) {
        throw new IllegalArgumentException(SqlError.NAMED_BIND_MARKER_NOT_ALLOWED.buildMessage());
      }
      return predicate.replaceEscape(positionalValueIterator.next());
    } else {
      return predicate;
    }
  }

  @SuppressWarnings("unchecked")
  public static  ImmutableList bindPredicateLists(
      ImmutableList predicateLists, Map namedValues) {
    ImmutableList.Builder builder = ImmutableList.builder();
    predicateLists.forEach(
        predicateList -> {
          ImmutableList.Builder predicateBuilder = ImmutableList.builder();
          predicateList
              .getPredicates()
              .forEach(p -> predicateBuilder.add(bindPredicate(p, namedValues)));
          if (predicateList instanceof AndPredicateList) {
            ((ImmutableList.Builder) builder)
                .add(AndPredicateList.predicates(predicateBuilder.build()).build());
          } else {
            assert predicateList instanceof OrPredicateList;
            ((ImmutableList.Builder) builder)
                .add(OrPredicateList.predicates(predicateBuilder.build()).build());
          }
        });
    return builder.build();
  }

  private static Predicate bindPredicate(Predicate predicate, Map namedValues) {
    if (predicate instanceof LikePredicate) {
      return bindLikePredicate((LikePredicate) predicate, namedValues);
    }

    if (predicate.value instanceof BindMarker) {
      if (predicate.value instanceof PositionalBindMarker) {
        throw new IllegalArgumentException(
            SqlError.POSITIONAL_BIND_MARKER_NOT_ALLOWED.buildMessage());
      }
      String name = ((NamedBindMarker) predicate.value).name;
      return namedValues.containsKey(name)
          ? predicate.replaceValue(namedValues.get(name))
          : predicate;
    } else {
      return predicate;
    }
  }

  private static LikePredicate bindLikePredicate(
      LikePredicate predicate, Map namedValues) {
    if (predicate.value instanceof BindMarker) {
      if (predicate.value instanceof PositionalBindMarker) {
        throw new IllegalArgumentException(
            SqlError.POSITIONAL_BIND_MARKER_NOT_ALLOWED.buildMessage());
      }
      String name = ((NamedBindMarker) predicate.value).name;
      if (predicate.escape instanceof BindMarker) {
        if (predicate.escape instanceof PositionalBindMarker) {
          throw new IllegalArgumentException(
              SqlError.POSITIONAL_BIND_MARKER_NOT_ALLOWED.buildMessage());
        }
        String escapeName = ((NamedBindMarker) predicate.escape).name;
        return predicate.replaceValueAndEscape(
            namedValues.containsKey(name) ? namedValues.get(name) : predicate.value,
            namedValues.containsKey(escapeName) ? namedValues.get(escapeName) : predicate.escape);
      }
      return namedValues.containsKey(name)
          ? predicate.replaceValue(namedValues.get(name))
          : predicate;
    } else if (predicate.escape instanceof BindMarker) {
      if (predicate.escape instanceof PositionalBindMarker) {
        throw new IllegalArgumentException(
            SqlError.POSITIONAL_BIND_MARKER_NOT_ALLOWED.buildMessage());
      }
      String escapeName = ((NamedBindMarker) predicate.escape).name;
      return namedValues.containsKey(escapeName)
          ? predicate.replaceEscape(namedValues.get(escapeName))
          : predicate;
    } else {
      return predicate;
    }
  }

  public static void appendOptions(StringBuilder builder, Map options) {
    boolean first = true;
    for (Entry entry : options.entrySet()) {
      if (!first) {
        builder.append(" AND ");
      } else {
        first = false;
      }
      appendStringLiteral(builder, entry.getKey());
      builder.append('=');
      appendStringLiteral(builder, entry.getValue());
    }
  }

  public static void appendStringLiteral(StringBuilder builder, String string) {
    builder.append('\'').append(string).append('\'');
  }

  public static void appendObjectName(StringBuilder builder, String object) {
    appendObjectName(builder, object, true);
  }

  public static void appendObjectName(StringBuilder builder, String object, boolean doubleQuote) {
    if (doubleQuote) {
      builder.append('"').append(object).append('"');
    } else {
      builder.append(object);
    }
  }

  public static void appendObjectNames(StringBuilder builder, Collection object) {
    appendObjectNames(builder, object, true);
  }

  public static void appendObjectNames(
      StringBuilder builder, Collection object, boolean doubleQuoteForObjectName) {
    boolean first = true;
    for (String o : object) {
      if (!first) {
        builder.append(',');
      } else {
        first = false;
      }
      StatementUtils.appendObjectName(builder, o, doubleQuoteForObjectName);
    }
  }

  public static void appendTable(StringBuilder builder, TableRef table) {
    appendTable(builder, table, true);
  }

  public static void appendTable(
      StringBuilder builder, TableRef table, boolean doubleQuoteForObjectName) {
    if (table.namespaceName != null) {
      StatementUtils.appendObjectName(builder, table.namespaceName, doubleQuoteForObjectName);
      builder.append('.');
    }
    StatementUtils.appendObjectName(builder, table.tableName, doubleQuoteForObjectName);
  }

  public static void appendTables(StringBuilder builder, Collection tables) {
    appendTables(builder, tables, true);
  }

  public static void appendTables(
      StringBuilder builder, Collection tables, boolean doubleQuoteForObjectName) {
    boolean first = true;
    for (TableRef table : tables) {
      if (!first) {
        builder.append(',');
      } else {
        first = false;
      }
      StatementUtils.appendTable(builder, table, doubleQuoteForObjectName);
    }
  }

  public static void appendColumn(StringBuilder builder, ColumnRef column) {
    appendColumn(builder, column, true);
  }

  public static void appendColumn(
      StringBuilder builder, ColumnRef column, boolean doubleQuoteForObjectName) {
    if (column.table != null) {
      appendTable(builder, column.table, doubleQuoteForObjectName);
      builder.append('.');
    }
    StatementUtils.appendObjectName(builder, column.columnName, doubleQuoteForObjectName);
  }

  public static void appendPredicate(StringBuilder builder, Predicate predicate) {
    appendPredicate(builder, predicate, true);
  }

  public static void appendPredicate(
      StringBuilder builder, Predicate predicate, boolean doubleQuoteForObjectName) {
    StatementUtils.appendColumn(builder, predicate.column, doubleQuoteForObjectName);

    switch (predicate.operator) {
      case EQUAL_TO:
        builder.append('=');
        StatementUtils.appendTerm(builder, predicate.value, doubleQuoteForObjectName);
        break;
      case NOT_EQUAL_TO:
        builder.append("<>");
        StatementUtils.appendTerm(builder, predicate.value, doubleQuoteForObjectName);
        break;
      case GREATER_THAN:
        builder.append('>');
        StatementUtils.appendTerm(builder, predicate.value, doubleQuoteForObjectName);
        break;
      case GREATER_THAN_OR_EQUAL_TO:
        builder.append(">=");
        StatementUtils.appendTerm(builder, predicate.value, doubleQuoteForObjectName);
        break;
      case LESS_THAN:
        builder.append('<');
        StatementUtils.appendTerm(builder, predicate.value, doubleQuoteForObjectName);
        break;
      case LESS_THAN_OR_EQUAL_TO:
        builder.append("<=");
        StatementUtils.appendTerm(builder, predicate.value, doubleQuoteForObjectName);
        break;
      case IS_NULL:
        builder.append(" IS NULL");
        break;
      case IS_NOT_NULL:
        builder.append(" IS NOT NULL");
        break;
      case LIKE:
      case NOT_LIKE:
        assert predicate instanceof LikePredicate;
        appendLikePredicate(builder, (LikePredicate) predicate, doubleQuoteForObjectName);
        break;
      default:
        throw new AssertionError();
    }
  }

  private static void appendLikePredicate(
      StringBuilder builder, LikePredicate predicate, boolean doubleQuoteForObjectName) {
    assert predicate.operator == Predicate.Operator.LIKE
        || predicate.operator == Predicate.Operator.NOT_LIKE;
    if (predicate.operator == Predicate.Operator.NOT_LIKE) {
      builder.append(" NOT");
    }
    builder.append(" LIKE ");
    StatementUtils.appendTerm(builder, predicate.value, doubleQuoteForObjectName);

    builder.append(" ESCAPE ");
    StatementUtils.appendTerm(builder, predicate.escape, doubleQuoteForObjectName);
  }

  public static void appendTerm(StringBuilder builder, Term term) {
    appendTerm(builder, term, true);
  }

  public static void appendTerm(
      StringBuilder builder, Term term, boolean doubleQuoteForObjectName) {
    if (term instanceof PositionalBindMarker) {
      builder.append('?');
    } else if (term instanceof NamedBindMarker) {
      builder.append(':');
      appendObjectName(builder, ((NamedBindMarker) term).name, doubleQuoteForObjectName);
    } else if (term instanceof Value) {
      Value value = (Value) term;
      switch (value.type) {
        case BOOLEAN:
          assert value.value != null;
          builder.append(((boolean) value.value) ? "TRUE" : "FALSE");
          break;
        case INT:
          assert value.value != null;
          builder.append((int) value.value);
          break;
        case BIGINT:
          assert value.value != null;
          builder.append((long) value.value);
          break;
        case FLOAT:
          assert value.value != null;
          builder.append((float) value.value);
          break;
        case DOUBLE:
          assert value.value != null;
          builder.append((double) value.value);
          break;
        case TEXT:
          assert value.value != null;
          appendStringLiteral(builder, (String) value.value);
          break;
        case BLOB_BYTES:
        case BLOB_BYTE_BUFFER:
          throw new IllegalStateException(SqlError.CANNOT_CONVERT_BLOB_TO_SQL.buildMessage());
        case NULL:
          builder.append("NULL");
          break;
        default:
          throw new AssertionError();
      }
    } else {
      assert term instanceof Literal;
      Literal literal = (Literal) term;
      switch (literal.type) {
        case BOOLEAN:
          assert literal.value != null;
          builder.append(((boolean) literal.value) ? "TRUE" : "FALSE");
          break;
        case DECIMAL:
        case FLOAT:
          assert literal.value != null;
          builder.append((String) literal.value);
          break;
        case STRING:
          assert literal.value != null;
          appendStringLiteral(builder, (String) literal.value);
          break;
        case NULL:
          builder.append("NULL");
          break;
        default:
          throw new AssertionError();
      }
    }
  }

  public static void appendWhere(
      StringBuilder builder,
      List andPredicateLists,
      List orPredicateLists) {
    appendWhere(builder, andPredicateLists, orPredicateLists, true);
  }

  public static void appendWhere(
      StringBuilder builder,
      List andPredicateLists,
      List orPredicateLists,
      boolean doubleQuoteForObjectName) {
    StringBuilder predicateBuilder = new StringBuilder();

    boolean isCnf = andPredicateLists.isEmpty();
    Iterator iterator =
        isCnf ? orPredicateLists.iterator() : andPredicateLists.iterator();
    String outerConjunction = isCnf ? " AND " : " OR ";
    String innerConjunction = isCnf ? " OR " : " AND ";
    boolean firstInClause = true;
    while (iterator.hasNext()) {
      PredicateList predicateList = iterator.next();
      if (!firstInClause) {
        predicateBuilder.append(outerConjunction);
      } else {
        firstInClause = false;
      }
      predicateBuilder.append("(");

      boolean firstInBrackets = true;
      for (Predicate predicate : predicateList.getPredicates()) {
        if (!firstInBrackets) {
          predicateBuilder.append(innerConjunction);
        } else {
          firstInBrackets = false;
        }
        StatementUtils.appendPredicate(predicateBuilder, predicate, doubleQuoteForObjectName);
      }

      predicateBuilder.append(")");
    }

    if (predicateBuilder.length() > 0) {
      builder.append(" WHERE ").append(predicateBuilder);
    }
  }

  public static void appendJoinPredicates(
      StringBuilder builder, List joinPredicates) {
    appendJoinPredicates(builder, joinPredicates, true);
  }

  public static void appendJoinPredicates(
      StringBuilder builder, List joinPredicates, boolean doubleQuoteForObjectName) {
    boolean first = true;
    for (JoinPredicate joinPredicate : joinPredicates) {
      if (!first) {
        builder.append(" AND ");
      } else {
        first = false;
      }
      appendJoinPredicate(builder, joinPredicate, doubleQuoteForObjectName);
    }
  }

  public static void appendJoinPredicate(StringBuilder builder, JoinPredicate joinPredicate) {
    appendJoinPredicate(builder, joinPredicate, true);
  }

  public static void appendJoinPredicate(
      StringBuilder builder, JoinPredicate joinPredicate, boolean doubleQuoteForObjectName) {
    StatementUtils.appendColumn(builder, joinPredicate.leftColumn, doubleQuoteForObjectName);
    builder.append('=');
    StatementUtils.appendColumn(builder, joinPredicate.rightColumn, doubleQuoteForObjectName);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy