Skip to content

Commit

Permalink
Query does not implement Expression
Browse files Browse the repository at this point in the history
  • Loading branch information
asereda-gs committed Jun 19, 2019
1 parent c3cda12 commit f307dd3
Show file tree
Hide file tree
Showing 21 changed files with 63 additions and 129 deletions.
21 changes: 13 additions & 8 deletions criteria/common/src/org/immutables/criteria/Criterias.java
Expand Up @@ -16,8 +16,10 @@


package org.immutables.criteria; package org.immutables.criteria;


import com.google.common.base.Preconditions;
import org.immutables.criteria.expression.Expression; import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.Expressional; import org.immutables.criteria.expression.Query;
import org.immutables.criteria.expression.Queryable;


import java.util.Objects; import java.util.Objects;


Expand All @@ -26,19 +28,22 @@ public final class Criterias {
private Criterias() {} private Criterias() {}


/** /**
* Extracts {@link Expressional} interface from a criteria. Any criteria implements * Extracts {@link Query} from a criteria. Any criteria implements
* {@code Expressional} interface at runtime. * {@code Queryable} interface at runtime.
*/ */
public static Expressional toExpressional(DocumentCriteria<?> criteria) { public static Query toQuery(DocumentCriteria<?> criteria) {
Objects.requireNonNull(criteria, "criteria"); Objects.requireNonNull(criteria, "criteria");
return (Expressional) criteria; Preconditions.checkArgument(criteria instanceof Queryable, "%s should implement %s",
criteria.getClass().getName(), Queryable.class.getName());

return ((Queryable) criteria).query();
} }


/** /**
* Extract directly expression from a criteria * Extract directly filter from a criteria
*/ */
public static Expression toExpression(DocumentCriteria<?> criteria) { public static Expression toFilterExpression(DocumentCriteria<?> criteria) {
return toExpressional(criteria).expression(); return toQuery(criteria).filter().orElseThrow(() -> new IllegalArgumentException("no defined filter for " + criteria));
} }


} }
Expand Up @@ -50,8 +50,4 @@ public T visit(Path path) {
return mapper.apply(path); return mapper.apply(path);
} }


@Override
public T visit(Query query) {
return query.filter().map(e -> e.accept(this)).orElseGet(() -> mapper.apply(query));
}
} }
Expand Up @@ -61,8 +61,4 @@ public Void visit(Path path) {
return null; return null;
} }


@Override
public Void visit(Query query) {
return query.filter().map(e -> e.accept(this)).orElse(null);
}
} }
Expand Up @@ -18,7 +18,6 @@


import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;


import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
Expand All @@ -30,7 +29,7 @@
* *
* <p>Example: {@code (A and B or C and D or E)} * <p>Example: {@code (A and B or C and D or E)}
*/ */
public class DnfExpression implements Expressional, Expression { public class DnfExpression implements Queryable {


private final Query root; private final Query root;
private final List<Expression> conjunctions; private final List<Expression> conjunctions;
Expand All @@ -46,18 +45,12 @@ public static DnfExpression create(Query root) {
return new DnfExpression(root, Collections.emptyList(), Collections.emptyList()); return new DnfExpression(root, Collections.emptyList(), Collections.emptyList());
} }


@Nullable
@Override @Override
public <R, C> R accept(ExpressionBiVisitor<R, C> visitor, @Nullable C context) { public Query query() {
return expression().accept(visitor, context);
}

@Override
public Expression expression() {
return simplify(); return simplify();
} }


private Expression simplify() { private Query simplify() {
final List<Expression> expressions = new ArrayList<>(disjunctions); final List<Expression> expressions = new ArrayList<>(disjunctions);
if (!conjunctions.isEmpty()) { if (!conjunctions.isEmpty()) {
expressions.add(Expressions.and(conjunctions)); expressions.add(Expressions.and(conjunctions));
Expand Down
Expand Up @@ -32,6 +32,4 @@ public interface ExpressionBiVisitor<V, C> {


V visit(Path path, @Nullable C context); V visit(Path path, @Nullable C context);


V visit(Query root, @Nullable C context);

} }
Expand Up @@ -31,6 +31,4 @@ public interface ExpressionVisitor<V> {


V visit(Path path); V visit(Path path);


V visit(Query query);

} }
Expand Up @@ -22,7 +22,6 @@
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional;


/** /**
* A set of predefined utilities and factories for expressions like {@link Constant} or {@link Call} * A set of predefined utilities and factories for expressions like {@link Constant} or {@link Call}
Expand Down Expand Up @@ -87,25 +86,10 @@ public V visit(Path path, @Nullable Void context) {
return visitor.visit(path); return visitor.visit(path);
} }


@Override
public V visit(Query root, @Nullable Void context) {
return visitor.visit(root);
}
}; };
} }


public static Optional<Expression> extractPredicate(Expression expression) {
if (expression instanceof Query) {
return ((Query) expression).filter();
}

return Optional.of(expression);
}

public static Expression not(Expression call) { public static Expression not(Expression call) {
if (call instanceof Query) {
return ((Query) call).transform(e -> call(Operators.NOT, e));
}
return Expressions.call(Operators.NOT, call); return Expressions.call(Operators.NOT, call);
} }


Expand Down
Expand Up @@ -16,15 +16,14 @@


package org.immutables.criteria.expression; package org.immutables.criteria.expression;


import javax.annotation.Nullable;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;


/** /**
* Query which is composed of predicates, projections, group by and order by expressions. * Query which is composed of predicates, projections, group by and order by expressions.
*/ */
public final class Query implements Expression { public final class Query {


private final EntityPath entityPath; private final EntityPath entityPath;
private final Expression filter; private final Expression filter;
Expand All @@ -34,16 +33,10 @@ private Query(EntityPath entityPath, Expression filter) {
this.filter = filter; this.filter = filter;
} }


@Nullable
@Override
public <R, C> R accept(ExpressionBiVisitor<R, C> visitor, @Nullable C context) {
return visitor.visit(this, context);
}

public EntityPath entityPath() { public EntityPath entityPath() {
return this.entityPath; return this.entityPath;
} }

public Optional<Expression> filter() { public Optional<Expression> filter() {
return Optional.ofNullable(filter); return Optional.ofNullable(filter);
} }
Expand Down
Expand Up @@ -18,13 +18,13 @@




/** /**
* Means an object can be expressed as Abstract Syntax Tree (AST). * Allows to expose current query
*/ */
public interface Expressional { public interface Queryable {


/** /**
* Expose expression used by an object. * Expose expression used by an object.
*/ */
Expression expression(); Query query();


} }
Expand Up @@ -20,11 +20,12 @@
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.immutables.criteria.expression.DnfExpression; import org.immutables.criteria.expression.DnfExpression;
import org.immutables.criteria.expression.Expression; import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.Expressional;
import org.immutables.criteria.expression.Expressions; import org.immutables.criteria.expression.Expressions;
import org.immutables.criteria.expression.Operator; import org.immutables.criteria.expression.Operator;
import org.immutables.criteria.expression.Operators; import org.immutables.criteria.expression.Operators;
import org.immutables.criteria.expression.Path; import org.immutables.criteria.expression.Path;
import org.immutables.criteria.expression.Query;
import org.immutables.criteria.expression.Queryable;


import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.List; import java.util.List;
Expand All @@ -35,7 +36,7 @@
* Link between front-end (Criteria DSL) and <a href="https://cs.lmu.edu/~ray/notes/ir/">Intermediate Representation</a> * Link between front-end (Criteria DSL) and <a href="https://cs.lmu.edu/~ray/notes/ir/">Intermediate Representation</a>
* (internally known as {@link Expression}). * (internally known as {@link Expression}).
*/ */
public final class CriteriaContext implements Expressional { public final class CriteriaContext implements Queryable {


private final List<CriteriaCreator<?>> creators; private final List<CriteriaCreator<?>> creators;
private final DnfExpression expression; private final DnfExpression expression;
Expand Down Expand Up @@ -159,8 +160,8 @@ public CriteriaContext or() {
} }


@Override @Override
public Expression expression() { public Query query() {
return this.expression.expression(); return this.expression.query();
} }


public CriteriaContext withOperator(UnaryOperator<Expression> operator) { public CriteriaContext withOperator(UnaryOperator<Expression> operator) {
Expand Down
Expand Up @@ -139,7 +139,7 @@ private static <T> T createWithReflection(Class<T> type, CriteriaContext context


/** /**
* Hacky (and temporary) reflection until we define proper sub-classes for criterias * Hacky (and temporary) reflection until we define proper sub-classes for criterias
* (to hide Expressional implementation). * (to hide Queryable implementation).
*/ */
static CriteriaContext extract(Object object) { static CriteriaContext extract(Object object) {
Objects.requireNonNull(object, "object"); Objects.requireNonNull(object, "object");
Expand All @@ -156,7 +156,7 @@ static <C> UnaryOperator<Expression> toExpressionOperator(Supplier<C> supplier,
return expression -> { return expression -> {
final C initial = supplier.get(); final C initial = supplier.get();
final C changed = expr.apply(initial); final C changed = expr.apply(initial);
return Matchers.extract(changed).expression(); return Matchers.extract(changed).query().filter().orElseThrow(() -> new IllegalStateException("filter should be set"));
}; };
} }


Expand All @@ -168,7 +168,7 @@ static <C> UnaryOperator<Expression> toExpressionOperator3(CriteriaContext conte
final CriteriaCreator.TriFactory<?, ?, C> factory = context.factory3(); final CriteriaCreator.TriFactory<?, ?, C> factory = context.factory3();
final C initial = (C) context.withCreators(factory.creator3(), factory.creator2(), factory.creator3()).factory3().create3(); final C initial = (C) context.withCreators(factory.creator3(), factory.creator2(), factory.creator3()).factory3().create3();
final C changed = expr.apply(initial); final C changed = expr.apply(initial);
return Matchers.extract(changed).expression(); return Matchers.extract(changed).query().filter().orElseThrow(() -> new IllegalStateException("filter should be set"));
}; };
} }


Expand Down
Expand Up @@ -69,7 +69,7 @@ public void not() {


private static void assertExpressional(DocumentCriteria<?> crit, String ... expectedLines) { private static void assertExpressional(DocumentCriteria<?> crit, String ... expectedLines) {
final StringWriter out = new StringWriter(); final StringWriter out = new StringWriter();
Criterias.toExpressional(crit).expression().accept(new DebugExpressionVisitor<>(new PrintWriter(out))); Criterias.toFilterExpression(crit).accept(new DebugExpressionVisitor<>(new PrintWriter(out)));
final String expected = Arrays.stream(expectedLines).collect(Collectors.joining(System.lineSeparator())); final String expected = Arrays.stream(expectedLines).collect(Collectors.joining(System.lineSeparator()));
Assert.assertEquals(expected, out.toString().trim()); Assert.assertEquals(expected, out.toString().trim());
} }
Expand Down
Expand Up @@ -18,12 +18,9 @@


import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.ExpressionConverter; import org.immutables.criteria.expression.ExpressionConverter;
import org.immutables.criteria.expression.Expressions;


import java.util.Objects; import java.util.Objects;
import java.util.Optional;


final class Elasticsearch { final class Elasticsearch {


Expand All @@ -33,15 +30,9 @@ static ExpressionConverter<ObjectNode> converter(ObjectMapper mapper) {
Objects.requireNonNull(mapper, "expression"); Objects.requireNonNull(mapper, "expression");


return expression -> { return expression -> {
Optional<Expression> predicate = Expressions.extractPredicate(expression);

if (!predicate.isPresent()) {
return mapper.createObjectNode();
}

final ObjectNode query = mapper.createObjectNode(); final ObjectNode query = mapper.createObjectNode();
final ElasticsearchQueryVisitor visitor = new ElasticsearchQueryVisitor(); final ElasticsearchQueryVisitor visitor = new ElasticsearchQueryVisitor();
final QueryBuilders.QueryBuilder builder = predicate.get().accept(visitor); final QueryBuilders.QueryBuilder builder = expression.accept(visitor);
query.set("query", QueryBuilders.constantScoreQuery(builder).toJson(mapper)); query.set("query", QueryBuilders.constantScoreQuery(builder).toJson(mapper));
return query; return query;
}; };
Expand Down
Expand Up @@ -30,6 +30,7 @@
import org.immutables.criteria.adapter.Backend; import org.immutables.criteria.adapter.Backend;
import org.immutables.criteria.adapter.Operations; import org.immutables.criteria.adapter.Operations;
import org.immutables.criteria.expression.Expression; import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.Query;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;


import java.io.IOException; import java.io.IOException;
Expand Down Expand Up @@ -68,12 +69,12 @@ public <T> Publisher<T> execute(Operation<T> query) {
return queryInternal((Operations.Query<T>) query); return queryInternal((Operations.Query<T>) query);
} }


private <T> Flowable<T> queryInternal(Operations.Query<T> query) { private <T> Flowable<T> queryInternal(Operations.Query<T> op) {
final Request request = new Request("POST", String.format("/%s/_search", index)); final Request request = new Request("POST", String.format("/%s/_search", index));
final Expression expression = Criterias.toExpression(query.criteria()); final Query query = Criterias.toQuery(op.criteria());
final ObjectNode json = Elasticsearch.converter(mapper).convert(expression); final ObjectNode json = query.filter().map(f -> Elasticsearch.converter(mapper).convert(f)).orElseGet(mapper::createObjectNode);
query.limit().ifPresent(limit -> json.put("size", limit)); op.limit().ifPresent(limit -> json.put("size", limit));
query.offset().ifPresent(offset -> json.put("start", offset)); op.offset().ifPresent(offset -> json.put("start", offset));
request.setEntity(new StringEntity(json.toString(), ContentType.APPLICATION_JSON)); request.setEntity(new StringEntity(json.toString(), ContentType.APPLICATION_JSON));
return Flowable.fromPublisher(new AsyncRestPublisher(restClient, request)) return Flowable.fromPublisher(new AsyncRestPublisher(restClient, request))
.map(r -> converter((Class<T>) type).apply(r)) .map(r -> converter((Class<T>) type).apply(r))
Expand Down
23 changes: 11 additions & 12 deletions criteria/geode/src/org/immutables/criteria/geode/GeodeBackend.java
Expand Up @@ -25,6 +25,7 @@
import org.immutables.criteria.Repository; import org.immutables.criteria.Repository;
import org.immutables.criteria.adapter.Backend; import org.immutables.criteria.adapter.Backend;
import org.immutables.criteria.adapter.Operations; import org.immutables.criteria.adapter.Operations;
import org.immutables.criteria.expression.Query;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;


import java.util.Collection; import java.util.Collection;
Expand All @@ -33,7 +34,7 @@
import java.util.Optional; import java.util.Optional;


/** /**
* Backend for * Backend for <a href="https://geode.apache.org/">Apache Geode</a>
*/ */
public class GeodeBackend implements Backend { public class GeodeBackend implements Backend {


Expand All @@ -58,19 +59,17 @@ public <T> Publisher<T> execute(Operation<T> operation) {
} }


private <T> Flowable<T> query(Operations.Query<T> op) { private <T> Flowable<T> query(Operations.Query<T> op) {
final StringBuilder query = new StringBuilder(); final StringBuilder oql = new StringBuilder();
final Query query = Criterias.toQuery(op.criteria());


query.append("SELECT * FROM ").append(region.getFullPath()); oql.append("SELECT * FROM ").append(region.getFullPath());


final String predicate = Geodes.converter().convert(Criterias.toExpression(op.criteria())); query.filter().ifPresent(e -> oql.append(" WHERE ").append(Geodes.converter().convert(e)));
if (!predicate.isEmpty()) {
query.append(" WHERE ").append(predicate);
}


op.limit().ifPresent(limit -> query.append(" LIMIT ").append(limit)); op.limit().ifPresent(limit -> oql.append(" LIMIT ").append(limit));
op.offset().ifPresent(offset -> query.append(" OFFSET ").append(offset)); op.offset().ifPresent(offset -> oql.append(" OFFSET ").append(offset));


return Flowable.<Collection<T>>fromCallable(() -> region.query(query.toString())) return Flowable.<Collection<T>>fromCallable(() -> region.query(oql.toString()))
.flatMapIterable(x -> x); .flatMapIterable(x -> x);
} }


Expand All @@ -89,7 +88,7 @@ private <T> Flowable<Repository.Success> insert(Operations.Insert<T> op) {
} }


private <T> Flowable<Repository.Success> delete(Operations.Delete op) { private <T> Flowable<Repository.Success> delete(Operations.Delete op) {
if (!Geodes.hasPredicate(op.criteria())) { if (!Criterias.toQuery(op.criteria()).filter().isPresent()) {
// means delete all (ie clear whole region) // means delete all (ie clear whole region)
return Completable.fromRunnable(region::clear) return Completable.fromRunnable(region::clear)
.toSingleDefault(Repository.Success.SUCCESS) .toSingleDefault(Repository.Success.SUCCESS)
Expand All @@ -106,7 +105,7 @@ private <T> Flowable<Repository.Success> delete(Operations.Delete op) {
} }




final String predicate = Criterias.toExpression(op.criteria()) final String predicate = Criterias.toFilterExpression(op.criteria())
.accept(new GeodeQueryVisitor(path -> String.format("e.value.%s", path.toStringPath()))); .accept(new GeodeQueryVisitor(path -> String.format("e.value.%s", path.toStringPath())));


final String query = String.format("select distinct e.key from %s.entries e where %s", region.getFullPath(), predicate); final String query = String.format("select distinct e.key from %s.entries e where %s", region.getFullPath(), predicate);
Expand Down

0 comments on commit f307dd3

Please sign in to comment.