org.babyfish.jimmer.sql.ast.Expression Maven / Gradle / Ivy
Show all versions of jimmer-sql Show documentation
package org.babyfish.jimmer.sql.ast;
import org.babyfish.jimmer.sql.ast.impl.*;
import org.babyfish.jimmer.sql.ast.impl.util.RowCounts;
import org.babyfish.jimmer.sql.ast.query.Order;
import org.babyfish.jimmer.sql.ast.query.TypedSubQuery;
import org.babyfish.jimmer.sql.ast.tuple.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.function.Consumer;
public interface Expression extends Selection {
/**
* Create `equal` predicate or `is null` predicate.
*
*
* - If {@code this} is null literal, returns {@code other.isNull()}
* - {@code other} is null literal, returns {@code this.isNull()}
*
*
* @param other The right operand which cannot be null
* @return `equal` predicate or `is null` predicate
* @exception NullPointerException The argument `other` is null
*/
@NotNull
Predicate eq(Expression other);
/**
* Create `equal` predicate or `is null` predicate.
*
* If {@code other} is null, creates an `is null` predicate
*
* @param other The right operand which can be null
* @return `equal` predicate or `is null` predicate
*/
@NotNull
Predicate eq(@Nullable T other);
/**
* Create `equal` predicate when certain conditions are met.
* @param condition If this argument is true and the {@code other}
* is neither null nor empty string, creates predicate;
* otherwise, returns null
* @param other The right operand which can be null. If it is null or empty string,
* returns null directly; otherwise, check if {@code condition}
* is true to decide whether to create predicate
* @return A predicate or null
* @see #eqIf(Object)
*/
@Nullable
default Predicate eqIf(boolean condition, @Nullable T other) {
return condition && other != null && !"".equals(other) ? eq(other) : null;
}
/**
* Create `equal` predicate when certain conditions are met.
*
* @param other The right operand which can be null, if it is null or empty string,
* returns null directly; otherwise, create predicate
* @return A predicate or null
* @see #eqIf(boolean, Object)
*/
@Nullable
default Predicate eqIf(@Nullable T other) {
return eqIf(true, other);
}
/**
* Create `not equal` predicate or `is not null` predicate.
*
*
* - If {@code this} is null literal, returns {@code other.isNotNull()}
* - {@code other} is null literal, returns {@code this.isNotNull()}
*
*
* @param other The right operand which cannot be null
* @return `not equal` predicate or `is not null` predicate
* @exception NullPointerException The argument `other` is null
*/
@NotNull
Predicate ne(Expression other);
/**
* Create `not equal` predicate or `is not null` predicate.
*
* If {@code other} is null, creates an `is not null` predicate
*
* @param other The right operand which can be null
* @return `not equal` predicate or `is not null` predicate
*/
@NotNull
Predicate ne(@Nullable T other);
/**
* Create `not equal` predicate when certain conditions are met.
* @param condition If this argument is true and the {@code other}
* is neither null nor empty string, creates predicate;
* otherwise, returns null
* @param other The right operand which can be null. If it is null or empty string,
* returns null directly; otherwise, check if {@code condition}
* is true to decide whether to create predicate
* @return `not equal` predicate or null
* @see #neIf(Object)
*/
@Nullable
default Predicate neIf(boolean condition, @Nullable T other) {
return condition && other != null && !"".equals(other) ? ne(other) : null;
}
/**
* Create `not equal` predicate when certain conditions are met.
*
* @param other The right operand which can be null, if it is null or empty string,
* returns null directly; otherwise, create predicate
* @return `not equal` predicate or null
* @see #eqIf(boolean, Object)
*/
@Nullable
default Predicate neIf(@Nullable T other) {
return neIf(true, other);
}
@NotNull
Predicate isNull();
@NotNull
Predicate isNotNull();
/**
* Create `in` predicate
*
* @param values A collection which cannot be null
* @return `in` predicate
* @exception NullPointerException The argument {@code values} is null
*/
@NotNull
Predicate in(Collection values);
/**
* Create `nullable in` predicate
*
*
* You can use `(a, b) in ((1, 2), (3, null), (5, 6), (7, null))`,
* it will be automatically translated to
* `(a, b) in ((1, 2), (5, 6)) or a = 3 and b is null or a = 7 and b is null`
*
*
* @param values A collection which cannot be null
* @return `in` predicate
* @exception NullPointerException The argument {@code values} is null
*/
@NotNull
Predicate nullableIn(Collection values);
/**
* Create `in` predicate when certain conditions are met.
* @param condition If this argument is true and the {@code other} is not null, creates predicate;
* otherwise, returns null
* @param values The right operand which can be null. If it is null,
* returns null directly; otherwise, check if {@code condition}
* is true to decide whether to create predicate
* @return `in` predicate or null
*/
@Nullable
default Predicate inIf(boolean condition, @Nullable Collection values) {
return condition && values != null ? in(values) : null;
}
/**
* Create `in` predicate when certain conditions are met.
* @param values The right operand which can be null. If it is null,
* returns null directly; otherwise, creates predicate
* @return `in` predicate or null
*/
@Nullable
default Predicate inIf(@Nullable Collection values) {
return inIf(true, values);
}
/**
* Create `nullable-in` predicate when certain conditions are met.
*
*
* You can use `(a, b) in ((1, 2), (3, null), (5, 6), (7, null))`,
* it will be automatically translated to
* `(a, b) in ((1, 2), (5, 6)) or a = 3 and b is null or a = 7 and b is null`
*
*
* @param condition If this argument is true and the {@code other} is not null, creates predicate;
* otherwise, returns null
* @param values The right operand which can be null. If it is null,
* returns null directly; otherwise, check if {@code condition}
* is true to decide whether to create predicate
* @return `in` predicate or null
*/
@Nullable
default Predicate nullableInIf(boolean condition, @Nullable Collection values) {
return condition && values != null ? nullableIn(values) : null;
}
/**
* Create `in` predicate when certain conditions are met.
*
*
* You can use `(a, b) in ((1, 2), (3, null), (5, 6), (7, null))`,
* it will be automatically translated to
* `(a, b) in ((1, 2), (5, 6)) or a = 3 and b is null or a = 7 and b is null`
*
*
* @param values The right operand which can be null. If it is null,
* returns null directly; otherwise, creates predicate
* @return `in` predicate or null
*/
@Nullable
default Predicate nullableInIf(@Nullable Collection values) {
return nullableInIf(true, values);
}
/**
* Create `not in` predicate
*
* @param values A collection which cannot be null
* @return `not in` predicate
* @exception NullPointerException The argument {@code values} is null
*/
@NotNull
Predicate notIn(Collection values);
/**
* Create `nullable not in` predicate
*
*
* You can use `(a, b) not ((1, 2), (3, null), (5, 6), (7, null))`,
* it will be automatically translated to
* `(a, b) not in ((1, 2), (5, 6)) and (a <> 3 or b is not null) and (a <> 7 or b is not null)`
*
*
* @param values A collection which cannot be null
* @return `in` predicate
* @exception NullPointerException The argument {@code values} is null
*/
@NotNull
Predicate nullableNotIn(Collection values);
/**
* Create `not in` predicate when certain conditions are met.
* @param condition If this argument is true and the {@code values} is not null, creates predicate;
* otherwise, returns null
* @param values The right operand which can be null. If it is null,
* returns null directly; otherwise, check if {@code condition}
* is true to decide whether to create predicate
* @return `not in` predicate or null
*/
@Nullable
default Predicate notInIf(boolean condition, @Nullable Collection values) {
return condition && values != null ? notIn(values) : null;
}
/**
* Create `not in` predicate when certain conditions are met.
* @param values The right operand which can be null. If it is null,
* returns null directly; otherwise, creates predicate
* @return `not in` predicate or null
*/
@Nullable
default Predicate notInIf(@Nullable Collection values) {
return notInIf(true, values);
}
/**
* Create `nullable not in` predicate when certain conditions are met.
*
*
* You can use `(a, b) not ((1, 2), (3, null), (5, 6), (7, null))`,
* it will be automatically translated to
* `(a, b) not in ((1, 2), (5, 6)) and (a <> 3 or b is not null) and (a <> 7 or b is not null)`
*
*
* @param condition If this argument is true and the {@code values} is not null, creates predicate;
* otherwise, returns null
* @param values The right operand which can be null. If it is null,
* returns null directly; otherwise, check if {@code condition}
* is true to decide whether to create predicate
* @return `not in` predicate or null
*/
@Nullable
default Predicate nullableNotInIf(boolean condition, @Nullable Collection values) {
return condition && values != null ? nullableNotIn(values) : null;
}
/**
* Create `nullable not in` predicate when certain conditions are met.
*
*
* You can use `(a, b) not ((1, 2), (3, null), (5, 6), (7, null))`,
* it will be automatically translated to
* `(a, b) not in ((1, 2), (5, 6)) and (a <> 3 or b is not null) and (a <> 7 or b is not null)`
*
*
* @param values The right operand which can be null. If it is null,
* returns null directly; otherwise, creates predicate
* @return `not in` predicate or null
*/
@Nullable
default Predicate nullableNotInIf(@Nullable Collection values) {
return nullableNotInIf(true, values);
}
/**
* Create `in` predicate
*
* @param subQuery A sub query which cannot be null
* @return `in` predicate
* @exception NullPointerException The argument {@code subQuery} is null
*/
@NotNull
Predicate in(TypedSubQuery subQuery);
/**
* Create `in` predicate when certain conditions are met.
* @param condition If this argument is true and the {@code subQuery} is not null, creates predicate;
* otherwise, returns null
* @param subQuery The right operand which can be null. If it is null,
* returns null directly; otherwise, check if {@code condition}
* is true to decide whether to create predicate
* @return `in` predicate or null
*/
@Nullable
default Predicate inIf(boolean condition, @Nullable TypedSubQuery subQuery) {
return condition && subQuery != null ? in(subQuery) : null;
}
/**
* Create `in` predicate when certain conditions are met.
* @param subQuery The right operand which can be null. If it is null,
* returns null directly; otherwise, creates predicate
* @return `in` predicate or null
*/
@Nullable
default Predicate inIf(@Nullable TypedSubQuery subQuery) {
return inIf(true, subQuery);
}
/**
* Create `not in` predicate
*
* @param subQuery A sub query which cannot be null
* @return `not in` predicate
* @exception NullPointerException The argument {@code subQuery} is null
*/
@NotNull
Predicate notIn(TypedSubQuery subQuery);
/**
* Create `not in` predicate when certain conditions are met.
* @param condition If this argument is true and the {@code subQuery} is not null, creates predicate;
* otherwise, returns null
* @param subQuery The right operand which can be null. If it is null,
* returns null directly; otherwise, check if {@code condition}
* is true to decide whether to create predicate
* @return `not in` predicate or null
*/
@Nullable
default Predicate notInIf(boolean condition, @Nullable TypedSubQuery subQuery) {
return condition && subQuery != null ? notIn(subQuery) : null;
}
/**
* Create `not in` predicate when certain conditions are met.
* @param subQuery The right operand which can be null. If it is null,
* returns null directly; otherwise, creates predicate
* @return `not in` predicate or null
*/
@Nullable
default Predicate notInIf(@Nullable TypedSubQuery subQuery) {
return notInIf(true, subQuery);
}
@SuppressWarnings("unchecked")
default Predicate expressionIn(Collection> operands) {
return new InExpressionCollectionPredicate(
false,
this,
(Collection>) (Collection>)operands
);
}
@SuppressWarnings("unchecked")
default Predicate expressionNotIn(Collection> operands) {
return new InExpressionCollectionPredicate(
true,
this,
(Collection>) (Collection>)operands
);
}
@NotNull
NumericExpression count();
@NotNull
NumericExpression count(boolean distinct);
@NotNull
Expression coalesce(T defaultValue);
@NotNull
Expression coalesce(Expression defaultExpr);
@NotNull
CoalesceBuilder coalesceBuilder();
@NotNull
Order asc();
@NotNull
Order desc();
@NotNull
static > NumericExpression constant(N value) {
return Constants.number(value);
}
@NotNull
static StringExpression constant(String value) {
return Constants.string(value);
}
/**
* Global expression for row count across tables
*
* @return The row count across tables
*
* @see #count() The count of id of a specific table
*/
@NotNull
static NumericExpression rowCount() {
return RowCounts.INSTANCE;
}
@NotNull
static StringFactory string() {
return ExpressionFactories.of(StringFactory.class);
}
@NotNull
static NumericFactory numeric() {
return ExpressionFactories.of(NumericFactory.class);
}
@NotNull
static ComparableFactory comparable() {
return ExpressionFactories.of(ComparableFactory.class);
}
@NotNull
static AnyFactory any() {
return ExpressionFactories.of(AnyFactory.class);
}
@NotNull
static Expression nullValue(Class type) {
return any().nullValue(type);
}
@NotNull
static Expression> tuple(
Expression expr1,
Expression expr2
) {
return new Tuples.Expr2<>(expr1, expr2);
}
@NotNull
static Expression> tuple(
Expression expr1,
Expression expr2,
Expression expr3
) {
return new Tuples.Expr3<>(expr1, expr2, expr3);
}
@NotNull
static Expression> tuple(
Expression expr1,
Expression expr2,
Expression expr3,
Expression expr4
) {
return new Tuples.Expr4<>(expr1, expr2, expr3, expr4);
}
@NotNull
static Expression> tuple(
Expression expr1,
Expression expr2,
Expression expr3,
Expression expr4,
Expression expr5
) {
return new Tuples.Expr5<>(expr1, expr2, expr3, expr4, expr5);
}
@NotNull
static Expression> tuple(
Expression expr1,
Expression expr2,
Expression expr3,
Expression expr4,
Expression expr5,
Expression expr6
) {
return new Tuples.Expr6<>(expr1, expr2, expr3, expr4, expr5, expr6);
}
@NotNull
static Expression> tuple(
Expression expr1,
Expression expr2,
Expression expr3,
Expression expr4,
Expression expr5,
Expression expr6,
Expression expr7
) {
return new Tuples.Expr7<>(expr1, expr2, expr3, expr4, expr5, expr6, expr7);
}
@NotNull
static Expression> tuple(
Expression expr1,
Expression expr2,
Expression expr3,
Expression expr4,
Expression expr5,
Expression expr6,
Expression expr7,
Expression expr8
) {
return new Tuples.Expr8<>(expr1, expr2, expr3, expr4, expr5, expr6, expr7, expr8);
}
@NotNull
static Expression> tuple(
Expression expr1,
Expression expr2,
Expression expr3,
Expression expr4,
Expression expr5,
Expression expr6,
Expression expr7,
Expression expr8,
Expression expr9
) {
return new Tuples.Expr9<>(expr1, expr2, expr3, expr4, expr5, expr6, expr7, expr8, expr9);
}
interface StringFactory {
@NotNull
StringExpression value(String value);
@NotNull
StringExpression sql(String sql);
@NotNull
StringExpression sql(String sql, Expression> expression, Object ... values);
@NotNull
StringExpression sql(String sql, Expression>[] expressions, Object ... values);
@NotNull
StringExpression sql(String sql, Consumer block);
@NotNull
SimpleCaseBuilder.Str caseBuilder(C value);
@NotNull
SimpleCaseBuilder.Str caseBuilder(Expression expression);
@NotNull
CaseBuilder.Str caseBuilder();
}
interface NumericFactory {
@NotNull
> NumericExpression value(N value);
@NotNull
> NumericExpression sql(Class type, String sql);
@NotNull
> NumericExpression sql(
Class type,
String sql,
Expression> expression,
Object ... values
);
@NotNull
> NumericExpression sql(
Class type,
String sql,
Expression>[] expressions,
Object ... values
);
@NotNull
> NumericExpression sql(
Class type,
String sql,
Consumer block
);
@NotNull
> SimpleCaseBuilder.Num caseBuilder(Class type, C value);
@NotNull
> SimpleCaseBuilder.Num caseBuilder(Class type, Expression expression);
@NotNull
> CaseBuilder.Num caseBuilder(Class type);
}
/*
* This class uses `T extends Comparable>`, not `T extends Comparable`,
* because not all types strictly implement the interface `Comparable`,
* such as `java.time.LocalDateTime`
*/
interface ComparableFactory {
@NotNull
> ComparableExpression value(T value);
@NotNull
> ComparableExpression sql(Class type, String sql);
@NotNull
> ComparableExpression sql(
Class type,
String sql,
Expression> expression,
Object ... values
);
@NotNull
> ComparableExpression sql(
Class type,
String sql,
Expression>[] expressions,
Object ... values
);
@NotNull
> ComparableExpression sql(
Class type,
String sql,
Consumer block
);
@NotNull
> SimpleCaseBuilder.Cmp caseBuilder(Class type, C value);
@NotNull
> SimpleCaseBuilder.Cmp caseBuilder(Class type, Expression expression);
@NotNull
> CaseBuilder.Cmp caseBuilder(Class type);
}
interface AnyFactory {
@NotNull
Expression value(T value);
@NotNull
Expression nullValue(Class type);
@NotNull
Expression sql(Class type, String sql);
@NotNull
Expression sql(
Class type,
String sql,
Expression> expression,
Object ... values
);
@NotNull
Expression sql(
Class type,
String sql,
Expression>[] expressions,
Object ... values
);
@NotNull
Expression sql(
Class type,
String sql,
Consumer block
);
@NotNull
SimpleCaseBuilder caseBuilder(Class type, C value);
@NotNull
SimpleCaseBuilder caseBuilder(Class type, Expression expression);
@NotNull
CaseBuilder caseBuilder(Class type);
}
}