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

io.github.matteobertozzi.easerinsights.jdbc.sql.impl.SqlExprImpl Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.github.matteobertozzi.easerinsights.jdbc.sql.impl;

import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

import io.github.matteobertozzi.easerinsights.jdbc.sql.Sql.SqlFieldNameBuilder;
import io.github.matteobertozzi.easerinsights.jdbc.sql.SqlExpr;
import io.github.matteobertozzi.easerinsights.jdbc.sql.SqlTableSchema.SqlField;

public class SqlExprImpl implements SqlExpr {
  private final SqlFieldNameBuilder nameBuilder;
  private final List bindParams;
  private final StringBuilder sql;
  private final T builder;
  private final int sqlOffset;
  private int subExprStack;

  public SqlExprImpl(final T builder, final StringBuilder sql, final List bindParams, final SqlFieldNameBuilder nameBuilder) {
    this.nameBuilder = nameBuilder;
    this.sql = sql;
    this.bindParams = bindParams;
    this.sqlOffset = sql.length();
    this.builder = builder;
    this.subExprStack = 0;
  }

  @Override public SqlExpr or() { sql.append(" OR "); return this; }
  @Override public SqlExpr and() { sql.append(" AND "); return this; }
  @Override public SqlExpr not() { sql.append(" NOT "); return this; }

  @Override public SqlExpr or(final Consumer> consumer) {
    sql.append(" OR (");
    consumer.accept(this);
    sql.append(") ");
    return this;
  }

  @Override public SqlExpr and(final Consumer> consumer) {
    sql.append(" AND (");
    consumer.accept(this);
    sql.append(") ");
    return this;
  }

  @Override public SqlExpr eq(final SqlField field, final Object value) { return addFieldOp(field, " = ?", value); }
  @Override public SqlExpr ne(final SqlField field, final Object value) { return addFieldOp(field, " != ?", value); }
  @Override public SqlExpr le(final SqlField field, final Object value) { return addFieldOp(field, " <= ?", value); }
  @Override public SqlExpr lt(final SqlField field, final Object value) { return addFieldOp(field, " < ?", value); }
  @Override public SqlExpr ge(final SqlField field, final Object value) { return addFieldOp(field, " >= ?", value); }
  @Override public SqlExpr gt(final SqlField field, final Object value) { return addFieldOp(field, " > ?", value); }

  @Override public SqlExpr like(final SqlField field, final String value) { return addFieldOp(field, " LIKE ?", value); }
  @Override public SqlExpr notLike(final SqlField field, final String value) { return addFieldOp(field, " LIKE ?", value); }

  @Override public SqlExpr isNull(final SqlField field) { return addFieldOp(field, " IS NULL"); }
  @Override public SqlExpr isNotNull(final SqlField field) { return addFieldOp(field, " IS NOT NULL "); }

@Override public SqlExpr in(final SqlField field, final short[] values) { return addFieldOpIn(field, " IN ", values); }
  @Override public SqlExpr notIn(final SqlField field, final short[] values) { return addFieldOpIn(field, " NOT IN ", values); }

  @Override public SqlExpr in(final SqlField field, final int[] values) { return addFieldOpIn(field, " IN ", values); }
  @Override public SqlExpr notIn(final SqlField field, final int[] values) { return addFieldOpIn(field, " NOT IN ", values); }

  @Override public SqlExpr in(final SqlField field, final long[] values) { return addFieldOpIn(field, " IN ", values); }
  @Override public SqlExpr notIn(final SqlField field, final long[] values) { return addFieldOpIn(field, " NOT IN ", values); }

  @Override public SqlExpr in(final SqlField field, final Object... values) { return addFieldOpIn(field, " IN ", values, Function.identity()); }
  @Override public SqlExpr notIn(final SqlField field, final Object... values) { return addFieldOpIn(field, " NOT IN ", values, Function.identity()); }

  @Override public  SqlExpr in(final SqlField field, final V[] values, final Function mapper) { return addFieldOpIn(field, " IN ", values, mapper); }
  @Override public  SqlExpr notIn(final SqlField field, final V[] values, final Function mapper) { return addFieldOpIn(field, " NOT IN ", values, mapper); }

  @Override public  SqlExpr in(final SqlField field, final Collection values, final Function mapper) { return addFieldOpIn(field, " IN ", values, mapper); }
  @Override public  SqlExpr notIn(final SqlField field, final Collection values, final Function mapper) { return addFieldOpIn(field, " NOT IN ", values, mapper); }

  @Override
  public SqlExpr between(final SqlField field, final Object a, final Object b) {
    nameBuilder.add(sql, field).append(" BETWEEN ? AND ?");
    bindParams.add(a);
    bindParams.add(b);
    return this;
  }

  private SqlExpr addFieldOp(final SqlField field, final String op) {
    nameBuilder.add(sql, field).append(op);
    return this;
  }

  private SqlExpr addFieldOp(final SqlField field, final String op, final Object value) {
    nameBuilder.add(sql, field).append(op);
    bindParams.add(value);
    return this;
  }

  private SqlExpr addFieldOpIn(final SqlField field, final String op, final short[] values) {
    if (values.length == 0) return this;

    nameBuilder.add(sql, field).append(op).append(" (?");
    bindParams.add(values[0]);
    for (int i = 1; i < values.length; ++i) {
      sql.append(",?");
      bindParams.add(values[i]);
    }
    sql.append(')');
    return this;
  }

  private SqlExpr addFieldOpIn(final SqlField field, final String op, final int[] values) {
    if (values.length == 0) return this;

    nameBuilder.add(sql, field).append(op).append(" (?");
    bindParams.add(values[0]);
    for (int i = 1; i < values.length; ++i) {
      sql.append(",?");
      bindParams.add(values[i]);
    }
    sql.append(')');
    return this;
  }

  private SqlExpr addFieldOpIn(final SqlField field, final String op, final long[] values) {
    if (values.length == 0) return this;

    nameBuilder.add(sql, field).append(op).append(" (?");
    bindParams.add(values[0]);
    for (int i = 1; i < values.length; ++i) {
      sql.append(",?");
      bindParams.add(values[i]);
    }
    sql.append(')');
    return this;
  }

  private  SqlExpr addFieldOpIn(final SqlField field, final String op, final V[] values, final Function mapping) {
    if (values.length == 0) return this;

    nameBuilder.add(sql, field).append(op).append(" (?");
    bindParams.add(mapping.apply(values[0]));
    for (int i = 1; i < values.length; ++i) {
      sql.append(",?");
      bindParams.add(mapping.apply(values[i]));
    }
    sql.append(')');
    return this;
  }

  private  SqlExpr addFieldOpIn(final SqlField field, final String op, final Collection values, final Function mapping) {
    if (values.isEmpty()) return this;

    int index = 0;
    nameBuilder.add(sql, field).append(op).append(" (?");
    for (final V value: values) {
      if (index++ > 0) sql.append(",?");
      bindParams.add(mapping.apply(value));
    }
    sql.append(')');
    return this;
  }

  @Override
  public SqlExpr openExpr() {
    subExprStack++;
    sql.append('(');
    return this;
  }

  @Override
  public SqlExpr closeExpr() {
    subExprStack--;
    sql.append(')');
    return this;
  }

  public T bind() {
    if (subExprStack != 0) {
      throw new IllegalArgumentException("parenthesis mismatch: " + sql.substring(sqlOffset));
    }
    return builder;
  }
}