mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
EQL - Simplify nested query where expressions after parsing
This commit is contained in:
@@ -59,11 +59,11 @@ package com.avaje.ebean;
|
||||
* .and()
|
||||
* .startsWith("name", "r")
|
||||
* .eq("anniversary", onAfter)
|
||||
* .endJunction()
|
||||
* .endAnd()
|
||||
* .and()
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .gt("id", 0)
|
||||
* .endJunction()
|
||||
* .endAnd()
|
||||
* .order().asc("name");
|
||||
*
|
||||
* q.findList();
|
||||
@@ -84,39 +84,41 @@ public interface Junction<T> extends Expression, ExpressionList<T> {
|
||||
/**
|
||||
* AND group.
|
||||
*/
|
||||
AND(" and ", ""),
|
||||
AND(" and ", "", false),
|
||||
|
||||
/**
|
||||
* OR group.
|
||||
*/
|
||||
OR(" or ", ""),
|
||||
OR(" or ", "", false),
|
||||
|
||||
/**
|
||||
* NOT group.
|
||||
*/
|
||||
NOT(" and ", "not "),
|
||||
NOT(" and ", "not ", false),
|
||||
|
||||
/**
|
||||
* Text search AND group.
|
||||
*/
|
||||
MUST("must", ""),
|
||||
MUST("must", "", true),
|
||||
|
||||
/**
|
||||
* Text search NOT group.
|
||||
*/
|
||||
MUST_NOT("must_not", ""),
|
||||
MUST_NOT("must_not", "", true),
|
||||
|
||||
/**
|
||||
* Text search OR group.
|
||||
*/
|
||||
SHOULD("should", "");
|
||||
SHOULD("should", "", true);
|
||||
|
||||
String prefix;
|
||||
String literal;
|
||||
private String prefix;
|
||||
private String literal;
|
||||
private boolean text;
|
||||
|
||||
Type(String literal, String prefix) {
|
||||
Type(String literal, String prefix, boolean text) {
|
||||
this.literal = literal;
|
||||
this.prefix = prefix;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,6 +134,14 @@ public interface Junction<T> extends Expression, ExpressionList<T> {
|
||||
public String prefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a text type.
|
||||
*/
|
||||
public boolean isText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,12 @@ import java.io.IOException;
|
||||
*/
|
||||
public interface SpiExpression extends Expression {
|
||||
|
||||
/**
|
||||
/**
|
||||
* Simplify nested expressions if possible.
|
||||
*/
|
||||
void simplify();
|
||||
|
||||
/**
|
||||
* Write the expression as an elastic search expression.
|
||||
*/
|
||||
void writeDocQuery(DocQueryContext context) throws IOException;
|
||||
|
||||
@@ -693,4 +693,8 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
OrmUpdateProperties getUpdateProperties();
|
||||
|
||||
/**
|
||||
* Simplify nested expression lists where possible.
|
||||
*/
|
||||
void simplifyExpressions();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ public abstract class AbstractExpression implements SpiExpression {
|
||||
this.propName = propName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// override on SimpleExpression
|
||||
|
||||
@@ -88,6 +88,11 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
if (!list.isEmpty()) {
|
||||
|
||||
@@ -97,6 +97,16 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
void simplifyEntries() {
|
||||
for (SpiExpression element : list) {
|
||||
element.simplify();
|
||||
}
|
||||
}
|
||||
|
||||
public void simplify() {
|
||||
simplifyEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write being aware if it is the Top level "text" expressions.
|
||||
* <p>
|
||||
|
||||
@@ -36,6 +36,11 @@ class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreExpress
|
||||
this.subQuery = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
throw new IllegalStateException("Not supported");
|
||||
|
||||
@@ -38,6 +38,11 @@ class InQueryExpression extends AbstractExpression implements UnsupportedDocStor
|
||||
this.bindParams = bindParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
throw new IllegalStateException("Not supported");
|
||||
|
||||
@@ -39,9 +39,9 @@ import java.util.Set;
|
||||
*/
|
||||
class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, ExpressionList<T> {
|
||||
|
||||
protected final DefaultExpressionList<T> exprList;
|
||||
protected DefaultExpressionList<T> exprList;
|
||||
|
||||
protected final Junction.Type type;
|
||||
protected Junction.Type type;
|
||||
|
||||
JunctionExpression(Junction.Type type, Query<T> query, ExpressionList<T> parent) {
|
||||
this.type = type;
|
||||
@@ -56,6 +56,31 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
this.exprList = exprList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplify nested expressions where possible.
|
||||
* <p>
|
||||
* This is expected to only used after expressions are built via query language parsing.
|
||||
* </p>
|
||||
*/
|
||||
public void simplify() {
|
||||
exprList.simplifyEntries();
|
||||
|
||||
List<SpiExpression> list = exprList.list;
|
||||
if (list.size() == 1 && list.get(0) instanceof JunctionExpression) {
|
||||
JunctionExpression nested = (JunctionExpression)list.get(0);
|
||||
if (type == Type.AND && !nested.type.isText()) {
|
||||
// and (and (a, b, c)) -> and (a, b, c)
|
||||
// and (not (a, b, c)) -> not (a, b, c)
|
||||
// and (or (a, b, c)) -> or (a, b, c)
|
||||
this.exprList = nested.exprList;
|
||||
this.type = nested.type;
|
||||
} else if (type == Type.NOT && nested.type == Type.AND) {
|
||||
// not (and (a, b, c)) -> not (a, b, c)
|
||||
this.exprList = nested.exprList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new JunctionExpression<T>(type, exprList.copyForPlanKey());
|
||||
}
|
||||
|
||||
@@ -57,6 +57,11 @@ abstract class LogicExpression implements SpiExpression {
|
||||
this.expTwo = (SpiExpression) expTwo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
|
||||
|
||||
+5
@@ -24,6 +24,11 @@ class NestedPathWrapperExpression implements SpiExpression {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
context.startNested(nestedPath);
|
||||
|
||||
@@ -8,6 +8,11 @@ import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
*/
|
||||
abstract class NonPrepareExpression implements SpiExpression {
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareExpression(BeanQueryRequest<?> request) {
|
||||
// do nothing
|
||||
|
||||
@@ -17,6 +17,11 @@ class NoopExpression implements SpiExpression {
|
||||
|
||||
protected static final NoopExpression INSTANCE = new NoopExpression();
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
|
||||
@@ -22,6 +22,11 @@ final class NotExpression implements SpiExpression {
|
||||
this.exp = (SpiExpression) exp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
context.startBoolMustNot();
|
||||
|
||||
@@ -27,8 +27,8 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
|
||||
private boolean textMode;
|
||||
|
||||
public EqlAdapter(Query<T> query) {
|
||||
this.query = (SpiQuery<T>)query;
|
||||
public EqlAdapter(SpiQuery<T> query) {
|
||||
this.query = query;
|
||||
this.helper = new EqlAdapterHelper(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.grammer;
|
||||
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.grammer.antlr.EQLLexer;
|
||||
import com.avaje.ebeaninternal.server.grammer.antlr.EQLParser;
|
||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||
@@ -9,7 +9,7 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
public class EqlParser {
|
||||
|
||||
public static <T> void parse(String raw, Query<T> query) {
|
||||
public static <T> void parse(String raw, SpiQuery<T> query) {
|
||||
|
||||
EQLLexer lexer = new EQLLexer(new ANTLRInputStream(raw));
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
@@ -20,5 +20,7 @@ public class EqlParser {
|
||||
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(adapter, context);
|
||||
|
||||
query.simplifyExpressions();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1349,6 +1349,13 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return whereExpressions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplifyExpressions() {
|
||||
if (whereExpressions != null) {
|
||||
whereExpressions.simplify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> having(Expression expression) {
|
||||
having().add(expression);
|
||||
|
||||
Reference in New Issue
Block a user