All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.babyfish.jimmer.sql.ast.impl.Literals Maven / Gradle / Ivy
package org.babyfish.jimmer.sql.ast.impl;
import org.babyfish.jimmer.meta.ImmutableProp;
import org.babyfish.jimmer.sql.ast.*;
import org.babyfish.jimmer.sql.ast.impl.render.AbstractSqlBuilder;
import org.babyfish.jimmer.sql.ast.impl.render.BatchSqlBuilder;
import org.babyfish.jimmer.sql.ast.table.spi.PropExpressionImplementor;
import org.babyfish.jimmer.sql.exception.ExecutionException;
import org.babyfish.jimmer.sql.runtime.JSqlClientImplementor;
import org.babyfish.jimmer.sql.runtime.ScalarProvider;
import org.babyfish.jimmer.sql.runtime.SqlBuilder;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import static org.babyfish.jimmer.sql.ScalarProviderUtils.toSql;
public class Literals {
private Literals() {}
public static StringExpression string(String value) {
return new Str(value);
}
public static > NumericExpression number(N value) {
return new Num<>(value);
}
public static > ComparableExpression comparable(T value) {
return new Cmp<>(value);
}
public static void bind(Expression> mayBeLiteral, Expression> expression) {
if (!(mayBeLiteral instanceof Any>)) {
return;
}
if (expression instanceof PropExpression>) {
((Any>)mayBeLiteral).setMatchedProp(((PropExpressionImplementor>)expression).getProp());
} else if (expression instanceof TupleExpressionImplementor>) {
TupleExpressionImplementor> tupleExpr = (TupleExpressionImplementor>) expression;
int size = tupleExpr.size();
ImmutableProp[] props = new ImmutableProp[size];
boolean hasProp = false;
for (int i = 0; i < size; i++) {
Selection> expr = tupleExpr.get(i);
if (expr instanceof PropExpression>) {
props[i] = ((PropExpressionImplementor>)expr).getProp();
hasProp = true;
}
}
if (hasProp) {
((Any>) mayBeLiteral).setMatchedProps(props);
}
}
}
@SuppressWarnings("unchecked")
public static Collection> convert(Collection> literals, Expression> expression, JSqlClientImplementor sqlClient) {
if (literals == null || literals.isEmpty()) {
return literals;
}
if (expression instanceof PropExpression>) {
ImmutableProp prop = ((PropExpressionImplementor>)expression).getProp();
ScalarProvider scalarProvider = sqlClient.getScalarProvider(prop);
if (scalarProvider == null) {
return literals;
}
List newLiterals = new ArrayList<>(literals.size());
for (Object literal : literals) {
try {
newLiterals.add(literal != null ? toSql(literal, scalarProvider, sqlClient.getDialect()) : null);
} catch (Exception ex) {
throw new ExecutionException(
"Cannot convert the value \"" +
literal +
"\" of prop \"" +
prop +
"\" by scalar provider \"" +
scalarProvider.getClass().getName() +
"\"",
ex
);
}
}
return newLiterals;
} else if (expression instanceof TupleExpressionImplementor>) {
TupleExpressionImplementor> tupleExpr = (TupleExpressionImplementor>) expression;
int size = tupleExpr.size();
ImmutableProp[] props = new ImmutableProp[size];
ScalarProvider[] scalarProviders = new ScalarProvider[size];
boolean hasScalarProvider = false;
for (int i = 0; i < size; i++) {
Selection> expr = tupleExpr.get(i);
if (expr instanceof PropExpression>) {
ImmutableProp prop = ((PropExpressionImplementor>)expr).getProp();
ScalarProvider scalarProvider = sqlClient.getScalarProvider(prop);
if (scalarProvider != null) {
props[i] = prop;
scalarProviders[i] = scalarProvider;
hasScalarProvider = true;
}
}
}
if (!hasScalarProvider) {
return literals;
}
List newLiterals = new ArrayList<>(literals.size());
for (Object literal : literals) {
newLiterals.add(
((TupleImplementor)literal).convert((value, index) -> {
if (value != null) {
ScalarProvider scalarProvider = scalarProviders[index];
if (scalarProvider != null) {
try {
return toSql(literal, scalarProvider, sqlClient.getDialect());
} catch (Exception ex) {
throw new ExecutionException(
"Cannot convert the tuple item[" +
"index" +
"] of prop \"" +
props[index] +
"\" by scalar provider \"" +
scalarProvider.getClass().getName() +
"\"",
ex
);
}
}
}
return value;
})
);
}
return newLiterals;
} else {
return literals;
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
public static Expression any(T value) {
if (value instanceof String) {
return (Expression) string((String)value);
}
if (value instanceof Number) {
return (Expression) number((Number & Comparable)value);
}
if (value instanceof Comparable>) {
return (Expression) comparable((Comparable)value);
}
if (value instanceof Expression>) {
return (Expression) value;
}
return new Any<>(value);
}
static class Any extends AbstractExpression implements LiteralExpressionImplementor {
private final T value;
// Single
private ImmutableProp matchedProp;
// Tuple
private ImmutableProp[] matchedProps;
public Any(T value) {
if (value == null) {
throw new IllegalArgumentException(
"The value of literal expression cannot be null." +
"Except for `eq` and `ne`, most SQL expressions cannot be constructed " +
"based on using null, in order to avoid this problem:\n" +
"- java users can\n" +
" Change `whereIf(, )` to whereIf(, () -> )\n" +
"- kotlin users can\n" +
" Change `if (value !== null) where()` to `value?.let { where() }`"
);
}
this.value = value;
}
@Override
public T getValue() {
return value;
}
@SuppressWarnings("unchecked")
@Override
public Class getType() {
return (Class)value.getClass();
}
@Override
public void accept(@NotNull AstVisitor visitor) {
}
@Override
public void renderTo(@NotNull AbstractSqlBuilder> builder) {
if (builder instanceof BatchSqlBuilder) {
((BatchSqlBuilder) builder).rawVariable(finalValue(builder.sqlClient()));
} else {
((SqlBuilder) builder).variable(finalValue(builder.sqlClient()));
}
}
private Object finalValue(JSqlClientImplementor sqlClient) {
if (matchedProp != null) {
ScalarProvider scalarProvider = sqlClient.getScalarProvider(matchedProp);
if (scalarProvider != null) {
try {
return toSql(value, scalarProvider, sqlClient.getDialect());
} catch (Exception ex) {
throw new ExecutionException(
"Cannot convert the value \"" +
value +
"\" of prop \"" +
matchedProp +
"\" by the scalar provider \"" +
scalarProvider.getClass().getName() +
"\"",
ex
);
}
}
} else if (matchedProps != null) {
return ((TupleImplementor)value).convert((it, index) -> {
ImmutableProp prop = matchedProps[index];
ScalarProvider scalarProvider =
sqlClient.getScalarProvider(prop);
if (scalarProvider != null) {
try {
return toSql(it, scalarProvider, sqlClient.getDialect());
} catch (Exception ex) {
throw new ExecutionException(
"Cannot convert the tuple item[" +
index +
"] of prop \"" +
matchedProps[index] +
"\" by the scalar provider \"" +
scalarProvider.getClass().getName() +
"\"",
ex
);
}
}
return it;
});
}
return Variables.process(value, getType(), sqlClient);
}
@Override
protected boolean determineHasVirtualPredicate() {
return false;
}
@Override
protected Ast onResolveVirtualPredicate(AstContext ctx) {
return this;
}
@Override
public int precedence() {
return 0;
}
public void setMatchedProp(ImmutableProp matchedProp) {
if (this.matchedProp != null && this.matchedProp != matchedProp) {
throw new IllegalStateException(
"The matched property of current literal expression has been configured, " +
"is the current literal expression is shared by difference parts of SQL DSL?"
);
}
this.matchedProp = matchedProp;
}
public void setMatchedProps(ImmutableProp[] matchedProps) {
if (this.matchedProps != null && this.matchedProps != matchedProps) {
throw new IllegalStateException(
"The matched properties of current literal expression has been configured, " +
"is the current literal expression is shared by difference parts of SQL DSL?"
);
}
this.matchedProps = matchedProps;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Any> any = (Any>) o;
return value.equals(any.value) && Objects.equals(matchedProp, any.matchedProp) && Arrays.equals(matchedProps, any.matchedProps);
}
@Override
public int hashCode() {
int result = Objects.hash(value, matchedProp);
result = 31 * result + Arrays.hashCode(matchedProps);
return result;
}
}
private static class Str extends Any implements StringExpressionImplementor {
public Str(String value) {
super(value);
}
}
private static class Num> extends Any implements NumericExpressionImplementor {
public Num(N value) {
super(value);
}
}
private static class Cmp> extends Any implements ComparableExpressionImplementor {
public Cmp(T value) {
super(value);
}
}
}