diff --git a/ebean-api/src/main/java/io/ebean/StdOperators.java b/ebean-api/src/main/java/io/ebean/StdOperators.java index 40bf84916..1ab0c55cf 100644 --- a/ebean-api/src/main/java/io/ebean/StdOperators.java +++ b/ebean-api/src/main/java/io/ebean/StdOperators.java @@ -4,43 +4,75 @@ import io.ebean.Query.Property; import java.util.Collection; +/** + * Standard Operators for use with strongly typed query construction. + *

+ * This is currently deemed to be experimental and subject to change. + */ @Deprecated(since = "experimental") public final class StdOperators { // ---- Functions ---- // + /** + * Sum of the given property. + */ public static Property sum(Property property) { return Property.of("sum(" + property + ")"); } + /** + * Count of the given property. + */ public static Property count(Property property) { return Property.of("count(" + property + ")"); } + /** + * Average of the given property. + */ public static Property avg(Property property) { return Property.of("avg(" + property + ")"); } + /** + * Max of the given property. + */ public static Property max(Property property) { return Property.of("max(" + property + ")"); } + /** + * Min of the given property. + */ public static Property min(Property property) { return Property.of("min(" + property + ")"); } + /** + * Coalesce of the property and value. + */ public static Property coalesce(Property property, Object value) { return Property.of("coalesce(" + property.toString() + "," + sqlValue(value) + ")"); } + /** + * Lower of the given property. + */ public static Property lower(Property property) { return Property.of("lower(" + property + ")"); } + /** + * Upper of the given property. + */ public static Property upper(Property property) { return Property.of("upper(" + property + ")"); } + /** + * Concat of the given property and values or other properties. + */ public static Property concat(Property property, Object... values) { StringBuilder expression = new StringBuilder(50); expression.append("concat(").append(property.toString()); @@ -52,146 +84,248 @@ public final class StdOperators { } 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) == '\''; + if (value instanceof Property) { + return value.toString(); + } else { + return sqlQuote(value); + } } + /** + * Allows numbers to be unquoted. + */ private static String sqlValue(Object value) { if (value instanceof Property || value instanceof Number) { return value.toString(); } else { - return "'" + value + "'"; + return sqlQuote(value); } } + /** + * SQL quoted escaping single quotes. + */ + private static String sqlQuote(Object value) { + return "'" + String.valueOf(value).replace("'", "''") + "'"; + } + // ---- Operators ---- // + /** + * Equal to - for a property and value. + */ public static Expression eq(Property property, T value) { return Expr.eq(property.toString(), value); } + /** + * Equal to - for a property and sub-query. + */ public static Expression eq(Property property, Query subQuery) { return Expr.in(property.toString(), subQuery); } + /** + * Equal to or null - for a property and value. + */ public static Expression eqOrNull(Property property, T value) { return Expr.factory().eqOrNull(property.toString(), value); } + /** + * Not equal to - for a property and value. + */ public static Expression ne(Property property, T value) { return Expr.ne(property.toString(), value); } + /** + * Not equal to - for a property and sub-query. + */ public static Expression ne(Property property, Query subQuery) { return Expr.ne(property.toString(), subQuery); } + /** + * Greater than - for a property and value. + */ public static Expression gt(Property property, T value) { return Expr.gt(property.toString(), value); } + /** + * Greater than - for a property and sub-query. + */ public static Expression gt(Property property, Query subQuery) { return Expr.gt(property.toString(), subQuery); } + /** + * Greater than or null - for a property and value. + */ public static Expression gtOrNull(Property property, T value) { return Expr.factory().gtOrNull(property.toString(), value); } + /** + * Greater than or equal to - for a property and value. + */ public static Expression ge(Property property, T value) { return Expr.ge(property.toString(), value); } + /** + * Greater than or equal to - for a property and sub-query. + */ public static Expression ge(Property property, Query subQuery) { return Expr.ge(property.toString(), subQuery); } + /** + * Greater than or null - for a property and value. + */ public static Expression geOrNull(Property property, T value) { return Expr.factory().geOrNull(property.toString(), value); } + /** + * Less than - for a property and value. + */ public static Expression lt(Property property, T value) { return Expr.lt(property.toString(), value); } + /** + * Less than - for a property and sub-query. + */ public static Expression lt(Property property, Query subQuery) { return Expr.lt(property.toString(), subQuery); } + /** + * Less than or null - for a property and value. + */ public static Expression ltOrNull(Property property, T value) { return Expr.factory().ltOrNull(property.toString(), value); } + /** + * Greater than or equal to - for a property and value. + */ public static Expression le(Property property, T value) { return Expr.le(property.toString(), value); } + /** + * Greater than or equal to - for a property and sub-query. + */ public static Expression le(Property property, Query subQuery) { return Expr.le(property.toString(), subQuery); } + /** + * Greater than or equal to or null - for a property and value. + */ public static Expression leOrNull(Property property, T value) { return Expr.factory().leOrNull(property.toString(), value); } + /** + * In range - for a property and values. + */ public static Expression inRange(Property property, T lowValue, T highValue) { return Expr.factory().inRange(property.toString(), lowValue, highValue); } + /** + * In range - for properties and a value. + */ public static Expression inRange(Property lowProperty, Property highProperty, T value) { return Expr.factory().inRangeWith(lowProperty.toString(), highProperty.toString(), value); } + /** + * In range - for properties. + */ public static Expression inRange(Property lowProperty, Property property, Property highProperty) { return Expr.factory().inRangeWithProperties(lowProperty.toString(), property.toString(), highProperty.toString()); } + /** + * In - for a given property and collection of values. + */ public static Expression in(Property property, Collection value) { return Expr.in(property.toString(), value); } + /** + * In - for a given property and sub-query. + */ public static Expression in(Property property, Query subQuery) { return Expr.in(property.toString(), subQuery); } + /** + * In or empty - for a given property and collection of values. + */ public static Expression inOrEmpty(Property property, Collection value) { return Expr.inOrEmpty(property.toString(), value); } + /** + * Not In - for a given property and collection of values. + */ public static Expression notIn(Property property, Collection value) { return Expr.factory().notIn(property.toString(), value); } + /** + * Not In - for a given property and sub-query. + */ public static Expression notIn(Property property, Query subQuery) { return Expr.factory().notIn(property.toString(), subQuery); } // ---- String operators ---- // + /** + * Like - for a given property and value. + */ public static Expression like(Property property, String value) { return Expr.like(property.toString(), value); } + /** + * Case-insensitive Like - for a given property and value. + */ public static Expression ilike(Property property, String value) { return Expr.ilike(property.toString(), value); } + /** + * Starts with - for a given property and value. + */ public static Expression startsWith(Property property, String value) { return Expr.startsWith(property.toString(), value); } + /** + * Case-insensitive starts with - for a given property and value. + */ public static Expression istartsWith(Property property, String value) { return Expr.istartsWith(property.toString(), value); } + /** + * Contains - for a given property and value. + */ public static Expression contains(Property property, String value) { return Expr.contains(property.toString(), value); } + /** + * Case-insensitive contains - for a given property and value. + */ public static Expression icontains(Property property, String value) { return Expr.icontains(property.toString(), value); } diff --git a/ebean-api/src/test/java/io/ebean/StdFunctionsTest.java b/ebean-api/src/test/java/io/ebean/StdFunctionsTest.java index 7c48d7fe7..a1a4c9891 100644 --- a/ebean-api/src/test/java/io/ebean/StdFunctionsTest.java +++ b/ebean-api/src/test/java/io/ebean/StdFunctionsTest.java @@ -66,4 +66,13 @@ class StdFunctionsTest { assertThat(coalesce(foo, "banana").toString()).isEqualTo("coalesce(foo,'banana')"); } + @Test + void testCoalesceWithQuoted() { + assertThat(coalesce(foo, "ba'nana").toString()).isEqualTo("coalesce(foo,'ba''nana')"); + } + + @Test + void testConcatWithQuoted() { + assertThat(concat(foo, "ba'nana").toString()).isEqualTo("concat(foo,'ba''nana')"); + } }