diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelectBuilder.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelectBuilder.java index 49ff3a2a0..6e590eae1 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelectBuilder.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelectBuilder.java @@ -325,6 +325,18 @@ class DefaultSelectBuilder implements SelectBuilder, SelectAndFrom, SelectFromAn return this; } + @Override + public SelectFromAndJoinCondition on(Condition condition) { + + if (this.condition == null) { + this.condition = condition; + } else { + this.condition = this.condition.and(condition); + } + + return this; + } + /* * (non-Javadoc) * @see org.springframework.data.relational.core.sql.SelectBuilder.SelectOnConditionComparison#equals(org.springframework.data.relational.core.sql.Expression) @@ -348,6 +360,12 @@ class DefaultSelectBuilder implements SelectBuilder, SelectAndFrom, SelectFromAn } private void finishCondition() { + + // Nothing to do if a complete join condition was used. + if (from == null && to == null) { + return; + } + Comparison comparison = Comparison.create(from, "=", to); if (condition == null) { diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SelectBuilder.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SelectBuilder.java index edb7b8fbe..0b701f72f 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SelectBuilder.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SelectBuilder.java @@ -501,6 +501,17 @@ public interface SelectBuilder { * @see Table#column(String) */ SelectOnConditionComparison on(Expression column); + + /** + * Declare a join condition in one step. + * + * Using conditions allows more flexibility in comparison to {@link #on(Expression)} which only allows for equality comparisons chained together with `AND`. + * + * @param condition must not be {@literal null}. + * @return {@code this} builder. + * @see Conditions + */ + SelectFromAndJoinCondition on(Condition condition); } /** diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/SelectRendererUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/SelectRendererUnitTests.java index 0394d4bab..c28f0087d 100644 --- a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/SelectRendererUnitTests.java +++ b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/SelectRendererUnitTests.java @@ -156,6 +156,28 @@ class SelectRendererUnitTests { + "AND employee.tenant = department.tenant"); } + @Test // GH-995 + public void shouldRenderArbitraryJoinCondition() { + + Table employee = SQL.table("employee"); + Table department = SQL.table("department"); + + Select select = Select.builder() // + .select(employee.column("id"), department.column("name")) // + .from(employee) // + .join(department) // + .on( + Conditions.isEqual( employee.column("department_id"),department.column("id")) // + .or( // + Conditions.isNotEqual( employee.column("tenant"),department.column("tenant")) // + )) // + .build(); + + assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT employee.id, department.name FROM employee " // + + "JOIN department ON employee.department_id = department.id " // + + "OR employee.tenant != department.tenant"); + } + @Test // DATAJDBC-309 void shouldRenderMultipleJoinWithAnd() {