Skip to content

Commit 129552d

Browse files
committed
Progress on implementing empty callback
1 parent 972cee0 commit 129552d

File tree

8 files changed

+88
-46
lines changed

8 files changed

+88
-46
lines changed

src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,24 @@
2222
import java.util.function.UnaryOperator;
2323
import java.util.stream.Stream;
2424

25-
public abstract class AbstractListValueCondition<T> implements VisitableCondition<T> {
25+
public abstract class AbstractListValueCondition<T, S extends AbstractListValueCondition<T, S>> implements VisitableCondition<T> {
2626
protected final Collection<T> values;
2727
protected final UnaryOperator<Stream<T>> valueStreamTransformer;
28-
protected boolean renderWhenEmpty = false;
28+
protected final Callback callback;
2929

3030
protected AbstractListValueCondition(Collection<T> values) {
31-
this(values, UnaryOperator.identity());
31+
this(values, UnaryOperator.identity(), () -> {});
3232
}
3333

3434
protected AbstractListValueCondition(Collection<T> values, UnaryOperator<Stream<T>> valueStreamTransformer) {
35+
this(values, valueStreamTransformer, () -> {});
36+
}
37+
38+
protected AbstractListValueCondition(Collection<T> values, UnaryOperator<Stream<T>> valueStreamTransformer,
39+
Callback callback) {
3540
this.values = new ArrayList<>(Objects.requireNonNull(values));
3641
this.valueStreamTransformer = Objects.requireNonNull(valueStreamTransformer);
42+
this.callback = Objects.requireNonNull(callback);
3743
}
3844

3945
public final <R> Stream<R> mapValues(Function<T, R> mapper) {
@@ -42,20 +48,19 @@ public final <R> Stream<R> mapValues(Function<T, R> mapper) {
4248

4349
@Override
4450
public boolean shouldRender() {
45-
return !values.isEmpty() || renderWhenEmpty;
51+
if (values.isEmpty()) {
52+
callback.call();
53+
return false;
54+
} else {
55+
return true;
56+
}
4657
}
4758

48-
/**
49-
* Use with caution - this could cause the library to render invalid SQL like "where column in ()".
50-
*/
51-
protected void forceRenderingWhenEmpty() {
52-
renderWhenEmpty = true;
53-
}
54-
5559
@Override
5660
public <R> R accept(ConditionVisitor<T, R> visitor) {
5761
return visitor.visit(this);
5862
}
5963

64+
public abstract S withListEmptyCallback(Callback callback);
6065
public abstract String renderCondition(String columnName, Stream<String> placeholders);
6166
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.mybatis.dynamic.sql;
2+
3+
import java.util.function.Function;
4+
5+
@FunctionalInterface
6+
public interface Callback {
7+
void call();
8+
9+
static Callback runtimeExceptionThrowingCallback(String message) {
10+
return exceptionThrowingCallback(message, RuntimeException::new);
11+
}
12+
13+
static Callback exceptionThrowingCallback(String message,
14+
Function<String, ? extends RuntimeException> exceptionBuilder) {
15+
return () -> {
16+
throw exceptionBuilder.apply(message);
17+
};
18+
}
19+
}

src/main/java/org/mybatis/dynamic/sql/ConditionVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
package org.mybatis.dynamic.sql;
1717

1818
public interface ConditionVisitor<T, R> {
19-
R visit(AbstractListValueCondition<T> condition);
19+
R visit(AbstractListValueCondition<T, ?> condition);
2020

2121
R visit(AbstractNoValueCondition<T> condition);
2222

src/main/java/org/mybatis/dynamic/sql/where/condition/IsIn.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,23 @@
2323
import java.util.stream.Stream;
2424

2525
import org.mybatis.dynamic.sql.AbstractListValueCondition;
26+
import org.mybatis.dynamic.sql.Callback;
2627

27-
public class IsIn<T> extends AbstractListValueCondition<T> {
28-
29-
protected IsIn(Collection<T> values, UnaryOperator<Stream<T>> valueStreamTransformer) {
30-
super(values, valueStreamTransformer);
31-
}
28+
public class IsIn<T> extends AbstractListValueCondition<T, IsIn<T>> {
3229

3330
protected IsIn(Collection<T> values) {
3431
super(values);
3532
}
3633

34+
protected IsIn(Collection<T> values, UnaryOperator<Stream<T>> valueStreamTransformer, Callback callback) {
35+
super(values, valueStreamTransformer, callback);
36+
}
37+
38+
@Override
39+
public IsIn<T> withListEmptyCallback(Callback callback) {
40+
return new IsIn<>(values, valueStreamTransformer, callback);
41+
}
42+
3743
@Override
3844
public String renderCondition(String columnName, Stream<String> placeholders) {
3945
return spaceAfter(columnName)
@@ -51,7 +57,7 @@ public String renderCondition(String columnName, Stream<String> placeholders) {
5157
* @return new condition with the specified transformer
5258
*/
5359
public IsIn<T> then(UnaryOperator<Stream<T>> valueStreamTransformer) {
54-
return new IsIn<>(values, valueStreamTransformer);
60+
return new IsIn<>(values, valueStreamTransformer, callback);
5561
}
5662

5763
public static <T> IsIn<T> of(Collection<T> values) {

src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitive.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,25 @@
2121
import java.util.stream.Stream;
2222

2323
import org.mybatis.dynamic.sql.AbstractListValueCondition;
24+
import org.mybatis.dynamic.sql.Callback;
2425
import org.mybatis.dynamic.sql.util.StringUtilities;
2526

26-
public class IsInCaseInsensitive extends AbstractListValueCondition<String> {
27+
public class IsInCaseInsensitive extends AbstractListValueCondition<String, IsInCaseInsensitive> {
2728

2829
protected IsInCaseInsensitive(Collection<String> values, UnaryOperator<Stream<String>> valueStreamTransformer) {
2930
super(values, valueStreamTransformer);
3031
}
3132

33+
protected IsInCaseInsensitive(Collection<String> values, UnaryOperator<Stream<String>> valueStreamTransformer,
34+
Callback callback) {
35+
super(values, valueStreamTransformer, callback);
36+
}
37+
38+
@Override
39+
public IsInCaseInsensitive withListEmptyCallback(Callback callback) {
40+
return new IsInCaseInsensitive(values, valueStreamTransformer, callback);
41+
}
42+
3243
@Override
3344
public String renderCondition(String columnName, Stream<String> placeholders) {
3445
return "upper(" + columnName + ") " + //$NON-NLS-1$ //$NON-NLS-2$

src/main/java/org/mybatis/dynamic/sql/where/condition/IsInCaseInsensitiveWhenPresent.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.mybatis.dynamic.sql.where.condition;
1717

18+
import org.mybatis.dynamic.sql.Callback;
1819
import org.mybatis.dynamic.sql.util.StringUtilities;
1920

2021
import java.util.Collection;
@@ -24,12 +25,21 @@
2425

2526
public class IsInCaseInsensitiveWhenPresent extends IsInCaseInsensitive {
2627

27-
protected IsInCaseInsensitiveWhenPresent(Collection<String> values, UnaryOperator<Stream<String>> valueStreamTransformer) {
28-
super(values, valueStreamTransformer);
28+
protected IsInCaseInsensitiveWhenPresent(Collection<String> values) {
29+
super(values, s -> s.filter(Objects::nonNull).map(StringUtilities::safelyUpperCase));
30+
}
31+
32+
protected IsInCaseInsensitiveWhenPresent(Collection<String> values, UnaryOperator<Stream<String>> valueStreamTransformer,
33+
Callback callback) {
34+
super(values, valueStreamTransformer, callback);
35+
}
36+
37+
@Override
38+
public IsInCaseInsensitiveWhenPresent withListEmptyCallback(Callback callback) {
39+
return new IsInCaseInsensitiveWhenPresent(values, valueStreamTransformer, callback);
2940
}
3041

3142
public static IsInCaseInsensitiveWhenPresent of(Collection<String> values) {
32-
return new IsInCaseInsensitiveWhenPresent(values,
33-
s -> s.filter(Objects::nonNull).map(StringUtilities::safelyUpperCase));
43+
return new IsInCaseInsensitiveWhenPresent(values);
3444
}
3545
}

src/main/java/org/mybatis/dynamic/sql/where/render/WhereConditionVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ private WhereConditionVisitor(Builder<T> builder) {
5050
}
5151

5252
@Override
53-
public FragmentAndParameters visit(AbstractListValueCondition<T> condition) {
53+
public FragmentAndParameters visit(AbstractListValueCondition<T, ?> condition) {
5454
FragmentCollector fc = condition.mapValues(this::toFragmentAndParameters)
5555
.collect(FragmentCollector.collect());
5656

src/test/java/examples/animal/data/AnimalDataTest.java

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import java.util.Map;
3434

3535
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
36-
import org.apache.ibatis.exceptions.PersistenceException;
3736
import org.apache.ibatis.jdbc.ScriptRunner;
3837
import org.apache.ibatis.mapping.Environment;
3938
import org.apache.ibatis.session.Configuration;
@@ -45,6 +44,7 @@
4544
import org.junit.jupiter.api.BeforeEach;
4645
import org.junit.jupiter.api.Test;
4746
import org.mybatis.dynamic.sql.BasicColumn;
47+
import org.mybatis.dynamic.sql.Callback;
4848
import org.mybatis.dynamic.sql.SqlTable;
4949
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
5050
import org.mybatis.dynamic.sql.insert.render.BatchInsert;
@@ -571,30 +571,21 @@ void testInCondition() {
571571

572572
@Test
573573
void testInConditionWithEmptyList() {
574-
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
575-
AnimalDataMapper mapper = sqlSession.getMapper(AnimalDataMapper.class);
576-
577-
SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
578-
.from(animalData)
579-
.where(id, IsInRequired.isIn(Collections.emptyList()))
580-
.build()
581-
.render(RenderingStrategies.MYBATIS3);
582-
583-
assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> mapper.selectMany(selectStatement));
584-
}
574+
assertThatExceptionOfType(RuntimeException.class).describedAs("Fred").isThrownBy(() ->
575+
select(id, animalName, bodyWeight, brainWeight)
576+
.from(animalData)
577+
.where(id, isInRequired(Collections.emptyList()))
578+
.build()
579+
.render(RenderingStrategies.MYBATIS3)
580+
);
585581
}
586582

587-
public static class IsInRequired<T> extends IsIn<T> {
588-
protected IsInRequired(Collection<T> values) {
589-
super(values);
590-
forceRenderingWhenEmpty();
591-
}
592-
593-
public static <T> IsInRequired<T> isIn(Collection<T> values) {
594-
return new IsInRequired<>(values);
595-
}
583+
public static <T> IsIn<T> isInRequired(Collection<T> values) {
584+
throw new RuntimeException("fred");
585+
// TODO...
586+
// return IsIn.of(values).withListEmptyCallback(Callback.runtimeExceptionThrowingCallback("Fred"));
596587
}
597-
588+
598589
@Test
599590
void testInCaseSensitiveCondition() {
600591
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {

0 commit comments

Comments
 (0)