Skip to content

Commit 48a428e

Browse files
authored
Add Support for "exists"and "not exists" in "where" Clauses (#296)
* Make SqlCriterion abstract so we can add support for exists * Add ExistsCriterion and renderer * First working exists test * Basic support for not exists * Basic support for not exists * Remove unnecessary if statement * Merge conflict resolution * Example Length Function * Initial refactor of where support Factor common where methods out of the DSL classes. THis will allow for an easier implementation of future where support such as "exists". � Conflicts: � src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java � src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java � src/main/java/org/mybatis/dynamic/sql/select/QueryExpressionDSL.java � src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java * More merge cleanup * More merge cleanup * Remove some useless code * Kotlin Polishing * Better Kotlin Pattern * Checkstyle and Sonar Updates * Better name for the base where support class * Merge conflict resolution * More merge cleanup * Better exists functions * Copyrights and polishing * Polishing * Coverage * Add exists to Kotlin DSL * Detekt Updates * Checkstyle updates * Add Exists support in the CriteriaCollector * Add Exists support in the standalone where clause and top level connectors * Documentation * Finally a better name * Add PR link to changelog
1 parent 6cfe8c2 commit 48a428e

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

+1800
-308
lines changed

CHANGELOG.md

+8-5
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=miles
1010

1111
The major themes of this release include the following:
1212

13-
1. Add support for subqueries in select statements - both in a from clause and a join clause
13+
1. Add support for subqueries in select statements - both in a from clause and a join clause.
14+
1. Add support for the "exists" and "not exists" operator. This will work in "where" clauses anywhere
15+
they are supported.
1416
1. Continue to refine the Kotlin DSL. Most changes to the Kotlin DSL are internal and should be source code
1517
compatible with existing code. There is one breaking change detailed below.
16-
1. Remove deprecated code from prior releases
18+
1. Remove deprecated code from prior releases.
1719

1820
### Breaking Change for Kotlin
1921

@@ -37,16 +39,17 @@ The new code looks like this:
3739
}
3840
```
3941

40-
This change makes the Kotlin DSL a bit more consistent and also makes it easier to implement sub-query support in the
42+
This change makes the Kotlin DSL a bit more consistent and also makes it easier to implement subquery support in the
4143
Kotlin DSL.
4244

4345
### Added
4446

4547
- Added a new sort specification that is useful in selects with joins ([#269](https://github.com/mybatis/mybatis-dynamic-sql/pull/269))
4648
- Added the capability to generate a camel cased alias for a column ([#272](https://github.com/mybatis/mybatis-dynamic-sql/issues/272))
47-
- Added sub-query support for "from" clauses in a select statement ([#282](https://github.com/mybatis/mybatis-dynamic-sql/pull/282))
49+
- Added subquery support for "from" clauses in a select statement ([#282](https://github.com/mybatis/mybatis-dynamic-sql/pull/282))
4850
- Added Kotlin DSL updates to support sub-queries in select statements, where clauses, and insert statements ([#282](https://github.com/mybatis/mybatis-dynamic-sql/pull/282))
49-
- Added sub-query support for "join" clauses in a select statement ([#293](https://github.com/mybatis/mybatis-dynamic-sql/pull/293))
51+
- Added subquery support for "join" clauses in a select statement ([#293](https://github.com/mybatis/mybatis-dynamic-sql/pull/293))
52+
- Added support for the "exists" and "not exists" operator in where clauses ([#296](https://github.com/mybatis/mybatis-dynamic-sql/pull/296))
5053

5154

5255
## Release 1.2.1 - September 29, 2020
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2016-2020 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+
* http://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;
17+
18+
import java.util.Objects;
19+
20+
public class ColumnAndConditionCriterion<T> extends SqlCriterion {
21+
private final BindableColumn<T> column;
22+
private final VisitableCondition<T> condition;
23+
24+
private ColumnAndConditionCriterion(Builder<T> builder) {
25+
super(builder);
26+
column = Objects.requireNonNull(builder.column);
27+
condition = Objects.requireNonNull(builder.condition);
28+
}
29+
30+
public BindableColumn<T> column() {
31+
return column;
32+
}
33+
34+
public VisitableCondition<T> condition() {
35+
return condition;
36+
}
37+
38+
@Override
39+
public <R> R accept(SqlCriterionVisitor<R> visitor) {
40+
return visitor.visit(this);
41+
}
42+
43+
public static <T> Builder<T> withColumn(BindableColumn<T> column) {
44+
return new Builder<T>().withColumn(column);
45+
}
46+
47+
public static class Builder<T> extends AbstractBuilder<Builder<T>> {
48+
private BindableColumn<T> column;
49+
private VisitableCondition<T> condition;
50+
51+
public Builder<T> withColumn(BindableColumn<T> column) {
52+
this.column = column;
53+
return this;
54+
}
55+
56+
public Builder<T> withCondition(VisitableCondition<T> condition) {
57+
this.condition = condition;
58+
return this;
59+
}
60+
61+
@Override
62+
protected Builder<T> getThis() {
63+
return this;
64+
}
65+
66+
public ColumnAndConditionCriterion<T> build() {
67+
return new ColumnAndConditionCriterion<>(this);
68+
}
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2016-2020 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+
* http://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;
17+
18+
import java.util.Objects;
19+
20+
public class ExistsCriterion extends SqlCriterion {
21+
private final ExistsPredicate existsPredicate;
22+
23+
private ExistsCriterion(Builder builder) {
24+
super(builder);
25+
this.existsPredicate = Objects.requireNonNull(builder.existsPredicate);
26+
}
27+
28+
public ExistsPredicate existsPredicate() {
29+
return existsPredicate;
30+
}
31+
32+
@Override
33+
public <R> R accept(SqlCriterionVisitor<R> visitor) {
34+
return visitor.visit(this);
35+
}
36+
37+
public static class Builder extends AbstractBuilder<Builder> {
38+
private ExistsPredicate existsPredicate;
39+
40+
public Builder withExistsPredicate(ExistsPredicate existsPredicate) {
41+
this.existsPredicate = existsPredicate;
42+
return this;
43+
}
44+
45+
public ExistsCriterion build() {
46+
return new ExistsCriterion(this);
47+
}
48+
49+
@Override
50+
protected Builder getThis() {
51+
return this;
52+
}
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2016-2020 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+
* http://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;
17+
18+
import java.util.Objects;
19+
20+
import org.jetbrains.annotations.NotNull;
21+
import org.mybatis.dynamic.sql.select.SelectModel;
22+
import org.mybatis.dynamic.sql.util.Buildable;
23+
24+
public class ExistsPredicate {
25+
private final Buildable<SelectModel> selectModelBuilder;
26+
private final String operator;
27+
28+
private ExistsPredicate(String operator, Buildable<SelectModel> selectModelBuilder) {
29+
this.selectModelBuilder = Objects.requireNonNull(selectModelBuilder);
30+
this.operator = Objects.requireNonNull(operator);
31+
}
32+
33+
public String operator() {
34+
return operator;
35+
}
36+
37+
public Buildable<SelectModel> selectModelBuilder() {
38+
return selectModelBuilder;
39+
}
40+
41+
@NotNull
42+
public static ExistsPredicate exists(Buildable<SelectModel> selectModelBuilder) {
43+
return new ExistsPredicate("exists", selectModelBuilder); //$NON-NLS-1$
44+
}
45+
46+
@NotNull
47+
public static ExistsPredicate notExists(Buildable<SelectModel> selectModelBuilder) {
48+
return new ExistsPredicate("not exists", selectModelBuilder); //$NON-NLS-1$
49+
}
50+
}

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

+57-11
Original file line numberDiff line numberDiff line change
@@ -235,43 +235,81 @@ static <T> WhereDSL where(BindableColumn<T> column, VisitableCondition<T> condit
235235
}
236236

237237
static <T> WhereDSL where(BindableColumn<T> column, VisitableCondition<T> condition,
238-
SqlCriterion<?>... subCriteria) {
238+
SqlCriterion... subCriteria) {
239239
return WhereDSL.where().where(column, condition, subCriteria);
240240
}
241241

242+
static WhereDSL where(ExistsPredicate existsPredicate) {
243+
return WhereDSL.where().where(existsPredicate);
244+
}
245+
246+
static WhereDSL where(ExistsPredicate existsPredicate, SqlCriterion... subCriteria) {
247+
return WhereDSL.where().where(existsPredicate, subCriteria);
248+
}
249+
242250
// where condition connectors
243-
static <T> SqlCriterion<T> or(BindableColumn<T> column, VisitableCondition<T> condition) {
244-
return SqlCriterion.withColumn(column)
251+
static <T> SqlCriterion or(BindableColumn<T> column, VisitableCondition<T> condition) {
252+
return ColumnAndConditionCriterion.withColumn(column)
245253
.withConnector("or") //$NON-NLS-1$
246254
.withCondition(condition)
247255
.build();
248256
}
249257

250-
static <T> SqlCriterion<T> or(BindableColumn<T> column, VisitableCondition<T> condition,
251-
SqlCriterion<?>...subCriteria) {
252-
return SqlCriterion.withColumn(column)
258+
static <T> SqlCriterion or(BindableColumn<T> column, VisitableCondition<T> condition,
259+
SqlCriterion...subCriteria) {
260+
return ColumnAndConditionCriterion.withColumn(column)
253261
.withConnector("or") //$NON-NLS-1$
254262
.withCondition(condition)
255263
.withSubCriteria(Arrays.asList(subCriteria))
256264
.build();
257265
}
258266

259-
static <T> SqlCriterion<T> and(BindableColumn<T> column, VisitableCondition<T> condition) {
260-
return SqlCriterion.withColumn(column)
267+
static SqlCriterion or(ExistsPredicate existsPredicate) {
268+
return new ExistsCriterion.Builder()
269+
.withConnector("or") //$NON-NLS-1$
270+
.withExistsPredicate(existsPredicate)
271+
.build();
272+
}
273+
274+
static SqlCriterion or(ExistsPredicate existsPredicate, SqlCriterion...subCriteria) {
275+
return new ExistsCriterion.Builder()
276+
.withConnector("or") //$NON-NLS-1$
277+
.withExistsPredicate(existsPredicate)
278+
.withSubCriteria(Arrays.asList(subCriteria))
279+
.build();
280+
}
281+
282+
static <T> SqlCriterion and(BindableColumn<T> column, VisitableCondition<T> condition) {
283+
return ColumnAndConditionCriterion.withColumn(column)
261284
.withConnector("and") //$NON-NLS-1$
262285
.withCondition(condition)
263286
.build();
264287
}
265288

266-
static <T> SqlCriterion<T> and(BindableColumn<T> column, VisitableCondition<T> condition,
267-
SqlCriterion<?>...subCriteria) {
268-
return SqlCriterion.withColumn(column)
289+
static <T> SqlCriterion and(BindableColumn<T> column, VisitableCondition<T> condition,
290+
SqlCriterion...subCriteria) {
291+
return ColumnAndConditionCriterion.withColumn(column)
269292
.withConnector("and") //$NON-NLS-1$
270293
.withCondition(condition)
271294
.withSubCriteria(Arrays.asList(subCriteria))
272295
.build();
273296
}
274297

298+
static SqlCriterion and(ExistsPredicate existsPredicate) {
299+
return new ExistsCriterion.Builder()
300+
.withConnector("and") //$NON-NLS-1$
301+
.withExistsPredicate(existsPredicate)
302+
.build();
303+
}
304+
305+
static SqlCriterion and(ExistsPredicate existsPredicate, SqlCriterion...subCriteria) {
306+
return new ExistsCriterion.Builder()
307+
.withConnector("and") //$NON-NLS-1$
308+
.withExistsPredicate(existsPredicate)
309+
.withSubCriteria(Arrays.asList(subCriteria))
310+
.build();
311+
}
312+
275313
// join support
276314
static JoinCriterion and(BasicColumn joinColumn, JoinCondition joinCondition) {
277315
return new JoinCriterion.Builder()
@@ -375,6 +413,14 @@ static Upper upper(BindableColumn<String> column) {
375413
}
376414

377415
// conditions for all data types
416+
static ExistsPredicate exists(Buildable<SelectModel> selectModelBuilder) {
417+
return ExistsPredicate.exists(selectModelBuilder);
418+
}
419+
420+
static ExistsPredicate notExists(Buildable<SelectModel> selectModelBuilder) {
421+
return ExistsPredicate.notExists(selectModelBuilder);
422+
}
423+
378424
static <T> IsNull<T> isNull() {
379425
return new IsNull<>();
380426
}

0 commit comments

Comments
 (0)