com.github.chengyuxing.sql.dsl.clause.Where Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rabbit-sql Show documentation
Show all versions of rabbit-sql Show documentation
Light wrapper of JDBC, support ddl, dml, query, plsql/procedure/function, transaction and manage sql
file.
package com.github.chengyuxing.sql.dsl.clause;
import com.github.chengyuxing.common.tuple.Pair;
import com.github.chengyuxing.sql.dsl.clause.condition.*;
import com.github.chengyuxing.sql.dsl.types.FieldReference;
import com.github.chengyuxing.sql.dsl.types.Logic;
import com.github.chengyuxing.sql.dsl.types.Operator;
import com.github.chengyuxing.sql.utils.SqlGenerator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import static com.github.chengyuxing.sql.dsl.types.StandardOperator.*;
/**
* Where clause builder.
*
* @param entity type
*/
public abstract class Where extends CriteriaBuilder {
protected List criteria = new ArrayList<>();
/**
* Construct a new Where builder.
*
* @param clazz entity class
*/
public Where(@NotNull Class clazz) {
super(clazz);
}
/**
* Construct a new Where builder with initial Where builder.
*
* @param clazz entity class
* @param other where builder
*/
public Where(@NotNull Class clazz, @NotNull Where other) {
super(clazz);
this.criteria = other.criteria;
}
/**
* Returns a new Where builder.
*
* @return where builder
*/
protected abstract Where newInstance();
/**
* Add a condition.
*
* @param column column
* @param operator {@link com.github.chengyuxing.sql.dsl.types.StandardOperator StandardOperator} or other trusted operator
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where of(FieldReference column, @NotNull Operator operator, E value, Predicate... predicates) {
if (operator == Logic.AND || operator == Logic.OR) {
throw new IllegalArgumentException("logic operator '" + operator.getValue() + "' invalid at this time");
}
if (isConditionMatched(value, predicates)) {
addCondition(column, operator, value);
}
return this;
}
/**
* {@code =}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where eq(FieldReference column, E value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
if (Objects.nonNull(value)) {
addCondition(column, EQ, value);
} else {
addCondition(column, IS_NULL, null);
}
}
return this;
}
/**
* {@code <>}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where neq(FieldReference column, E value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
if (Objects.nonNull(value)) {
addCondition(column, NEQ, value);
} else {
addCondition(column, IS_NOT_NULL, null);
}
}
return this;
}
/**
* {@code >}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where gt(FieldReference column, E value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, GT, value);
}
return this;
}
/**
* {@code <}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where lt(FieldReference column, E value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, LT, value);
}
return this;
}
/**
* {@code >=}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where gte(FieldReference column, E value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, GTE, value);
}
return this;
}
/**
* {@code <=}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where lte(FieldReference column, E value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, LTE, value);
}
return this;
}
/**
* {@code in (...)}
*
* @param column column
* @param values {@link Collection} or Array.
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value item type
* @param value type
* @return where builder
*/
@SafeVarargs
public final > Where in(FieldReference column, V values, Predicate... predicates) {
if (isConditionMatched(values, predicates)) {
criteria.add(new InCondition<>(getColumnName(column), IN, values));
}
return this;
}
/**
* {@code not in (...)}
*
* @param column column
* @param values {@link Collection} or Array.
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value item type
* @param value type
* @return where builder
*/
@SafeVarargs
public final > Where notIn(FieldReference column, V values, Predicate... predicates) {
if (isConditionMatched(values, predicates)) {
criteria.add(new InCondition<>(getColumnName(column), NOT_IN, values));
}
return this;
}
/**
* {@code between} a {@code and} b
*
* @param column column
* @param a value 1.
* @param b value 2.
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where between(FieldReference column, E a, E b, BiPredicate... predicates) {
if (isConditionMatched(a, b, predicates)) {
criteria.add(new BetweenCondition(getColumnName(column), BETWEEN, Pair.of(a, b)));
}
return this;
}
/**
* {@code not between} a {@code and} b
*
* @param column column
* @param a value 1.
* @param b value 2.
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @param value type
* @return where builder
*/
@SafeVarargs
public final Where notBetween(FieldReference column, E a, E b, BiPredicate... predicates) {
if (isConditionMatched(a, b, predicates)) {
criteria.add(new BetweenCondition(getColumnName(column), NOT_BETWEEN, Pair.of(a, b)));
}
return this;
}
/**
* {@code like '%} str {@code %'}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @return where builder
*/
@SafeVarargs
public final Where like(FieldReference column, String value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, LIKE, "%" + value + "%");
}
return this;
}
/**
* {@code not like '%} str {@code %'}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @return where builder
*/
@SafeVarargs
public final Where notLike(FieldReference column, String value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, NOT_LIKE, "%" + value + "%");
}
return this;
}
/**
* {@code like '} str {@code %'}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @return where builder
*/
@SafeVarargs
public final Where startsWith(FieldReference column, String value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, LIKE, value + "%");
}
return this;
}
/**
* {@code not like '} str {@code %'}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @return where builder
*/
@SafeVarargs
public final Where notStartsWith(FieldReference column, String value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, NOT_LIKE, value + "%");
}
return this;
}
/**
* {@code like '%} str {@code '}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @return where builder
*/
@SafeVarargs
public final Where endsWith(FieldReference column, String value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, LIKE, "%" + value);
}
return this;
}
/**
* {@code not like '%} str {@code '}
*
* @param column column
* @param value value
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @return where builder
*/
@SafeVarargs
public final Where notEndsWith(FieldReference column, String value, Predicate... predicates) {
if (isConditionMatched(value, predicates)) {
addCondition(column, NOT_LIKE, "%" + value);
}
return this;
}
/**
* {@code is null}
*
* @param column column
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @return where builder
*/
public Where isNull(FieldReference column, boolean... predicates) {
if (isConditionMatched(predicates)) {
addCondition(column, IS_NULL, null);
}
return this;
}
/**
* {@code is not null}
*
* @param column column
* @param predicates all predicates to the true add the condition otherwise avoid the condition.
* @return where builder
*/
public Where isNotNull(FieldReference column, boolean... predicates) {
if (isConditionMatched(predicates)) {
addCondition(column, IS_NOT_NULL, null);
}
return this;
}
/**
* And group, all condition will be concat with {@code or}, {@code and (...or...or...or...)}
* E.g. the complex nest condition:
*
* ((name = 'cyx' and age = 30) or (name = 'jack' and age = 60))
*
* The built struct:
*
* w -> w.and(o -> o.or(a -> a.eq(Guest::getName, "cyx")
* .eq(Guest::getAge, 30))
* .or(r -> r.eq(Guest::getName, "jack")
* .eq(Guest::getAge, 60))
* )
*
*
* @param orGroup and group
* @param predicates all predicates to the true add the group otherwise avoid the group.
* @return where builder
* @see #or(Function, boolean...)
*/
public Where and(Function, Where> orGroup, boolean... predicates) {
if (isConditionMatched(predicates)) {
List criteriaList = orGroup.apply(newInstance()).criteria;
criteria.add(new AndGroup(criteriaList));
}
return this;
}
/**
* Or group, all condition will be concat with {@code and}, {@code or (...and...ang...and...)}
* E.g. simple nest condition:
*
* {@code (age < 15 or age > 60) and name = 'cyx'}
*
*
* w -> w.and(o -> o.lt(Guest::getAge, 15)
* .gt(Guest::getAge, 60))
* .eq(Guest::getName, "cyx")
*
*
* @param andGroup or group
* @param predicates all predicates to the true add the group otherwise avoid the group.
* @return where builder
* @see #and(Function, boolean...)
*/
public Where or(Function, Where> andGroup, boolean... predicates) {
if (isConditionMatched(predicates)) {
List criteriaList = andGroup.apply(newInstance()).criteria;
criteria.add(new OrGroup(criteriaList));
}
return this;
}
/**
* Returns a where condition consisting of the where builder, check the built result currently.
*
* @param consumer built result consumer (sql, (name parameter sql, params)) -> _
* @return where builder
*/
public Where peek(BiConsumer>> consumer) {
Pair> where = build();
String sql = new SqlGenerator(namedParamPrefix()).generateSql(where.getItem1(), where.getItem2());
consumer.accept(sql, where);
return this;
}
/**
* Returns where clause and params.
*
* @return where clause and params.
*/
protected @NotNull @Unmodifiable Pair> build() {
Pair> where = build(new AtomicInteger(0), criteria, Logic.AND, 0);
if (!where.getItem1().isEmpty()) {
return Pair.of("\nwhere " + where.getItem1(), Collections.unmodifiableMap(where.getItem2()));
}
return where;
}
private void addCondition(FieldReference column, Operator operator, Object value) {
criteria.add(new Condition<>(getColumnName(column), operator, value));
}
private static boolean isConditionMatched(boolean... predicates) {
boolean matched = true;
for (boolean predicate : predicates) {
if (!predicate) {
matched = false;
break;
}
}
return matched;
}
@SafeVarargs
private static boolean isConditionMatched(E value, Predicate... predicates) {
boolean matched = true;
for (Predicate predicate : predicates) {
if (!predicate.test(value)) {
matched = false;
break;
}
}
return matched;
}
@SafeVarargs
private static boolean isConditionMatched(E a, E b, BiPredicate... predicates) {
boolean matched = true;
for (BiPredicate predicate : predicates) {
if (!predicate.test(a, b)) {
matched = false;
break;
}
}
return matched;
}
}