DB: some improvements
- Refactor auto-conversion of custom types - Ability to create a WHERE ... IN ... expression with a custom left operand - Typos in Javadoc
This commit is contained in:
parent
56632867ec
commit
5d294ea172
@ -361,7 +361,7 @@ public abstract class SQLElement<E extends SQLElement<E>> {
|
||||
first = false;
|
||||
concatValues.append(" ? ");
|
||||
concatFields.append("`").append(entry.getKey().getName()).append("`");
|
||||
addValueToSQLObjectList(psValues, entry.getKey(), entry.getValue());
|
||||
psValues.add(entry.getKey().fromJavaTypeToJDBCType(entry.getValue()));
|
||||
}
|
||||
|
||||
try (Connection c = db.getConnection();
|
||||
@ -389,20 +389,6 @@ public abstract class SQLElement<E extends SQLElement<E>> {
|
||||
return (E) this;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
/* package */ static <E extends SQLElement<E>> void addValueToSQLObjectList(List<Object> list, SQLField<E, ?> field, Object jValue) throws DBException {
|
||||
if (jValue != null && field.type instanceof SQLCustomType) {
|
||||
try {
|
||||
jValue = ((SQLCustomType)field.type).javaToDbConv.apply(jValue);
|
||||
} catch (Exception e) {
|
||||
throw new DBException("Error while converting value of field '"+field.getName()+"' with SQLCustomType from "+field.type.getJavaType()
|
||||
+"(java source) to "+((SQLCustomType<?, ?>)field.type).intermediateJavaType+"(jdbc destination). The original value is '"+jValue+"'", e);
|
||||
}
|
||||
}
|
||||
list.add(jValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if this entry is currently stored in DB or not.
|
||||
* @return true if this entry is currently stored in DB, or false otherwise.
|
||||
|
@ -133,7 +133,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression comparing this field with the provided value using the {@code =} operator.
|
||||
* @param r the value to compare with.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> eq(T r) {
|
||||
return comp(SQLComparator.EQ, r);
|
||||
@ -142,7 +142,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression comparing this field with the provided value using the {@code >=} operator.
|
||||
* @param r the value to compare with.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> geq(T r) {
|
||||
return comp(SQLComparator.GEQ, r);
|
||||
@ -151,7 +151,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression comparing this field with the provided value using the {@code >} operator.
|
||||
* @param r the value to compare with.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> gt(T r) {
|
||||
return comp(SQLComparator.GT, r);
|
||||
@ -160,7 +160,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression comparing this field with the provided value using the {@code <=} operator.
|
||||
* @param r the value to compare with.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> leq(T r) {
|
||||
return comp(SQLComparator.LEQ, r);
|
||||
@ -169,7 +169,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression comparing this field with the provided value using the {@code <} operator.
|
||||
* @param r the value to compare with.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> lt(T r) {
|
||||
return comp(SQLComparator.LT, r);
|
||||
@ -178,7 +178,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression comparing this field with the provided value using the {@code !=} operator.
|
||||
* @param r the value to compare with.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> neq(T r) {
|
||||
return comp(SQLComparator.NEQ, r);
|
||||
@ -194,7 +194,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
* Create a SQL {@code WHERE} expression comparing this field with the provided value using the {@code LIKE}
|
||||
* keyword.
|
||||
* @param like the value to compare with.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> like(String like) {
|
||||
return new SQLWhereLike<>(this, like);
|
||||
@ -206,7 +206,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
* Create a SQL {@code WHERE} expression testing the presence of this field in the provided collection of value
|
||||
* using the {@code IN} keyword.
|
||||
* @param v the value to compare with.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> in(Collection<T> v) {
|
||||
return new SQLWhereIn<>(this, v);
|
||||
@ -216,7 +216,7 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression testing the nullity of this field using the {@code IS NULL} keyword.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> isNull() {
|
||||
return new SQLWhereNull<>(this, true);
|
||||
@ -225,10 +225,39 @@ public class SQLField<E extends SQLElement<E>, T> {
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression testing the non-nullity of this field using the {@code IS NOT NULL}
|
||||
* keyword.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public fr.pandacube.lib.db.SQLWhere<E> isNotNull() {
|
||||
return new SQLWhereNull<>(this, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public Object fromJavaTypeToJDBCType(Object value) throws DBException {
|
||||
Object ret = value;
|
||||
if (value != null && type instanceof SQLCustomType customType) {
|
||||
try {
|
||||
ret = customType.javaToDbConv.apply(value);
|
||||
} catch (Exception e) {
|
||||
throw new DBException("Error while converting value of field '" + name + "' with SQLCustomType from " + type.getJavaType()
|
||||
+ "(java source) to " + customType.intermediateJavaType + "(jdbc destination). The original value is '" + value + "'", e);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Collection<Object> fromListJavaTypeToJDBCType(Collection<?> values) throws DBException {
|
||||
if (values == null)
|
||||
return null;
|
||||
List<Object> ret = new ArrayList<>(values.size());
|
||||
for (Object value : values) {
|
||||
ret.add(fromJavaTypeToJDBCType(value));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public class SQLUpdateBuilder<E extends SQLElement<E>> {
|
||||
if (!first)
|
||||
sql.append(", ");
|
||||
sql.append("`").append(entry.getKey().getName()).append("` = ? ");
|
||||
SQLElement.addValueToSQLObjectList(params, entry.getKey(), entry.getValue());
|
||||
params.add(entry.getKey().fromJavaTypeToJDBCType(entry.getValue()));
|
||||
first = false;
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,12 @@ package fr.pandacube.lib.db;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import fr.pandacube.lib.util.log.Log;
|
||||
|
||||
/**
|
||||
* A SQL {@code WHERE} expression.
|
||||
* SQL {@code WHERE} expression.
|
||||
* @param <E> the table type.
|
||||
*/
|
||||
public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
@ -29,7 +30,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
* Create a SQL {@code WHERE} expression that is true when this expression {@code AND} the provided expression is
|
||||
* true.
|
||||
* @param other the other expression.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public SQLWhere<E> and(SQLWhere<E> other) {
|
||||
return SQLWhere.<E>and().and(this).and(other);
|
||||
@ -39,7 +40,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
* Create a SQL {@code WHERE} expression that is true when this expression {@code OR} the provided expression is
|
||||
* true.
|
||||
* @param other the other expression.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public SQLWhere<E> or(SQLWhere<E> other) {
|
||||
return SQLWhere.<E>or().or(this).or(other);
|
||||
@ -48,7 +49,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression builder joining multiple expressions with the {@code AND} operator.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
* @param <E> the table type.
|
||||
*/
|
||||
public static <E extends SQLElement<E>> SQLWhereAndBuilder<E> and() {
|
||||
@ -57,7 +58,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
|
||||
/**
|
||||
* Create a SQL {@code WHERE} expression builder joining multiple expressions with the {@code OR} operator.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
* @param <E> the table type.
|
||||
*/
|
||||
public static <E extends SQLElement<E>> SQLWhereOrBuilder<E> or() {
|
||||
@ -67,7 +68,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
/**
|
||||
* Create a custom SQL {@code WHERE} expression.
|
||||
* @param whereExpr the raw SQL {@code WHERE} expression.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public static <E extends SQLElement<E>> SQLWhere<E> expression(String whereExpr) {
|
||||
return expression(whereExpr, List.of());
|
||||
@ -77,12 +78,33 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
* Create a custom SQL {@code WHERE} expression.
|
||||
* @param whereExpr the raw SQL {@code WHERE} expression.
|
||||
* @param params the parameters of the provided expression.
|
||||
* @return a SQL {@code WHERE} expression.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public static <E extends SQLElement<E>> SQLWhere<E> expression(String whereExpr, List<Object> params) {
|
||||
return new SQLWhereCustomExpression<>(whereExpr, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SQL {@code WHERE ... IN ...} expression with a custom left operand.
|
||||
* @param leftExpr the raw SQL left operand.
|
||||
* @param valuesIn the values on the right of the {@code IN} operator.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public static <E extends SQLElement<E>> SQLWhere<E> expressionIn(String leftExpr, Collection<?> valuesIn) {
|
||||
return expressionIn(leftExpr, List.of(), valuesIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SQL {@code WHERE ... IN ...} expression with a custom left operand.
|
||||
* @param leftExpr the raw SQL left operand.
|
||||
* @param leftParams the parameters of the left operand.
|
||||
* @param valuesIn the values on the right of the {@code IN} operator.
|
||||
* @return a new SQL {@code WHERE} expression.
|
||||
*/
|
||||
public static <E extends SQLElement<E>> SQLWhere<E> expressionIn(String leftExpr, List<Object> leftParams, Collection<?> valuesIn) {
|
||||
return new SQLWhereInCustom<>(leftExpr, leftParams, valuesIn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -232,9 +254,8 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
|
||||
@Override
|
||||
/* package */ ParameterizedSQLString toSQL() throws DBException {
|
||||
List<Object> params = new ArrayList<>();
|
||||
SQLElement.addValueToSQLObjectList(params, left, right);
|
||||
return new ParameterizedSQLString("`" + left.getName() + "` " + comp.sql + " ? ", params);
|
||||
return new ParameterizedSQLString("`" + left.getName() + "` " + comp.sql + " ? ",
|
||||
List.of(left.fromJavaTypeToJDBCType(right)));
|
||||
}
|
||||
|
||||
/* package */ enum SQLComparator {
|
||||
@ -266,33 +287,39 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
|
||||
|
||||
|
||||
/* package */ static class SQLWhereIn<E extends SQLElement<E>> extends SQLWhere<E> {
|
||||
/* package */ static class SQLWhereInCustom<E extends SQLElement<E>> extends SQLWhere<E> {
|
||||
|
||||
private final SQLField<E, ?> field;
|
||||
private final Collection<?> values;
|
||||
private final String leftExpression;
|
||||
private final List<Object> leftExpressionParameters;
|
||||
protected Collection<?> collectionIn;
|
||||
|
||||
/* package */ <T> SQLWhereIn(SQLField<E, T> f, Collection<T> v) {
|
||||
if (f == null || v == null)
|
||||
throw new IllegalArgumentException("All arguments for SQLWhereIn constructor can't be null");
|
||||
field = f;
|
||||
values = v;
|
||||
/* package */ <T> SQLWhereInCustom(String leftExpr, List<Object> leftExprParams, Collection<T> collectionIn) {
|
||||
if (leftExpr == null)
|
||||
throw new IllegalArgumentException("leftExpr can't be null");
|
||||
if (leftExprParams == null)
|
||||
leftExprParams = List.of();
|
||||
if (collectionIn == null)
|
||||
collectionIn = List.of();
|
||||
leftExpression = leftExpr;
|
||||
leftExpressionParameters = leftExprParams;
|
||||
this.collectionIn = collectionIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
/* package */ ParameterizedSQLString toSQL() throws DBException {
|
||||
List<Object> params = new ArrayList<>();
|
||||
|
||||
if (values.isEmpty())
|
||||
if (collectionIn.isEmpty())
|
||||
return new ParameterizedSQLString(" 1=0 ", params);
|
||||
|
||||
for (Object v : values)
|
||||
SQLElement.addValueToSQLObjectList(params, field, v);
|
||||
params.addAll(leftExpressionParameters);
|
||||
params.addAll(collectionIn);
|
||||
|
||||
char[] questions = new char[values.isEmpty() ? 0 : (values.size() * 2 - 1)];
|
||||
char[] questions = new char[collectionIn.size() * 2 - 1];
|
||||
for (int i = 0; i < questions.length; i++)
|
||||
questions[i] = i % 2 == 0 ? '?' : ',';
|
||||
|
||||
return new ParameterizedSQLString("`" + field.getName() + "` IN (" + new String(questions) + ") ", params);
|
||||
return new ParameterizedSQLString("(" + leftExpression + ") IN (" + new String(questions) + ") ", params);
|
||||
}
|
||||
|
||||
}
|
||||
@ -302,6 +329,32 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
|
||||
|
||||
|
||||
|
||||
/* package */ static class SQLWhereIn<E extends SQLElement<E>> extends SQLWhereInCustom<E> {
|
||||
|
||||
private final SQLField<E, ?> field;
|
||||
private boolean collectionFiltered = false;
|
||||
|
||||
/* package */ <T> SQLWhereIn(SQLField<E, T> f, Collection<T> v) {
|
||||
super("`" + Objects.requireNonNull(f).getName() + "`", List.of(), v);
|
||||
field = f;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
ParameterizedSQLString toSQL() throws DBException {
|
||||
if (!collectionFiltered) {
|
||||
collectionIn = field.fromListJavaTypeToJDBCType(collectionIn);
|
||||
collectionFiltered = true;
|
||||
}
|
||||
return super.toSQL();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* package */ static class SQLWhereLike<E extends SQLElement<E>> extends SQLWhere<E> {
|
||||
|
Loading…
Reference in New Issue
Block a user