Skip to content

Add new flexible syntax for coding join specifications #842

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 11 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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