mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Add more operators to StdOperators
- stricter use of UpdateQuery.set() - Numbers just use their own type - PBaseNumber - PEnum just uses its own type - Expr.factory() to expose factory
This commit is contained in:
@@ -30,6 +30,13 @@ public final class Expr {
|
||||
private Expr() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying expression factory.
|
||||
*/
|
||||
public static ExpressionFactory factory() {
|
||||
return DB.expressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
|
||||
@@ -1773,16 +1773,16 @@ public interface Query<T> extends CancelableQuery {
|
||||
* <p>
|
||||
* Implemented by query bean properties and expressions based on those properties.
|
||||
* <p>
|
||||
* The base type determines which {@link StdFunctions} can be used on the property.
|
||||
* The base type determines which {@link StdOperators} can be used on the property.
|
||||
*
|
||||
* @param <BT> The base type of the property Number, String, Temporal, Boolean or Object.
|
||||
* @param <T> The property type.
|
||||
*/
|
||||
interface Property<BT> {
|
||||
interface Property<T> {
|
||||
|
||||
/**
|
||||
* Return a property given the expression.
|
||||
*/
|
||||
static <BT> Property<BT> of(String expression) {
|
||||
static <T> Property<T> of(String expression) {
|
||||
return new SimpleProperty<>(expression);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.Query.Property;
|
||||
|
||||
import java.time.temporal.Temporal;
|
||||
|
||||
public final class StdFunctions {
|
||||
|
||||
public static Property<Number> count(Property<?> property) {
|
||||
return Property.of("count(" + property + ")");
|
||||
}
|
||||
|
||||
public static Property<Number> sum(Property<Number> property) {
|
||||
return Property.of("sum(" + property + ")");
|
||||
}
|
||||
|
||||
public static <BT> Property<BT> avg(Property<BT> property) {
|
||||
return Property.of("avg(" + property + ")");
|
||||
}
|
||||
|
||||
public static <BT> Property<BT> max(Property<BT> property) {
|
||||
return Property.of("max(" + property + ")");
|
||||
}
|
||||
|
||||
public static <BT> Property<BT> min(Property<BT> property) {
|
||||
return Property.of("min(" + property + ")");
|
||||
}
|
||||
|
||||
public static <BT> Property<BT> coalesce(Property<BT> property, Object value) {
|
||||
return Property.of("coalesce(" + property.toString() + "," + sqlValue(value) + ")");
|
||||
}
|
||||
|
||||
public static Property<String> lower(Property<String> property) {
|
||||
return Property.of("lower(" + property + ")");
|
||||
}
|
||||
|
||||
public static Property<String> upper(Property<String> property) {
|
||||
return Property.of("upper(" + property + ")");
|
||||
}
|
||||
|
||||
public static Property<String> concat(Property<?> property, Object... values) {
|
||||
StringBuilder expression = new StringBuilder(50);
|
||||
expression.append("concat(").append(property.toString());
|
||||
for (Object value : values) {
|
||||
expression.append(",").append(sqlConcatString(value));
|
||||
}
|
||||
expression.append(")");
|
||||
return Property.of(expression.toString());
|
||||
}
|
||||
|
||||
private static String sqlConcatString(Object value) {
|
||||
String asStr = String.valueOf(value);
|
||||
return (value instanceof Property || isSqlQuoted(asStr)) ? asStr : "'" + value + "'";
|
||||
}
|
||||
|
||||
private static boolean isSqlQuoted(String asStr) {
|
||||
return asStr.length() > 0 && asStr.charAt(0) == '\'';
|
||||
}
|
||||
|
||||
private static String sqlValue(Object value) {
|
||||
if (value instanceof Property || value instanceof Number) {
|
||||
return value.toString();
|
||||
} else {
|
||||
return "'" + value + "'";
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------- //
|
||||
// ---- Expressions --------------------------------------------------------------------------- //
|
||||
|
||||
public static Expression eq(Property<Number> property, Number value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression eq(Property<String> property, String value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression eq(Property<Temporal> property, Temporal value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression eq(Property<Boolean> property, boolean value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression eq(Property<Object> property, Object value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
//----
|
||||
|
||||
public static Expression gt(Property<Number> property, Number value) {
|
||||
return Expr.gt(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression gt(Property<String> property, String value) {
|
||||
return Expr.gt(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression gt(Property<Temporal> property, Temporal value) {
|
||||
return Expr.gt(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression gt(Property<Object> property, Object value) {
|
||||
return Expr.gt(property.toString(), value);
|
||||
}
|
||||
|
||||
//----
|
||||
|
||||
public static Expression like(Property<String> property, String value) {
|
||||
return Expr.like(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression ilike(Property<String> property, String value) {
|
||||
return Expr.ilike(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression startsWith(Property<String> property, String value) {
|
||||
return Expr.startsWith(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression istartsWith(Property<String> property, String value) {
|
||||
return Expr.istartsWith(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression contains(Property<String> property, String value) {
|
||||
return Expr.contains(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression icontains(Property<String> property, String value) {
|
||||
return Expr.icontains(property.toString(), value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.Query.Property;
|
||||
|
||||
import java.time.temporal.Temporal;
|
||||
|
||||
@Deprecated(since = "experimental")
|
||||
public final class StdLegacyOps {
|
||||
|
||||
public static Expression eq(Property<Temporal> property, java.util.Calendar value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression eqOrNull(Property<Temporal> property, java.util.Calendar value) {
|
||||
return Expr.factory().eqOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression ne(Property<Temporal> property, java.util.Calendar value) {
|
||||
return Expr.factory().ne(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression lt(Property<Temporal> property, java.util.Calendar value) {
|
||||
return Expr.factory().lt(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression ltOrNull(Property<Temporal> property, java.util.Calendar value) {
|
||||
return Expr.factory().ltOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression le(Property<Temporal> property, java.util.Calendar value) {
|
||||
return Expr.factory().le(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression leOrNull(Property<Temporal> property, java.util.Calendar value) {
|
||||
return Expr.factory().leOrNull(property.toString(), value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.Query.Property;
|
||||
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.Collection;
|
||||
|
||||
@Deprecated(since = "experimental")
|
||||
public final class StdOperators {
|
||||
|
||||
// ---- Functions ---- //
|
||||
|
||||
public static Property<Number> sum(Property<? extends Number> property) {
|
||||
return Property.of("sum(" + property + ")");
|
||||
}
|
||||
|
||||
public static Property<Number> count(Property<?> property) {
|
||||
return Property.of("count(" + property + ")");
|
||||
}
|
||||
|
||||
public static <T> Property<T> avg(Property<T> property) {
|
||||
return Property.of("avg(" + property + ")");
|
||||
}
|
||||
|
||||
public static <T> Property<T> max(Property<T> property) {
|
||||
return Property.of("max(" + property + ")");
|
||||
}
|
||||
|
||||
public static <T> Property<T> min(Property<T> property) {
|
||||
return Property.of("min(" + property + ")");
|
||||
}
|
||||
|
||||
public static <T> Property<T> coalesce(Property<T> property, Object value) {
|
||||
return Property.of("coalesce(" + property.toString() + "," + sqlValue(value) + ")");
|
||||
}
|
||||
|
||||
public static Property<String> lower(Property<String> property) {
|
||||
return Property.of("lower(" + property + ")");
|
||||
}
|
||||
|
||||
public static Property<String> upper(Property<String> property) {
|
||||
return Property.of("upper(" + property + ")");
|
||||
}
|
||||
|
||||
public static Property<String> concat(Property<?> property, Object... values) {
|
||||
StringBuilder expression = new StringBuilder(50);
|
||||
expression.append("concat(").append(property.toString());
|
||||
for (Object value : values) {
|
||||
expression.append(",").append(sqlConcatString(value));
|
||||
}
|
||||
expression.append(")");
|
||||
return Property.of(expression.toString());
|
||||
}
|
||||
|
||||
private static String sqlConcatString(Object value) {
|
||||
String asStr = String.valueOf(value);
|
||||
return (value instanceof Property || isSqlQuoted(asStr)) ? asStr : "'" + value + "'";
|
||||
}
|
||||
|
||||
private static boolean isSqlQuoted(String asStr) {
|
||||
return asStr.length() > 0 && asStr.charAt(0) == '\'';
|
||||
}
|
||||
|
||||
private static String sqlValue(Object value) {
|
||||
if (value instanceof Property || value instanceof Number) {
|
||||
return value.toString();
|
||||
} else {
|
||||
return "'" + value + "'";
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Operators ---- //
|
||||
|
||||
public static <T> Expression eq(Property<T> property, T value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression eq(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.in(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
public static Expression eq(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression eqOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().eqOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression eqOrNull(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.factory().eqOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression ne(Property<T> property, T value) {
|
||||
return Expr.ne(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression ne(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.ne(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
public static Expression ne(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.ne(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression gt(Property<T> property, T value) {
|
||||
return Expr.gt(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression gt(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.gt(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
public static Expression gt(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.gt(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression gtOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().gtOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression gtOrNull(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.factory().gtOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression ge(Property<T> property, T value) {
|
||||
return Expr.ge(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression ge(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.ge(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
public static Expression ge(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.ge(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression geOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().geOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression geOrNull(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.factory().geOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression lt(Property<T> property, T value) {
|
||||
return Expr.lt(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression lt(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.lt(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
public static Expression lt(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.lt(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression ltOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().ltOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression ltOrNull(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.factory().ltOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression le(Property<T> property, T value) {
|
||||
return Expr.le(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression le(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.le(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
public static Expression le(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.le(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression leOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().leOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression leOrNull(Property<Temporal> property, java.util.Date value) {
|
||||
return Expr.factory().leOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression inRange(Property<T> property, T lowValue, T highValue) {
|
||||
return Expr.factory().inRange(property.toString(), lowValue, highValue);
|
||||
}
|
||||
|
||||
public static Expression inRange(Property<Temporal> property, java.util.Date lowValue, java.util.Date highValue) {
|
||||
return Expr.factory().inRange(property.toString(), lowValue, highValue);
|
||||
}
|
||||
|
||||
public static <T> Expression inRange(Property<T> lowProperty, Property<T> highProperty, T value) {
|
||||
return Expr.factory().inRangeWith(lowProperty.toString(), highProperty.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression inRange(Property<Temporal> lowProperty, Property<Temporal> highProperty, java.util.Date value) {
|
||||
return Expr.factory().inRangeWith(lowProperty.toString(), highProperty.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression inRange(Property<T> lowProperty, Property<T> property, Property<T> highProperty) {
|
||||
return Expr.factory().inRangeWithProperties(lowProperty.toString(), property.toString(), highProperty.toString());
|
||||
}
|
||||
|
||||
public static <T> Expression in(Property<T> property, Collection<T> value) {
|
||||
return Expr.in(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression in(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.in(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
public static <T> Expression inOrEmpty(Property<T> property, Collection<T> value) {
|
||||
return Expr.inOrEmpty(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression notIn(Property<T> property, Collection<T> value) {
|
||||
return Expr.factory().notIn(property.toString(), value);
|
||||
}
|
||||
|
||||
public static <T> Expression notIn(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.factory().notIn(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
// ---- String operators ---- //
|
||||
|
||||
public static Expression like(Property<String> property, String value) {
|
||||
return Expr.like(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression ilike(Property<String> property, String value) {
|
||||
return Expr.ilike(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression startsWith(Property<String> property, String value) {
|
||||
return Expr.startsWith(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression istartsWith(Property<String> property, String value) {
|
||||
return Expr.istartsWith(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression contains(Property<String> property, String value) {
|
||||
return Expr.contains(property.toString(), value);
|
||||
}
|
||||
|
||||
public static Expression icontains(Property<String> property, String value) {
|
||||
return Expr.icontains(property.toString(), value);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public interface UpdateQuery<T> {
|
||||
* @param property The bean property to be set
|
||||
* @param value The value to set the property to
|
||||
*/
|
||||
UpdateQuery<T> set(Query.Property<?> property, Object value);
|
||||
<P> UpdateQuery<T> set(Query.Property<P> property, P value);
|
||||
|
||||
/**
|
||||
* Set the property to be null.
|
||||
|
||||
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static io.ebean.StdFunctions.*;
|
||||
import static io.ebean.StdOperators.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class StdFunctionsTest {
|
||||
|
||||
@@ -7,7 +7,7 @@ package io.ebean.typequery;
|
||||
* @param <T> the number type
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public abstract class PBaseNumber<R, T extends Comparable> extends PBaseCompareable<R, T, Number> {
|
||||
public abstract class PBaseNumber<R, T extends Comparable> extends PBaseCompareable<R, T, T> {
|
||||
|
||||
/**
|
||||
* Construct with a property name and root instance.
|
||||
|
||||
@@ -6,7 +6,7 @@ package io.ebean.typequery;
|
||||
* @param <E> the enum specific type
|
||||
* @param <R> the root query bean type
|
||||
*/
|
||||
public final class PEnum<R, E> extends PBaseValueEqual<R, E, Object> {
|
||||
public final class PEnum<R, E> extends PBaseValueEqual<R, E, E> {
|
||||
|
||||
/**
|
||||
* Construct with a property name and root instance.
|
||||
|
||||
@@ -278,7 +278,7 @@ public abstract class TQRootBean<T, R> {
|
||||
|
||||
/**
|
||||
* Specify the properties to be loaded on the 'main' root level entity bean
|
||||
* also allowing for functions to be used like {@link StdFunctions#max(Query.Property)}.
|
||||
* also allowing for functions to be used like {@link StdOperators#max(Query.Property)}.
|
||||
*
|
||||
* @param properties the list of properties to fetch
|
||||
*/
|
||||
|
||||
@@ -15,11 +15,13 @@ import org.junit.jupiter.api.Test;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static io.ebean.StdOperators.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.example.domain.query.QAddress.Alias.country;
|
||||
import static org.example.domain.query.QAddress.Alias.line1;
|
||||
@@ -692,6 +694,32 @@ public class QCustomerTest {
|
||||
assertThat(customerExists).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkingPropertyTypesToEQOperator() {
|
||||
|
||||
QCustomer c = QCustomer.alias();
|
||||
|
||||
new QCustomer()
|
||||
.select(c.version, count(c.id))
|
||||
.version.gt(0)
|
||||
.having()
|
||||
.add(gt(count(c.id), 1))
|
||||
.findList();
|
||||
|
||||
new QCustomer()
|
||||
.add(in(QCustomer.Alias.name, List.of("foo", "bar")))
|
||||
.add(eq(QCustomer.Alias.currentInet, Inet.of("asd").toString()))
|
||||
.findList();
|
||||
|
||||
new QCustomer()
|
||||
//.add(gt(sum(QCustomer.Alias.version), 45))
|
||||
.add(eq(QCustomer.Alias.version, 45L))
|
||||
.add(eq(QCustomer.Alias.name, "junk"))
|
||||
.add(eq(QCustomer.Alias.registered, new Date()))
|
||||
.add(eq(QCustomer.Alias.whenUpdated, new Timestamp(System.currentTimeMillis())))
|
||||
.findList();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuery() {
|
||||
|
||||
|
||||
@@ -17,9 +17,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static io.ebean.StdFunctions.gt;
|
||||
import static io.ebean.StdFunctions.ilike;
|
||||
import static io.ebean.StdFunctions.*;
|
||||
import static io.ebean.StdOperators.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class QOrderTest {
|
||||
@@ -227,7 +225,7 @@ public class QOrderTest {
|
||||
.status.eq(Order.Status.COMPLETE)
|
||||
.orderDate.gt(new java.sql.Date(System.currentTimeMillis()))
|
||||
.asUpdate()
|
||||
.set(QOrder.Alias.version, 42L)
|
||||
.set(QOrder.Alias.version, 56L)
|
||||
.setNull(QOrder.Alias.orderDate)
|
||||
.update();
|
||||
|
||||
@@ -258,7 +256,7 @@ public class QOrderTest {
|
||||
Query<Order> query = new QOrder()
|
||||
.select(o.id, o.status)
|
||||
.or()
|
||||
.add(gt(coalesce(o.customer.version, 0), 42))
|
||||
.add(gt(coalesce(o.customer.version, 0), 42L))
|
||||
.id.lt(12)
|
||||
.endOr()
|
||||
.query();
|
||||
|
||||
@@ -5,7 +5,7 @@ import io.ebean.Query;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
|
||||
import static io.ebean.StdFunctions.*;
|
||||
import static io.ebean.StdOperators.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user