Skip to content

Commit 010d7d6

Browse files
committed
Simply Having support
1 parent bb18534 commit 010d7d6

File tree

8 files changed

+113
-90
lines changed

8 files changed

+113
-90
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2016-2023 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 org.mybatis.dynamic.sql.SqlCriterion;
19+
import org.mybatis.dynamic.sql.common.AbstractBooleanExpressionDSL;
20+
21+
public abstract class AbstractHavingFinisher<T extends AbstractHavingFinisher<T>> extends AbstractBooleanExpressionDSL<T> {
22+
void initialize(SqlCriterion sqlCriterion) {
23+
setInitialCriterion(sqlCriterion, "ERROR.31"); //$NON-NLS-1$
24+
}
25+
}

src/main/java/org/mybatis/dynamic/sql/select/AbstractHavingDSL.java renamed to src/main/java/org/mybatis/dynamic/sql/select/AbstractHavingStarter.java

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,40 +24,46 @@
2424
import org.mybatis.dynamic.sql.CriteriaGroup;
2525
import org.mybatis.dynamic.sql.SqlCriterion;
2626
import org.mybatis.dynamic.sql.VisitableCondition;
27-
import org.mybatis.dynamic.sql.common.AbstractBooleanExpressionDSL;
2827

29-
public abstract class AbstractHavingDSL<T extends AbstractHavingDSL<T>> extends AbstractBooleanExpressionDSL<T> {
30-
public <S> T having(BindableColumn<S> column, VisitableCondition<S> condition,
31-
AndOrCriteriaGroup... subCriteria) {
28+
public abstract class AbstractHavingStarter<F extends AbstractHavingFinisher<?>> {
29+
30+
public <T> F having(BindableColumn<T> column, VisitableCondition<T> condition,
31+
AndOrCriteriaGroup... subCriteria) {
3232
return having(column, condition, Arrays.asList(subCriteria));
3333
}
3434

35-
public <S> T having(BindableColumn<S> column, VisitableCondition<S> condition,
36-
List<AndOrCriteriaGroup> subCriteria) {
37-
setInitialCriterion(ColumnAndConditionCriterion.withColumn(column)
35+
public <T> F having(BindableColumn<T> column, VisitableCondition<T> condition,
36+
List<AndOrCriteriaGroup> subCriteria) {
37+
SqlCriterion ic = ColumnAndConditionCriterion.withColumn(column)
3838
.withCondition(condition)
3939
.withSubCriteria(subCriteria)
40-
.build(), "ERROR.31"); //$NON-NLS-1$
41-
return getThis();
40+
.build();
41+
42+
F finisher = getFinisher();
43+
finisher.initialize(ic);
44+
return finisher;
4245
}
4346

44-
public T having(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) {
47+
public F having(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) {
4548
return having(initialCriterion, Arrays.asList(subCriteria));
4649
}
4750

48-
public T having(SqlCriterion initialCriterion, List<AndOrCriteriaGroup> subCriteria) {
49-
setInitialCriterion(new CriteriaGroup.Builder()
51+
public F having(SqlCriterion initialCriterion, List<AndOrCriteriaGroup> subCriteria) {
52+
SqlCriterion ic = new CriteriaGroup.Builder()
5053
.withInitialCriterion(initialCriterion)
5154
.withSubCriteria(subCriteria)
52-
.build(), "ERROR.31"); //$NON-NLS-1$
53-
return getThis();
55+
.build();
56+
57+
F finisher = getFinisher();
58+
finisher.initialize(ic);
59+
return finisher;
5460
}
5561

56-
public T applyHaving(HavingApplier havingApplier) {
57-
havingApplier.accept(this);
58-
return getThis();
62+
public F applyHaving(HavingApplier havingApplier) {
63+
F finisher = getFinisher();
64+
havingApplier.accept(finisher);
65+
return finisher;
5966
}
6067

61-
@Override
62-
protected abstract T getThis();
68+
protected abstract F getFinisher();
6369
}

src/main/java/org/mybatis/dynamic/sql/select/AbstractHavingSupport.java

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

src/main/java/org/mybatis/dynamic/sql/select/HavingApplier.java

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

18-
import org.mybatis.dynamic.sql.common.AbstractBooleanExpressionDSL;
19-
18+
import java.util.Arrays;
19+
import java.util.List;
2020
import java.util.function.Consumer;
2121

22+
import org.mybatis.dynamic.sql.AndOrCriteriaGroup;
23+
import org.mybatis.dynamic.sql.BindableColumn;
24+
import org.mybatis.dynamic.sql.ColumnAndConditionCriterion;
25+
import org.mybatis.dynamic.sql.CriteriaGroup;
26+
import org.mybatis.dynamic.sql.SqlCriterion;
27+
import org.mybatis.dynamic.sql.VisitableCondition;
28+
import org.mybatis.dynamic.sql.common.AbstractBooleanExpressionDSL;
29+
2230
@FunctionalInterface
2331
public interface HavingApplier {
2432

25-
void accept(AbstractHavingDSL<?> havingDSL);
33+
void accept(AbstractBooleanExpressionDSL<?> havingStarter);
2634

2735
/**
2836
* Return a composed having applier that performs this operation followed by the after operation.
@@ -37,4 +45,32 @@ default HavingApplier andThen(Consumer<AbstractBooleanExpressionDSL<?>> after) {
3745
after.accept(t);
3846
};
3947
}
48+
49+
static <T> HavingApplier having(BindableColumn<T> column, VisitableCondition<T> condition,
50+
AndOrCriteriaGroup... subCriteria) {
51+
return having(column, condition, Arrays.asList(subCriteria));
52+
}
53+
54+
static <T> HavingApplier having(BindableColumn<T> column, VisitableCondition<T> condition,
55+
List<AndOrCriteriaGroup> subCriteria) {
56+
ColumnAndConditionCriterion<T> initialCriterion = ColumnAndConditionCriterion.withColumn(column)
57+
.withCondition(condition)
58+
.withSubCriteria(subCriteria)
59+
.build();
60+
61+
return d -> d.and(initialCriterion);
62+
}
63+
64+
static HavingApplier having(SqlCriterion initialCriterion, AndOrCriteriaGroup... subCriteria) {
65+
return having(initialCriterion, Arrays.asList(subCriteria));
66+
}
67+
68+
static HavingApplier having(SqlCriterion initialCriterion, List<AndOrCriteriaGroup> subCriteria) {
69+
CriteriaGroup ic = new CriteriaGroup.Builder()
70+
.withInitialCriterion(initialCriterion)
71+
.withSubCriteria(subCriteria)
72+
.build();
73+
74+
return d -> d.and(ic);
75+
}
4076
}

src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.jetbrains.annotations.NotNull;
2626
import org.mybatis.dynamic.sql.BasicColumn;
27+
import org.mybatis.dynamic.sql.CriteriaGroup;
2728
import org.mybatis.dynamic.sql.SortSpecification;
2829
import org.mybatis.dynamic.sql.SqlTable;
2930
import org.mybatis.dynamic.sql.TableExpression;
@@ -85,6 +86,15 @@ protected QueryExpressionHavingBuilder having() {
8586
return havingBuilder;
8687
}
8788

89+
/**
90+
* This method is meant for use by the Kotlin DSL. We expect a full set of criteria.
91+
*
92+
* @param criteriaGroup the full criteria for a Kotlin Having clause
93+
*/
94+
protected void applyHaving(CriteriaGroup criteriaGroup) {
95+
having().initialize(criteriaGroup);
96+
}
97+
8898
@NotNull
8999
@Override
90100
public R build() {
@@ -492,7 +502,7 @@ public SelectDSL<R>.FetchFirstFinisher fetchFirst(long fetchFirstRows) {
492502
}
493503
}
494504

495-
public class GroupByFinisher extends AbstractHavingSupport<QueryExpressionHavingBuilder> implements Buildable<R> {
505+
public class GroupByFinisher extends AbstractHavingStarter<QueryExpressionHavingBuilder> implements Buildable<R> {
496506
public SelectDSL<R> orderBy(SortSpecification... columns) {
497507
return orderBy(Arrays.asList(columns));
498508
}
@@ -528,7 +538,7 @@ public SelectDSL<R>.FetchFirstFinisher fetchFirst(long fetchFirstRows) {
528538
}
529539

530540
@Override
531-
public QueryExpressionHavingBuilder having() {
541+
public QueryExpressionHavingBuilder getFinisher() {
532542
return QueryExpressionDSL.this.having();
533543
}
534544
}
@@ -566,7 +576,7 @@ public FromGatherer<R> selectDistinct(List<BasicColumn> selectList) {
566576
}
567577
}
568578

569-
public class QueryExpressionHavingBuilder extends AbstractHavingDSL<QueryExpressionHavingBuilder>
579+
public class QueryExpressionHavingBuilder extends AbstractHavingFinisher<QueryExpressionHavingBuilder>
570580
implements Buildable<R> {
571581

572582
public SelectDSL<R>.FetchFirstFinisher fetchFirst(long fetchFirstRows) {

src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/KotlinSelectBuilder.kt

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

18-
import org.mybatis.dynamic.sql.AndOrCriteriaGroup
1918
import org.mybatis.dynamic.sql.BasicColumn
19+
import org.mybatis.dynamic.sql.CriteriaGroup
2020
import org.mybatis.dynamic.sql.SortSpecification
21-
import org.mybatis.dynamic.sql.SqlCriterion
2221
import org.mybatis.dynamic.sql.SqlTable
2322
import org.mybatis.dynamic.sql.select.QueryExpressionDSL
2423
import org.mybatis.dynamic.sql.select.SelectModel
@@ -53,7 +52,7 @@ class KotlinSelectBuilder(private val fromGatherer: QueryExpressionDSL.FromGathe
5352

5453
fun having(criteria: GroupingCriteriaReceiver): Unit =
5554
GroupingCriteriaCollector().apply(criteria).let {
56-
getDsl().having(it.initialCriterion, it.subCriteria)
55+
getDsl().applyHaving(it)
5756
}
5857

5958
fun orderBy(vararg columns: SortSpecification) {
@@ -99,8 +98,12 @@ class KQueryExpressionDSL: QueryExpressionDSL<SelectModel> {
9998
constructor(fromGatherer: FromGatherer<SelectModel>, subQuery: KotlinQualifiedSubQueryBuilder) :
10099
super(fromGatherer, buildSubQuery(subQuery))
101100

102-
internal fun having(initialCriterion: SqlCriterion?, subCriteria: List<AndOrCriteriaGroup>) {
103-
having().applyHaving{ it.having(initialCriterion, subCriteria) }
101+
internal fun applyHaving(collector: GroupingCriteriaCollector) {
102+
val cg = CriteriaGroup.Builder()
103+
.withInitialCriterion(collector.initialCriterion)
104+
.withSubCriteria(collector.subCriteria)
105+
.build()
106+
applyHaving(cg)
104107
}
105108

106109
companion object {

src/test/java/examples/groupby/GroupByTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,5 +712,5 @@ void testComposedHaving() {
712712
}
713713
}
714714

715-
private final HavingApplier commonHaving = d -> d.having(count(), isEqualTo(3L));
715+
private final HavingApplier commonHaving = HavingApplier.having(count(), isEqualTo(3L));
716716
}

src/test/kotlin/examples/kotlin/mybatis3/general/KGroupingTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,8 @@ class KGroupingTest {
425425
select(A, count()) {
426426
from(foo)
427427
groupBy(A)
428-
having { count() isGreaterThanWhenPresent null }
429-
having { count() isGreaterThanWhenPresent null }
428+
having { count() isGreaterThan 6 }
429+
having { count() isGreaterThan 5 }
430430
}
431431
}.withMessage(Messages.getString("ERROR.31"))
432432
}

0 commit comments

Comments
 (0)