Skip to content

Commit 7327c88

Browse files
committed
Basic support for "having"
1 parent b5189a8 commit 7327c88

File tree

13 files changed

+525
-199
lines changed

13 files changed

+525
-199
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright 2016-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.mybatis.dynamic.sql.common;
17+
18+
import java.util.ArrayList;
19+
import java.util.Arrays;
20+
import java.util.List;
21+
22+
import org.jetbrains.annotations.NotNull;
23+
import org.mybatis.dynamic.sql.AndOrCriteriaGroup;
24+
import org.mybatis.dynamic.sql.BindableColumn;
25+
import org.mybatis.dynamic.sql.ColumnAndConditionCriterion;
26+
import org.mybatis.dynamic.sql.CriteriaGroup;
27+
import org.mybatis.dynamic.sql.ExistsCriterion;
28+
import org.mybatis.dynamic.sql.ExistsPredicate;
29+
import org.mybatis.dynamic.sql.SqlCriterion;
30+
import org.mybatis.dynamic.sql.VisitableCondition;
31+
32+
public abstract class AbstractBooleanExpressionDSL<T extends AbstractBooleanExpressionDSL<T>> {
33+
protected SqlCriterion initialCriterion; // WARNING - may be null!
34+
protected final List<AndOrCriteriaGroup> subCriteria = new ArrayList<>();
35+
36+
@NotNull
37+
public <S> T and(BindableColumn<S> column, VisitableCondition<S> condition,
38+
AndOrCriteriaGroup... subCriteria) {
39+
return and(column, condition, Arrays.asList(subCriteria));
40+
}
41+
42+
@NotNull
43+
public <S> T and(BindableColumn<S> column, VisitableCondition<S> condition,
44+
List<AndOrCriteriaGroup> subCriteria) {
45+
addSubCriteria("and", buildCriterion(column, condition), subCriteria); //$NON-NLS-1$
46+
return getThis();
47+
}
48+
49+
@NotNull
50+
public T and(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) {
51+
return and(existsPredicate, Arrays.asList(subCriteria));
52+
}
53+
54+
@NotNull
55+
public T and(ExistsPredicate existsPredicate, List<AndOrCriteriaGroup> subCriteria) {
56+
addSubCriteria("and", buildCriterion(existsPredicate), subCriteria); //$NON-NLS-1$
57+
return getThis();
58+
}
59+
60+
@NotNull
61+
public T and(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) {
62+
return and(initialCriterion, Arrays.asList(subCriteria));
63+
}
64+
65+
@NotNull
66+
public T and(SqlCriterion initialCriterion, List<AndOrCriteriaGroup> subCriteria) {
67+
addSubCriteria("and", buildCriterion(initialCriterion), subCriteria); //$NON-NLS-1$
68+
return getThis();
69+
}
70+
71+
@NotNull
72+
public T and(List<AndOrCriteriaGroup> criteria) {
73+
addSubCriteria("and", criteria); //$NON-NLS-1$
74+
return getThis();
75+
}
76+
77+
@NotNull
78+
public <S> T or(BindableColumn<S> column, VisitableCondition<S> condition,
79+
AndOrCriteriaGroup... subCriteria) {
80+
return or(column, condition, Arrays.asList(subCriteria));
81+
}
82+
83+
@NotNull
84+
public <S> T or(BindableColumn<S> column, VisitableCondition<S> condition,
85+
List<AndOrCriteriaGroup> subCriteria) {
86+
addSubCriteria("or", buildCriterion(column, condition), subCriteria); //$NON-NLS-1$
87+
return getThis();
88+
}
89+
90+
@NotNull
91+
public T or(ExistsPredicate existsPredicate, AndOrCriteriaGroup... subCriteria) {
92+
return or(existsPredicate, Arrays.asList(subCriteria));
93+
}
94+
95+
@NotNull
96+
public T or(ExistsPredicate existsPredicate, List<AndOrCriteriaGroup> subCriteria) {
97+
addSubCriteria("or", buildCriterion(existsPredicate), subCriteria); //$NON-NLS-1$
98+
return getThis();
99+
}
100+
101+
@NotNull
102+
public T or(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) {
103+
return or(initialCriterion, Arrays.asList(subCriteria));
104+
}
105+
106+
@NotNull
107+
public T or(SqlCriterion initialCriterion, List<AndOrCriteriaGroup> subCriteria) {
108+
addSubCriteria("or", buildCriterion(initialCriterion), subCriteria); //$NON-NLS-1$
109+
return getThis();
110+
}
111+
112+
@NotNull
113+
public T or(List<AndOrCriteriaGroup> criteria) {
114+
addSubCriteria("or", criteria); //$NON-NLS-1$
115+
return getThis();
116+
}
117+
118+
private <R> SqlCriterion buildCriterion(BindableColumn<R> column, VisitableCondition<R> condition) {
119+
return ColumnAndConditionCriterion.withColumn(column).withCondition(condition).build();
120+
}
121+
122+
private SqlCriterion buildCriterion(ExistsPredicate existsPredicate) {
123+
return new ExistsCriterion.Builder().withExistsPredicate(existsPredicate).build();
124+
}
125+
126+
private SqlCriterion buildCriterion(SqlCriterion initialCriterion) {
127+
return new CriteriaGroup.Builder().withInitialCriterion(initialCriterion).build();
128+
}
129+
130+
private void addSubCriteria(String connector, SqlCriterion initialCriterion,
131+
List<AndOrCriteriaGroup> subCriteria) {
132+
this.subCriteria.add(new AndOrCriteriaGroup.Builder()
133+
.withInitialCriterion(initialCriterion)
134+
.withConnector(connector)
135+
.withSubCriteria(subCriteria)
136+
.build());
137+
}
138+
139+
private void addSubCriteria(String connector, List<AndOrCriteriaGroup> criteria) {
140+
this.subCriteria.add(new AndOrCriteriaGroup.Builder()
141+
.withConnector(connector)
142+
.withSubCriteria(criteria)
143+
.build());
144+
}
145+
146+
protected abstract T getThis();
147+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2016-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.mybatis.dynamic.sql.common;
17+
18+
import java.util.ArrayList;
19+
import java.util.Collections;
20+
import java.util.List;
21+
import java.util.Optional;
22+
23+
import org.mybatis.dynamic.sql.AndOrCriteriaGroup;
24+
import org.mybatis.dynamic.sql.SqlCriterion;
25+
26+
public abstract class AbstractBooleanExpressionModel {
27+
private final SqlCriterion initialCriterion;
28+
private final List<AndOrCriteriaGroup> subCriteria = new ArrayList<>();
29+
30+
protected AbstractBooleanExpressionModel(SqlCriterion initialCriterion, List<AndOrCriteriaGroup> subCriteria) {
31+
this.initialCriterion = initialCriterion;
32+
this.subCriteria.addAll(subCriteria);
33+
}
34+
35+
public Optional<SqlCriterion> initialCriterion() {
36+
return Optional.ofNullable(initialCriterion);
37+
}
38+
39+
public List<AndOrCriteriaGroup> subCriteria() {
40+
return Collections.unmodifiableList(subCriteria);
41+
}
42+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright 2016-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.mybatis.dynamic.sql.common;
17+
18+
import java.util.Objects;
19+
import java.util.Optional;
20+
import java.util.concurrent.atomic.AtomicInteger;
21+
import java.util.stream.Collectors;
22+
23+
import org.mybatis.dynamic.sql.SqlCriterion;
24+
import org.mybatis.dynamic.sql.render.RenderingStrategy;
25+
import org.mybatis.dynamic.sql.render.TableAliasCalculator;
26+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
27+
import org.mybatis.dynamic.sql.util.FragmentCollector;
28+
import org.mybatis.dynamic.sql.where.render.CriterionRenderer;
29+
import org.mybatis.dynamic.sql.where.render.RenderedCriterion;
30+
31+
public abstract class AbstractBooleanExpressionRenderer<M extends AbstractBooleanExpressionModel> {
32+
protected final M model;
33+
private final CriterionRenderer criterionRenderer;
34+
private final String prefix;
35+
36+
protected AbstractBooleanExpressionRenderer(AbstractBuilder<M, ?> builder) {
37+
model = Objects.requireNonNull(builder.model);
38+
39+
criterionRenderer = new CriterionRenderer.Builder()
40+
.withSequence(builder.sequence)
41+
.withRenderingStrategy(builder.renderingStrategy)
42+
.withTableAliasCalculator(builder.tableAliasCalculator)
43+
.withParameterName(builder.parameterName)
44+
.build();
45+
46+
prefix = Objects.requireNonNull(builder.prefix);
47+
}
48+
49+
public Optional<FragmentAndParameters> render() {
50+
return model.initialCriterion()
51+
.map(this::renderWithInitialCriterion)
52+
.orElseGet(this::renderWithoutInitialCriterion)
53+
.map(rc -> FragmentAndParameters.withFragment(rc.fragmentAndParameters().fragment())
54+
.withParameters(rc.fragmentAndParameters().parameters())
55+
.build()
56+
);
57+
}
58+
59+
private Optional<RenderedCriterion> renderWithInitialCriterion(SqlCriterion initialCriterion) {
60+
return criterionRenderer.render(initialCriterion, model.subCriteria(), this::calculateClause);
61+
}
62+
63+
private Optional<RenderedCriterion> renderWithoutInitialCriterion() {
64+
return criterionRenderer.render(model.subCriteria(), this::calculateClause);
65+
}
66+
67+
private String calculateClause(FragmentCollector collector) {
68+
return collector.fragments()
69+
.collect(Collectors.joining(" ", prefix + " ", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
70+
}
71+
72+
public abstract static class AbstractBuilder<M, B extends AbstractBuilder<M, B>> {
73+
private final M model;
74+
private RenderingStrategy renderingStrategy;
75+
private TableAliasCalculator tableAliasCalculator;
76+
private AtomicInteger sequence;
77+
private String parameterName;
78+
79+
private final String prefix;
80+
81+
protected AbstractBuilder(String prefix, M model) {
82+
this.prefix = prefix;
83+
this.model = model;
84+
}
85+
86+
public B withRenderingStrategy(RenderingStrategy renderingStrategy) {
87+
this.renderingStrategy = renderingStrategy;
88+
return getThis();
89+
}
90+
91+
public B withTableAliasCalculator(TableAliasCalculator tableAliasCalculator) {
92+
this.tableAliasCalculator = tableAliasCalculator;
93+
return getThis();
94+
}
95+
96+
public B withSequence(AtomicInteger sequence) {
97+
this.sequence = sequence;
98+
return getThis();
99+
}
100+
101+
public B withParameterName(String parameterName) {
102+
this.parameterName = parameterName;
103+
return getThis();
104+
}
105+
106+
protected abstract B getThis();
107+
}
108+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2016-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.mybatis.dynamic.sql.select;
17+
18+
import java.util.List;
19+
20+
import org.mybatis.dynamic.sql.AndOrCriteriaGroup;
21+
import org.mybatis.dynamic.sql.SqlCriterion;
22+
import org.mybatis.dynamic.sql.common.AbstractBooleanExpressionModel;
23+
24+
public class HavingModel extends AbstractBooleanExpressionModel {
25+
public HavingModel(SqlCriterion initialCriterion, List<AndOrCriteriaGroup> subCriteria) {
26+
super(initialCriterion, subCriteria);
27+
}
28+
}

0 commit comments

Comments
 (0)