Search in sources :

Example 1 with Constant

use of org.immutables.criteria.expression.Constant in project immutables by immutables.

the class FindVisitor method binaryCall.

private Bson binaryCall(Call call) {
    Preconditions.checkArgument(call.operator().arity() == Operator.Arity.BINARY, "%s is not binary", call.operator());
    final Operator op = call.operator();
    Expression left = call.arguments().get(0);
    Expression right = call.arguments().get(1);
    if (!(left instanceof Path && right instanceof Constant)) {
        // special case when $expr has to be used
        return call.accept(new MongoExpr(naming, codecRegistry)).asDocument();
    }
    final String field = naming.name(Visitors.toPath(left));
    final Object value = Visitors.toConstant(right).value();
    if (op == Operators.EQUAL || op == Operators.NOT_EQUAL) {
        if ("".equals(value) && op == Operators.NOT_EQUAL) {
            // special case for empty string. string != "" should not return missing strings
            return Filters.and(Filters.nin(field, value, null), Filters.exists(field));
        }
        return op == Operators.EQUAL ? Filters.eq(field, value) : Filters.ne(field, value);
    }
    if (ComparableOperators.isComparable(op)) {
        if (op == ComparableOperators.GREATER_THAN) {
            return Filters.gt(field, value);
        } else if (op == ComparableOperators.GREATER_THAN_OR_EQUAL) {
            return Filters.gte(field, value);
        } else if (op == ComparableOperators.LESS_THAN) {
            return Filters.lt(field, value);
        } else if (op == ComparableOperators.LESS_THAN_OR_EQUAL) {
            return Filters.lte(field, value);
        }
        throw new UnsupportedOperationException("Unknown comparison " + call);
    }
    if (op == Operators.IN || op == Operators.NOT_IN) {
        final Collection<Object> values = ImmutableSet.copyOf(Visitors.toConstant(right).values());
        Preconditions.checkNotNull(values, "not expected to be null for %s", op);
        if (values.size() == 1) {
            // optimization: convert IN, NIN (where argument is a list with single element) into EQ / NE
            Operators newOperator = op == Operators.IN ? Operators.EQUAL : Operators.NOT_EQUAL;
            Call newCall = Expressions.binaryCall(newOperator, left, Expressions.constant(values.iterator().next()));
            return binaryCall(newCall);
        }
        return op == Operators.IN ? Filters.in(field, values) : Filters.nin(field, values);
    }
    if (op == StringOperators.MATCHES || op == StringOperators.CONTAINS) {
        Object newValue = value;
        if (op == StringOperators.CONTAINS) {
            // handle special case for string contains with regexp
            newValue = Pattern.compile(".*" + Pattern.quote(value.toString()) + ".*");
        }
        Preconditions.checkArgument(newValue instanceof Pattern, "%s is not regex pattern", value);
        return Filters.regex(field, (Pattern) newValue);
    }
    if (op == IterableOperators.HAS_SIZE) {
        Preconditions.checkArgument(value instanceof Number, "%s is not a number", value);
        int size = ((Number) value).intValue();
        return Filters.size(field, size);
    }
    if (op == IterableOperators.CONTAINS) {
        return Filters.eq(field, value);
    }
    if (op == StringOperators.HAS_LENGTH) {
        Preconditions.checkArgument(value instanceof Number, "%s is not a number", value);
        final int length = ((Number) value).intValue();
        // use strLenCP function
        // https://docs.mongodb.com/manual/reference/operator/aggregation/strLenCP/#exp._S_strLenCP
        final Bson lengthExpr = Document.parse(String.format("{$expr:{$eq:[{$strLenCP: \"$%s\"}, %d]}}}", field, length));
        // field should exists and not be null
        return Filters.and(Filters.exists(field), Filters.ne(field, null), lengthExpr);
    }
    if (op == StringOperators.STARTS_WITH || op == StringOperators.ENDS_WITH) {
        // regular expression
        final String pattern = String.format("%s%s%s", op == StringOperators.STARTS_WITH ? "^" : "", Pattern.quote(value.toString()), op == StringOperators.ENDS_WITH ? "$" : "");
        return Filters.regex(field, Pattern.compile(pattern));
    }
    throw new UnsupportedOperationException(String.format("Unsupported binary call %s", call));
}
Also used : Operator(org.immutables.criteria.expression.Operator) Path(org.immutables.criteria.expression.Path) Call(org.immutables.criteria.expression.Call) Pattern(java.util.regex.Pattern) IterableOperators(org.immutables.criteria.expression.IterableOperators) StringOperators(org.immutables.criteria.expression.StringOperators) ComparableOperators(org.immutables.criteria.expression.ComparableOperators) Operators(org.immutables.criteria.expression.Operators) OptionalOperators(org.immutables.criteria.expression.OptionalOperators) Constant(org.immutables.criteria.expression.Constant) BsonString(org.bson.BsonString) Bson(org.bson.conversions.Bson) Expression(org.immutables.criteria.expression.Expression)

Example 2 with Constant

use of org.immutables.criteria.expression.Constant in project immutables by immutables.

the class GeodeQueryVisitor method binaryOperator.

/**
 * Used for operators with two arguments like {@code =}, {@code IN} etc.
 */
private Oql binaryOperator(Call call) {
    final Operator op = call.operator();
    final List<Expression> args = call.arguments();
    Preconditions.checkArgument(args.size() == 2, "Size should be 2 for %s but was %s on call %s", op, args.size(), call);
    // left node
    Expression left = args.get(0);
    // right node
    Expression right = args.get(1);
    if (op == IterableOperators.CONTAINS || op == StringOperators.MATCHES || op == StringOperators.CONTAINS || op == StringOperators.STARTS_WITH || op == StringOperators.ENDS_WITH) {
        return oql(String.format("%s.%s(%s)", left.accept(this).oql(), toMethodName(op), right.accept(this).oql()));
    }
    if (op == StringOperators.HAS_LENGTH || op == IterableOperators.HAS_SIZE) {
        return oql(String.format("%s.%s = %s", left.accept(this).oql(), toMethodName(op), right.accept(this).oql()));
    }
    final String operator;
    if (op == Operators.EQUAL || op == Operators.NOT_EQUAL) {
        operator = op == Operators.EQUAL ? "=" : "!=";
    } else if (op == Operators.IN || op == Operators.NOT_IN) {
        if (right instanceof Constant) {
            // optimization for IN / NOT IN operators
            // make constant value(s) distinct using Set
            Set<Object> newValues = ImmutableSet.copyOf(Visitors.toConstant(right).values());
            right = Expressions.constant(newValues);
        }
        operator = op == Operators.IN ? "IN" : "NOT IN";
    } else if (op == ComparableOperators.GREATER_THAN) {
        operator = ">";
    } else if (op == ComparableOperators.GREATER_THAN_OR_EQUAL) {
        operator = ">=";
    } else if (op == ComparableOperators.LESS_THAN) {
        operator = "<";
    } else if (op == ComparableOperators.LESS_THAN_OR_EQUAL) {
        operator = "<=";
    } else {
        throw new IllegalArgumentException("Unknown binary operator " + call);
    }
    return oql(String.format("%s %s %s", left.accept(this).oql(), operator, right.accept(this).oql()));
}
Also used : Operator(org.immutables.criteria.expression.Operator) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Expression(org.immutables.criteria.expression.Expression) Constant(org.immutables.criteria.expression.Constant)

Aggregations

Constant (org.immutables.criteria.expression.Constant)2 Expression (org.immutables.criteria.expression.Expression)2 Operator (org.immutables.criteria.expression.Operator)2 ImmutableSet (com.google.common.collect.ImmutableSet)1 Set (java.util.Set)1 Pattern (java.util.regex.Pattern)1 BsonString (org.bson.BsonString)1 Bson (org.bson.conversions.Bson)1 Call (org.immutables.criteria.expression.Call)1 ComparableOperators (org.immutables.criteria.expression.ComparableOperators)1 IterableOperators (org.immutables.criteria.expression.IterableOperators)1 Operators (org.immutables.criteria.expression.Operators)1 OptionalOperators (org.immutables.criteria.expression.OptionalOperators)1 Path (org.immutables.criteria.expression.Path)1 StringOperators (org.immutables.criteria.expression.StringOperators)1