Skip to content

Add Support for "exists"and "not exists" in "where" Clauses #296

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 32 commits into from
Dec 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
820ac22
Make SqlCriterion abstract so we can add support for exists
jeffgbutler Nov 21, 2020
94b069d
Add ExistsCriterion and renderer
jeffgbutler Nov 22, 2020
161f069
First working exists test
jeffgbutler Nov 22, 2020
7a9ad99
Basic support for not exists
jeffgbutler Nov 22, 2020
ec98ec7
Basic support for not exists
jeffgbutler Nov 23, 2020
d21764c
Remove unnecessary if statement
jeffgbutler Nov 23, 2020
7756e00
Merge branch 'master' into exists-infrastructure
jeffgbutler Nov 30, 2020
dd43a85
Merge conflict resolution
jeffgbutler Nov 30, 2020
d66bced
Example Length Function
jeffgbutler Nov 29, 2020
cca11d2
Initial refactor of where support
jeffgbutler Nov 30, 2020
3906447
More merge cleanup
jeffgbutler Nov 30, 2020
84a6523
More merge cleanup
jeffgbutler Nov 30, 2020
7784536
Remove some useless code
jeffgbutler Nov 27, 2020
688cdc8
Kotlin Polishing
jeffgbutler Nov 29, 2020
84361fd
Better Kotlin Pattern
jeffgbutler Nov 29, 2020
d6604f0
Checkstyle and Sonar Updates
jeffgbutler Nov 30, 2020
dbea6c6
Better name for the base where support class
jeffgbutler Nov 30, 2020
dc782d5
Merge conflict resolution
jeffgbutler Nov 30, 2020
075ce9d
Merge remote-tracking branch 'origin/exists-infrastructure' into exis…
jeffgbutler Nov 30, 2020
83617c2
More merge cleanup
jeffgbutler Nov 30, 2020
1ad37ec
Better exists functions
jeffgbutler Nov 30, 2020
af20a93
Copyrights and polishing
jeffgbutler Nov 30, 2020
e2a80c2
Polishing
jeffgbutler Nov 30, 2020
fa716e9
Coverage
jeffgbutler Nov 30, 2020
9c3b876
Add exists to Kotlin DSL
jeffgbutler Nov 30, 2020
d39fb6f
Detekt Updates
jeffgbutler Nov 30, 2020
7149bee
Checkstyle updates
jeffgbutler Nov 30, 2020
07cfa81
Add Exists support in the CriteriaCollector
jeffgbutler Nov 30, 2020
0ff6592
Add Exists support in the standalone where clause and top level conne…
jeffgbutler Nov 30, 2020
827a6ed
Documentation
jeffgbutler Dec 1, 2020
034c72e
Finally a better name
jeffgbutler Dec 1, 2020
6f018e2
Add PR link to changelog
jeffgbutler Dec 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=miles

The major themes of this release include the following:

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

### Breaking Change for Kotlin

Expand All @@ -37,16 +39,17 @@ The new code looks like this:
}
```

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

### Added

- Added a new sort specification that is useful in selects with joins ([#269](https://github.com/mybatis/mybatis-dynamic-sql/pull/269))
- Added the capability to generate a camel cased alias for a column ([#272](https://github.com/mybatis/mybatis-dynamic-sql/issues/272))
- Added sub-query support for "from" clauses in a select statement ([#282](https://github.com/mybatis/mybatis-dynamic-sql/pull/282))
- Added subquery support for "from" clauses in a select statement ([#282](https://github.com/mybatis/mybatis-dynamic-sql/pull/282))
- 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))
- Added sub-query support for "join" clauses in a select statement ([#293](https://github.com/mybatis/mybatis-dynamic-sql/pull/293))
- Added subquery support for "join" clauses in a select statement ([#293](https://github.com/mybatis/mybatis-dynamic-sql/pull/293))
- Added support for the "exists" and "not exists" operator in where clauses ([#296](https://github.com/mybatis/mybatis-dynamic-sql/pull/296))


## Release 1.2.1 - September 29, 2020
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2016-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mybatis.dynamic.sql;

import java.util.Objects;

public class ColumnAndConditionCriterion<T> extends SqlCriterion {
private final BindableColumn<T> column;
private final VisitableCondition<T> condition;

private ColumnAndConditionCriterion(Builder<T> builder) {
super(builder);
column = Objects.requireNonNull(builder.column);
condition = Objects.requireNonNull(builder.condition);
}

public BindableColumn<T> column() {
return column;
}

public VisitableCondition<T> condition() {
return condition;
}

@Override
public <R> R accept(SqlCriterionVisitor<R> visitor) {
return visitor.visit(this);
}

public static <T> Builder<T> withColumn(BindableColumn<T> column) {
return new Builder<T>().withColumn(column);
}

public static class Builder<T> extends AbstractBuilder<Builder<T>> {
private BindableColumn<T> column;
private VisitableCondition<T> condition;

public Builder<T> withColumn(BindableColumn<T> column) {
this.column = column;
return this;
}

public Builder<T> withCondition(VisitableCondition<T> condition) {
this.condition = condition;
return this;
}

@Override
protected Builder<T> getThis() {
return this;
}

public ColumnAndConditionCriterion<T> build() {
return new ColumnAndConditionCriterion<>(this);
}
}
}
54 changes: 54 additions & 0 deletions src/main/java/org/mybatis/dynamic/sql/ExistsCriterion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2016-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mybatis.dynamic.sql;

import java.util.Objects;

public class ExistsCriterion extends SqlCriterion {
private final ExistsPredicate existsPredicate;

private ExistsCriterion(Builder builder) {
super(builder);
this.existsPredicate = Objects.requireNonNull(builder.existsPredicate);
}

public ExistsPredicate existsPredicate() {
return existsPredicate;
}

@Override
public <R> R accept(SqlCriterionVisitor<R> visitor) {
return visitor.visit(this);
}

public static class Builder extends AbstractBuilder<Builder> {
private ExistsPredicate existsPredicate;

public Builder withExistsPredicate(ExistsPredicate existsPredicate) {
this.existsPredicate = existsPredicate;
return this;
}

public ExistsCriterion build() {
return new ExistsCriterion(this);
}

@Override
protected Builder getThis() {
return this;
}
}
}
50 changes: 50 additions & 0 deletions src/main/java/org/mybatis/dynamic/sql/ExistsPredicate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2016-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mybatis.dynamic.sql;

import java.util.Objects;

import org.jetbrains.annotations.NotNull;
import org.mybatis.dynamic.sql.select.SelectModel;
import org.mybatis.dynamic.sql.util.Buildable;

public class ExistsPredicate {
private final Buildable<SelectModel> selectModelBuilder;
private final String operator;

private ExistsPredicate(String operator, Buildable<SelectModel> selectModelBuilder) {
this.selectModelBuilder = Objects.requireNonNull(selectModelBuilder);
this.operator = Objects.requireNonNull(operator);
}

public String operator() {
return operator;
}

public Buildable<SelectModel> selectModelBuilder() {
return selectModelBuilder;
}

@NotNull
public static ExistsPredicate exists(Buildable<SelectModel> selectModelBuilder) {
return new ExistsPredicate("exists", selectModelBuilder); //$NON-NLS-1$
}

@NotNull
public static ExistsPredicate notExists(Buildable<SelectModel> selectModelBuilder) {
return new ExistsPredicate("not exists", selectModelBuilder); //$NON-NLS-1$
}
}
68 changes: 57 additions & 11 deletions src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,43 +235,81 @@ static <T> WhereDSL where(BindableColumn<T> column, VisitableCondition<T> condit
}

static <T> WhereDSL where(BindableColumn<T> column, VisitableCondition<T> condition,
SqlCriterion<?>... subCriteria) {
SqlCriterion... subCriteria) {
return WhereDSL.where().where(column, condition, subCriteria);
}

static WhereDSL where(ExistsPredicate existsPredicate) {
return WhereDSL.where().where(existsPredicate);
}

static WhereDSL where(ExistsPredicate existsPredicate, SqlCriterion... subCriteria) {
return WhereDSL.where().where(existsPredicate, subCriteria);
}

// where condition connectors
static <T> SqlCriterion<T> or(BindableColumn<T> column, VisitableCondition<T> condition) {
return SqlCriterion.withColumn(column)
static <T> SqlCriterion or(BindableColumn<T> column, VisitableCondition<T> condition) {
return ColumnAndConditionCriterion.withColumn(column)
.withConnector("or") //$NON-NLS-1$
.withCondition(condition)
.build();
}

static <T> SqlCriterion<T> or(BindableColumn<T> column, VisitableCondition<T> condition,
SqlCriterion<?>...subCriteria) {
return SqlCriterion.withColumn(column)
static <T> SqlCriterion or(BindableColumn<T> column, VisitableCondition<T> condition,
SqlCriterion...subCriteria) {
return ColumnAndConditionCriterion.withColumn(column)
.withConnector("or") //$NON-NLS-1$
.withCondition(condition)
.withSubCriteria(Arrays.asList(subCriteria))
.build();
}

static <T> SqlCriterion<T> and(BindableColumn<T> column, VisitableCondition<T> condition) {
return SqlCriterion.withColumn(column)
static SqlCriterion or(ExistsPredicate existsPredicate) {
return new ExistsCriterion.Builder()
.withConnector("or") //$NON-NLS-1$
.withExistsPredicate(existsPredicate)
.build();
}

static SqlCriterion or(ExistsPredicate existsPredicate, SqlCriterion...subCriteria) {
return new ExistsCriterion.Builder()
.withConnector("or") //$NON-NLS-1$
.withExistsPredicate(existsPredicate)
.withSubCriteria(Arrays.asList(subCriteria))
.build();
}

static <T> SqlCriterion and(BindableColumn<T> column, VisitableCondition<T> condition) {
return ColumnAndConditionCriterion.withColumn(column)
.withConnector("and") //$NON-NLS-1$
.withCondition(condition)
.build();
}

static <T> SqlCriterion<T> and(BindableColumn<T> column, VisitableCondition<T> condition,
SqlCriterion<?>...subCriteria) {
return SqlCriterion.withColumn(column)
static <T> SqlCriterion and(BindableColumn<T> column, VisitableCondition<T> condition,
SqlCriterion...subCriteria) {
return ColumnAndConditionCriterion.withColumn(column)
.withConnector("and") //$NON-NLS-1$
.withCondition(condition)
.withSubCriteria(Arrays.asList(subCriteria))
.build();
}

static SqlCriterion and(ExistsPredicate existsPredicate) {
return new ExistsCriterion.Builder()
.withConnector("and") //$NON-NLS-1$
.withExistsPredicate(existsPredicate)
.build();
}

static SqlCriterion and(ExistsPredicate existsPredicate, SqlCriterion...subCriteria) {
return new ExistsCriterion.Builder()
.withConnector("and") //$NON-NLS-1$
.withExistsPredicate(existsPredicate)
.withSubCriteria(Arrays.asList(subCriteria))
.build();
}

// join support
static JoinCriterion and(BasicColumn joinColumn, JoinCondition joinCondition) {
return new JoinCriterion.Builder()
Expand Down Expand Up @@ -375,6 +413,14 @@ static Upper upper(BindableColumn<String> column) {
}

// conditions for all data types
static ExistsPredicate exists(Buildable<SelectModel> selectModelBuilder) {
return ExistsPredicate.exists(selectModelBuilder);
}

static ExistsPredicate notExists(Buildable<SelectModel> selectModelBuilder) {
return ExistsPredicate.notExists(selectModelBuilder);
}

static <T> IsNull<T> isNull() {
return new IsNull<>();
}
Expand Down
Loading