Skip to content

Commit a747ac1

Browse files
committed
Add support for optional conditions
1 parent 0015d0d commit a747ac1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2529
-255
lines changed

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

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,14 +17,15 @@
1717

1818
import java.util.ArrayList;
1919
import java.util.List;
20+
import java.util.Objects;
2021
import java.util.function.Function;
2122
import java.util.stream.Stream;
2223

2324
public abstract class AbstractListValueCondition<T> implements VisitableCondition<T> {
24-
private List<T> values = new ArrayList<>();
25+
private List<T> values;
2526

26-
protected AbstractListValueCondition(List<T> values) {
27-
this.values.addAll(values);
27+
protected AbstractListValueCondition(AbstractBuilder<T, ?> builder) {
28+
values = Objects.requireNonNull(builder.values);
2829
}
2930

3031
public final <R> Stream<R> mapValues(Function<T, R> mapper) {
@@ -54,4 +55,15 @@ protected T mapValue(T value) {
5455
}
5556

5657
public abstract String renderCondition(String columnName, Stream<String> placeholders);
58+
59+
public abstract static class AbstractBuilder<T, B extends AbstractBuilder<T, B>> {
60+
private List<T> values = new ArrayList<>();
61+
62+
public B withValues(List<T> values) {
63+
this.values.addAll(values);
64+
return getThis();
65+
}
66+
67+
public abstract B getThis();
68+
}
5769
}

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

+156-2
Original file line numberDiff line numberDiff line change
@@ -49,35 +49,51 @@
4949
import org.mybatis.dynamic.sql.util.Buildable;
5050
import org.mybatis.dynamic.sql.where.WhereDSL;
5151
import org.mybatis.dynamic.sql.where.condition.IsBetween;
52+
import org.mybatis.dynamic.sql.where.condition.IsBetweenWhenPresent;
5253
import org.mybatis.dynamic.sql.where.condition.IsEqualTo;
5354
import org.mybatis.dynamic.sql.where.condition.IsEqualToColumn;
55+
import org.mybatis.dynamic.sql.where.condition.IsEqualToWhenPresent;
5456
import org.mybatis.dynamic.sql.where.condition.IsEqualToWithSubselect;
5557
import org.mybatis.dynamic.sql.where.condition.IsGreaterThan;
5658
import org.mybatis.dynamic.sql.where.condition.IsGreaterThanColumn;
5759
import org.mybatis.dynamic.sql.where.condition.IsGreaterThanOrEqualTo;
5860
import org.mybatis.dynamic.sql.where.condition.IsGreaterThanOrEqualToColumn;
61+
import org.mybatis.dynamic.sql.where.condition.IsGreaterThanOrEqualToWhenPresent;
5962
import org.mybatis.dynamic.sql.where.condition.IsGreaterThanOrEqualToWithSubselect;
63+
import org.mybatis.dynamic.sql.where.condition.IsGreaterThanWhenPresent;
6064
import org.mybatis.dynamic.sql.where.condition.IsGreaterThanWithSubselect;
6165
import org.mybatis.dynamic.sql.where.condition.IsIn;
6266
import org.mybatis.dynamic.sql.where.condition.IsInCaseInsensitive;
67+
import org.mybatis.dynamic.sql.where.condition.IsInCaseInsensitiveWhenPresent;
68+
import org.mybatis.dynamic.sql.where.condition.IsInWhenPresent;
6369
import org.mybatis.dynamic.sql.where.condition.IsInWithSubselect;
6470
import org.mybatis.dynamic.sql.where.condition.IsLessThan;
6571
import org.mybatis.dynamic.sql.where.condition.IsLessThanColumn;
6672
import org.mybatis.dynamic.sql.where.condition.IsLessThanOrEqualTo;
6773
import org.mybatis.dynamic.sql.where.condition.IsLessThanOrEqualToColumn;
74+
import org.mybatis.dynamic.sql.where.condition.IsLessThanOrEqualToWhenPresent;
6875
import org.mybatis.dynamic.sql.where.condition.IsLessThanOrEqualToWithSubselect;
76+
import org.mybatis.dynamic.sql.where.condition.IsLessThanWhenPresent;
6977
import org.mybatis.dynamic.sql.where.condition.IsLessThanWithSubselect;
7078
import org.mybatis.dynamic.sql.where.condition.IsLike;
7179
import org.mybatis.dynamic.sql.where.condition.IsLikeCaseInsensitive;
80+
import org.mybatis.dynamic.sql.where.condition.IsLikeCaseInsensitiveWhenPresent;
81+
import org.mybatis.dynamic.sql.where.condition.IsLikeWhenPresent;
7282
import org.mybatis.dynamic.sql.where.condition.IsNotBetween;
83+
import org.mybatis.dynamic.sql.where.condition.IsNotBetweenWhenPresent;
7384
import org.mybatis.dynamic.sql.where.condition.IsNotEqualTo;
7485
import org.mybatis.dynamic.sql.where.condition.IsNotEqualToColumn;
86+
import org.mybatis.dynamic.sql.where.condition.IsNotEqualToWhenPresent;
7587
import org.mybatis.dynamic.sql.where.condition.IsNotEqualToWithSubselect;
7688
import org.mybatis.dynamic.sql.where.condition.IsNotIn;
7789
import org.mybatis.dynamic.sql.where.condition.IsNotInCaseInsensitive;
90+
import org.mybatis.dynamic.sql.where.condition.IsNotInCaseInsensitiveWhenPresent;
91+
import org.mybatis.dynamic.sql.where.condition.IsNotInWhenPresent;
7892
import org.mybatis.dynamic.sql.where.condition.IsNotInWithSubselect;
7993
import org.mybatis.dynamic.sql.where.condition.IsNotLike;
8094
import org.mybatis.dynamic.sql.where.condition.IsNotLikeCaseInsensitive;
95+
import org.mybatis.dynamic.sql.where.condition.IsNotLikeCaseInsensitiveWhenPresent;
96+
import org.mybatis.dynamic.sql.where.condition.IsNotLikeWhenPresent;
8197
import org.mybatis.dynamic.sql.where.condition.IsNotNull;
8298
import org.mybatis.dynamic.sql.where.condition.IsNull;
8399

@@ -267,6 +283,14 @@ static <T> IsEqualToColumn<T> isEqualTo(BasicColumn column) {
267283
return IsEqualToColumn.of(column);
268284
}
269285

286+
static <T> IsEqualToWhenPresent<T> isEqualToWhenPresent(T value) {
287+
return isEqualToWhenPresent(() -> value);
288+
}
289+
290+
static <T> IsEqualToWhenPresent<T> isEqualToWhenPresent(Supplier<T> valueSupplier) {
291+
return IsEqualToWhenPresent.of(valueSupplier);
292+
}
293+
270294
static <T> IsNotEqualTo<T> isNotEqualTo(T value) {
271295
return isNotEqualTo(() -> value);
272296
}
@@ -283,6 +307,14 @@ static <T> IsNotEqualToColumn<T> isNotEqualTo(BasicColumn column) {
283307
return IsNotEqualToColumn.of(column);
284308
}
285309

310+
static <T> IsNotEqualToWhenPresent<T> isNotEqualToWhenPresent(T value) {
311+
return isNotEqualToWhenPresent(() -> value);
312+
}
313+
314+
static <T> IsNotEqualToWhenPresent<T> isNotEqualToWhenPresent(Supplier<T> valueSupplier) {
315+
return IsNotEqualToWhenPresent.of(valueSupplier);
316+
}
317+
286318
static <T> IsGreaterThan<T> isGreaterThan(T value) {
287319
return isGreaterThan(() -> value);
288320
}
@@ -299,6 +331,14 @@ static <T> IsGreaterThanColumn<T> isGreaterThan(BasicColumn column) {
299331
return IsGreaterThanColumn.of(column);
300332
}
301333

334+
static <T> IsGreaterThanWhenPresent<T> isGreaterThanWhenPresent(T value) {
335+
return isGreaterThanWhenPresent(() -> value);
336+
}
337+
338+
static <T> IsGreaterThanWhenPresent<T> isGreaterThanWhenPresent(Supplier<T> valueSupplier) {
339+
return IsGreaterThanWhenPresent.of(valueSupplier);
340+
}
341+
302342
static <T> IsGreaterThanOrEqualTo<T> isGreaterThanOrEqualTo(T value) {
303343
return isGreaterThanOrEqualTo(() -> value);
304344
}
@@ -316,6 +356,14 @@ static <T> IsGreaterThanOrEqualToColumn<T> isGreaterThanOrEqualTo(BasicColumn co
316356
return IsGreaterThanOrEqualToColumn.of(column);
317357
}
318358

359+
static <T> IsGreaterThanOrEqualToWhenPresent<T> isGreaterThanOrEqualToWhenPresent(T value) {
360+
return isGreaterThanOrEqualToWhenPresent(() -> value);
361+
}
362+
363+
static <T> IsGreaterThanOrEqualToWhenPresent<T> isGreaterThanOrEqualToWhenPresent(Supplier<T> valueSupplier) {
364+
return IsGreaterThanOrEqualToWhenPresent.of(valueSupplier);
365+
}
366+
319367
static <T> IsLessThan<T> isLessThan(T value) {
320368
return isLessThan(() -> value);
321369
}
@@ -332,6 +380,14 @@ static <T> IsLessThanColumn<T> isLessThan(BasicColumn column) {
332380
return IsLessThanColumn.of(column);
333381
}
334382

383+
static <T> IsLessThanWhenPresent<T> isLessThanWhenPresent(T value) {
384+
return isLessThanWhenPresent(() -> value);
385+
}
386+
387+
static <T> IsLessThanWhenPresent<T> isLessThanWhenPresent(Supplier<T> valueSupplier) {
388+
return IsLessThanWhenPresent.of(valueSupplier);
389+
}
390+
335391
static <T> IsLessThanOrEqualTo<T> isLessThanOrEqualTo(T value) {
336392
return isLessThanOrEqualTo(() -> value);
337393
}
@@ -348,6 +404,14 @@ static <T> IsLessThanOrEqualToColumn<T> isLessThanOrEqualTo(BasicColumn column)
348404
return IsLessThanOrEqualToColumn.of(column);
349405
}
350406

407+
static <T> IsLessThanOrEqualToWhenPresent<T> isLessThanOrEqualToWhenPresent(T value) {
408+
return isLessThanOrEqualToWhenPresent(() -> value);
409+
}
410+
411+
static <T> IsLessThanOrEqualToWhenPresent<T> isLessThanOrEqualToWhenPresent(Supplier<T> valueSupplier) {
412+
return IsLessThanOrEqualToWhenPresent.of(valueSupplier);
413+
}
414+
351415
@SafeVarargs
352416
static <T> IsIn<T> isIn(T...values) {
353417
return isIn(Arrays.asList(values));
@@ -361,6 +425,15 @@ static <T> IsInWithSubselect<T> isIn(Buildable<SelectModel> selectModelBuilder)
361425
return IsInWithSubselect.of(selectModelBuilder);
362426
}
363427

428+
@SafeVarargs
429+
static <T> IsInWhenPresent<T> isInWhenPresent(T...values) {
430+
return isInWhenPresent(Arrays.asList(values));
431+
}
432+
433+
static <T> IsInWhenPresent<T> isInWhenPresent(List<T> values) {
434+
return IsInWhenPresent.of(values);
435+
}
436+
364437
@SafeVarargs
365438
static <T> IsNotIn<T> isNotIn(T...values) {
366439
return isNotIn(Arrays.asList(values));
@@ -374,6 +447,15 @@ static <T> IsNotInWithSubselect<T> isNotIn(Buildable<SelectModel> selectModelBui
374447
return IsNotInWithSubselect.of(selectModelBuilder);
375448
}
376449

450+
@SafeVarargs
451+
static <T> IsNotInWhenPresent<T> isNotInWhenPresent(T...values) {
452+
return isNotInWhenPresent(Arrays.asList(values));
453+
}
454+
455+
static <T> IsNotInWhenPresent<T> isNotInWhenPresent(List<T> values) {
456+
return IsNotInWhenPresent.of(values);
457+
}
458+
377459
static <T> IsBetween.Builder<T> isBetween(T value1) {
378460
return isBetween(() -> value1);
379461
}
@@ -382,6 +464,14 @@ static <T> IsBetween.Builder<T> isBetween(Supplier<T> valueSupplier1) {
382464
return IsBetween.isBetween(valueSupplier1);
383465
}
384466

467+
static <T> IsBetweenWhenPresent.Builder<T> isBetweenWhenPresent(T value1) {
468+
return isBetweenWhenPresent(() -> value1);
469+
}
470+
471+
static <T> IsBetweenWhenPresent.Builder<T> isBetweenWhenPresent(Supplier<T> valueSupplier1) {
472+
return IsBetweenWhenPresent.isBetweenWhenPresent(valueSupplier1);
473+
}
474+
385475
static <T> IsNotBetween.Builder<T> isNotBetween(T value1) {
386476
return isNotBetween(() -> value1);
387477
}
@@ -390,6 +480,14 @@ static <T> IsNotBetween.Builder<T> isNotBetween(Supplier<T> valueSupplier1) {
390480
return IsNotBetween.isNotBetween(valueSupplier1);
391481
}
392482

483+
static <T> IsNotBetweenWhenPresent.Builder<T> isNotBetweenWhenPresent(T value1) {
484+
return isNotBetweenWhenPresent(() -> value1);
485+
}
486+
487+
static <T> IsNotBetweenWhenPresent.Builder<T> isNotBetweenWhenPresent(Supplier<T> valueSupplier1) {
488+
return IsNotBetweenWhenPresent.isNotBetweenWhenPresent(valueSupplier1);
489+
}
490+
393491
// for string columns, but generic for columns with type handlers
394492
static <T> IsLike<T> isLike(T value) {
395493
return isLike(() -> value);
@@ -399,6 +497,14 @@ static <T> IsLike<T> isLike(Supplier<T> valueSupplier) {
399497
return IsLike.of(valueSupplier);
400498
}
401499

500+
static <T> IsLikeWhenPresent<T> isLikeWhenPresent(T value) {
501+
return isLikeWhenPresent(() -> value);
502+
}
503+
504+
static <T> IsLikeWhenPresent<T> isLikeWhenPresent(Supplier<T> valueSupplier) {
505+
return IsLikeWhenPresent.of(valueSupplier);
506+
}
507+
402508
static <T> IsNotLike<T> isNotLike(T value) {
403509
return isNotLike(() -> value);
404510
}
@@ -407,6 +513,14 @@ static <T> IsNotLike<T> isNotLike(Supplier<T> valueSupplier) {
407513
return IsNotLike.of(valueSupplier);
408514
}
409515

516+
static <T> IsNotLikeWhenPresent<T> isNotLikeWhenPresent(T value) {
517+
return isNotLikeWhenPresent(() -> value);
518+
}
519+
520+
static <T> IsNotLikeWhenPresent<T> isNotLikeWhenPresent(Supplier<T> valueSupplier) {
521+
return IsNotLikeWhenPresent.of(valueSupplier);
522+
}
523+
410524
// conditions for strings only
411525
static IsLikeCaseInsensitive isLikeCaseInsensitive(String value) {
412526
return isLikeCaseInsensitive(() -> value);
@@ -416,6 +530,14 @@ static IsLikeCaseInsensitive isLikeCaseInsensitive(Supplier<String> valueSupplie
416530
return IsLikeCaseInsensitive.of(valueSupplier);
417531
}
418532

533+
static IsLikeCaseInsensitiveWhenPresent isLikeCaseInsensitiveWhenPresent(String value) {
534+
return isLikeCaseInsensitiveWhenPresent(() -> value);
535+
}
536+
537+
static IsLikeCaseInsensitiveWhenPresent isLikeCaseInsensitiveWhenPresent(Supplier<String> valueSupplier) {
538+
return IsLikeCaseInsensitiveWhenPresent.of(valueSupplier);
539+
}
540+
419541
static IsNotLikeCaseInsensitive isNotLikeCaseInsensitive(String value) {
420542
return isNotLikeCaseInsensitive(() -> value);
421543
}
@@ -424,14 +546,46 @@ static IsNotLikeCaseInsensitive isNotLikeCaseInsensitive(Supplier<String> valueS
424546
return IsNotLikeCaseInsensitive.of(valueSupplier);
425547
}
426548

549+
static IsNotLikeCaseInsensitiveWhenPresent isNotLikeCaseInsensitiveWhenPresent(String value) {
550+
return isNotLikeCaseInsensitiveWhenPresent(() -> value);
551+
}
552+
553+
static IsNotLikeCaseInsensitiveWhenPresent isNotLikeCaseInsensitiveWhenPresent(Supplier<String> valueSupplier) {
554+
return IsNotLikeCaseInsensitiveWhenPresent.of(valueSupplier);
555+
}
556+
427557
static IsInCaseInsensitive isInCaseInsensitive(String...values) {
428-
return IsInCaseInsensitive.of(Arrays.asList(values));
558+
return isInCaseInsensitive(Arrays.asList(values));
559+
}
560+
561+
static IsInCaseInsensitive isInCaseInsensitive(List<String> values) {
562+
return IsInCaseInsensitive.of(values);
563+
}
564+
565+
static IsInCaseInsensitiveWhenPresent isInCaseInsensitiveWhenPresent(String...values) {
566+
return isInCaseInsensitiveWhenPresent(Arrays.asList(values));
567+
}
568+
569+
static IsInCaseInsensitiveWhenPresent isInCaseInsensitiveWhenPresent(List<String> values) {
570+
return IsInCaseInsensitiveWhenPresent.of(values);
429571
}
430572

431573
static IsNotInCaseInsensitive isNotInCaseInsensitive(String...values) {
432-
return IsNotInCaseInsensitive.of(Arrays.asList(values));
574+
return isNotInCaseInsensitive(Arrays.asList(values));
575+
}
576+
577+
static IsNotInCaseInsensitive isNotInCaseInsensitive(List<String> values) {
578+
return IsNotInCaseInsensitive.of(values);
433579
}
434580

581+
static IsNotInCaseInsensitiveWhenPresent isNotInCaseInsensitiveWhenPresent(String...values) {
582+
return isNotInCaseInsensitiveWhenPresent(Arrays.asList(values));
583+
}
584+
585+
static IsNotInCaseInsensitiveWhenPresent isNotInCaseInsensitiveWhenPresent(List<String> values) {
586+
return IsNotInCaseInsensitiveWhenPresent.of(values);
587+
}
588+
435589
// order by support
436590
static SortSpecification sortColumn(String name) {
437591
return SimpleSortSpecification.of(name);

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

-4
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,6 @@ public VisitableCondition<T> condition() {
4848
return condition;
4949
}
5050

51-
public boolean hasSubCriteria() {
52-
return !subCriteria.isEmpty();
53-
}
54-
5551
public <R> Stream<R> mapSubCriteria(Function<SqlCriterion<?>, R> mapper) {
5652
return subCriteria.stream().map(mapper);
5753
}

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,4 +18,14 @@
1818
@FunctionalInterface
1919
public interface VisitableCondition<T> {
2020
<R> R accept(ConditionVisitor<T,R> visitor);
21+
22+
/**
23+
* Subclasses can override this to inform the renderer if the condition should not be included
24+
* in the rendered SQL. For example, IsEqualWhenPresent will not render if the value is null.
25+
*
26+
* @return true if the condition should render.
27+
*/
28+
default boolean shouldRender() {
29+
return true;
30+
}
2131
}

0 commit comments

Comments
 (0)