From 82c70ab99f95709334fdc5455e23a38c3255aab6 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 22 Jul 2021 09:25:35 +0200 Subject: [PATCH] Allow for arbitrary conditions as join condition. Closes #995. Original pull request: #1014. --- .../core/sql/DefaultSelectBuilder.java | 18 +++++++++++++++ .../relational/core/sql/SelectBuilder.java | 11 ++++++++++ .../sql/render/SelectRendererUnitTests.java | 22 +++++++++++++++++++ 3 files changed, 51 insertions(+) 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 49ff3a2a..6e590eae 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 edb7b8fb..0b701f72 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 0394d4ba..c28f0087 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() {