Skip to content

Commit 1ae2e43

Browse files
committed
Allow Conditions Increased Control over Rendering
1 parent 978152d commit 1ae2e43

14 files changed

+198
-238
lines changed

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

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

18+
import static org.mybatis.dynamic.sql.util.StringUtilities.spaceBefore;
19+
20+
import org.mybatis.dynamic.sql.render.RenderingContext;
21+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
22+
1823
public abstract class AbstractColumnComparisonCondition<T> implements VisitableCondition<T> {
1924

2025
protected final BasicColumn rightColumn;
@@ -23,14 +28,10 @@ protected AbstractColumnComparisonCondition(BasicColumn rightColumn) {
2328
this.rightColumn = rightColumn;
2429
}
2530

26-
public BasicColumn rightColumn() {
27-
return rightColumn;
28-
}
31+
public abstract String operator();
2932

3033
@Override
31-
public <R> R accept(ConditionVisitor<T, R> visitor) {
32-
return visitor.visit(this);
34+
public FragmentAndParameters renderCondition(RenderingContext renderingContext, BindableColumn<T> leftColumn) {
35+
return rightColumn.render(renderingContext).mapFragment(f -> operator() + spaceBefore(f));
3336
}
34-
35-
public abstract String operator();
3637
}

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

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

26+
import org.mybatis.dynamic.sql.render.RenderedParameterInfo;
27+
import org.mybatis.dynamic.sql.render.RenderingContext;
28+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
29+
import org.mybatis.dynamic.sql.util.FragmentCollector;
30+
2631
public abstract class AbstractListValueCondition<T> implements VisitableCondition<T> {
2732
protected final Collection<T> values;
2833

@@ -39,19 +44,14 @@ public boolean isEmpty() {
3944
return values.isEmpty();
4045
}
4146

42-
@Override
43-
public <R> R accept(ConditionVisitor<T, R> visitor) {
44-
return visitor.visit(this);
45-
}
46-
4747
private <R> Collection<R> applyMapper(Function<? super T, ? extends R> mapper) {
4848
Objects.requireNonNull(mapper);
49-
return values.stream().map(mapper).collect(Collectors.toList());
49+
return values().map(mapper).collect(Collectors.toList());
5050
}
5151

5252
private Collection<T> applyFilter(Predicate<? super T> predicate) {
5353
Objects.requireNonNull(predicate);
54-
return values.stream().filter(predicate).toList();
54+
return values().filter(predicate).toList();
5555
}
5656

5757
protected <S extends AbstractListValueCondition<T>> S filterSupport(Predicate<? super T> predicate,
@@ -84,4 +84,20 @@ protected <R, S extends AbstractListValueCondition<R>> S mapSupport(Function<? s
8484
public abstract AbstractListValueCondition<T> filter(Predicate<? super T> predicate);
8585

8686
public abstract String operator();
87+
88+
@Override
89+
public FragmentAndParameters renderCondition(RenderingContext renderingContext, BindableColumn<T> leftColumn) {
90+
return values().map(v -> toFragmentAndParameters(v, renderingContext, leftColumn))
91+
.collect(FragmentCollector.collect())
92+
.toFragmentAndParameters(Collectors.joining(",", //$NON-NLS-1$
93+
operator() + " (", ")")); //$NON-NLS-1$ //$NON-NLS-2$
94+
}
95+
96+
private FragmentAndParameters toFragmentAndParameters(T value, RenderingContext renderingContext,
97+
BindableColumn<T> leftColumn) {
98+
RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo(leftColumn);
99+
return FragmentAndParameters.withFragment(parameterInfo.renderedPlaceHolder())
100+
.withParameter(parameterInfo.parameterMapKey(), leftColumn.convertParameterType(value))
101+
.build();
102+
}
87103
}

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@
1818
import java.util.function.BooleanSupplier;
1919
import java.util.function.Supplier;
2020

21-
public abstract class AbstractNoValueCondition<T> implements VisitableCondition<T> {
21+
import org.mybatis.dynamic.sql.render.RenderingContext;
22+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
2223

23-
@Override
24-
public <R> R accept(ConditionVisitor<T, R> visitor) {
25-
return visitor.visit(this);
26-
}
24+
public abstract class AbstractNoValueCondition<T> implements VisitableCondition<T> {
2725

2826
protected <S extends AbstractNoValueCondition<?>> S filterSupport(BooleanSupplier booleanSupplier,
2927
Supplier<S> emptySupplier, S self) {
@@ -35,4 +33,9 @@ protected <S extends AbstractNoValueCondition<?>> S filterSupport(BooleanSupplie
3533
}
3634

3735
public abstract String operator();
36+
37+
@Override
38+
public FragmentAndParameters renderCondition(RenderingContext renderingContext, BindableColumn<T> leftColumn) {
39+
return FragmentAndParameters.fromFragment(operator());
40+
}
3841
}

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@
1515
*/
1616
package org.mybatis.dynamic.sql;
1717

18+
import static org.mybatis.dynamic.sql.util.StringUtilities.spaceBefore;
19+
1820
import java.util.function.Function;
1921
import java.util.function.Predicate;
2022
import java.util.function.Supplier;
2123

24+
import org.mybatis.dynamic.sql.render.RenderedParameterInfo;
25+
import org.mybatis.dynamic.sql.render.RenderingContext;
26+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
27+
2228
public abstract class AbstractSingleValueCondition<T> implements VisitableCondition<T> {
2329
protected final T value;
2430

@@ -30,11 +36,6 @@ public T value() {
3036
return value;
3137
}
3238

33-
@Override
34-
public <R> R accept(ConditionVisitor<T, R> visitor) {
35-
return visitor.visit(this);
36-
}
37-
3839
protected <S extends AbstractSingleValueCondition<T>> S filterSupport(Predicate<? super T> predicate,
3940
Supplier<S> emptySupplier, S self) {
4041
if (isEmpty()) {
@@ -64,4 +65,14 @@ protected <R, S extends AbstractSingleValueCondition<R>> S mapSupport(Function<?
6465
public abstract AbstractSingleValueCondition<T> filter(Predicate<? super T> predicate);
6566

6667
public abstract String operator();
68+
69+
@Override
70+
public FragmentAndParameters renderCondition(RenderingContext renderingContext, BindableColumn<T> leftColumn) {
71+
RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo(leftColumn);
72+
String finalFragment = operator() + spaceBefore(parameterInfo.renderedPlaceHolder());
73+
74+
return FragmentAndParameters.withFragment(finalFragment)
75+
.withParameter(parameterInfo.parameterMapKey(), leftColumn.convertParameterType(value()))
76+
.build();
77+
}
6778
}

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

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

18+
import org.mybatis.dynamic.sql.render.RenderingContext;
1819
import org.mybatis.dynamic.sql.select.SelectModel;
20+
import org.mybatis.dynamic.sql.select.render.SubQueryRenderer;
1921
import org.mybatis.dynamic.sql.util.Buildable;
22+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
2023

2124
public abstract class AbstractSubselectCondition<T> implements VisitableCondition<T> {
2225
private final SelectModel selectModel;
@@ -25,14 +28,15 @@ protected AbstractSubselectCondition(Buildable<SelectModel> selectModelBuilder)
2528
this.selectModel = selectModelBuilder.build();
2629
}
2730

28-
public SelectModel selectModel() {
29-
return selectModel;
30-
}
31+
public abstract String operator();
3132

3233
@Override
33-
public <R> R accept(ConditionVisitor<T, R> visitor) {
34-
return visitor.visit(this);
34+
public FragmentAndParameters renderCondition(RenderingContext renderingContext, BindableColumn<T> leftColumn) {
35+
return SubQueryRenderer.withSelectModel(selectModel)
36+
.withRenderingContext(renderingContext)
37+
.withPrefix(operator() + " (") //$NON-NLS-1$
38+
.withSuffix(")") //$NON-NLS-1$
39+
.build()
40+
.render();
3541
}
36-
37-
public abstract String operator();
3842
}

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@
1515
*/
1616
package org.mybatis.dynamic.sql;
1717

18+
import static org.mybatis.dynamic.sql.util.StringUtilities.spaceBefore;
19+
1820
import java.util.function.BiFunction;
1921
import java.util.function.BiPredicate;
2022
import java.util.function.Function;
2123
import java.util.function.Predicate;
2224
import java.util.function.Supplier;
2325

26+
import org.mybatis.dynamic.sql.render.RenderedParameterInfo;
27+
import org.mybatis.dynamic.sql.render.RenderingContext;
28+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
29+
2430
public abstract class AbstractTwoValueCondition<T> implements VisitableCondition<T> {
2531
protected final T value1;
2632
protected final T value2;
@@ -38,11 +44,6 @@ public T value2() {
3844
return value2;
3945
}
4046

41-
@Override
42-
public <R> R accept(ConditionVisitor<T, R> visitor) {
43-
return visitor.visit(this);
44-
}
45-
4647
protected <S extends AbstractTwoValueCondition<T>> S filterSupport(BiPredicate<? super T, ? super T> predicate,
4748
Supplier<S> emptySupplier, S self) {
4849
if (isEmpty()) {
@@ -90,4 +91,20 @@ protected <R, S extends AbstractTwoValueCondition<R>> S mapSupport(Function<? su
9091
public abstract String operator1();
9192

9293
public abstract String operator2();
94+
95+
@Override
96+
public FragmentAndParameters renderCondition(RenderingContext renderingContext, BindableColumn<T> leftColumn) {
97+
RenderedParameterInfo parameterInfo1 = renderingContext.calculateParameterInfo(leftColumn);
98+
RenderedParameterInfo parameterInfo2 = renderingContext.calculateParameterInfo(leftColumn);
99+
100+
String finalFragment = operator1()
101+
+ spaceBefore(parameterInfo1.renderedPlaceHolder())
102+
+ spaceBefore(operator2())
103+
+ spaceBefore(parameterInfo2.renderedPlaceHolder());
104+
105+
return FragmentAndParameters.withFragment(finalFragment)
106+
.withParameter(parameterInfo1.parameterMapKey(), leftColumn.convertParameterType(value1()))
107+
.withParameter(parameterInfo2.parameterMapKey(), leftColumn.convertParameterType(value2()))
108+
.build();
109+
}
93110
}

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

Lines changed: 0 additions & 30 deletions
This file was deleted.

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

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,17 @@
1616
package org.mybatis.dynamic.sql;
1717

1818
import org.mybatis.dynamic.sql.render.RenderingContext;
19+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
1920

2021
@FunctionalInterface
2122
public interface VisitableCondition<T> {
22-
<R> R accept(ConditionVisitor<T, R> visitor);
23+
FragmentAndParameters renderCondition(RenderingContext renderingContext, BindableColumn<T> leftColumn);
24+
25+
default FragmentAndParameters renderLeftColumn(RenderingContext renderingContext, BindableColumn<T> leftColumn) {
26+
return leftColumn.alias()
27+
.map(FragmentAndParameters::fromFragment)
28+
.orElseGet(() -> leftColumn.render(renderingContext));
29+
}
2330

2431
/**
2532
* Subclasses can override this to inform the renderer if the condition should not be included
@@ -46,16 +53,4 @@ default boolean isEmpty() {
4653
* returns false.
4754
*/
4855
default void renderingSkipped() {}
49-
50-
/**
51-
* This method is called during rendering. Its purpose is to allow conditions to change
52-
* the value of the rendered left column. This is primarily used in the case-insensitive conditions
53-
* where we surround the rendered column with "upper(" and ")".
54-
*
55-
* @param renderedLeftColumn the rendered left column
56-
* @return the altered column - by default no change is applied
57-
*/
58-
default String overrideRenderedLeftColumn(String renderedLeftColumn) {
59-
return renderedLeftColumn;
60-
}
6156
}

src/main/java/org/mybatis/dynamic/sql/select/render/SimpleCaseWhenConditionRenderer.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,14 @@
2828
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
2929
import org.mybatis.dynamic.sql.util.FragmentCollector;
3030
import org.mybatis.dynamic.sql.util.Validator;
31-
import org.mybatis.dynamic.sql.where.render.DefaultConditionVisitor;
3231

3332
public class SimpleCaseWhenConditionRenderer<T> implements SimpleCaseWhenConditionVisitor<T, FragmentAndParameters> {
3433
private final RenderingContext renderingContext;
3534
private final BindableColumn<T> column;
36-
private final DefaultConditionVisitor<T> conditionVisitor;
3735

3836
public SimpleCaseWhenConditionRenderer(RenderingContext renderingContext, BindableColumn<T> column) {
3937
this.renderingContext = Objects.requireNonNull(renderingContext);
4038
this.column = Objects.requireNonNull(column);
41-
conditionVisitor = new DefaultConditionVisitor.Builder<T>()
42-
.withColumn(column)
43-
.withRenderingContext(renderingContext)
44-
.build();
4539
}
4640

4741
@Override
@@ -68,7 +62,7 @@ private boolean shouldRender(VisitableCondition<T> condition) {
6862
}
6963

7064
private FragmentAndParameters renderCondition(VisitableCondition<T> condition) {
71-
return condition.accept(conditionVisitor);
65+
return condition.renderCondition(renderingContext, column);
7266
}
7367

7468
private FragmentAndParameters renderBasicValue(T value) {

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

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

18+
import org.mybatis.dynamic.sql.BindableColumn;
1819
import org.mybatis.dynamic.sql.VisitableCondition;
20+
import org.mybatis.dynamic.sql.render.RenderingContext;
21+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
1922

2023
public interface CaseInsensitiveVisitableCondition extends VisitableCondition<String> {
2124

2225
@Override
23-
default String overrideRenderedLeftColumn(String renderedLeftColumn) {
24-
return "upper(" + renderedLeftColumn + ")"; //$NON-NLS-1$ //$NON-NLS-2$
26+
default FragmentAndParameters renderLeftColumn(RenderingContext renderingContext,
27+
BindableColumn<String> leftColumn) {
28+
return VisitableCondition.super.renderLeftColumn(renderingContext, leftColumn)
29+
.mapFragment(s -> "upper(" + s + ")"); //$NON-NLS-1$ //$NON-NLS-2$
2530
}
2631
}

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

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,20 @@ public class ColumnAndConditionRenderer<T> {
2929
private final BindableColumn<T> column;
3030
private final VisitableCondition<T> condition;
3131
private final RenderingContext renderingContext;
32-
private final DefaultConditionVisitor<T> visitor;
3332

3433
private ColumnAndConditionRenderer(Builder<T> builder) {
3534
column = Objects.requireNonNull(builder.column);
3635
condition = Objects.requireNonNull(builder.condition);
3736
renderingContext = Objects.requireNonNull(builder.renderingContext);
38-
visitor = DefaultConditionVisitor.withColumn(column)
39-
.withRenderingContext(renderingContext)
40-
.build();
4137
}
4238

4339
public FragmentAndParameters render() {
4440
FragmentCollector fc = new FragmentCollector();
45-
fc.add(renderLeftColumn());
46-
fc.add(condition.accept(visitor));
41+
fc.add(condition.renderLeftColumn(renderingContext, column));
42+
fc.add(condition.renderCondition(renderingContext, column));
4743
return fc.toFragmentAndParameters(Collectors.joining(" ")); //$NON-NLS-1$
4844
}
4945

50-
private FragmentAndParameters renderLeftColumn() {
51-
return column.alias()
52-
.map(FragmentAndParameters::fromFragment)
53-
.orElseGet(() -> column.render(renderingContext))
54-
.mapFragment(condition::overrideRenderedLeftColumn);
55-
}
56-
5746
public static class Builder<T> {
5847
private @Nullable BindableColumn<T> column;
5948
private @Nullable VisitableCondition<T> condition;

0 commit comments

Comments
 (0)