Add StdFunctions, StdExpressions, TQColumn marker interface

This commit is contained in:
Rob Bygrave
2022-11-03 11:16:30 +13:00
parent 2789d0f97c
commit 96e79248dc
6 changed files with 176 additions and 22 deletions
@@ -0,0 +1,35 @@
package io.ebean.typequery;
import io.ebean.Expr;
import io.ebean.Expression;
public class StdExpressions {
public static Expression gt(TQColumn property, Object value) {
return Expr.gt(property.toString(), value);
}
public static Expression like(TQColumn property, String value) {
return Expr.like(property.toString(), value);
}
public static Expression ilike(TQColumn property, String value) {
return Expr.ilike(property.toString(), value);
}
public static Expression startsWith(TQColumn property, String value) {
return Expr.startsWith(property.toString(), value);
}
public static Expression istartsWith(TQColumn property, String value) {
return Expr.istartsWith(property.toString(), value);
}
public static Expression contains(TQColumn property, String value) {
return Expr.contains(property.toString(), value);
}
public static Expression icontains(TQColumn property, String value) {
return Expr.icontains(property.toString(), value);
}
}
@@ -0,0 +1,52 @@
package io.ebean.typequery;
public final class StdFunctions {
public static TQColumn max(TQColumn property) {
return new Standard("max(" + property + ")");
}
public static TQColumn sum(TQColumn property) {
return new Standard("sum(" + property + ")");
}
public static TQColumn concat(TQColumn property, Object... values) {
StringBuilder expression = new StringBuilder(50);
expression.append("concat(").append(property.toString());
for (Object value : values) {
expression.append(",").append(sqlStringExpression(value));
}
expression.append(")");
return new Standard(expression.toString());
}
public static TQColumn coalesce(TQColumn property, Object value) {
StringBuilder expression = new StringBuilder(50);
expression.append("coalesce(").append(property.toString()).append(",");
expression.append(sqlStringExpression(value));
expression.append(")");
return new Standard(expression.toString());
}
private static String sqlStringExpression(Object value) {
if (value instanceof TQColumn || value instanceof Number) {
return value.toString();
} else {
return "'" + value + "'";
}
}
private static class Standard implements TQColumn {
private final String expression;
private Standard(String expression) {
this.expression = expression;
}
@Override
public String toString() {
return expression;
}
}
}
@@ -0,0 +1,7 @@
package io.ebean.typequery;
/**
* Marker interface for type safe properties and expressions.
*/
public interface TQColumn {
}
@@ -7,7 +7,7 @@ import io.ebean.ExpressionList;
*
* @param <R> The type of the owning root bean
*/
public class TQProperty<R> {
public class TQProperty<R> implements TQColumn {
protected final String _name;
@@ -31,6 +31,7 @@ public class TQProperty<R> {
this._name = TQPath.add(prefix, name);
}
@Override
public String toString() {
return _name;
}
@@ -233,8 +233,13 @@ public abstract class TQRootBean<T, R> {
}
/**
* Tune the query by specifying the properties to be loaded on the
* 'main' root level entity bean (aka partial object).
* Specify the properties to be loaded on the 'main' root level entity bean.
* <p>
* The resulting entities with be "partially loaded" aka partial objects.
* <p>
* Alternatively we can use a {@link #select(FetchGroup)} to specify all properties
* to load on all parts of the graph.
*
* <pre>{@code
*
* // alias for the customer properties in select()
@@ -245,12 +250,12 @@ public abstract class TQRootBean<T, R> {
*
* List<Customer> customers =
* new QCustomer()
* // tune query
* // specify the parts of the graph we want to load
* .select(cust.id, cust.name)
* .contacts.fetch(contact.firstName, contact.lastName, contact.email)
*
* // predicates
* .id.greaterThan(1)
* .id.gt(1)
* .findList();
*
* }</pre>
@@ -263,14 +268,25 @@ public abstract class TQRootBean<T, R> {
return root;
}
private Set<String> properties(TQProperty<R>[] properties) {
private Set<String> properties(TQColumn[] properties) {
Set<String> props = new LinkedHashSet<>();
for (TQProperty<R> property : properties) {
props.add(property.propertyName());
for (TQColumn property : properties) {
props.add(property.toString());
}
return props;
}
/**
* Specify the properties to be loaded on the 'main' root level entity bean
* also allowing for functions to be used like {@link StdFunctions#max(TQColumn)}.
*
* @param properties the list of properties to fetch
*/
public final R select(TQColumn... properties) {
((SpiQueryFetch) query).selectProperties(properties(properties));
return root;
}
/**
* Specify a path to load including all its properties.
*
@@ -499,6 +515,14 @@ public abstract class TQRootBean<T, R> {
return root;
}
/**
* Add an expression to the WHERE or HAVING clause.
*/
public R add(Expression expression) {
peekExprList().add(expression);
return root;
}
/**
* Set root table alias.
*/