Search in sources :

Example 6 with Operator

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

the class GeodeQueryVisitor method visit.

@Override
public Oql visit(Call call) {
    final Operator op = call.operator();
    final List<Expression> args = call.arguments();
    if (op == Operators.NOT_IN || op == IterableOperators.NOT_EMPTY) {
        // convert "foo not in [1, 2, 3]" into "not (foo in [1, 2, 3])"
        return visit(Expressions.not(Expressions.call(inverseOp(op), call.arguments())));
    }
    if (op == Operators.AND || op == Operators.OR) {
        Preconditions.checkArgument(!args.isEmpty(), "Size should be >=1 for %s but was %s", op, args.size());
        final String join = ") " + op.name() + " (";
        final String newOql = "(" + args.stream().map(a -> a.accept(this)).map(Oql::oql).collect(Collectors.joining(join)) + ")";
        return new Oql(variables, newOql);
    }
    if (op.arity() == Operator.Arity.BINARY) {
        return binaryOperator(call);
    }
    if (op.arity() == Operator.Arity.UNARY) {
        return unaryOperator(call);
    }
    throw new UnsupportedOperationException("Don't know how to handle " + call);
}
Also used : Operator(org.immutables.criteria.expression.Operator) Expression(org.immutables.criteria.expression.Expression)

Example 7 with Operator

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

the class GeodeQueryVisitor method unaryOperator.

/**
 * Operator with single operator: {@code NOT}, {@code IS_PRESENT}
 */
private Oql unaryOperator(Call call) {
    final Operator op = call.operator();
    final List<Expression> args = call.arguments();
    Preconditions.checkArgument(args.size() == 1, "Size should be == 1 for unary operator %s but was %s", op, args.size());
    Expression arg0 = args.get(0);
    String path = arg0.accept(this).oql();
    if (op instanceof OptionalOperators) {
        // use IS_DEFINED / IS_UNDEFINED functions
        String expr;
        if (op == OptionalOperators.IS_PRESENT) {
            expr = String.format("is_defined(%s) AND %s != null", path, path);
        } else {
            expr = String.format("is_undefined(%s) OR %s = null", path, path);
        }
        return oql(expr);
    } else if (op == Operators.NOT) {
        return oql(String.format("NOT (%s)", path));
    } else if (op == IterableOperators.IS_EMPTY || op == StringOperators.TO_LOWER_CASE || op == StringOperators.TO_UPPER_CASE) {
        return oql(String.format("%s.%s()", path, toMethodName(op)));
    }
    throw new UnsupportedOperationException("Unknown unary operator " + call);
}
Also used : Operator(org.immutables.criteria.expression.Operator) Expression(org.immutables.criteria.expression.Expression) OptionalOperators(org.immutables.criteria.expression.OptionalOperators)

Example 8 with Operator

use of org.immutables.criteria.expression.Operator 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)

Example 9 with Operator

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

the class ElasticsearchQueryVisitor method binaryCall.

private QueryBuilders.QueryBuilder binaryCall(Call call) {
    final List<Expression> arguments = call.arguments();
    Preconditions.checkArgument(arguments.size() == 2, "Size should be 2 for %s but was %s", call.operator(), arguments.size());
    final Operator op = call.operator();
    final Path path = Visitors.toPath(arguments.get(0));
    final String field = pathNaming.name(path);
    final Object value = Visitors.toConstant(arguments.get(1)).value();
    if (op == Operators.EQUAL || op == Operators.NOT_EQUAL) {
        QueryBuilders.QueryBuilder builder;
        if (idPredicate.test(path)) {
            // use more efficient ids query for keys
            builder = QueryBuilders.idsQuery(Collections.singleton(value));
        } else {
            builder = QueryBuilders.termQuery(field, value);
        }
        if (op == Operators.NOT_EQUAL) {
            QueryBuilders.BoolQueryBuilder bool = QueryBuilders.boolQuery().mustNot(builder);
            if ("".equals(value)) {
                // string is not empty (should also exists)
                bool = bool.should(QueryBuilders.existsQuery(field));
            }
            builder = bool;
        }
        return builder;
    }
    if (op == Operators.IN || op == Operators.NOT_IN) {
        final Collection<Object> values = ImmutableSet.copyOf(Visitors.toConstant(arguments.get(1)).values());
        QueryBuilders.QueryBuilder builder;
        if (idPredicate.test(path)) {
            // more efficient query by ID
            builder = QueryBuilders.idsQuery(values);
        } else {
            builder = QueryBuilders.termsQuery(field, values);
        }
        if (op == Operators.NOT_IN) {
            builder = QueryBuilders.boolQuery().mustNot(builder);
        }
        return builder;
    }
    if (ComparableOperators.isComparable(op)) {
        final QueryBuilders.RangeQueryBuilder builder = QueryBuilders.rangeQuery(field);
        if (op == ComparableOperators.GREATER_THAN) {
            builder.gt(value);
        } else if (op == ComparableOperators.GREATER_THAN_OR_EQUAL) {
            builder.gte(value);
        } else if (op == ComparableOperators.LESS_THAN) {
            builder.lt(value);
        } else if (op == ComparableOperators.LESS_THAN_OR_EQUAL) {
            builder.lte(value);
        } else {
            throw new UnsupportedOperationException("Unknown comparison " + call);
        }
        return builder;
    }
    if (op == StringOperators.STARTS_WITH) {
        return QueryBuilders.prefixQuery(field, value.toString());
    }
    if (op == StringOperators.MATCHES) {
        Preconditions.checkArgument(value instanceof Pattern, "%s is not regex pattern", value);
        // In elastic / lucene, patterns match the entire string.
        return QueryBuilders.regexpQuery(field, ((Pattern) value).pattern());
    }
    if (op == StringOperators.ENDS_WITH || op == StringOperators.CONTAINS) {
        return QueryBuilders.wildcardQuery(field, "*" + value.toString() + (op == StringOperators.CONTAINS ? "*" : ""));
    }
    throw new UnsupportedOperationException(String.format("Call %s not supported", call));
}
Also used : Operator(org.immutables.criteria.expression.Operator) Path(org.immutables.criteria.expression.Path) Pattern(java.util.regex.Pattern) Expression(org.immutables.criteria.expression.Expression)

Aggregations

Operator (org.immutables.criteria.expression.Operator)9 Expression (org.immutables.criteria.expression.Expression)8 Pattern (java.util.regex.Pattern)5 Call (org.immutables.criteria.expression.Call)5 OptionalOperators (org.immutables.criteria.expression.OptionalOperators)5 Path (org.immutables.criteria.expression.Path)5 ImmutableSet (com.google.common.collect.ImmutableSet)4 BsonString (org.bson.BsonString)4 ComparableOperators (org.immutables.criteria.expression.ComparableOperators)4 Constant (org.immutables.criteria.expression.Constant)4 Operators (org.immutables.criteria.expression.Operators)4 StringOperators (org.immutables.criteria.expression.StringOperators)4 Preconditions (com.google.common.base.Preconditions)3 Collection (java.util.Collection)3 Collections (java.util.Collections)3 List (java.util.List)3 Objects (java.util.Objects)3 Bson (org.bson.conversions.Bson)3 PathNaming (org.immutables.criteria.backend.PathNaming)3 AbstractExpressionVisitor (org.immutables.criteria.expression.AbstractExpressionVisitor)3