Skip to content

Commit

Permalink
Merge pull request #842 from jeffgbutler/new-join-syntax
Browse files Browse the repository at this point in the history
Add new flexible syntax for coding join specifications
  • Loading branch information
jeffgbutler committed Aug 19, 2024
2 parents 3057702 + 0f1ad9c commit e89fd77
Show file tree
Hide file tree
Showing 31 changed files with 2,605 additions and 639 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ Other important changes:
With this change, the exception thrown is more predictable and the error is caught before sending the SQL to the
database.
- All the paging methods (limit, offset, fetchFirst) now have "WhenPresent" variations that will drop the phrase from
rendering if a null value is passed in
rendering if a null value is passed in
- The JOIN syntax is updated and now allows full boolean expressions like a WHERE clause. The prior JOIN syntax
is deprecated and will be removed in a future release.

## Release 1.5.2 - June 3, 2024

Expand Down
50 changes: 27 additions & 23 deletions src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@
import org.mybatis.dynamic.sql.select.function.Substring;
import org.mybatis.dynamic.sql.select.function.Subtract;
import org.mybatis.dynamic.sql.select.function.Upper;
import org.mybatis.dynamic.sql.select.join.EqualTo;
import org.mybatis.dynamic.sql.select.join.EqualToValue;
import org.mybatis.dynamic.sql.select.join.JoinCondition;
import org.mybatis.dynamic.sql.select.join.JoinCriterion;
import org.mybatis.dynamic.sql.update.UpdateDSL;
import org.mybatis.dynamic.sql.update.UpdateModel;
import org.mybatis.dynamic.sql.util.Buildable;
Expand Down Expand Up @@ -433,20 +429,36 @@ static AndOrCriteriaGroup and(List<AndOrCriteriaGroup> subCriteria) {
}

// join support
static <T> JoinCriterion<T> and(BindableColumn<T> joinColumn, JoinCondition<T> joinCondition) {
return new JoinCriterion.Builder<T>()
.withConnector("and") //$NON-NLS-1$
.withJoinColumn(joinColumn)
.withJoinCondition(joinCondition)
static <T> ColumnAndConditionCriterion<T> on(BindableColumn<T> joinColumn, VisitableCondition<T> joinCondition) {
return ColumnAndConditionCriterion.withColumn(joinColumn)
.withCondition(joinCondition)
.build();
}

static <T> JoinCriterion<T> on(BindableColumn<T> joinColumn, JoinCondition<T> joinCondition) {
return new JoinCriterion.Builder<T>()
.withConnector("on") //$NON-NLS-1$
.withJoinColumn(joinColumn)
.withJoinCondition(joinCondition)
.build();
/**
* Starting in version 2.0.0, this function is a synonym for {@link SqlBuilder#isEqualTo(BasicColumn)}.
*
* @param column the column
* @param <T> the column type
* @return an IsEqualToColumn condition
* @deprecated since 2.0.0. Please replace with isEqualTo(column)
*/
@Deprecated(since = "2.0.0", forRemoval = true)
static <T> IsEqualToColumn<T> equalTo(BindableColumn<T> column) {
return isEqualTo(column);
}

/**
* Starting in version 2.0.0, this function is a synonym for {@link SqlBuilder#isEqualTo(Object)}.
*
* @param value the value
* @param <T> the column type
* @return an IsEqualTo condition
* @deprecated since 2.0.0. Please replace with isEqualTo(value)
*/
@Deprecated(since = "2.0.0", forRemoval = true)
static <T> IsEqualTo<T> equalTo(T value) {
return isEqualTo(value);
}

// case expressions
Expand All @@ -460,14 +472,6 @@ static SearchedCaseDSL case_() {
return SearchedCaseDSL.searchedCase();
}

static <T> EqualTo<T> equalTo(BindableColumn<T> column) {
return new EqualTo<>(column);
}

static <T> EqualToValue<T> equalTo(T value) {
return new EqualToValue<>(value);
}

// aggregate support
static CountAll count() {
return new CountAll();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/mybatis/dynamic/sql/delete/DeleteDSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
import org.mybatis.dynamic.sql.where.AbstractWhereStarter;
import org.mybatis.dynamic.sql.where.EmbeddedWhereModel;

public class DeleteDSL<R> extends AbstractWhereStarter<DeleteDSL<R>.DeleteWhereBuilder, DeleteDSL<R>>
implements Buildable<R> {
public class DeleteDSL<R> implements AbstractWhereStarter<DeleteDSL<R>.DeleteWhereBuilder, DeleteDSL<R>>,
Buildable<R> {

private final Function<DeleteModel, R> adapterFunction;
private final SqlTable table;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;

import org.mybatis.dynamic.sql.AndOrCriteriaGroup;
import org.mybatis.dynamic.sql.SqlCriterion;
import org.mybatis.dynamic.sql.SqlTable;
import org.mybatis.dynamic.sql.TableExpression;
import org.mybatis.dynamic.sql.exception.DuplicateTableAliasException;
import org.mybatis.dynamic.sql.select.join.JoinCriterion;
import org.mybatis.dynamic.sql.select.join.JoinModel;
import org.mybatis.dynamic.sql.select.join.JoinSpecification;
import org.mybatis.dynamic.sql.select.join.JoinType;
Expand All @@ -37,9 +39,9 @@

public abstract class AbstractQueryExpressionDSL<W extends AbstractWhereFinisher<?>,
T extends AbstractQueryExpressionDSL<W, T>>
extends AbstractWhereStarter<W, T> {
implements AbstractWhereStarter<W, T> {

private final List<JoinSpecification.Builder> joinSpecificationBuilders = new ArrayList<>();
private final List<Supplier<JoinSpecification>> joinSpecificationSuppliers = new ArrayList<>();
private final Map<SqlTable, String> tableAliases = new HashMap<>();
private final TableExpression table;

Expand All @@ -51,151 +53,151 @@ public TableExpression table() {
return table;
}

public T join(SqlTable joinTable, JoinCriterion<?> onJoinCriterion,
JoinCriterion<?>... andJoinCriteria) {
addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.INNER, Arrays.asList(andJoinCriteria));
public T join(SqlTable joinTable, SqlCriterion onJoinCriterion,
AndOrCriteriaGroup... andJoinCriteria) {
addJoinSpecificationSupplier(joinTable, onJoinCriterion, JoinType.INNER, Arrays.asList(andJoinCriteria));
return getThis();
}

public T join(SqlTable joinTable, String tableAlias, JoinCriterion<?> onJoinCriterion,
JoinCriterion<?>... andJoinCriteria) {
public T join(SqlTable joinTable, String tableAlias, SqlCriterion onJoinCriterion,
AndOrCriteriaGroup... andJoinCriteria) {
addTableAlias(joinTable, tableAlias);
return join(joinTable, onJoinCriterion, andJoinCriteria);
}

public T join(SqlTable joinTable, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.INNER, andJoinCriteria);
public T join(SqlTable joinTable, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addJoinSpecificationSupplier(joinTable, onJoinCriterion, JoinType.INNER, andJoinCriteria);
return getThis();
}

public T join(SqlTable joinTable, String tableAlias, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
public T join(SqlTable joinTable, String tableAlias, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addTableAlias(joinTable, tableAlias);
return join(joinTable, onJoinCriterion, andJoinCriteria);
}

public T join(Buildable<SelectModel> subQuery, String tableAlias, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
addJoinSpecificationBuilder(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.INNER,
public T join(Buildable<SelectModel> subQuery, String tableAlias, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addJoinSpecificationSupplier(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.INNER,
andJoinCriteria);
return getThis();
}

public T leftJoin(SqlTable joinTable, JoinCriterion<?> onJoinCriterion,
JoinCriterion<?>... andJoinCriteria) {
addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.LEFT, Arrays.asList(andJoinCriteria));
public T leftJoin(SqlTable joinTable, SqlCriterion onJoinCriterion,
AndOrCriteriaGroup... andJoinCriteria) {
addJoinSpecificationSupplier(joinTable, onJoinCriterion, JoinType.LEFT, Arrays.asList(andJoinCriteria));
return getThis();
}

public T leftJoin(SqlTable joinTable, String tableAlias, JoinCriterion<?> onJoinCriterion,
JoinCriterion<?>... andJoinCriteria) {
public T leftJoin(SqlTable joinTable, String tableAlias, SqlCriterion onJoinCriterion,
AndOrCriteriaGroup... andJoinCriteria) {
addTableAlias(joinTable, tableAlias);
return leftJoin(joinTable, onJoinCriterion, andJoinCriteria);
}

public T leftJoin(SqlTable joinTable, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.LEFT, andJoinCriteria);
public T leftJoin(SqlTable joinTable, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addJoinSpecificationSupplier(joinTable, onJoinCriterion, JoinType.LEFT, andJoinCriteria);
return getThis();
}

public T leftJoin(SqlTable joinTable, String tableAlias, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
public T leftJoin(SqlTable joinTable, String tableAlias, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addTableAlias(joinTable, tableAlias);
return leftJoin(joinTable, onJoinCriterion, andJoinCriteria);
}

public T leftJoin(Buildable<SelectModel> subQuery, String tableAlias, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
addJoinSpecificationBuilder(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.LEFT,
public T leftJoin(Buildable<SelectModel> subQuery, String tableAlias, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addJoinSpecificationSupplier(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.LEFT,
andJoinCriteria);
return getThis();
}

public T rightJoin(SqlTable joinTable, JoinCriterion<?> onJoinCriterion,
JoinCriterion<?>... andJoinCriteria) {
addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.RIGHT, Arrays.asList(andJoinCriteria));
public T rightJoin(SqlTable joinTable, SqlCriterion onJoinCriterion,
AndOrCriteriaGroup... andJoinCriteria) {
addJoinSpecificationSupplier(joinTable, onJoinCriterion, JoinType.RIGHT, Arrays.asList(andJoinCriteria));
return getThis();
}

public T rightJoin(SqlTable joinTable, String tableAlias, JoinCriterion<?> onJoinCriterion,
JoinCriterion<?>... andJoinCriteria) {
public T rightJoin(SqlTable joinTable, String tableAlias, SqlCriterion onJoinCriterion,
AndOrCriteriaGroup... andJoinCriteria) {
addTableAlias(joinTable, tableAlias);
return rightJoin(joinTable, onJoinCriterion, andJoinCriteria);
}

public T rightJoin(SqlTable joinTable, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.RIGHT, andJoinCriteria);
public T rightJoin(SqlTable joinTable, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addJoinSpecificationSupplier(joinTable, onJoinCriterion, JoinType.RIGHT, andJoinCriteria);
return getThis();
}

public T rightJoin(SqlTable joinTable, String tableAlias, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
public T rightJoin(SqlTable joinTable, String tableAlias, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addTableAlias(joinTable, tableAlias);
return rightJoin(joinTable, onJoinCriterion, andJoinCriteria);
}

public T rightJoin(Buildable<SelectModel> subQuery, String tableAlias, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
addJoinSpecificationBuilder(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.RIGHT,
public T rightJoin(Buildable<SelectModel> subQuery, String tableAlias, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addJoinSpecificationSupplier(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.RIGHT,
andJoinCriteria);
return getThis();
}

public T fullJoin(SqlTable joinTable, JoinCriterion<?> onJoinCriterion,
JoinCriterion<?>... andJoinCriteria) {
addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.FULL, Arrays.asList(andJoinCriteria));
public T fullJoin(SqlTable joinTable, SqlCriterion onJoinCriterion,
AndOrCriteriaGroup... andJoinCriteria) {
addJoinSpecificationSupplier(joinTable, onJoinCriterion, JoinType.FULL, Arrays.asList(andJoinCriteria));
return getThis();
}

public T fullJoin(SqlTable joinTable, String tableAlias, JoinCriterion<?> onJoinCriterion,
JoinCriterion<?>... andJoinCriteria) {
public T fullJoin(SqlTable joinTable, String tableAlias, SqlCriterion onJoinCriterion,
AndOrCriteriaGroup... andJoinCriteria) {
addTableAlias(joinTable, tableAlias);
return fullJoin(joinTable, onJoinCriterion, andJoinCriteria);
}

public T fullJoin(SqlTable joinTable, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
addJoinSpecificationBuilder(joinTable, onJoinCriterion, JoinType.FULL, andJoinCriteria);
public T fullJoin(SqlTable joinTable, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addJoinSpecificationSupplier(joinTable, onJoinCriterion, JoinType.FULL, andJoinCriteria);
return getThis();
}

public T fullJoin(SqlTable joinTable, String tableAlias, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
public T fullJoin(SqlTable joinTable, String tableAlias, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addTableAlias(joinTable, tableAlias);
return fullJoin(joinTable, onJoinCriterion, andJoinCriteria);
}

public T fullJoin(Buildable<SelectModel> subQuery, String tableAlias, JoinCriterion<?> onJoinCriterion,
List<JoinCriterion<?>> andJoinCriteria) {
addJoinSpecificationBuilder(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.FULL,
public T fullJoin(Buildable<SelectModel> subQuery, String tableAlias, SqlCriterion onJoinCriterion,
List<AndOrCriteriaGroup> andJoinCriteria) {
addJoinSpecificationSupplier(buildSubQuery(subQuery, tableAlias), onJoinCriterion, JoinType.FULL,
andJoinCriteria);
return getThis();
}

private void addJoinSpecificationBuilder(TableExpression joinTable, JoinCriterion<?> onJoinCriterion,
JoinType joinType, List<JoinCriterion<?>> andJoinCriteria) {
joinSpecificationBuilders.add(new JoinSpecification.Builder()
private void addJoinSpecificationSupplier(TableExpression joinTable, SqlCriterion onJoinCriterion,
JoinType joinType, List<AndOrCriteriaGroup> andJoinCriteria) {
joinSpecificationSuppliers.add(() -> new JoinSpecification.Builder()
.withJoinTable(joinTable)
.withJoinType(joinType)
.withJoinCriterion(onJoinCriterion)
.withJoinCriteria(andJoinCriteria));
.withInitialCriterion(onJoinCriterion)
.withSubCriteria(andJoinCriteria).build());
}

protected void addJoinSpecificationBuilder(JoinSpecification.Builder builder) {
joinSpecificationBuilders.add(builder);
protected void addJoinSpecificationSupplier(Supplier<JoinSpecification> joinSpecificationSupplier) {
joinSpecificationSuppliers.add(joinSpecificationSupplier);
}

protected Optional<JoinModel> buildJoinModel() {
if (joinSpecificationBuilders.isEmpty()) {
if (joinSpecificationSuppliers.isEmpty()) {
return Optional.empty();
}

return Optional.of(JoinModel.of(joinSpecificationBuilders.stream()
.map(JoinSpecification.Builder::build)
.toList()));
return Optional.of(JoinModel.of(joinSpecificationSuppliers.stream()
.map(Supplier::get)
.toList()));
}

protected void addTableAlias(SqlTable table, String tableAlias) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public OffsetFirstFinisher<MultiSelectModel> offsetWhenPresent(Long offset) {
@Override
public FetchFirstFinisher<MultiSelectModel> fetchFirstWhenPresent(Long fetchFirstRows) {
this.fetchFirstRows = fetchFirstRows;
return () -> MultiSelectDSL.this;
return () -> this;
}

@NotNull
Expand Down
Loading

0 comments on commit e89fd77

Please sign in to comment.