Skip to content

Commit

Permalink
Merge pull request #434 from jeffgbutler/gh-430
Browse files Browse the repository at this point in the history
Add support for CriteriaGroups
  • Loading branch information
jeffgbutler committed Jan 12, 2022
2 parents 9e70008 + 9fda0e4 commit b28ca54
Show file tree
Hide file tree
Showing 18 changed files with 973 additions and 357 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

This log will detail notable changes to MyBatis Dynamic SQL. Full details are available on the GitHub milestone pages.

## Release 1.4.0 - Unreleased

GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.4.0+](https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.4.0+)

1. Added support for arbitrary placement of nested criteria. For example, it is now
possible to write a where clause like this: `where (a < 5 and B = 3) and ((C = 4 or D = 5) and E = 6)`. Previously
we did not support the grouping of criteria at the beginning of a where clause or the beginning of an and/or
condition. Adding this support required significant refactoring, but that should be transparent to most users.
([#434](https://github.com/mybatis/mybatis-dynamic-sql/pull/434))

## Release 1.3.1 - December 18, 2021

This is a minor release with a few small enhancements. Most deprecated methods will be removed in the next release.
Expand Down
78 changes: 78 additions & 0 deletions src/main/java/org/mybatis/dynamic/sql/AndOrCriteriaGroup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2016-2022 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.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
* This class represents a criteria group with either an AND or an OR connector.
* This class is intentionally NOT derived from SqlCriterion because we only want it to be
* available where an AND or an OR condition is appropriate.
*
* @author Jeff Butler
* @since 1.4.0
*/
public class AndOrCriteriaGroup {
private final String connector;
private final SqlCriterion initialCriterion;
private final List<AndOrCriteriaGroup> subCriteria;

private AndOrCriteriaGroup(Builder builder) {
connector = Objects.requireNonNull(builder.connector);
initialCriterion = Objects.requireNonNull(builder.initialCriterion);
subCriteria = builder.subCriteria;
}

public String connector() {
return connector;
}

public SqlCriterion initialCriterion() {
return initialCriterion;
}

public List<AndOrCriteriaGroup> subCriteria() {
return Collections.unmodifiableList(subCriteria);
}

public static class Builder {
private String connector;
private SqlCriterion initialCriterion;
private final List<AndOrCriteriaGroup> subCriteria = new ArrayList<>();

public Builder withConnector(String connector) {
this.connector = connector;
return this;
}

public Builder withInitialCriterion(SqlCriterion initialCriterion) {
this.initialCriterion = initialCriterion;
return this;
}

public Builder withSubCriteria(List<AndOrCriteriaGroup> subCriteria) {
this.subCriteria.addAll(subCriteria);
return this;
}

public AndOrCriteriaGroup build() {
return new AndOrCriteriaGroup(this);
}
}
}
62 changes: 62 additions & 0 deletions src/main/java/org/mybatis/dynamic/sql/CriteriaGroup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2016-2022 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;

/**
* This class represents a criteria group without an AND or an OR connector. This is useful
* in situations where the initial SqlCriterion in a list should be further grouped
* as in an expression like ((A &lt; 5 and B &gt; 6) or C = 3)
*
* @author Jeff Butler, inspired by @JoshuaJeme
* @since 1.4.0
*/
public class CriteriaGroup extends SqlCriterion {
private final SqlCriterion initialCriterion;

private CriteriaGroup(Builder builder) {
super(builder);
initialCriterion = Objects.requireNonNull(builder.initialCriterion);
}

public SqlCriterion initialCriterion() {
return initialCriterion;
}

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

public static class Builder extends AbstractBuilder<Builder> {
private SqlCriterion initialCriterion;

public Builder withInitialCriterion(SqlCriterion initialCriterion) {
this.initialCriterion = initialCriterion;
return this;
}

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

@Override
protected Builder getThis() {
return this;
}
}
}
105 changes: 66 additions & 39 deletions src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2021 the original author or authors.
* Copyright 2016-2022 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.
Expand Down Expand Up @@ -214,82 +214,109 @@ static WhereDSL where() {
return WhereDSL.where();
}

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

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

static WhereDSL where(ExistsPredicate existsPredicate) {
return WhereDSL.where().where(existsPredicate);
static WhereDSL where(CriteriaGroup criteriaGroup, AndOrCriteriaGroup... subCriteria) {
return WhereDSL.where().where(criteriaGroup, subCriteria);
}

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

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

static <T> CriteriaGroup group(BindableColumn<T> column, VisitableCondition<T> condition,
List<AndOrCriteriaGroup> subCriteria) {
return new CriteriaGroup.Builder()
.withInitialCriterion(new ColumnAndConditionCriterion.Builder<T>().withColumn(column)
.withCondition(condition).build())
.withSubCriteria(subCriteria)
.build();
}

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))
static CriteriaGroup group(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) {
return group(existsPredicate, Arrays.asList(subCriteria));
}

static CriteriaGroup group(ExistsPredicate existsPredicate, List<AndOrCriteriaGroup> subCriteria) {
return new CriteriaGroup.Builder()
.withInitialCriterion(new ExistsCriterion.Builder()
.withExistsPredicate(existsPredicate).build())
.withSubCriteria(subCriteria)
.build();
}

static SqlCriterion or(ExistsPredicate existsPredicate) {
return new ExistsCriterion.Builder()
static CriteriaGroup group(CriteriaGroup criteriaGroup, AndOrCriteriaGroup...subCriteria) {
return group(criteriaGroup, Arrays.asList(subCriteria));
}

static CriteriaGroup group(CriteriaGroup criteriaGroup, List<AndOrCriteriaGroup> subCriteria) {
return new CriteriaGroup.Builder()
.withInitialCriterion(criteriaGroup)
.withSubCriteria(subCriteria)
.build();
}

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

static SqlCriterion or(ExistsPredicate existsPredicate, SqlCriterion...subCriteria) {
return new ExistsCriterion.Builder()
static AndOrCriteriaGroup or(ExistsPredicate existsPredicate, AndOrCriteriaGroup...subCriteria) {
return new AndOrCriteriaGroup.Builder()
.withInitialCriterion(new ExistsCriterion.Builder()
.withExistsPredicate(existsPredicate).build())
.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)
static AndOrCriteriaGroup or(CriteriaGroup criteriaGroup, AndOrCriteriaGroup...subCriteria) {
return new AndOrCriteriaGroup.Builder()
.withConnector("or") //$NON-NLS-1$
.withInitialCriterion(criteriaGroup)
.withSubCriteria(Arrays.asList(subCriteria))
.build();
}

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

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

static SqlCriterion and(ExistsPredicate existsPredicate, SqlCriterion...subCriteria) {
return new ExistsCriterion.Builder()
static AndOrCriteriaGroup and(CriteriaGroup criteriaGroup, AndOrCriteriaGroup...subCriteria) {
return new AndOrCriteriaGroup.Builder()
.withConnector("and") //$NON-NLS-1$
.withExistsPredicate(existsPredicate)
.withInitialCriterion(criteriaGroup)
.withSubCriteria(Arrays.asList(subCriteria))
.build();
}
Expand Down
31 changes: 8 additions & 23 deletions src/main/java/org/mybatis/dynamic/sql/SqlCriterion.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 the original author or authors.
* Copyright 2016-2022 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.
Expand All @@ -16,42 +16,27 @@
package org.mybatis.dynamic.sql;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

public abstract class SqlCriterion {

private final String connector;
private final List<SqlCriterion> subCriteria;
private final List<AndOrCriteriaGroup> subCriteria = new ArrayList<>();

protected SqlCriterion(AbstractBuilder<?> builder) {
connector = builder.connector;
subCriteria = Objects.requireNonNull(builder.subCriteria);
subCriteria.addAll(builder.subCriteria);
}

public Optional<String> connector() {
return Optional.ofNullable(connector);
}

public <R> Stream<R> mapSubCriteria(Function<SqlCriterion, R> mapper) {
return subCriteria.stream().map(mapper);
public List<AndOrCriteriaGroup> subCriteria() {
return Collections.unmodifiableList(subCriteria);
}

public abstract <R> R accept(SqlCriterionVisitor<R> visitor);

protected abstract static class AbstractBuilder<T extends AbstractBuilder<T>> {
private String connector;
private final List<SqlCriterion> subCriteria = new ArrayList<>();

public T withConnector(String connector) {
this.connector = connector;
return getThis();
}
private final List<AndOrCriteriaGroup> subCriteria = new ArrayList<>();

public T withSubCriteria(List<SqlCriterion> subCriteria) {
public T withSubCriteria(List<AndOrCriteriaGroup> subCriteria) {
this.subCriteria.addAll(subCriteria);
return getThis();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 the original author or authors.
* Copyright 2016-2022 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.
Expand All @@ -19,4 +19,6 @@ public interface SqlCriterionVisitor<R> {
<T> R visit(ColumnAndConditionCriterion<T> criterion);

R visit(ExistsCriterion criterion);

R visit(CriteriaGroup criterion);
}
Loading

0 comments on commit b28ca54

Please sign in to comment.