diff --git a/ebean-api/src/main/java/io/ebean/ExpressionFactory.java b/ebean-api/src/main/java/io/ebean/ExpressionFactory.java index 3bcd5cb39..d8f047908 100644 --- a/ebean-api/src/main/java/io/ebean/ExpressionFactory.java +++ b/ebean-api/src/main/java/io/ebean/ExpressionFactory.java @@ -181,6 +181,23 @@ public interface ExpressionFactory { */ Expression inRangeWith(String lowProperty, String highProperty, Object value); + /** + * A Property is in Range between 2 properties. + * + *
{@code
+   *
+   *    .orderDate.inRangeWith(QOrder.Alias.product.startDate, QOrder.Alias.product.endDate)
+   *
+   *    // which equates to
+   *    product.startDate <= orderDate and (orderDate < product.endDate or product.endDate is null)
+   *
+   * }
+ * + *

+ * This is a convenience expression combining a number of simple expressions. + */ + Expression inRangeWithProperties(String propertyName, String lowProperty, String highProperty); + /** * Between - property between the two given values. */ diff --git a/ebean-api/src/main/java/io/ebean/ExpressionList.java b/ebean-api/src/main/java/io/ebean/ExpressionList.java index 00f61a798..74426fe95 100644 --- a/ebean-api/src/main/java/io/ebean/ExpressionList.java +++ b/ebean-api/src/main/java/io/ebean/ExpressionList.java @@ -890,6 +890,23 @@ public interface ExpressionList { */ ExpressionList inRangeWith(String lowProperty, String highProperty, Object value); + /** + * A Property is in Range between 2 properties. + * + *

{@code
+   *
+   *    .orderDate.inRangeWith(QOrder.Alias.product.startDate, QOrder.Alias.product.endDate)
+   *
+   *    // which equates to
+   *    product.startDate <= orderDate and (orderDate < product.endDate or product.endDate is null)
+   *
+   * }
+ * + *

+ * This is a convenience expression combining a number of simple expressions. + */ + ExpressionList inRangeWithProperties(String propertyName, String lowProperty, String highProperty); + /** * In Range - {@code property >= value1 and property < value2}. *

diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionFactory.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionFactory.java index 81f434762..9ce606961 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionFactory.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionFactory.java @@ -237,6 +237,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory { return and(le(lowProperty, value), gtOrNull(highProperty, value)); } + @Override + public Expression inRangeWithProperties(String propertyName, String lowProperty, String highProperty) { + return raw(lowProperty + " <= " + propertyName + " and (" + propertyName + " < " + highProperty + " or " + highProperty + " is null)"); + } + /** * Between - property between the two given values. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionList.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionList.java index 234fd28c2..408cdc4b8 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionList.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/DefaultExpressionList.java @@ -833,6 +833,11 @@ public class DefaultExpressionList implements SpiExpressionList { return add(expr.inRangeWith(lowProperty, highProperty, value)); } + @Override + public ExpressionList inRangeWithProperties(String propertyName, String lowProperty, String highProperty) { + return add(expr.inRangeWithProperties(propertyName, lowProperty, highProperty)); + } + @Override public ExpressionList inRange(String propertyName, Object value1, Object value2) { return add(expr.inRange(propertyName, value1, value2)); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/JunctionExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/JunctionExpression.java index 5bc19ca10..d3f968c22 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/JunctionExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/JunctionExpression.java @@ -279,6 +279,11 @@ final class JunctionExpression implements SpiJunction, SpiExpression, Expr return exprList.inRangeWith(lowProperty, highProperty, value); } + @Override + public ExpressionList inRangeWithProperties(String propertyName, String lowProperty, String highProperty) { + return exprList.inRangeWithProperties(propertyName, lowProperty, highProperty); + } + @Override public ExpressionList inRange(String propertyName, Object value1, Object value2) { return exprList.inRange(propertyName, value1, value2); diff --git a/ebean-querybean/src/main/java/io/ebean/typequery/PBaseCompareable.java b/ebean-querybean/src/main/java/io/ebean/typequery/PBaseCompareable.java index 466093ac2..75b279619 100644 --- a/ebean-querybean/src/main/java/io/ebean/typequery/PBaseCompareable.java +++ b/ebean-querybean/src/main/java/io/ebean/typequery/PBaseCompareable.java @@ -200,6 +200,29 @@ public class PBaseCompareable extends PBaseValueEqual { return _root; } + /** + * A Property is in Range between 2 other properties. + * + *

{@code
+   *  var o = QOrder.alias();
+   *
+   *  new QOrder()
+   *    .orderDate.inRangeWith(o.product.startDate, o.product.endDate)
+   *    .findList();
+   *
+   *    // which equates to
+   *    product.startDate <= orderDate and (product.endDate > orderDate or product.endDate is null)
+   *
+   * }
+ * + *

+ * This is a convenience expression combining a number of simple expressions. + */ + public final R inRangeWith(TQProperty lowProperty, TQProperty highProperty) { + expr().inRangeWithProperties(_name, lowProperty.propertyName(), highProperty.propertyName()); + return _root; + } + /** * Between lower and upper values. * diff --git a/ebean-querybean/src/test/java/org/querytest/QCustomerTest.java b/ebean-querybean/src/test/java/org/querytest/QCustomerTest.java index 18cb0dfc7..2db089274 100644 --- a/ebean-querybean/src/test/java/org/querytest/QCustomerTest.java +++ b/ebean-querybean/src/test/java/org/querytest/QCustomerTest.java @@ -665,6 +665,22 @@ public class QCustomerTest { .findList(); } + @Test + void query_inRangeWithOtherProperties() { + var c = QCustomer.alias(); + + Query query = new QCustomer() + .select(c.id) + .name.inRangeWith(c.contacts.firstName, c.contacts.lastName) + .query(); + + // select distinct t0.id from be_customer t0 + // left join be_contact t1 on t1.customer_id = t0.id + // where t1.first_name <= t0.name and (t0.name < t1.last_name or t1.last_name is null) + query.findList(); + assertThat(query.getGeneratedSql()).contains(" where t1.first_name <= t0.name and (t0.name < t1.last_name or t1.last_name is null)"); + } + @Test public void query_exists() {