mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-21 06:41:12 +00:00
#2847 - Add support for Sub-query EQ, NE, LT, LE, GT, GE expressions
This commit is contained in:
@@ -117,6 +117,11 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression arrayIsNotEmpty(String propertyName);
|
||||
|
||||
/**
|
||||
* Equal To the result of a sub-query.
|
||||
*/
|
||||
Expression eq(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
@@ -127,6 +132,11 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression eqOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Not Equal To the result of a sub-query.
|
||||
*/
|
||||
Expression ne(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
@@ -224,11 +234,21 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression geOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than the result of a sub-query.
|
||||
*/
|
||||
Expression gt(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
Expression gt(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to the result of a sub-query.
|
||||
*/
|
||||
Expression ge(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to - property greater than or equal to the given
|
||||
* value.
|
||||
@@ -251,11 +271,21 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression leOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than the result of a sub-query.
|
||||
*/
|
||||
Expression lt(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
Expression lt(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to the result of a sub-query.
|
||||
*/
|
||||
Expression le(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to - property less than or equal to the given value.
|
||||
*/
|
||||
|
||||
@@ -830,6 +830,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> addAll(ExpressionList<T> exprList);
|
||||
|
||||
/**
|
||||
* Equal To the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> eq(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Equal To - property is equal to a given value.
|
||||
*/
|
||||
@@ -854,6 +859,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> eqOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Not Equal To the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> ne(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
@@ -925,6 +935,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> gt(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
@@ -940,12 +955,22 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> geOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> ge(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to - property greater than or equal to the given
|
||||
* value.
|
||||
*/
|
||||
ExpressionList<T> ge(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> lt(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
@@ -961,6 +986,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> leOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> le(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to - property less than or equal to the given value.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -148,7 +148,7 @@ public class BaseQueryTuner {
|
||||
case UPDATE:
|
||||
case DELETE:
|
||||
case SQ_EXISTS:
|
||||
case SQ_IN:
|
||||
case SQ_EX:
|
||||
return false;
|
||||
default:
|
||||
// not using autoTune when explicitly loading the l2 bean cache
|
||||
|
||||
@@ -103,14 +103,14 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
|
||||
COUNT(FIND_COUNT, "findCount"),
|
||||
|
||||
/**
|
||||
* A subquery used as part of an exists where clause.
|
||||
* A sub-query used as part of an exists where clause.
|
||||
*/
|
||||
SQ_EXISTS(FIND_SUBQUERY, "sqExists", false, false),
|
||||
|
||||
/**
|
||||
* A subquery used as part of an in where clause.
|
||||
* A sub-query expression used as part of where clause.
|
||||
*/
|
||||
SQ_IN(FIND_SUBQUERY, "sqIn", false, false),
|
||||
SQ_EX(FIND_SUBQUERY, "sqEx", false, false),
|
||||
|
||||
/**
|
||||
* Delete query.
|
||||
|
||||
+35
-15
@@ -1,21 +1,11 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.ExampleExpression;
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.ExpressionFactory;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.Junction;
|
||||
import io.ebean.LikeType;
|
||||
import io.ebean.Pairs;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.*;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.search.Match;
|
||||
import io.ebean.search.MultiMatch;
|
||||
import io.ebean.search.TextCommonTerms;
|
||||
import io.ebean.search.TextQueryString;
|
||||
import io.ebean.search.TextSimple;
|
||||
import io.ebean.search.*;
|
||||
import io.ebeaninternal.api.SpiExpressionFactory;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.expression.SubQueryExpression.SQOp;
|
||||
import io.ebeaninternal.server.grammer.EqlParser;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -157,6 +147,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
EqlParser.parseWhere(expressions, list, this, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression eq(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.EQ, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
@@ -173,6 +168,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return or(eq(propertyName, value), isNull(propertyName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression ne(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.NE, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
@@ -258,6 +258,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new BetweenPropertyExpression(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression gt(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.GT, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
@@ -279,6 +284,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return or(ge(propertyName, value), isNull(propertyName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression ge(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.GE, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to - property greater than or equal to the given
|
||||
* value.
|
||||
@@ -301,6 +311,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return or(le(propertyName, value), isNull(propertyName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression lt(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.LT, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
@@ -309,6 +324,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new SimpleExpression(propertyName, Op.LT, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression le(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.LE, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than or Equal to - property less than or equal to the given value.
|
||||
*/
|
||||
@@ -465,7 +485,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression in(String propertyName, Query<?> subQuery) {
|
||||
return new InQueryExpression(propertyName, (SpiQuery<?>) subQuery, false);
|
||||
return new SubQueryExpression(SQOp.IN, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -507,7 +527,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression notIn(String propertyName, Query<?> subQuery) {
|
||||
return new InQueryExpression(propertyName, (SpiQuery<?>) subQuery, true);
|
||||
return new SubQueryExpression(SQOp.NOTIN, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+33
-6
@@ -788,6 +788,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.bitwiseAnd(propertyName, flags, match));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eq(String propertyName, Query<?> subQuery) {
|
||||
return add(expr.eq(propertyName, subQuery));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eq(String propertyName, Object value) {
|
||||
return add(expr.eq(propertyName, value));
|
||||
@@ -813,6 +818,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.ine(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ne(String propertyName, Query<?> subQuery) {
|
||||
return add(expr.ne(propertyName, subQuery));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ne(String propertyName, Object value) {
|
||||
return add(expr.ne(propertyName, value));
|
||||
@@ -863,10 +873,19 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.endsWith(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ge(String propertyName, Query<?> subQuery) {
|
||||
return add(expr.ge(propertyName, subQuery));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ge(String propertyName, Object value) {
|
||||
add(expr.ge(propertyName, value));
|
||||
return this;
|
||||
return add(expr.ge(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gt(String propertyName, Query<?> subQuery) {
|
||||
return add(expr.gt(propertyName, subQuery));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -876,14 +895,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gtOrNull(String propertyName, Object value) {
|
||||
add(expr.gtOrNull(propertyName, value));
|
||||
return this;
|
||||
return add(expr.gtOrNull(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> geOrNull(String propertyName, Object value) {
|
||||
add(expr.geOrNull(propertyName, value));
|
||||
return this;
|
||||
return add(expr.geOrNull(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -999,6 +1016,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.istartsWith(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> le(String propertyName, Query<?> subQuery) {
|
||||
return add(expr.le(propertyName, subQuery));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> le(String propertyName, Object value) {
|
||||
return add(expr.le(propertyName, value));
|
||||
@@ -1019,6 +1041,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.like(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> lt(String propertyName, Query<?> subQuery) {
|
||||
return add(expr.lt(propertyName, subQuery));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> lt(String propertyName, Object value) {
|
||||
return add(expr.lt(propertyName, value));
|
||||
|
||||
@@ -309,6 +309,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.endsWith(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eq(String propertyName, Query<?> subQuery) {
|
||||
return exprList.eq(propertyName, subQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eq(String propertyName, Object value) {
|
||||
return exprList.eq(propertyName, value);
|
||||
@@ -642,11 +647,21 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.bitwiseNot(propertyName, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ge(String propertyName, Query<?> subQuery) {
|
||||
return exprList.ge(propertyName, subQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ge(String propertyName, Object value) {
|
||||
return exprList.ge(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gt(String propertyName, Query<?> subQuery) {
|
||||
return exprList.gt(propertyName, subQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gt(String propertyName, Object value) {
|
||||
return exprList.gt(propertyName, value);
|
||||
@@ -787,6 +802,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.istartsWith(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> le(String propertyName, Query<?> subQuery) {
|
||||
return exprList.le(propertyName, subQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> le(String propertyName, Object value) {
|
||||
return exprList.le(propertyName, value);
|
||||
@@ -797,6 +817,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.like(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> lt(String propertyName, Query<?> subQuery) {
|
||||
return exprList.lt(propertyName, subQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> lt(String propertyName, Object value) {
|
||||
return exprList.lt(propertyName, value);
|
||||
@@ -812,6 +837,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.leOrNull(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ne(String propertyName, Query<?> subQuery) {
|
||||
return exprList.ne(propertyName, subQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ne(String propertyName, Object value) {
|
||||
return exprList.ne(propertyName, value);
|
||||
|
||||
+28
-19
@@ -8,32 +8,47 @@ import io.ebeaninternal.server.query.CQuery;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* In expression using a sub query.
|
||||
* Sub-Query expression.
|
||||
*/
|
||||
final class InQueryExpression extends AbstractExpression implements UnsupportedDocStoreExpression {
|
||||
final class SubQueryExpression extends AbstractExpression implements UnsupportedDocStoreExpression {
|
||||
|
||||
private final boolean not;
|
||||
enum SQOp {
|
||||
EQ(" = "),
|
||||
NE(" <> "),
|
||||
GT(" > "),
|
||||
GE(" >= "),
|
||||
LT(" < "),
|
||||
LE(" <= "),
|
||||
IN(" in "),
|
||||
NOTIN(" not in ");
|
||||
final String expression;
|
||||
SQOp(String expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
|
||||
private final SQOp op;
|
||||
private final SpiQuery<?> subQuery;
|
||||
private List<Object> bindParams;
|
||||
private String sql;
|
||||
|
||||
InQueryExpression(String propertyName, SpiQuery<?> subQuery, boolean not) {
|
||||
SubQueryExpression(SQOp op, String propertyName, SpiQuery<?> subQuery) {
|
||||
super(propertyName);
|
||||
this.op = op;
|
||||
this.subQuery = subQuery;
|
||||
this.not = not;
|
||||
}
|
||||
|
||||
InQueryExpression(String propertyName, boolean not, String sql, List<Object> bindParams) {
|
||||
SubQueryExpression(SQOp op, String propertyName, String sql, List<Object> bindParams) {
|
||||
super(propertyName);
|
||||
this.op = op;
|
||||
this.subQuery = null;
|
||||
this.not = not;
|
||||
this.sql = sql;
|
||||
this.bindParams = bindParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copy() {
|
||||
return subQuery == null ? this : new InQueryExpression(propName, subQuery.copy(), not);
|
||||
return subQuery == null ? this : new SubQueryExpression(op, propName, subQuery.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,8 +70,8 @@ final class InQueryExpression extends AbstractExpression implements UnsupportedD
|
||||
|
||||
@Override
|
||||
public void queryPlanHash(StringBuilder builder) {
|
||||
builder.append("InQuery[").append(propName)
|
||||
.append(" not:").append(not).append(" sql:").append(sql)
|
||||
builder.append("SubQuery[").append(propName).append(op.expression)
|
||||
.append(" sql:").append(sql)
|
||||
.append(" ?:").append(bindParams.size()).append("]");
|
||||
}
|
||||
|
||||
@@ -65,7 +80,7 @@ final class InQueryExpression extends AbstractExpression implements UnsupportedD
|
||||
*/
|
||||
private CQuery<?> compileSubQuery(BeanQueryRequest<?> queryRequest) {
|
||||
SpiEbeanServer ebeanServer = (SpiEbeanServer) queryRequest.database();
|
||||
return ebeanServer.compileQuery(Type.SQ_IN, subQuery, queryRequest.transaction());
|
||||
return ebeanServer.compileQuery(Type.SQ_EX, subQuery, queryRequest.transaction());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,13 +90,7 @@ final class InQueryExpression extends AbstractExpression implements UnsupportedD
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append(propName);
|
||||
if (not) {
|
||||
request.append(" not");
|
||||
}
|
||||
request.append(" in (");
|
||||
request.append(sql);
|
||||
request.append(")");
|
||||
request.append(propName).append(op.expression).append("(").append(sql).append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,7 +102,7 @@ final class InQueryExpression extends AbstractExpression implements UnsupportedD
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
InQueryExpression that = (InQueryExpression) other;
|
||||
SubQueryExpression that = (SubQueryExpression) other;
|
||||
if (this.bindParams.size() != that.bindParams.size()) {
|
||||
return false;
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public final class SqlTreeBuilder {
|
||||
this.disableLazyLoad = query.isDisableLazyLoading();
|
||||
this.readOnly = Boolean.TRUE.equals(query.isReadOnly());
|
||||
this.subQuery = Type.SQ_EXISTS == query.getType()
|
||||
|| Type.SQ_IN == query.getType()
|
||||
|| Type.SQ_EX == query.getType()
|
||||
|| Type.ID_LIST == query.getType()
|
||||
|| Type.DELETE == query.getType()
|
||||
|| query.isCountDistinct();
|
||||
|
||||
+5
-5
@@ -35,7 +35,7 @@ public class DefaultExpressionFactoryTest {
|
||||
public void testEq() {
|
||||
|
||||
DefaultExpressionFactory factory = new DefaultExpressionFactory(false, false);
|
||||
Expression expression = factory.eq("name", null);
|
||||
Expression expression = factory.eq("name", (String)null);
|
||||
assertThat(expression).isInstanceOf(NullExpression.class);
|
||||
assertThat(toQueryPlanHash(expression)).isEqualTo("Null[name]");
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class DefaultExpressionFactoryTest {
|
||||
public void testNe() {
|
||||
|
||||
DefaultExpressionFactory factory = new DefaultExpressionFactory(false, false);
|
||||
Expression expression = factory.ne("name", null);
|
||||
Expression expression = factory.ne("name", (String)null);
|
||||
assertThat(expression).isInstanceOf(NullExpression.class);
|
||||
assertThat(toQueryPlanHash(expression)).isEqualTo("NotNull[name]");
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public class DefaultExpressionFactoryTest {
|
||||
public void testEq_with_equalsWithNullAsNoop() {
|
||||
|
||||
DefaultExpressionFactory factory = new DefaultExpressionFactory(true, false);
|
||||
Expression expression = factory.eq("name", null);
|
||||
Expression expression = factory.eq("name", (String)null);
|
||||
assertThat(expression).isInstanceOf(NoopExpression.class);
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class DefaultExpressionFactoryTest {
|
||||
public void testNe_with_equalsWithNullAsNoop() {
|
||||
|
||||
DefaultExpressionFactory factory = new DefaultExpressionFactory(true, false);
|
||||
Expression expression = factory.ne("name", null);
|
||||
Expression expression = factory.ne("name", (String)null);
|
||||
assertThat(expression).isInstanceOf(NoopExpression.class);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class DefaultExpressionFactoryTest {
|
||||
public void testIeq_with_equalsWithNullAsNoop() {
|
||||
|
||||
DefaultExpressionFactory factory = new DefaultExpressionFactory(true, false);
|
||||
Expression expression = factory.ieq("name", null);
|
||||
Expression expression = factory.ieq("name", (String)null);
|
||||
assertThat(expression).isInstanceOf(NoopExpression.class);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -12,14 +12,15 @@ import static org.mockito.Mockito.verify;
|
||||
|
||||
public class InQueryExpressionTest extends BaseExpressionTest {
|
||||
|
||||
private InQueryExpression exp(String propertyName, boolean not, String sql, Object... bindValues) {
|
||||
return new InQueryExpression(propertyName, not, sql, Arrays.asList(bindValues));
|
||||
private SubQueryExpression exp(String propertyName, boolean not, String sql, Object... bindValues) {
|
||||
var op = not ? SubQueryExpression.SQOp.NOTIN : SubQueryExpression.SQOp.IN;
|
||||
return new SubQueryExpression(op, propertyName, sql, Arrays.asList(bindValues));
|
||||
}
|
||||
|
||||
@Test
|
||||
void copy_subQuery_expectNewInstance() {
|
||||
SpiQuery<?> subQuery = mock(SpiQuery.class);
|
||||
var orig = new InQueryExpression("name", subQuery, false);
|
||||
var orig = new SubQueryExpression(SubQueryExpression.SQOp.IN, "name", subQuery);
|
||||
SpiExpression copy = orig.copy();
|
||||
assertThat(copy).isNotSameAs(orig);
|
||||
verify(subQuery).copy();
|
||||
|
||||
@@ -27,9 +27,9 @@ public class NoopExpressionTest extends BaseExpressionTest {
|
||||
initTables();
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.select("id")
|
||||
.where().eq("name", null)
|
||||
.where().eq("name", (String) null)
|
||||
.add(NoopExpression.INSTANCE)
|
||||
.ne("status", null)
|
||||
.ne("status", (String) null)
|
||||
.query();
|
||||
|
||||
query.findList();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.ebean.typequery;
|
||||
|
||||
|
||||
import io.ebean.Query;
|
||||
|
||||
/**
|
||||
* Base property for all comparable types.
|
||||
*
|
||||
@@ -301,4 +303,47 @@ public class PBaseCompareable<R, T> extends PBaseValueEqual<R, T> {
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property is Less Than or Equal To the result of a sub-query.
|
||||
*
|
||||
* @param subQuery value provided by a subQuery
|
||||
* @return the root query bean instance
|
||||
*/
|
||||
public final R le(Query<?> subQuery) {
|
||||
expr().le(_name, subQuery);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property is Less Than the result of a sub-query.
|
||||
*
|
||||
* @param subQuery value provided by a subQuery
|
||||
* @return the root query bean instance
|
||||
*/
|
||||
public final R lt(Query<?> subQuery) {
|
||||
expr().lt(_name, subQuery);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property is Greater Than or Equal To the result of a sub-query.
|
||||
*
|
||||
* @param subQuery value provided by a subQuery
|
||||
* @return the root query bean instance
|
||||
*/
|
||||
public final R ge(Query<?> subQuery) {
|
||||
expr().ge(_name, subQuery);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property is Greater Than the result of a sub-query.
|
||||
*
|
||||
* @param subQuery value provided by a subQuery
|
||||
* @return the root query bean instance
|
||||
*/
|
||||
public final R gt(Query<?> subQuery) {
|
||||
expr().gt(_name, subQuery);
|
||||
return _root;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ public abstract class PBaseValueEqual<R, T> extends TQPropertyBase<R> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Is in the result of a subquery. Synonym for in().
|
||||
* Is in the result of a sub-query. Synonym for in().
|
||||
*
|
||||
* @param subQuery values provided by a subQuery
|
||||
* @return the root query bean instance
|
||||
@@ -291,7 +291,7 @@ public abstract class PBaseValueEqual<R, T> extends TQPropertyBase<R> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Is NOT in the result of a subquery.
|
||||
* Is NOT in the result of a sub-query.
|
||||
*
|
||||
* @param subQuery values provided by a subQuery
|
||||
* @return the root query bean instance
|
||||
@@ -300,4 +300,26 @@ public abstract class PBaseValueEqual<R, T> extends TQPropertyBase<R> {
|
||||
expr().notIn(_name, subQuery);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property is equal to the result of a sub-query.
|
||||
*
|
||||
* @param subQuery value provided by a subQuery
|
||||
* @return the root query bean instance
|
||||
*/
|
||||
public final R eq(Query<?> subQuery) {
|
||||
expr().eq(_name, subQuery);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property is not equal to the result of a sub-query.
|
||||
*
|
||||
* @param subQuery value provided by a subQuery
|
||||
* @return the root query bean instance
|
||||
*/
|
||||
public final R ne(Query<?> subQuery) {
|
||||
expr().ne(_name, subQuery);
|
||||
return _root;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.ebean.DB;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.typequery.TQProperty;
|
||||
import org.example.domain.Customer;
|
||||
import org.example.domain.Order;
|
||||
import org.example.domain.OrderDetail;
|
||||
@@ -217,6 +218,96 @@ public class QOrderTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void geSubQuery() {
|
||||
var subQuery = new QOrder()
|
||||
.select(StdFunctions.max(QOrder.Alias.orderDate))
|
||||
.query();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(QCustomer.Alias.id)
|
||||
.registered.ge(subQuery)
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered >= (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void gtSubQuery() {
|
||||
var subQuery = new QOrder()
|
||||
.select("max(orderDate)")
|
||||
.query();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(QCustomer.Alias.id)
|
||||
.registered.gt(subQuery)
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered > (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void leSubQuery() {
|
||||
var subQuery = new QOrder()
|
||||
.select("max(orderDate)")
|
||||
.query();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(QCustomer.Alias.id)
|
||||
.registered.le(subQuery)
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered <= (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void ltSubQuery() {
|
||||
var subQuery = new QOrder()
|
||||
.select("max(orderDate)")
|
||||
.query();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(QCustomer.Alias.id)
|
||||
.registered.lt(subQuery)
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered < (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void eqSubQuery() {
|
||||
var subQuery = new QOrder()
|
||||
.select("max(orderDate)")
|
||||
.query();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(QCustomer.Alias.id)
|
||||
.registered.eq(subQuery)
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered = (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void neSubQuery() {
|
||||
var subQuery = new QOrder()
|
||||
.select(StdFunctions.max(QOrder.Alias.orderDate))
|
||||
.query();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(QCustomer.Alias.id)
|
||||
.registered.ne(subQuery)
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered <> (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void propertyCompare() {
|
||||
Query<Order> query = new QOrder()
|
||||
@@ -283,4 +374,10 @@ public class QOrderTest {
|
||||
order.setCustomer(customer);
|
||||
order.save();
|
||||
}
|
||||
|
||||
static class StdFunctions {
|
||||
static String max(TQProperty<?> prop) {
|
||||
return "max(" + prop + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class TestQueryIsNull extends BaseTestCase {
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Order> query = DB.find(Order.class).select("id, status")
|
||||
.where().eq("status", null).query();
|
||||
.where().eq("status", (String) null).query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).isEqualTo("select t0.id, t0.status from o_order t0 where t0.status is null");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
@@ -19,13 +19,13 @@ public class TestQueryNullAssocOne extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Order> q0 = DB.find(Order.class).where().eq("customer", null).query();
|
||||
Query<Order> q0 = DB.find(Order.class).where().eq("customer", (String) null).query();
|
||||
|
||||
List<Order> orders = q0.findList();
|
||||
assertNotNull(orders);
|
||||
assertTrue(q0.getGeneratedSql().contains("where t0.kcustomer_id is null"));
|
||||
|
||||
Query<Order> q1 = DB.find(Order.class).where().eq("customer.id", null).query();
|
||||
Query<Order> q1 = DB.find(Order.class).where().eq("customer.id", (String) null).query();
|
||||
|
||||
List<Order> o1 = q1.findList();
|
||||
assertTrue(o1.size() == orders.size());
|
||||
|
||||
@@ -38,7 +38,7 @@ public class TestSelfParent extends BaseTestCase {
|
||||
DB.save(child21);
|
||||
DB.save(child22);
|
||||
|
||||
List<SelfParent> roots = DB.find(SelfParent.class).where().eq("parent", null).findList();
|
||||
List<SelfParent> roots = DB.find(SelfParent.class).where().eq("parent", (String) null).findList();
|
||||
|
||||
assertEquals(1, roots.size());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user