SQL: Fix issue with date range queries and timezone (#56115) (#56174)

Previously, the timezone parameter was not passed to the RangeQuery
and as a results queries that use the ES date math notation (now,
now-1d, now/d, now/h, now+2h, etc.) were using the UTC timezone and
not the one passed through the "timezone"/"time_zone" JDBC/REST params.
As a consequence, the date math defined dates were always considered in
UTC and possibly led to incorrect results for queries like:
```
SELECT * FROM t WHERE date BETWEEN now-1d/d AND now/d
```

Fixes: #56049
(cherry picked from commit 300f010c0b18ed0f10a41d5e1606466ba0a3088f)
This commit is contained in:
Marios Trivyzas 2020-05-05 10:54:23 +02:00 committed by GitHub
parent 8a23da429a
commit cc21468559
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 662 additions and 426 deletions

View File

@ -30,6 +30,7 @@ import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import static java.lang.String.format; import static java.lang.String.format;
import static org.elasticsearch.xpack.ql.type.DateUtils.UTC;
public class EqlParser { public class EqlParser {
@ -41,7 +42,7 @@ public class EqlParser {
* Parses an EQL statement into execution plan * Parses an EQL statement into execution plan
*/ */
public LogicalPlan createStatement(String eql) { public LogicalPlan createStatement(String eql) {
return createStatement(eql, new ParserParams()); return createStatement(eql, new ParserParams(UTC));
} }
public LogicalPlan createStatement(String eql, ParserParams params) { public LogicalPlan createStatement(String eql, ParserParams params) {
@ -52,7 +53,7 @@ public class EqlParser {
} }
public Expression createExpression(String expression) { public Expression createExpression(String expression) {
return createExpression(expression, new ParserParams()); return createExpression(expression, new ParserParams(UTC));
} }
public Expression createExpression(String expression, ParserParams params) { public Expression createExpression(String expression, ParserParams params) {

View File

@ -45,6 +45,7 @@ import org.elasticsearch.xpack.ql.type.DataType;
import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.DataTypes;
import org.elasticsearch.xpack.ql.util.StringUtils; import org.elasticsearch.xpack.ql.util.StringUtils;
import java.time.ZoneId;
import java.util.List; import java.util.List;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@ -52,6 +53,12 @@ import static java.util.Collections.emptyList;
public class ExpressionBuilder extends IdentifierBuilder { public class ExpressionBuilder extends IdentifierBuilder {
protected final ParserParams params;
public ExpressionBuilder(ParserParams params) {
this.params = params;
}
protected Expression expression(ParseTree ctx) { protected Expression expression(ParseTree ctx) {
return typedParsing(ctx, Expression.class); return typedParsing(ctx, Expression.class);
} }
@ -115,20 +122,21 @@ public class ExpressionBuilder extends IdentifierBuilder {
TerminalNode op = (TerminalNode) ctx.comparisonOperator().getChild(0); TerminalNode op = (TerminalNode) ctx.comparisonOperator().getChild(0);
Source source = source(ctx); Source source = source(ctx);
ZoneId zoneId = params.zoneId();
switch (op.getSymbol().getType()) { switch (op.getSymbol().getType()) {
case EqlBaseParser.EQ: case EqlBaseParser.EQ:
return new Equals(source, left, right); return new Equals(source, left, right, zoneId);
case EqlBaseParser.NEQ: case EqlBaseParser.NEQ:
return new NotEquals(source, left, right); return new NotEquals(source, left, right, zoneId);
case EqlBaseParser.LT: case EqlBaseParser.LT:
return new LessThan(source, left, right); return new LessThan(source, left, right, zoneId);
case EqlBaseParser.LTE: case EqlBaseParser.LTE:
return new LessThanOrEqual(source, left, right); return new LessThanOrEqual(source, left, right, zoneId);
case EqlBaseParser.GT: case EqlBaseParser.GT:
return new GreaterThan(source, left, right); return new GreaterThan(source, left, right, zoneId);
case EqlBaseParser.GTE: case EqlBaseParser.GTE:
return new GreaterThanOrEqual(source, left, right); return new GreaterThanOrEqual(source, left, right, zoneId);
default: default:
throw new ParsingException(source, "Unknown operator {}", source.text()); throw new ParsingException(source, "Unknown operator {}", source.text());
} }

View File

@ -38,11 +38,10 @@ import static java.util.Collections.singletonList;
public abstract class LogicalPlanBuilder extends ExpressionBuilder { public abstract class LogicalPlanBuilder extends ExpressionBuilder {
private final ParserParams params;
private final UnresolvedRelation RELATION = new UnresolvedRelation(Source.EMPTY, null, "", false, ""); private final UnresolvedRelation RELATION = new UnresolvedRelation(Source.EMPTY, null, "", false, "");
public LogicalPlanBuilder(ParserParams params) { public LogicalPlanBuilder(ParserParams params) {
this.params = params; super(params);
} }
@Override @Override
@ -56,7 +55,7 @@ public abstract class LogicalPlanBuilder extends ExpressionBuilder {
Literal eventValue = new Literal(eventSource, eventName, DataTypes.KEYWORD); Literal eventValue = new Literal(eventSource, eventName, DataTypes.KEYWORD);
UnresolvedAttribute eventField = new UnresolvedAttribute(eventSource, params.fieldEventCategory()); UnresolvedAttribute eventField = new UnresolvedAttribute(eventSource, params.fieldEventCategory());
Expression eventMatch = new Equals(eventSource, eventField, eventValue); Expression eventMatch = new Equals(eventSource, eventField, eventValue, params.zoneId());
condition = new And(source, eventMatch, condition); condition = new And(source, eventMatch, condition);
} }

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.eql.parser; package org.elasticsearch.xpack.eql.parser;
import java.time.ZoneId;
import java.util.List; import java.util.List;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@ -15,11 +16,16 @@ import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_IMPLICIT_
public class ParserParams { public class ParserParams {
private final ZoneId zoneId;
private String fieldEventCategory = FIELD_EVENT_CATEGORY; private String fieldEventCategory = FIELD_EVENT_CATEGORY;
private String fieldTimestamp = FIELD_TIMESTAMP; private String fieldTimestamp = FIELD_TIMESTAMP;
private String implicitJoinKey = FIELD_IMPLICIT_JOIN_KEY; private String implicitJoinKey = FIELD_IMPLICIT_JOIN_KEY;
private List<Object> queryParams = emptyList(); private List<Object> queryParams = emptyList();
public ParserParams(ZoneId zoneId) {
this.zoneId = zoneId;
}
public String fieldEventCategory() { public String fieldEventCategory() {
return fieldEventCategory; return fieldEventCategory;
} }
@ -55,4 +61,8 @@ public class ParserParams {
this.queryParams = params; this.queryParams = params;
return this; return this;
} }
public ZoneId zoneId() {
return zoneId;
}
} }

View File

@ -64,7 +64,7 @@ public class TransportEqlSearchAction extends HandledTransportAction<EqlSearchRe
boolean includeFrozen = request.indicesOptions().ignoreThrottled() == false; boolean includeFrozen = request.indicesOptions().ignoreThrottled() == false;
String clientId = null; String clientId = null;
ParserParams params = new ParserParams() ParserParams params = new ParserParams(zoneId)
.fieldEventCategory(request.eventCategoryField()) .fieldEventCategory(request.eventCategoryField())
.fieldTimestamp(request.timestampField()) .fieldTimestamp(request.timestampField())
.implicitJoinKey(request.implicitJoinKeyField()); .implicitJoinKey(request.implicitJoinKeyField());

View File

@ -30,6 +30,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.elasticsearch.xpack.eql.parser.AbstractBuilder.unquoteString; import static org.elasticsearch.xpack.eql.parser.AbstractBuilder.unquoteString;
import static org.elasticsearch.xpack.ql.TestUtils.UTC;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
@ -144,12 +145,12 @@ public class ExpressionTests extends ESTestCase {
Expression field = expr(fieldText); Expression field = expr(fieldText);
Expression value = expr(valueText); Expression value = expr(valueText);
assertEquals(new Equals(null, field, value), expr(fieldText + "==" + valueText)); assertEquals(new Equals(null, field, value, UTC), expr(fieldText + "==" + valueText));
assertEquals(new NotEquals(null, field, value), expr(fieldText + "!=" + valueText)); assertEquals(new NotEquals(null, field, value, UTC), expr(fieldText + "!=" + valueText));
assertEquals(new LessThanOrEqual(null, field, value), expr(fieldText + "<=" + valueText)); assertEquals(new LessThanOrEqual(null, field, value, UTC), expr(fieldText + "<=" + valueText));
assertEquals(new GreaterThanOrEqual(null, field, value), expr(fieldText + ">=" + valueText)); assertEquals(new GreaterThanOrEqual(null, field, value, UTC), expr(fieldText + ">=" + valueText));
assertEquals(new GreaterThan(null, field, value), expr(fieldText + ">" + valueText)); assertEquals(new GreaterThan(null, field, value, UTC), expr(fieldText + ">" + valueText));
assertEquals(new LessThan(null, field, value), expr(fieldText + "<" + valueText)); assertEquals(new LessThan(null, field, value, UTC), expr(fieldText + "<" + valueText));
} }
public void testBoolean() { public void testBoolean() {

View File

@ -26,6 +26,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.elasticsearch.xpack.ql.type.DateUtils.UTC;
public class LogicalPlanTests extends ESTestCase { public class LogicalPlanTests extends ESTestCase {
@ -56,7 +57,7 @@ public class LogicalPlanTests extends ESTestCase {
} }
public void testParameterizedEventQuery() { public void testParameterizedEventQuery() {
ParserParams params = new ParserParams().fieldEventCategory("myCustomEvent"); ParserParams params = new ParserParams(UTC).fieldEventCategory("myCustomEvent");
LogicalPlan fullQuery = parser.createStatement("process where process_name == 'net.exe'", params); LogicalPlan fullQuery = parser.createStatement("process where process_name == 'net.exe'", params);
Expression fullExpression = expr("myCustomEvent == 'process' and process_name == 'net.exe'"); Expression fullExpression = expr("myCustomEvent == 'process' and process_name == 'net.exe'");

View File

@ -22,6 +22,7 @@ import org.elasticsearch.xpack.ql.tree.Source;
import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.DataType;
import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.DataTypes;
import java.time.ZoneId;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
@ -35,20 +36,22 @@ public class Range extends ScalarFunction {
private final Expression value, lower, upper; private final Expression value, lower, upper;
private final boolean includeLower, includeUpper; private final boolean includeLower, includeUpper;
private final ZoneId zoneId;
public Range(Source source, Expression value, Expression lower, boolean includeLower, Expression upper, boolean includeUpper) { public Range(Source src, Expression value, Expression lower, boolean inclLower, Expression upper, boolean inclUpper, ZoneId zoneId) {
super(source, asList(value, lower, upper)); super(src, asList(value, lower, upper));
this.value = value; this.value = value;
this.lower = lower; this.lower = lower;
this.upper = upper; this.upper = upper;
this.includeLower = includeLower; this.includeLower = inclLower;
this.includeUpper = includeUpper; this.includeUpper = inclUpper;
this.zoneId = zoneId;
} }
@Override @Override
protected NodeInfo<Range> info() { protected NodeInfo<Range> info() {
return NodeInfo.create(this, Range::new, value, lower, includeLower, upper, includeUpper); return NodeInfo.create(this, Range::new, value, lower, includeLower, upper, includeUpper, zoneId);
} }
@Override @Override
@ -56,7 +59,7 @@ public class Range extends ScalarFunction {
if (newChildren.size() != 3) { if (newChildren.size() != 3) {
throw new IllegalArgumentException("expected [3] children but received [" + newChildren.size() + "]"); throw new IllegalArgumentException("expected [3] children but received [" + newChildren.size() + "]");
} }
return new Range(source(), newChildren.get(0), newChildren.get(1), includeLower, newChildren.get(2), includeUpper); return new Range(source(), newChildren.get(0), newChildren.get(1), includeLower, newChildren.get(2), includeUpper, zoneId);
} }
public Expression value() { public Expression value() {
@ -79,6 +82,10 @@ public class Range extends ScalarFunction {
return includeUpper; return includeUpper;
} }
public ZoneId zoneId() {
return zoneId;
}
@Override @Override
public boolean foldable() { public boolean foldable() {
if (lower.foldable() && upper.foldable()) { if (lower.foldable() && upper.foldable()) {
@ -160,7 +167,7 @@ public class Range extends ScalarFunction {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(includeLower, includeUpper, value, lower, upper); return Objects.hash(includeLower, includeUpper, value, lower, upper, zoneId);
} }
@Override @Override
@ -178,6 +185,7 @@ public class Range extends ScalarFunction {
&& Objects.equals(includeUpper, other.includeUpper) && Objects.equals(includeUpper, other.includeUpper)
&& Objects.equals(value, other.value) && Objects.equals(value, other.value)
&& Objects.equals(lower, other.lower) && Objects.equals(lower, other.lower)
&& Objects.equals(upper, other.upper); && Objects.equals(upper, other.upper)
&& Objects.equals(zoneId, other.zoneId);
} }
} }

View File

@ -15,11 +15,20 @@ import org.elasticsearch.xpack.ql.tree.Source;
import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.DataType;
import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.DataTypes;
import java.time.ZoneId;
// marker class to indicate operations that rely on values // marker class to indicate operations that rely on values
public abstract class BinaryComparison extends BinaryOperator<Object, Object, Boolean, BinaryComparisonOperation> { public abstract class BinaryComparison extends BinaryOperator<Object, Object, Boolean, BinaryComparisonOperation> {
protected BinaryComparison(Source source, Expression left, Expression right, BinaryComparisonOperation operation) { private final ZoneId zoneId;
protected BinaryComparison(Source source, Expression left, Expression right, BinaryComparisonOperation operation, ZoneId zoneId) {
super(source, left, right, operation); super(source, left, right, operation);
this.zoneId = zoneId;
}
public ZoneId zoneId() {
return zoneId;
} }
@Override @Override

View File

@ -11,29 +11,35 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Binar
import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.NodeInfo;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.time.ZoneId;
public class Equals extends BinaryComparison implements Negatable<BinaryComparison> { public class Equals extends BinaryComparison implements Negatable<BinaryComparison> {
public Equals(Source source, Expression left, Expression right) { public Equals(Source source, Expression left, Expression right) {
super(source, left, right, BinaryComparisonOperation.EQ); super(source, left, right, BinaryComparisonOperation.EQ, null);
}
public Equals(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.EQ, zoneId);
} }
@Override @Override
protected NodeInfo<Equals> info() { protected NodeInfo<Equals> info() {
return NodeInfo.create(this, Equals::new, left(), right()); return NodeInfo.create(this, Equals::new, left(), right(), zoneId());
} }
@Override @Override
protected Equals replaceChildren(Expression newLeft, Expression newRight) { protected Equals replaceChildren(Expression newLeft, Expression newRight) {
return new Equals(source(), newLeft, newRight); return new Equals(source(), newLeft, newRight, zoneId());
} }
@Override @Override
public Equals swapLeftAndRight() { public Equals swapLeftAndRight() {
return new Equals(source(), right(), left()); return new Equals(source(), right(), left(), zoneId());
} }
@Override @Override
public BinaryComparison negate() { public BinaryComparison negate() {
return new NotEquals(source(), left(), right()); return new NotEquals(source(), left(), right(), zoneId());
} }
} }

View File

@ -11,29 +11,31 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Binar
import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.NodeInfo;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.time.ZoneId;
public class GreaterThan extends BinaryComparison implements Negatable<BinaryComparison> { public class GreaterThan extends BinaryComparison implements Negatable<BinaryComparison> {
public GreaterThan(Source source, Expression left, Expression right) { public GreaterThan(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.GT); super(source, left, right, BinaryComparisonOperation.GT, zoneId);
} }
@Override @Override
protected NodeInfo<GreaterThan> info() { protected NodeInfo<GreaterThan> info() {
return NodeInfo.create(this, GreaterThan::new, left(), right()); return NodeInfo.create(this, GreaterThan::new, left(), right(), zoneId());
} }
@Override @Override
protected GreaterThan replaceChildren(Expression newLeft, Expression newRight) { protected GreaterThan replaceChildren(Expression newLeft, Expression newRight) {
return new GreaterThan(source(), newLeft, newRight); return new GreaterThan(source(), newLeft, newRight, zoneId());
} }
@Override @Override
public LessThan swapLeftAndRight() { public LessThan swapLeftAndRight() {
return new LessThan(source(), right(), left()); return new LessThan(source(), right(), left(), zoneId());
} }
@Override @Override
public LessThanOrEqual negate() { public LessThanOrEqual negate() {
return new LessThanOrEqual(source(), left(), right()); return new LessThanOrEqual(source(), left(), right(), zoneId());
} }
} }

View File

@ -11,29 +11,31 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Binar
import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.NodeInfo;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.time.ZoneId;
public class GreaterThanOrEqual extends BinaryComparison implements Negatable<BinaryComparison> { public class GreaterThanOrEqual extends BinaryComparison implements Negatable<BinaryComparison> {
public GreaterThanOrEqual(Source source, Expression left, Expression right) { public GreaterThanOrEqual(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.GTE); super(source, left, right, BinaryComparisonOperation.GTE, zoneId);
} }
@Override @Override
protected NodeInfo<GreaterThanOrEqual> info() { protected NodeInfo<GreaterThanOrEqual> info() {
return NodeInfo.create(this, GreaterThanOrEqual::new, left(), right()); return NodeInfo.create(this, GreaterThanOrEqual::new, left(), right(), zoneId());
} }
@Override @Override
protected GreaterThanOrEqual replaceChildren(Expression newLeft, Expression newRight) { protected GreaterThanOrEqual replaceChildren(Expression newLeft, Expression newRight) {
return new GreaterThanOrEqual(source(), newLeft, newRight); return new GreaterThanOrEqual(source(), newLeft, newRight, zoneId());
} }
@Override @Override
public LessThanOrEqual swapLeftAndRight() { public LessThanOrEqual swapLeftAndRight() {
return new LessThanOrEqual(source(), right(), left()); return new LessThanOrEqual(source(), right(), left(), zoneId());
} }
@Override @Override
public LessThan negate() { public LessThan negate() {
return new LessThan(source(), left(), right()); return new LessThan(source(), left(), right(), zoneId());
} }
} }

View File

@ -11,29 +11,31 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Binar
import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.NodeInfo;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.time.ZoneId;
public class LessThan extends BinaryComparison implements Negatable<BinaryComparison> { public class LessThan extends BinaryComparison implements Negatable<BinaryComparison> {
public LessThan(Source source, Expression left, Expression right) { public LessThan(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.LT); super(source, left, right, BinaryComparisonOperation.LT, zoneId);
} }
@Override @Override
protected NodeInfo<LessThan> info() { protected NodeInfo<LessThan> info() {
return NodeInfo.create(this, LessThan::new, left(), right()); return NodeInfo.create(this, LessThan::new, left(), right(), zoneId());
} }
@Override @Override
protected LessThan replaceChildren(Expression newLeft, Expression newRight) { protected LessThan replaceChildren(Expression newLeft, Expression newRight) {
return new LessThan(source(), newLeft, newRight); return new LessThan(source(), newLeft, newRight, zoneId());
} }
@Override @Override
public GreaterThan swapLeftAndRight() { public GreaterThan swapLeftAndRight() {
return new GreaterThan(source(), right(), left()); return new GreaterThan(source(), right(), left(), zoneId());
} }
@Override @Override
public GreaterThanOrEqual negate() { public GreaterThanOrEqual negate() {
return new GreaterThanOrEqual(source(), left(), right()); return new GreaterThanOrEqual(source(), left(), right(), zoneId());
} }
} }

View File

@ -11,29 +11,31 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Binar
import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.NodeInfo;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.time.ZoneId;
public class LessThanOrEqual extends BinaryComparison implements Negatable<BinaryComparison> { public class LessThanOrEqual extends BinaryComparison implements Negatable<BinaryComparison> {
public LessThanOrEqual(Source source, Expression left, Expression right) { public LessThanOrEqual(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.LTE); super(source, left, right, BinaryComparisonOperation.LTE, zoneId);
} }
@Override @Override
protected NodeInfo<LessThanOrEqual> info() { protected NodeInfo<LessThanOrEqual> info() {
return NodeInfo.create(this, LessThanOrEqual::new, left(), right()); return NodeInfo.create(this, LessThanOrEqual::new, left(), right(), zoneId());
} }
@Override @Override
protected LessThanOrEqual replaceChildren(Expression newLeft, Expression newRight) { protected LessThanOrEqual replaceChildren(Expression newLeft, Expression newRight) {
return new LessThanOrEqual(source(), newLeft, newRight); return new LessThanOrEqual(source(), newLeft, newRight, zoneId());
} }
@Override @Override
public GreaterThanOrEqual swapLeftAndRight() { public GreaterThanOrEqual swapLeftAndRight() {
return new GreaterThanOrEqual(source(), right(), left()); return new GreaterThanOrEqual(source(), right(), left(), zoneId());
} }
@Override @Override
public GreaterThan negate() { public GreaterThan negate() {
return new GreaterThan(source(), left(), right()); return new GreaterThan(source(), left(), right(), zoneId());
} }
} }

View File

@ -11,29 +11,31 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Binar
import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.NodeInfo;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.time.ZoneId;
public class NotEquals extends BinaryComparison implements Negatable<BinaryComparison> { public class NotEquals extends BinaryComparison implements Negatable<BinaryComparison> {
public NotEquals(Source source, Expression left, Expression right) { public NotEquals(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.NEQ); super(source, left, right, BinaryComparisonOperation.NEQ, zoneId);
} }
@Override @Override
protected NodeInfo<NotEquals> info() { protected NodeInfo<NotEquals> info() {
return NodeInfo.create(this, NotEquals::new, left(), right()); return NodeInfo.create(this, NotEquals::new, left(), right(), zoneId());
} }
@Override @Override
protected NotEquals replaceChildren(Expression newLeft, Expression newRight) { protected NotEquals replaceChildren(Expression newLeft, Expression newRight) {
return new NotEquals(source(), newLeft, newRight); return new NotEquals(source(), newLeft, newRight, zoneId());
} }
@Override @Override
public NotEquals swapLeftAndRight() { public NotEquals swapLeftAndRight() {
return new NotEquals(source(), right(), left()); return new NotEquals(source(), right(), left(), zoneId());
} }
@Override @Override
public BinaryComparison negate() { public BinaryComparison negate() {
return new Equals(source(), left(), right()); return new Equals(source(), left(), right(), zoneId());
} }
} }

View File

@ -11,28 +11,30 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Binar
import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.NodeInfo;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.time.ZoneId;
/** /**
* Implements the MySQL {@code <=>} operator * Implements the MySQL {@code <=>} operator
*/ */
public class NullEquals extends BinaryComparison { public class NullEquals extends BinaryComparison {
public NullEquals(Source source, Expression left, Expression right) { public NullEquals(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.NULLEQ); super(source, left, right, BinaryComparisonOperation.NULLEQ, zoneId);
} }
@Override @Override
protected NodeInfo<NullEquals> info() { protected NodeInfo<NullEquals> info() {
return NodeInfo.create(this, NullEquals::new, left(), right()); return NodeInfo.create(this, NullEquals::new, left(), right(), zoneId());
} }
@Override @Override
protected NullEquals replaceChildren(Expression newLeft, Expression newRight) { protected NullEquals replaceChildren(Expression newLeft, Expression newRight) {
return new NullEquals(source(), newLeft, newRight); return new NullEquals(source(), newLeft, newRight, zoneId());
} }
@Override @Override
public NullEquals swapLeftAndRight() { public NullEquals swapLeftAndRight() {
return new NullEquals(source(), right(), left()); return new NullEquals(source(), right(), left(), zoneId());
} }
@Override @Override

View File

@ -446,14 +446,14 @@ public final class OptimizerRules {
if (lowerComp != null && lowerComp == 0) { if (lowerComp != null && lowerComp == 0) {
if (!range.includeLower()) { // a = 2 OR 2 < a < ? -> 2 <= a < ? if (!range.includeLower()) { // a = 2 OR 2 < a < ? -> 2 <= a < ?
ranges.set(i, new Range(range.source(), range.value(), range.lower(), true, ranges.set(i, new Range(range.source(), range.value(), range.lower(), true,
range.upper(), range.includeUpper())); range.upper(), range.includeUpper(), range.zoneId()));
} // else : a = 2 OR 2 <= a < ? -> 2 <= a < ? } // else : a = 2 OR 2 <= a < ? -> 2 <= a < ?
removeEquals = true; // update range with lower equality instead or simply superfluous removeEquals = true; // update range with lower equality instead or simply superfluous
break; break;
} else if (upperComp != null && upperComp == 0) { } else if (upperComp != null && upperComp == 0) {
if (!range.includeUpper()) { // a = 2 OR ? < a < 2 -> ? < a <= 2 if (!range.includeUpper()) { // a = 2 OR ? < a < 2 -> ? < a <= 2
ranges.set(i, new Range(range.source(), range.value(), range.lower(), range.includeLower(), ranges.set(i, new Range(range.source(), range.value(), range.lower(), range.includeLower(),
range.upper(), true)); range.upper(), true, range.zoneId()));
} // else : a = 2 OR ? < a <= 2 -> ? < a <= 2 } // else : a = 2 OR ? < a <= 2 -> ? < a <= 2
removeEquals = true; // update range with upper equality instead removeEquals = true; // update range with upper equality instead
break; break;
@ -481,7 +481,7 @@ public final class OptimizerRules {
if (comp < 0) { // a = 1 OR a > 2 -> nop if (comp < 0) { // a = 1 OR a > 2 -> nop
continue; continue;
} else if (comp == 0 && bc instanceof GreaterThan) { // a = 2 OR a > 2 -> a >= 2 } else if (comp == 0 && bc instanceof GreaterThan) { // a = 2 OR a > 2 -> a >= 2
inequalities.set(i, new GreaterThanOrEqual(bc.source(), bc.left(), bc.right())); inequalities.set(i, new GreaterThanOrEqual(bc.source(), bc.left(), bc.right(), bc.zoneId()));
} // else (0 < comp || bc instanceof GreaterThanOrEqual) : } // else (0 < comp || bc instanceof GreaterThanOrEqual) :
// a = 3 OR a > 2 -> a > 2; a = 2 OR a => 2 -> a => 2 // a = 3 OR a > 2 -> a > 2; a = 2 OR a => 2 -> a => 2
@ -492,7 +492,7 @@ public final class OptimizerRules {
continue; continue;
} }
if (comp == 0 && bc instanceof LessThan) { // a = 2 OR a < 2 -> a <= 2 if (comp == 0 && bc instanceof LessThan) { // a = 2 OR a < 2 -> a <= 2
inequalities.set(i, new LessThanOrEqual(bc.source(), bc.left(), bc.right())); inequalities.set(i, new LessThanOrEqual(bc.source(), bc.left(), bc.right(), bc.zoneId()));
} // else (comp < 0 || bc instanceof LessThanOrEqual) : a = 2 OR a < 3 -> a < 3; a = 2 OR a <= 2 -> a <= 2 } // else (comp < 0 || bc instanceof LessThanOrEqual) : a = 2 OR a < 3 -> a < 3; a = 2 OR a <= 2 -> a <= 2
removeEquals = true; // update range with equality instead or simply superfluous removeEquals = true; // update range with equality instead or simply superfluous
break; break;
@ -598,7 +598,7 @@ public final class OptimizerRules {
ranges.add(new Range(and.source(), main.left(), ranges.add(new Range(and.source(), main.left(),
main.right(), main instanceof GreaterThanOrEqual, main.right(), main instanceof GreaterThanOrEqual,
other.right(), other instanceof LessThanOrEqual)); other.right(), other instanceof LessThanOrEqual, main.zoneId()));
changed = true; changed = true;
step = 0; step = 0;
@ -612,7 +612,7 @@ public final class OptimizerRules {
ranges.add(new Range(and.source(), main.left(), ranges.add(new Range(and.source(), main.left(),
other.right(), other instanceof GreaterThanOrEqual, other.right(), other instanceof GreaterThanOrEqual,
main.right(), main instanceof LessThanOrEqual)); main.right(), main instanceof LessThanOrEqual, main.zoneId()));
changed = true; changed = true;
step = 0; step = 0;
@ -739,7 +739,8 @@ public final class OptimizerRules {
lower ? main.lower() : other.lower(), lower ? main.lower() : other.lower(),
lower ? main.includeLower() : other.includeLower(), lower ? main.includeLower() : other.includeLower(),
upper ? main.upper() : other.upper(), upper ? main.upper() : other.upper(),
upper ? main.includeUpper() : other.includeUpper())); upper ? main.includeUpper() : other.includeUpper(),
main.zoneId()));
} }
// range was comparable // range was comparable
@ -755,7 +756,8 @@ public final class OptimizerRules {
lower ? main.lower() : other.lower(), lower ? main.lower() : other.lower(),
lower ? main.includeLower() : other.includeLower(), lower ? main.includeLower() : other.includeLower(),
upper ? main.upper() : other.upper(), upper ? main.upper() : other.upper(),
upper ? main.includeUpper() : other.includeUpper())); upper ? main.includeUpper() : other.includeUpper(),
main.zoneId()));
return true; return true;
} }
@ -790,7 +792,7 @@ public final class OptimizerRules {
ranges.add(i, ranges.add(i,
new Range(other.source(), other.value(), new Range(other.source(), other.value(),
main.right(), lowerEq ? false : main instanceof GreaterThanOrEqual, main.right(), lowerEq ? false : main instanceof GreaterThanOrEqual,
other.upper(), other.includeUpper())); other.upper(), other.includeUpper(), other.zoneId()));
} }
// found a match // found a match
@ -810,7 +812,7 @@ public final class OptimizerRules {
ranges.remove(i); ranges.remove(i);
ranges.add(i, new Range(other.source(), other.value(), ranges.add(i, new Range(other.source(), other.value(),
other.lower(), other.includeLower(), other.lower(), other.includeLower(),
main.right(), upperEq ? false : main instanceof LessThanOrEqual)); main.right(), upperEq ? false : main instanceof LessThanOrEqual, other.zoneId()));
} }
// found a match // found a match
@ -924,7 +926,7 @@ public final class OptimizerRules {
if (comp <= 0) { if (comp <= 0) {
if (comp == 0 && range.includeLower()) { // a != 2 AND 2 <= a < ? -> 2 < a < ? if (comp == 0 && range.includeLower()) { // a != 2 AND 2 <= a < ? -> 2 < a < ?
ranges.set(i, new Range(range.source(), range.value(), range.lower(), false, range.upper(), ranges.set(i, new Range(range.source(), range.value(), range.lower(), false, range.upper(),
range.includeUpper())); range.includeUpper(), range.zoneId()));
} }
// else: !.includeLower() : a != 2 AND 2 < a < 3 -> 2 < a < 3; or: // else: !.includeLower() : a != 2 AND 2 < a < 3 -> 2 < a < 3; or:
// else: comp < 0 : a != 2 AND 3 < a < ? -> 3 < a < ? // else: comp < 0 : a != 2 AND 3 < a < ? -> 3 < a < ?
@ -935,7 +937,7 @@ public final class OptimizerRules {
if (comp != null && comp >= 0) { if (comp != null && comp >= 0) {
if (comp == 0 && range.includeUpper()) { // a != 4 AND 2 < a <= 4 -> 2 < a < 4 if (comp == 0 && range.includeUpper()) { // a != 4 AND 2 < a <= 4 -> 2 < a < 4
ranges.set(i, new Range(range.source(), range.value(), range.lower(), range.includeLower(), ranges.set(i, new Range(range.source(), range.value(), range.lower(), range.includeLower(),
range.upper(), false)); range.upper(), false, range.zoneId()));
} }
// else: !.includeUpper() : a != 4 AND 2 < a < 4 -> 2 < a < 4 // else: !.includeUpper() : a != 4 AND 2 < a < 4 -> 2 < a < 4
// else: comp > 0 : a != 4 AND 2 < a < 3 -> 2 < a < 3 // else: comp > 0 : a != 4 AND 2 < a < 3 -> 2 < a < 3
@ -951,7 +953,7 @@ public final class OptimizerRules {
if (comp != null && comp >= 0) { if (comp != null && comp >= 0) {
if (comp == 0 && range.includeUpper()) { // a != 3 AND ?? < a <= 3 -> ?? < a < 3 if (comp == 0 && range.includeUpper()) { // a != 3 AND ?? < a <= 3 -> ?? < a < 3
ranges.set(i, new Range(range.source(), range.value(), range.lower(), range.includeLower(), range.upper(), ranges.set(i, new Range(range.source(), range.value(), range.lower(), range.includeLower(), range.upper(),
false)); false, range.zoneId()));
} }
// else: !.includeUpper() : a != 3 AND ?? < a < 3 -> ?? < a < 3 // else: !.includeUpper() : a != 3 AND ?? < a < 3 -> ?? < a < 3
// else: comp > 0 : a != 3 and ?? < a < 2 -> ?? < a < 2 // else: comp > 0 : a != 3 and ?? < a < 2 -> ?? < a < 2
@ -979,7 +981,7 @@ public final class OptimizerRules {
if (comp != null) { if (comp != null) {
if (comp >= 0) { if (comp >= 0) {
if (comp == 0 && bc instanceof LessThanOrEqual) { // a != 2 AND a <= 2 -> a < 2 if (comp == 0 && bc instanceof LessThanOrEqual) { // a != 2 AND a <= 2 -> a < 2
bcs.set(i, new LessThan(bc.source(), bc.left(), bc.right())); bcs.set(i, new LessThan(bc.source(), bc.left(), bc.right(), bc.zoneId()));
} // else : comp > 0 (a != 2 AND a </<= 1 -> a </<= 1), or == 0 && bc i.of "<" (a != 2 AND a < 2 -> a < 2) } // else : comp > 0 (a != 2 AND a </<= 1 -> a </<= 1), or == 0 && bc i.of "<" (a != 2 AND a < 2 -> a < 2)
return true; return true;
} // else: comp < 0 : a != 2 AND a </<= 3 -> nop } // else: comp < 0 : a != 2 AND a </<= 3 -> nop
@ -989,7 +991,7 @@ public final class OptimizerRules {
if (comp != null) { if (comp != null) {
if (comp <= 0) { if (comp <= 0) {
if (comp == 0 && bc instanceof GreaterThanOrEqual) { // a != 2 AND a >= 2 -> a > 2 if (comp == 0 && bc instanceof GreaterThanOrEqual) { // a != 2 AND a >= 2 -> a > 2
bcs.set(i, new GreaterThan(bc.source(), bc.left(), bc.right())); bcs.set(i, new GreaterThan(bc.source(), bc.left(), bc.right(), bc.zoneId()));
} // else: comp < 0 (a != 2 AND a >/>= 3 -> a >/>= 3), or == 0 && bc i.of ">" (a != 2 AND a > 2 -> a > 2) } // else: comp < 0 (a != 2 AND a >/>= 3 -> a >/>= 3), or == 0 && bc i.of ">" (a != 2 AND a > 2 -> a > 2)
return true; return true;
} // else: comp > 0 : a != 2 AND a >/>= 1 -> nop } // else: comp > 0 : a != 2 AND a >/>= 1 -> nop

View File

@ -52,6 +52,7 @@ import org.elasticsearch.xpack.ql.util.CollectionUtils;
import org.elasticsearch.xpack.ql.util.Holder; import org.elasticsearch.xpack.ql.util.Holder;
import java.time.OffsetTime; import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
import java.util.Arrays; import java.util.Arrays;
@ -59,6 +60,7 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME;
public final class ExpressionTranslators { public final class ExpressionTranslators {
@ -250,17 +252,21 @@ public final class ExpressionTranslators {
isDateLiteralComparison = true; isDateLiteralComparison = true;
} }
ZoneId zoneId = null;
if (bc.left().dataType() == DATETIME) {
zoneId = bc.zoneId();
}
if (bc instanceof GreaterThan) { if (bc instanceof GreaterThan) {
return new RangeQuery(source, name, value, false, null, false, format); return new RangeQuery(source, name, value, false, null, false, format, zoneId);
} }
if (bc instanceof GreaterThanOrEqual) { if (bc instanceof GreaterThanOrEqual) {
return new RangeQuery(source, name, value, true, null, false, format); return new RangeQuery(source, name, value, true, null, false, format, zoneId);
} }
if (bc instanceof LessThan) { if (bc instanceof LessThan) {
return new RangeQuery(source, name, null, false, value, false, format); return new RangeQuery(source, name, null, false, value, false, format, zoneId);
} }
if (bc instanceof LessThanOrEqual) { if (bc instanceof LessThanOrEqual) {
return new RangeQuery(source, name, null, false, value, true, format); return new RangeQuery(source, name, null, false, value, true, format, zoneId);
} }
if (bc instanceof Equals || bc instanceof NullEquals || bc instanceof NotEquals) { if (bc instanceof Equals || bc instanceof NullEquals || bc instanceof NotEquals) {
if (bc.left() instanceof FieldAttribute) { if (bc.left() instanceof FieldAttribute) {
@ -271,7 +277,7 @@ public final class ExpressionTranslators {
Query query; Query query;
if (isDateLiteralComparison) { if (isDateLiteralComparison) {
// dates equality uses a range query because it's the one that has a "format" parameter // dates equality uses a range query because it's the one that has a "format" parameter
query = new RangeQuery(source, name, value, true, value, true, format); query = new RangeQuery(source, name, value, true, value, true, format, zoneId);
} else { } else {
query = new TermQuery(source, name, value); query = new TermQuery(source, name, value);
} }
@ -325,7 +331,7 @@ public final class ExpressionTranslators {
} }
query = handler.wrapFunctionQuery(r, val, new RangeQuery(r.source(), handler.nameOf(val), lower.get(), r.includeLower(), query = handler.wrapFunctionQuery(r, val, new RangeQuery(r.source(), handler.nameOf(val), lower.get(), r.includeLower(),
upper.get(), r.includeUpper(), format.get())); upper.get(), r.includeUpper(), format.get(), r.zoneId()));
return query; return query;
} }

View File

@ -10,6 +10,7 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.RangeQueryBuilder; import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.time.ZoneId;
import java.util.Objects; import java.util.Objects;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery; import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
@ -20,13 +21,14 @@ public class RangeQuery extends LeafQuery {
private final Object lower, upper; private final Object lower, upper;
private final boolean includeLower, includeUpper; private final boolean includeLower, includeUpper;
private final String format; private final String format;
private final ZoneId zoneId;
public RangeQuery(Source source, String field, Object lower, boolean includeLower, Object upper, boolean includeUpper) { public RangeQuery(Source source, String field, Object lower, boolean includeLower, Object upper, boolean includeUpper, ZoneId zoneId) {
this(source, field, lower, includeLower, upper, includeUpper, null); this(source, field, lower, includeLower, upper, includeUpper, null, zoneId);
} }
public RangeQuery(Source source, String field, Object lower, boolean includeLower, Object upper, public RangeQuery(Source source, String field, Object lower, boolean includeLower, Object upper,
boolean includeUpper, String format) { boolean includeUpper, String format, ZoneId zoneId) {
super(source); super(source);
this.field = field; this.field = field;
this.lower = lower; this.lower = lower;
@ -34,6 +36,7 @@ public class RangeQuery extends LeafQuery {
this.includeLower = includeLower; this.includeLower = includeLower;
this.includeUpper = includeUpper; this.includeUpper = includeUpper;
this.format = format; this.format = format;
this.zoneId = zoneId;
} }
public String field() { public String field() {
@ -60,19 +63,26 @@ public class RangeQuery extends LeafQuery {
return format; return format;
} }
public ZoneId zoneId() {
return zoneId;
}
@Override @Override
public QueryBuilder asBuilder() { public QueryBuilder asBuilder() {
RangeQueryBuilder queryBuilder = rangeQuery(field).from(lower, includeLower).to(upper, includeUpper); RangeQueryBuilder queryBuilder = rangeQuery(field).from(lower, includeLower).to(upper, includeUpper);
if (Strings.hasText(format)) { if (Strings.hasText(format)) {
queryBuilder.format(format); queryBuilder.format(format);
} }
if (zoneId != null) {
queryBuilder.timeZone(zoneId.getId());
}
return queryBuilder; return queryBuilder;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(field, lower, upper, includeLower, includeUpper, format); return Objects.hash(field, lower, upper, includeLower, includeUpper, format, zoneId);
} }
@Override @Override
@ -91,13 +101,14 @@ public class RangeQuery extends LeafQuery {
Objects.equals(includeUpper, other.includeUpper) && Objects.equals(includeUpper, other.includeUpper) &&
Objects.equals(lower, other.lower) && Objects.equals(lower, other.lower) &&
Objects.equals(upper, other.upper) && Objects.equals(upper, other.upper) &&
Objects.equals(format, other.format); Objects.equals(format, other.format) &&
Objects.equals(zoneId, other.zoneId);
} }
@Override @Override
protected String innerToString() { protected String innerToString() {
return field + ":" return field + ":"
+ (includeLower ? "[" : "(") + lower + ", " + (includeLower ? "[" : "(") + lower + ", "
+ upper + (includeUpper ? "]" : ")"); + upper + (includeUpper ? "]" : ")") + "@" + zoneId.getId();
} }
} }

View File

@ -6,7 +6,16 @@
package org.elasticsearch.xpack.ql; package org.elasticsearch.xpack.ql;
import org.elasticsearch.xpack.ql.expression.Expression;
import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.Literal;
import org.elasticsearch.xpack.ql.expression.predicate.Range;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThan;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThanOrEqual;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NullEquals;
import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.session.Configuration;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.DataTypes;
@ -15,6 +24,7 @@ import java.time.ZoneId;
import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength; import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength;
import static org.elasticsearch.test.ESTestCase.randomZone; import static org.elasticsearch.test.ESTestCase.randomZone;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
public final class TestUtils { public final class TestUtils {
@ -49,4 +59,36 @@ public final class TestUtils {
} }
return new Literal(source, value, DataTypes.fromJava(value)); return new Literal(source, value, DataTypes.fromJava(value));
} }
public static Equals equalsOf(Expression left, Expression right) {
return new Equals(EMPTY, left, right, randomZone());
}
public static NotEquals notEqualsOf(Expression left, Expression right) {
return new NotEquals(EMPTY, left, right, randomZone());
}
public static NullEquals nullEqualsOf(Expression left, Expression right) {
return new NullEquals(EMPTY, left, right, randomZone());
}
public static LessThan lessThanOf(Expression left, Expression right) {
return new LessThan(EMPTY, left, right, randomZone());
}
public static LessThanOrEqual lessThanOrEqualOf(Expression left, Expression right) {
return new LessThanOrEqual(EMPTY, left, right, randomZone());
}
public static GreaterThan greaterThanOf(Expression left, Expression right) {
return new GreaterThan(EMPTY, left, right, randomZone());
}
public static GreaterThanOrEqual greaterThanOrEqualOf(Expression left, Expression right) {
return new GreaterThanOrEqual(EMPTY, left, right, randomZone());
}
public static Range rangeOf(Expression value, Expression lower, boolean includeLower, Expression upper, boolean includeUpper) {
return new Range(EMPTY, value, lower, includeLower, upper, includeUpper, randomZone());
}
} }

View File

@ -13,6 +13,13 @@ import org.elasticsearch.xpack.ql.expression.Literal;
import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor;
import org.elasticsearch.xpack.ql.expression.processor.Processors; import org.elasticsearch.xpack.ql.expression.processor.Processors;
import static org.elasticsearch.xpack.ql.TestUtils.equalsOf;
import static org.elasticsearch.xpack.ql.TestUtils.greaterThanOf;
import static org.elasticsearch.xpack.ql.TestUtils.greaterThanOrEqualOf;
import static org.elasticsearch.xpack.ql.TestUtils.lessThanOf;
import static org.elasticsearch.xpack.ql.TestUtils.lessThanOrEqualOf;
import static org.elasticsearch.xpack.ql.TestUtils.notEqualsOf;
import static org.elasticsearch.xpack.ql.TestUtils.nullEqualsOf;
import static org.elasticsearch.xpack.ql.expression.Literal.NULL; import static org.elasticsearch.xpack.ql.expression.Literal.NULL;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
@ -40,54 +47,54 @@ public class BinaryComparisonProcessorTests extends AbstractWireSerializingTestC
} }
public void testEq() { public void testEq() {
assertEquals(true, new Equals(EMPTY, l(4), l(4)).makePipe().asProcessor().process(null)); assertEquals(true, equalsOf(l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, new Equals(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null)); assertEquals(false, equalsOf(l(3), l(4)).makePipe().asProcessor().process(null));
} }
public void testNullEq() { public void testNullEq() {
assertEquals(true, new NullEquals(EMPTY, l(4), l(4)).makePipe().asProcessor().process(null)); assertEquals(true, nullEqualsOf(l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, new NullEquals(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null)); assertEquals(false, nullEqualsOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, new NullEquals(EMPTY, NULL, NULL).makePipe().asProcessor().process(null)); assertEquals(true, nullEqualsOf(NULL, NULL).makePipe().asProcessor().process(null));
assertEquals(false, new NullEquals(EMPTY, l(4), NULL).makePipe().asProcessor().process(null)); assertEquals(false, nullEqualsOf(l(4), NULL).makePipe().asProcessor().process(null));
assertEquals(false, new NullEquals(EMPTY, NULL, l(4)).makePipe().asProcessor().process(null)); assertEquals(false, nullEqualsOf(NULL, l(4)).makePipe().asProcessor().process(null));
} }
public void testNEq() { public void testNEq() {
assertEquals(false, new NotEquals(EMPTY, l(4), l(4)).makePipe().asProcessor().process(null)); assertEquals(false, notEqualsOf(l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, new NotEquals(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null)); assertEquals(true, notEqualsOf(l(3), l(4)).makePipe().asProcessor().process(null));
} }
public void testGt() { public void testGt() {
assertEquals(true, new GreaterThan(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null)); assertEquals(true, greaterThanOf(l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(false, new GreaterThan(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null)); assertEquals(false, greaterThanOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, new GreaterThan(EMPTY, l(3), l(3)).makePipe().asProcessor().process(null)); assertEquals(false, greaterThanOf(l(3), l(3)).makePipe().asProcessor().process(null));
} }
public void testGte() { public void testGte() {
assertEquals(true, new GreaterThanOrEqual(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null)); assertEquals(true, greaterThanOrEqualOf(l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(false, new GreaterThanOrEqual(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null)); assertEquals(false, greaterThanOrEqualOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, new GreaterThanOrEqual(EMPTY, l(3), l(3)).makePipe().asProcessor().process(null)); assertEquals(true, greaterThanOrEqualOf(l(3), l(3)).makePipe().asProcessor().process(null));
} }
public void testLt() { public void testLt() {
assertEquals(false, new LessThan(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null)); assertEquals(false, lessThanOf(l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(true, new LessThan(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null)); assertEquals(true, lessThanOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, new LessThan(EMPTY, l(3), l(3)).makePipe().asProcessor().process(null)); assertEquals(false, lessThanOf(l(3), l(3)).makePipe().asProcessor().process(null));
} }
public void testLte() { public void testLte() {
assertEquals(false, new LessThanOrEqual(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null)); assertEquals(false, lessThanOrEqualOf(l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(true, new LessThanOrEqual(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null)); assertEquals(true, lessThanOrEqualOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, new LessThanOrEqual(EMPTY, l(3), l(3)).makePipe().asProcessor().process(null)); assertEquals(true, lessThanOrEqualOf(l(3), l(3)).makePipe().asProcessor().process(null));
} }
public void testHandleNull() { public void testHandleNull() {
assertNull(new Equals(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null)); assertNull(equalsOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new NotEquals(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null)); assertNull(notEqualsOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new GreaterThan(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null)); assertNull(greaterThanOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new GreaterThanOrEqual(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null)); assertNull(greaterThanOrEqualOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new LessThan(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null)); assertNull(lessThanOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new LessThanOrEqual(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null)); assertNull(lessThanOrEqualOf(NULL, l(3)).makePipe().asProcessor().process(null));
} }
private static Literal l(Object value) { private static Literal l(Object value) {

View File

@ -44,12 +44,21 @@ import org.elasticsearch.xpack.ql.tree.Source;
import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.DataType;
import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.type.EsField;
import java.time.ZoneId;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static org.elasticsearch.xpack.ql.TestUtils.equalsOf;
import static org.elasticsearch.xpack.ql.TestUtils.greaterThanOf;
import static org.elasticsearch.xpack.ql.TestUtils.greaterThanOrEqualOf;
import static org.elasticsearch.xpack.ql.TestUtils.lessThanOf;
import static org.elasticsearch.xpack.ql.TestUtils.lessThanOrEqualOf;
import static org.elasticsearch.xpack.ql.TestUtils.notEqualsOf;
import static org.elasticsearch.xpack.ql.TestUtils.nullEqualsOf;
import static org.elasticsearch.xpack.ql.TestUtils.of; import static org.elasticsearch.xpack.ql.TestUtils.of;
import static org.elasticsearch.xpack.ql.TestUtils.rangeOf;
import static org.elasticsearch.xpack.ql.expression.Literal.FALSE; import static org.elasticsearch.xpack.ql.expression.Literal.FALSE;
import static org.elasticsearch.xpack.ql.expression.Literal.NULL; import static org.elasticsearch.xpack.ql.expression.Literal.NULL;
import static org.elasticsearch.xpack.ql.expression.Literal.TRUE; import static org.elasticsearch.xpack.ql.expression.Literal.TRUE;
@ -144,21 +153,21 @@ public class OptimizerRulesTests extends ESTestCase {
} }
public void testConstantFoldingBinaryComparison() { public void testConstantFoldingBinaryComparison() {
assertEquals(FALSE, new ConstantFolding().rule(new GreaterThan(EMPTY, TWO, THREE)).canonical()); assertEquals(FALSE, new ConstantFolding().rule(greaterThanOf(TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new GreaterThanOrEqual(EMPTY, TWO, THREE)).canonical()); assertEquals(FALSE, new ConstantFolding().rule(greaterThanOrEqualOf(TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new Equals(EMPTY, TWO, THREE)).canonical()); assertEquals(FALSE, new ConstantFolding().rule(equalsOf(TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new NullEquals(EMPTY, TWO, THREE)).canonical()); assertEquals(FALSE, new ConstantFolding().rule(nullEqualsOf(TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new NullEquals(EMPTY, TWO, NULL)).canonical()); assertEquals(FALSE, new ConstantFolding().rule(nullEqualsOf(TWO, NULL)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(new NotEquals(EMPTY, TWO, THREE)).canonical()); assertEquals(TRUE, new ConstantFolding().rule(notEqualsOf(TWO, THREE)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(new LessThanOrEqual(EMPTY, TWO, THREE)).canonical()); assertEquals(TRUE, new ConstantFolding().rule(lessThanOrEqualOf(TWO, THREE)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(new LessThan(EMPTY, TWO, THREE)).canonical()); assertEquals(TRUE, new ConstantFolding().rule(lessThanOf(TWO, THREE)).canonical());
} }
public void testConstantFoldingBinaryLogic() { public void testConstantFoldingBinaryLogic() {
assertEquals(FALSE, assertEquals(FALSE,
new ConstantFolding().rule(new And(EMPTY, new GreaterThan(EMPTY, TWO, THREE), TRUE)).canonical()); new ConstantFolding().rule(new And(EMPTY, greaterThanOf(TWO, THREE), TRUE)).canonical());
assertEquals(TRUE, assertEquals(TRUE,
new ConstantFolding().rule(new Or(EMPTY, new GreaterThanOrEqual(EMPTY, TWO, THREE), TRUE)).canonical()); new ConstantFolding().rule(new Or(EMPTY, greaterThanOrEqualOf(TWO, THREE), TRUE)).canonical());
} }
public void testConstantFoldingBinaryLogic_WithNullHandling() { public void testConstantFoldingBinaryLogic_WithNullHandling() {
@ -176,8 +185,8 @@ public class OptimizerRulesTests extends ESTestCase {
} }
public void testConstantFoldingRange() { public void testConstantFoldingRange() {
assertEquals(true, new ConstantFolding().rule(new Range(EMPTY, FIVE, FIVE, true, L(10), false)).fold()); assertEquals(true, new ConstantFolding().rule(rangeOf(FIVE, FIVE, true, L(10), false)).fold());
assertEquals(false, new ConstantFolding().rule(new Range(EMPTY, FIVE, FIVE, false, L(10), false)).fold()); assertEquals(false, new ConstantFolding().rule(rangeOf(FIVE, FIVE, false, L(10), false)).fold());
} }
public void testConstantNot() { public void testConstantNot() {
@ -211,14 +220,14 @@ public class OptimizerRulesTests extends ESTestCase {
public void testLiteralsOnTheRight() { public void testLiteralsOnTheRight() {
Alias a = new Alias(EMPTY, "a", L(10)); Alias a = new Alias(EMPTY, "a", L(10));
Expression result = new BooleanLiteralsOnTheRight().rule(new Equals(EMPTY, FIVE, a)); Expression result = new BooleanLiteralsOnTheRight().rule(equalsOf(FIVE, a));
assertTrue(result instanceof Equals); assertTrue(result instanceof Equals);
Equals eq = (Equals) result; Equals eq = (Equals) result;
assertEquals(a, eq.left()); assertEquals(a, eq.left());
assertEquals(FIVE, eq.right()); assertEquals(FIVE, eq.right());
a = new Alias(EMPTY, "a", L(10)); a = new Alias(EMPTY, "a", L(10));
result = new BooleanLiteralsOnTheRight().rule(new NullEquals(EMPTY, FIVE, a)); result = new BooleanLiteralsOnTheRight().rule(nullEqualsOf(FIVE, a));
assertTrue(result instanceof NullEquals); assertTrue(result instanceof NullEquals);
NullEquals nullEquals= (NullEquals) result; NullEquals nullEquals= (NullEquals) result;
assertEquals(a, nullEquals.left()); assertEquals(a, nullEquals.left());
@ -271,7 +280,7 @@ public class OptimizerRulesTests extends ESTestCase {
public void testFoldExcludingRangeToFalse() { public void testFoldExcludingRangeToFalse() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r = new Range(EMPTY, fa, SIX, false, FIVE, true); Range r = rangeOf(fa, SIX, false, FIVE, true);
assertTrue(r.foldable()); assertTrue(r.foldable());
assertEquals(Boolean.FALSE, r.fold()); assertEquals(Boolean.FALSE, r.fold());
} }
@ -280,7 +289,7 @@ public class OptimizerRulesTests extends ESTestCase {
public void testFoldExcludingRangeWithDifferentTypesToFalse() { public void testFoldExcludingRangeWithDifferentTypesToFalse() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r = new Range(EMPTY, fa, SIX, false, L(5.5d), true); Range r = rangeOf(fa, SIX, false, L(5.5d), true);
assertTrue(r.foldable()); assertTrue(r.foldable());
assertEquals(Boolean.FALSE, r.fold()); assertEquals(Boolean.FALSE, r.fold());
} }
@ -289,8 +298,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsNotComparable() { public void testCombineBinaryComparisonsNotComparable() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, SIX); LessThanOrEqual lte = lessThanOrEqualOf(fa, SIX);
LessThan lt = new LessThan(EMPTY, fa, FALSE); LessThan lt = lessThanOf(fa, FALSE);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
And and = new And(EMPTY, lte, lt); And and = new And(EMPTY, lte, lt);
@ -301,8 +310,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a <= 6 AND a < 5 -> a < 5 // a <= 6 AND a < 5 -> a < 5
public void testCombineBinaryComparisonsUpper() { public void testCombineBinaryComparisonsUpper() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, SIX); LessThanOrEqual lte = lessThanOrEqualOf(fa, SIX);
LessThan lt = new LessThan(EMPTY, fa, FIVE); LessThan lt = lessThanOf(fa, FIVE);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -315,8 +324,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 6 <= a AND 5 < a -> 6 <= a // 6 <= a AND 5 < a -> 6 <= a
public void testCombineBinaryComparisonsLower() { public void testCombineBinaryComparisonsLower() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, SIX); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, SIX);
GreaterThan gt = new GreaterThan(EMPTY, fa, FIVE); GreaterThan gt = greaterThanOf(fa, FIVE);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -329,8 +338,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 5 <= a AND 5 < a -> 5 < a // 5 <= a AND 5 < a -> 5 < a
public void testCombineBinaryComparisonsInclude() { public void testCombineBinaryComparisonsInclude() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, FIVE); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, FIVE);
GreaterThan gt = new GreaterThan(EMPTY, fa, FIVE); GreaterThan gt = greaterThanOf(fa, FIVE);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -344,8 +353,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsAndRangeLower() { public void testCombineBinaryComparisonsAndRangeLower() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThan gt = new GreaterThan(EMPTY, fa, TWO); GreaterThan gt = greaterThanOf(fa, TWO);
Range range = new Range(EMPTY, fa, TWO, true, THREE, false); Range range = rangeOf(fa, TWO, true, THREE, false);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression exp = rule.rule(new And(EMPTY, gt, range)); Expression exp = rule.rule(new And(EMPTY, gt, range));
@ -361,8 +370,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsAndRangeUpper() { public void testCombineBinaryComparisonsAndRangeUpper() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
LessThan lt = new LessThan(EMPTY, fa, FOUR); LessThan lt = lessThanOf(fa, FOUR);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false); Range range = rangeOf(fa, ONE, false, THREE, false);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression exp = rule.rule(new And(EMPTY, range, lt)); Expression exp = rule.rule(new And(EMPTY, range, lt));
@ -378,8 +387,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsAndRangeUpperEqual() { public void testCombineBinaryComparisonsAndRangeUpperEqual() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, TWO); LessThanOrEqual lte = lessThanOrEqualOf(fa, TWO);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false); Range range = rangeOf(fa, ONE, false, THREE, false);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression exp = rule.rule(new And(EMPTY, lte, range)); Expression exp = rule.rule(new And(EMPTY, lte, range));
@ -394,10 +403,10 @@ public class OptimizerRulesTests extends ESTestCase {
// 3 <= a AND 4 < a AND a <= 7 AND a < 6 -> 4 < a < 6 // 3 <= a AND 4 < a AND a <= 7 AND a < 6 -> 4 < a < 6
public void testCombineMultipleBinaryComparisons() { public void testCombineMultipleBinaryComparisons() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, THREE); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, THREE);
GreaterThan gt = new GreaterThan(EMPTY, fa, FOUR); GreaterThan gt = greaterThanOf(fa, FOUR);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, L(7)); LessThanOrEqual lte = lessThanOrEqualOf(fa, L(7));
LessThan lt = new LessThan(EMPTY, fa, SIX); LessThan lt = lessThanOf(fa, SIX);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -413,10 +422,10 @@ public class OptimizerRulesTests extends ESTestCase {
// 3 <= a AND TRUE AND 4 < a AND a != 5 AND a <= 7 -> 4 < a <= 7 AND a != 5 AND TRUE // 3 <= a AND TRUE AND 4 < a AND a != 5 AND a <= 7 -> 4 < a <= 7 AND a != 5 AND TRUE
public void testCombineMixedMultipleBinaryComparisons() { public void testCombineMixedMultipleBinaryComparisons() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, THREE); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, THREE);
GreaterThan gt = new GreaterThan(EMPTY, fa, FOUR); GreaterThan gt = greaterThanOf(fa, FOUR);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, L(7)); LessThanOrEqual lte = lessThanOrEqualOf(fa, L(7));
Expression ne = new Not(EMPTY, new Equals(EMPTY, fa, FIVE)); Expression ne = new Not(EMPTY, equalsOf(fa, FIVE));
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -435,8 +444,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 1 <= a AND a < 5 -> 1 <= a < 5 // 1 <= a AND a < 5 -> 1 <= a < 5
public void testCombineComparisonsIntoRange() { public void testCombineComparisonsIntoRange() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, ONE); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, ONE);
LessThan lt = new LessThan(EMPTY, fa, FIVE); LessThan lt = lessThanOf(fa, FIVE);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression exp = rule.rule(new And(EMPTY, gte, lt)); Expression exp = rule.rule(new And(EMPTY, gte, lt));
@ -455,19 +464,20 @@ public class OptimizerRulesTests extends ESTestCase {
FieldAttribute fb = getFieldAttribute("b"); FieldAttribute fb = getFieldAttribute("b");
FieldAttribute fc = getFieldAttribute("c"); FieldAttribute fc = getFieldAttribute("c");
GreaterThan agt1 = new GreaterThan(EMPTY, fa, ONE); ZoneId zoneId = randomZone();
LessThan alt3 = new LessThan(EMPTY, fa, THREE); GreaterThan agt1 = new GreaterThan(EMPTY, fa, ONE, zoneId);
GreaterThan bgt2 = new GreaterThan(EMPTY, fb, TWO); LessThan alt3 = new LessThan(EMPTY, fa, THREE, zoneId);
LessThan blt4 = new LessThan(EMPTY, fb, FOUR); GreaterThan bgt2 = new GreaterThan(EMPTY, fb, TWO, zoneId);
LessThan clt4 = new LessThan(EMPTY, fc, FOUR); LessThan blt4 = new LessThan(EMPTY, fb, FOUR, zoneId);
LessThan clt4 = new LessThan(EMPTY, fc, FOUR, zoneId);
Expression inputAnd = Predicates.combineAnd(Arrays.asList(agt1, alt3, bgt2, blt4, clt4)); Expression inputAnd = Predicates.combineAnd(Arrays.asList(agt1, alt3, bgt2, blt4, clt4));
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression outputAnd = rule.rule(inputAnd); Expression outputAnd = rule.rule(inputAnd);
Range agt1lt3 = new Range(EMPTY, fa, ONE, false, THREE, false); Range agt1lt3 = new Range(EMPTY, fa, ONE, false, THREE, false, zoneId);
Range bgt2lt4 = new Range(EMPTY, fb, TWO, false, FOUR, false); Range bgt2lt4 = new Range(EMPTY, fb, TWO, false, FOUR, false, zoneId);
// The actual outcome is (c < 4) AND (1 < a < 3) AND (2 < b < 4), due to the way the Expression types are combined in the Optimizer // The actual outcome is (c < 4) AND (1 < a < 3) AND (2 < b < 4), due to the way the Expression types are combined in the Optimizer
Expression expectedAnd = Predicates.combineAnd(Arrays.asList(clt4, agt1lt3, bgt2lt4)); Expression expectedAnd = Predicates.combineAnd(Arrays.asList(clt4, agt1lt3, bgt2lt4));
@ -479,8 +489,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionOfIncludedRange() { public void testCombineBinaryComparisonsConjunctionOfIncludedRange() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, FOUR, false); Range r2 = rangeOf(fa, ONE, false, FOUR, false);
And and = new And(EMPTY, r1, r2); And and = new And(EMPTY, r1, r2);
@ -493,8 +503,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionOfNonOverlappingBoundaries() { public void testCombineBinaryComparisonsConjunctionOfNonOverlappingBoundaries() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, TWO, false); Range r2 = rangeOf(fa, ONE, false, TWO, false);
And and = new And(EMPTY, r1, r2); And and = new And(EMPTY, r1, r2);
@ -513,8 +523,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionOfUpperEqualsOverlappingBoundaries() { public void testCombineBinaryComparisonsConjunctionOfUpperEqualsOverlappingBoundaries() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, true); Range r2 = rangeOf(fa, TWO, false, THREE, true);
And and = new And(EMPTY, r1, r2); And and = new And(EMPTY, r1, r2);
@ -527,8 +537,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionOverlappingUpperBoundary() { public void testCombineBinaryComparisonsConjunctionOverlappingUpperBoundary() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r2 = rangeOf(fa, TWO, false, THREE, false);
Range r1 = new Range(EMPTY, fa, ONE, false, THREE, false); Range r1 = rangeOf(fa, ONE, false, THREE, false);
And and = new And(EMPTY, r1, r2); And and = new And(EMPTY, r1, r2);
@ -541,8 +551,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionWithDifferentUpperLimitInclusion() { public void testCombineBinaryComparisonsConjunctionWithDifferentUpperLimitInclusion() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, ONE, false, THREE, false); Range r1 = rangeOf(fa, ONE, false, THREE, false);
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, true); Range r2 = rangeOf(fa, TWO, false, THREE, true);
And and = new And(EMPTY, r1, r2); And and = new And(EMPTY, r1, r2);
@ -560,8 +570,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testRangesOverlappingConjunctionNoLowerBoundary() { public void testRangesOverlappingConjunctionNoLowerBoundary() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, L(0), false, ONE, true); Range r1 = rangeOf(fa, L(0), false, ONE, true);
Range r2 = new Range(EMPTY, fa, L(0), true, TWO, false); Range r2 = rangeOf(fa, L(0), true, TWO, false);
And and = new And(EMPTY, r1, r2); And and = new And(EMPTY, r1, r2);
@ -574,8 +584,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt3Lt5() { public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt3Lt5() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
Range range = new Range(EMPTY, fa, THREE, false, FIVE, false); Range range = rangeOf(fa, THREE, false, FIVE, false);
And and = new And(EMPTY, range, neq); And and = new And(EMPTY, range, neq);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -592,8 +602,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt0Lt1() { public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt0Lt1() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
Range range = new Range(EMPTY, fa, L(0), false, ONE, false); Range range = rangeOf(fa, L(0), false, ONE, false);
And and = new And(EMPTY, neq, range); And and = new And(EMPTY, neq, range);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -610,8 +620,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGte2Lt3() { public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGte2Lt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
Range range = new Range(EMPTY, fa, TWO, true, THREE, false); Range range = rangeOf(fa, TWO, true, THREE, false);
And and = new And(EMPTY, neq, range); And and = new And(EMPTY, neq, range);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -628,8 +638,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq3AndRangeGt2Lte3() { public void testCombineBinaryComparisonsConjunction_Neq3AndRangeGt2Lte3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, THREE); NotEquals neq = notEqualsOf(fa, THREE);
Range range = new Range(EMPTY, fa, TWO, false, THREE, true); Range range = rangeOf(fa, TWO, false, THREE, true);
And and = new And(EMPTY, neq, range); And and = new And(EMPTY, neq, range);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -646,8 +656,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt1Lt3() { public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt1Lt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false); Range range = rangeOf(fa, ONE, false, THREE, false);
And and = new And(EMPTY, neq, range); And and = new And(EMPTY, neq, range);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -659,8 +669,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndGt3() { public void testCombineBinaryComparisonsConjunction_Neq2AndGt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, THREE); GreaterThan gt = greaterThanOf(fa, THREE);
And and = new And(EMPTY, neq, gt); And and = new And(EMPTY, neq, gt);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -672,8 +682,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndGte2() { public void testCombineBinaryComparisonsConjunction_Neq2AndGte2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, TWO); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, TWO);
And and = new And(EMPTY, neq, gte); And and = new And(EMPTY, neq, gte);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -687,8 +697,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndGte1() { public void testCombineBinaryComparisonsConjunction_Neq2AndGte1() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, ONE); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, ONE);
And and = new And(EMPTY, neq, gte); And and = new And(EMPTY, neq, gte);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -700,8 +710,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndLte3() { public void testCombineBinaryComparisonsConjunction_Neq2AndLte3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, THREE); LessThanOrEqual lte = lessThanOrEqualOf(fa, THREE);
And and = new And(EMPTY, neq, lte); And and = new And(EMPTY, neq, lte);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -713,8 +723,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndLte2() { public void testCombineBinaryComparisonsConjunction_Neq2AndLte2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, TWO); LessThanOrEqual lte = lessThanOrEqualOf(fa, TWO);
And and = new And(EMPTY, neq, lte); And and = new And(EMPTY, neq, lte);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -728,8 +738,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndLte1() { public void testCombineBinaryComparisonsConjunction_Neq2AndLte1() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, ONE); LessThanOrEqual lte = lessThanOrEqualOf(fa, ONE);
And and = new And(EMPTY, neq, lte); And and = new And(EMPTY, neq, lte);
CombineBinaryComparisons rule = new CombineBinaryComparisons(); CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -742,8 +752,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionNotComparable() { public void testCombineBinaryComparisonsDisjunctionNotComparable() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThan gt1 = new GreaterThan(EMPTY, fa, ONE); GreaterThan gt1 = greaterThanOf(fa, ONE);
GreaterThan gt2 = new GreaterThan(EMPTY, fa, FALSE); GreaterThan gt2 = greaterThanOf(fa, FALSE);
Or or = new Or(EMPTY, gt1, gt2); Or or = new Or(EMPTY, gt1, gt2);
@ -757,9 +767,9 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionLowerBound() { public void testCombineBinaryComparisonsDisjunctionLowerBound() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThan gt1 = new GreaterThan(EMPTY, fa, ONE); GreaterThan gt1 = greaterThanOf(fa, ONE);
GreaterThan gt2 = new GreaterThan(EMPTY, fa, TWO); GreaterThan gt2 = greaterThanOf(fa, TWO);
GreaterThan gt3 = new GreaterThan(EMPTY, fa, THREE); GreaterThan gt3 = greaterThanOf(fa, THREE);
Or or = new Or(EMPTY, gt1, new Or(EMPTY, gt2, gt3)); Or or = new Or(EMPTY, gt1, new Or(EMPTY, gt2, gt3));
@ -775,9 +785,9 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionIncludeLowerBounds() { public void testCombineBinaryComparisonsDisjunctionIncludeLowerBounds() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
GreaterThan gt1 = new GreaterThan(EMPTY, fa, ONE); GreaterThan gt1 = greaterThanOf(fa, ONE);
GreaterThan gt2 = new GreaterThan(EMPTY, fa, TWO); GreaterThan gt2 = greaterThanOf(fa, TWO);
GreaterThanOrEqual gte3 = new GreaterThanOrEqual(EMPTY, fa, THREE); GreaterThanOrEqual gte3 = greaterThanOrEqualOf(fa, THREE);
Or or = new Or(EMPTY, new Or(EMPTY, gt1, gt2), gte3); Or or = new Or(EMPTY, new Or(EMPTY, gt1, gt2), gte3);
@ -793,9 +803,9 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionUpperBound() { public void testCombineBinaryComparisonsDisjunctionUpperBound() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
LessThan lt1 = new LessThan(EMPTY, fa, ONE); LessThan lt1 = lessThanOf(fa, ONE);
LessThan lt2 = new LessThan(EMPTY, fa, TWO); LessThan lt2 = lessThanOf(fa, TWO);
LessThan lt3 = new LessThan(EMPTY, fa, THREE); LessThan lt3 = lessThanOf(fa, THREE);
Or or = new Or(EMPTY, new Or(EMPTY, lt1, lt2), lt3); Or or = new Or(EMPTY, new Or(EMPTY, lt1, lt2), lt3);
@ -811,9 +821,9 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionIncludeUpperBounds() { public void testCombineBinaryComparisonsDisjunctionIncludeUpperBounds() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
LessThan lt1 = new LessThan(EMPTY, fa, ONE); LessThan lt1 = lessThanOf(fa, ONE);
LessThan lt2 = new LessThan(EMPTY, fa, TWO); LessThan lt2 = lessThanOf(fa, TWO);
LessThanOrEqual lte2 = new LessThanOrEqual(EMPTY, fa, TWO); LessThanOrEqual lte2 = lessThanOrEqualOf(fa, TWO);
Or or = new Or(EMPTY, lt2, new Or(EMPTY, lte2, lt1)); Or or = new Or(EMPTY, lt2, new Or(EMPTY, lte2, lt1));
@ -829,11 +839,11 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionOfLowerAndUpperBounds() { public void testCombineBinaryComparisonsDisjunctionOfLowerAndUpperBounds() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
LessThan lt1 = new LessThan(EMPTY, fa, ONE); LessThan lt1 = lessThanOf(fa, ONE);
LessThan lt2 = new LessThan(EMPTY, fa, TWO); LessThan lt2 = lessThanOf(fa, TWO);
GreaterThan gt3 = new GreaterThan(EMPTY, fa, THREE); GreaterThan gt3 = greaterThanOf(fa, THREE);
GreaterThan gt4 = new GreaterThan(EMPTY, fa, FOUR); GreaterThan gt4 = greaterThanOf(fa, FOUR);
Or or = new Or(EMPTY, new Or(EMPTY, lt2, gt3), new Or(EMPTY, lt1, gt4)); Or or = new Or(EMPTY, new Or(EMPTY, lt2, gt3), new Or(EMPTY, lt1, gt4));
@ -855,8 +865,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionOfIncludedRangeNotComparable() { public void testCombineBinaryComparisonsDisjunctionOfIncludedRangeNotComparable() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, FALSE, false); Range r2 = rangeOf(fa, ONE, false, FALSE, false);
Or or = new Or(EMPTY, r1, r2); Or or = new Or(EMPTY, r1, r2);
@ -870,8 +880,8 @@ public class OptimizerRulesTests extends ESTestCase {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, FOUR, false); Range r2 = rangeOf(fa, ONE, false, FOUR, false);
Or or = new Or(EMPTY, r1, r2); Or or = new Or(EMPTY, r1, r2);
@ -890,8 +900,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionOfNonOverlappingBoundaries() { public void testCombineBinaryComparisonsDisjunctionOfNonOverlappingBoundaries() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, TWO, false); Range r2 = rangeOf(fa, ONE, false, TWO, false);
Or or = new Or(EMPTY, r1, r2); Or or = new Or(EMPTY, r1, r2);
@ -904,8 +914,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionOfUpperEqualsOverlappingBoundaries() { public void testCombineBinaryComparisonsDisjunctionOfUpperEqualsOverlappingBoundaries() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, true); Range r2 = rangeOf(fa, TWO, false, THREE, true);
Or or = new Or(EMPTY, r1, r2); Or or = new Or(EMPTY, r1, r2);
@ -918,8 +928,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsOverlappingUpperBoundary() { public void testCombineBinaryComparisonsOverlappingUpperBoundary() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, false); Range r2 = rangeOf(fa, TWO, false, THREE, false);
Range r1 = new Range(EMPTY, fa, ONE, false, THREE, false); Range r1 = rangeOf(fa, ONE, false, THREE, false);
Or or = new Or(EMPTY, r1, r2); Or or = new Or(EMPTY, r1, r2);
@ -932,8 +942,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsWithDifferentUpperLimitInclusion() { public void testCombineBinaryComparisonsWithDifferentUpperLimitInclusion() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, ONE, false, THREE, false); Range r1 = rangeOf(fa, ONE, false, THREE, false);
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, true); Range r2 = rangeOf(fa, TWO, false, THREE, true);
Or or = new Or(EMPTY, r1, r2); Or or = new Or(EMPTY, r1, r2);
@ -948,9 +958,9 @@ public class OptimizerRulesTests extends ESTestCase {
FieldAttribute fb = getFieldAttribute("b"); FieldAttribute fb = getFieldAttribute("b");
FieldAttribute fc = getFieldAttribute("c"); FieldAttribute fc = getFieldAttribute("c");
Expression a1 = new Equals(EMPTY, fa, ONE); Expression a1 = equalsOf(fa, ONE);
Expression a2 = new Equals(EMPTY, fa, TWO); Expression a2 = equalsOf(fa, TWO);
And common = new And(EMPTY, new Equals(EMPTY, fb, THREE), new Equals(EMPTY, fc, FOUR)); And common = new And(EMPTY, equalsOf(fb, THREE), equalsOf(fc, FOUR));
And left = new And(EMPTY, a1, common); And left = new And(EMPTY, a1, common);
And right = new And(EMPTY, a2, common); And right = new And(EMPTY, a2, common);
Or or = new Or(EMPTY, left, right); Or or = new Or(EMPTY, left, right);
@ -963,8 +973,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testRangesOverlappingNoLowerBoundary() { public void testRangesOverlappingNoLowerBoundary() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Range r2 = new Range(EMPTY, fa, L(0), false, TWO, false); Range r2 = rangeOf(fa, L(0), false, TWO, false);
Range r1 = new Range(EMPTY, fa, L(0), false, ONE, true); Range r1 = rangeOf(fa, L(0), false, ONE, true);
Or or = new Or(EMPTY, r1, r2); Or or = new Or(EMPTY, r1, r2);
@ -979,8 +989,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 1 <= a < 10 AND a == 1 -> a == 1 // 1 <= a < 10 AND a == 1 -> a == 1
public void testEliminateRangeByEqualsInInterval() { public void testEliminateRangeByEqualsInInterval() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq1 = new Equals(EMPTY, fa, ONE); Equals eq1 = equalsOf(fa, ONE);
Range r = new Range(EMPTY, fa, ONE, true, L(10), false); Range r = rangeOf(fa, ONE, true, L(10), false);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, r)); Expression exp = rule.rule(new And(EMPTY, eq1, r));
@ -990,8 +1000,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 1 <= a < 10 AND a <=> 1 -> a <=> 1 // 1 <= a < 10 AND a <=> 1 -> a <=> 1
public void testEliminateRangeByNullEqualsInInterval() { public void testEliminateRangeByNullEqualsInInterval() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NullEquals eq1 = new NullEquals(EMPTY, fa, ONE); NullEquals eq1 = nullEqualsOf(fa, ONE);
Range r = new Range(EMPTY, fa, ONE, true, L(10), false); Range r = rangeOf(fa, ONE, true, L(10), false);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, r)); Expression exp = rule.rule(new And(EMPTY, eq1, r));
@ -1006,8 +1016,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a == 1 AND a == 2 -> FALSE // a == 1 AND a == 2 -> FALSE
public void testDualEqualsConjunction() { public void testDualEqualsConjunction() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq1 = new Equals(EMPTY, fa, ONE); Equals eq1 = equalsOf(fa, ONE);
Equals eq2 = new Equals(EMPTY, fa, TWO); Equals eq2 = equalsOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, eq2)); Expression exp = rule.rule(new And(EMPTY, eq1, eq2));
@ -1017,8 +1027,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a <=> 1 AND a <=> 2 -> FALSE // a <=> 1 AND a <=> 2 -> FALSE
public void testDualNullEqualsConjunction() { public void testDualNullEqualsConjunction() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NullEquals eq1 = new NullEquals(EMPTY, fa, ONE); NullEquals eq1 = nullEqualsOf(fa, ONE);
NullEquals eq2 = new NullEquals(EMPTY, fa, TWO); NullEquals eq2 = nullEqualsOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, eq2)); Expression exp = rule.rule(new And(EMPTY, eq1, eq2));
@ -1028,8 +1038,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 1 < a < 10 AND a == 10 -> FALSE // 1 < a < 10 AND a == 10 -> FALSE
public void testEliminateRangeByEqualsOutsideInterval() { public void testEliminateRangeByEqualsOutsideInterval() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq1 = new Equals(EMPTY, fa, L(10)); Equals eq1 = equalsOf(fa, L(10));
Range r = new Range(EMPTY, fa, ONE, false, L(10), false); Range r = rangeOf(fa, ONE, false, L(10), false);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, r)); Expression exp = rule.rule(new And(EMPTY, eq1, r));
@ -1039,8 +1049,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 1 < a < 10 AND a <=> 10 -> FALSE // 1 < a < 10 AND a <=> 10 -> FALSE
public void testEliminateRangeByNullEqualsOutsideInterval() { public void testEliminateRangeByNullEqualsOutsideInterval() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NullEquals eq1 = new NullEquals(EMPTY, fa, L(10)); NullEquals eq1 = nullEqualsOf(fa, L(10));
Range r = new Range(EMPTY, fa, ONE, false, L(10), false); Range r = rangeOf(fa, ONE, false, L(10), false);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, r)); Expression exp = rule.rule(new And(EMPTY, eq1, r));
@ -1050,8 +1060,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a != 3 AND a = 3 -> FALSE // a != 3 AND a = 3 -> FALSE
public void testPropagateEquals_VarNeq3AndVarEq3() { public void testPropagateEquals_VarNeq3AndVarEq3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, THREE); NotEquals neq = notEqualsOf(fa, THREE);
Equals eq = new Equals(EMPTY, fa, THREE); Equals eq = equalsOf(fa, THREE);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, neq, eq)); Expression exp = rule.rule(new And(EMPTY, neq, eq));
@ -1061,8 +1071,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a != 4 AND a = 3 -> a = 3 // a != 4 AND a = 3 -> a = 3
public void testPropagateEquals_VarNeq4AndVarEq3() { public void testPropagateEquals_VarNeq4AndVarEq3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, FOUR); NotEquals neq = notEqualsOf(fa, FOUR);
Equals eq = new Equals(EMPTY, fa, THREE); Equals eq = equalsOf(fa, THREE);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, neq, eq)); Expression exp = rule.rule(new And(EMPTY, neq, eq));
@ -1073,8 +1083,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a < 2 -> FALSE // a = 2 AND a < 2 -> FALSE
public void testPropagateEquals_VarEq2AndVarLt2() { public void testPropagateEquals_VarEq2AndVarLt2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
LessThan lt = new LessThan(EMPTY, fa, TWO); LessThan lt = lessThanOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, lt)); Expression exp = rule.rule(new And(EMPTY, eq, lt));
@ -1084,8 +1094,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a <= 2 -> a = 2 // a = 2 AND a <= 2 -> a = 2
public void testPropagateEquals_VarEq2AndVarLte2() { public void testPropagateEquals_VarEq2AndVarLte2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
LessThanOrEqual lt = new LessThanOrEqual(EMPTY, fa, TWO); LessThanOrEqual lt = lessThanOrEqualOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, lt)); Expression exp = rule.rule(new And(EMPTY, eq, lt));
@ -1095,8 +1105,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a <= 1 -> FALSE // a = 2 AND a <= 1 -> FALSE
public void testPropagateEquals_VarEq2AndVarLte1() { public void testPropagateEquals_VarEq2AndVarLte1() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
LessThanOrEqual lt = new LessThanOrEqual(EMPTY, fa, ONE); LessThanOrEqual lt = lessThanOrEqualOf(fa, ONE);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, lt)); Expression exp = rule.rule(new And(EMPTY, eq, lt));
@ -1106,8 +1116,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a > 2 -> FALSE // a = 2 AND a > 2 -> FALSE
public void testPropagateEquals_VarEq2AndVarGt2() { public void testPropagateEquals_VarEq2AndVarGt2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, TWO); GreaterThan gt = greaterThanOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, gt)); Expression exp = rule.rule(new And(EMPTY, eq, gt));
@ -1117,8 +1127,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a >= 2 -> a = 2 // a = 2 AND a >= 2 -> a = 2
public void testPropagateEquals_VarEq2AndVarGte2() { public void testPropagateEquals_VarEq2AndVarGte2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, TWO); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, gte)); Expression exp = rule.rule(new And(EMPTY, eq, gte));
@ -1128,8 +1138,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a > 3 -> FALSE // a = 2 AND a > 3 -> FALSE
public void testPropagateEquals_VarEq2AndVarLt3() { public void testPropagateEquals_VarEq2AndVarLt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, THREE); GreaterThan gt = greaterThanOf(fa, THREE);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, gt)); Expression exp = rule.rule(new And(EMPTY, eq, gt));
@ -1139,10 +1149,10 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a < 3 AND a > 1 AND a != 4 -> a = 2 // a = 2 AND a < 3 AND a > 1 AND a != 4 -> a = 2
public void testPropagateEquals_VarEq2AndVarLt3AndVarGt1AndVarNeq4() { public void testPropagateEquals_VarEq2AndVarLt3AndVarGt1AndVarNeq4() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
LessThan lt = new LessThan(EMPTY, fa, THREE); LessThan lt = lessThanOf(fa, THREE);
GreaterThan gt = new GreaterThan(EMPTY, fa, ONE); GreaterThan gt = greaterThanOf(fa, ONE);
NotEquals neq = new NotEquals(EMPTY, fa, FOUR); NotEquals neq = notEqualsOf(fa, FOUR);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression and = Predicates.combineAnd(Arrays.asList(eq, lt, gt, neq)); Expression and = Predicates.combineAnd(Arrays.asList(eq, lt, gt, neq));
@ -1153,10 +1163,10 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND 1 < a < 3 AND a > 0 AND a != 4 -> a = 2 // a = 2 AND 1 < a < 3 AND a > 0 AND a != 4 -> a = 2
public void testPropagateEquals_VarEq2AndVarRangeGt1Lt3AndVarGt0AndVarNeq4() { public void testPropagateEquals_VarEq2AndVarRangeGt1Lt3AndVarGt0AndVarNeq4() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false); Range range = rangeOf(fa, ONE, false, THREE, false);
GreaterThan gt = new GreaterThan(EMPTY, fa, L(0)); GreaterThan gt = greaterThanOf(fa, L(0));
NotEquals neq = new NotEquals(EMPTY, fa, FOUR); NotEquals neq = notEqualsOf(fa, FOUR);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression and = Predicates.combineAnd(Arrays.asList(eq, range, gt, neq)); Expression and = Predicates.combineAnd(Arrays.asList(eq, range, gt, neq));
@ -1167,8 +1177,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 OR a > 1 -> a > 1 // a = 2 OR a > 1 -> a > 1
public void testPropagateEquals_VarEq2OrVarGt1() { public void testPropagateEquals_VarEq2OrVarGt1() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, ONE); GreaterThan gt = greaterThanOf(fa, ONE);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, gt)); Expression exp = rule.rule(new Or(EMPTY, eq, gt));
@ -1178,8 +1188,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 OR a > 2 -> a >= 2 // a = 2 OR a > 2 -> a >= 2
public void testPropagateEquals_VarEq2OrVarGte2() { public void testPropagateEquals_VarEq2OrVarGte2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, TWO); GreaterThan gt = greaterThanOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, gt)); Expression exp = rule.rule(new Or(EMPTY, eq, gt));
@ -1191,8 +1201,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 OR a < 3 -> a < 3 // a = 2 OR a < 3 -> a < 3
public void testPropagateEquals_VarEq2OrVarLt3() { public void testPropagateEquals_VarEq2OrVarLt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
LessThan lt = new LessThan(EMPTY, fa, THREE); LessThan lt = lessThanOf(fa, THREE);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, lt)); Expression exp = rule.rule(new Or(EMPTY, eq, lt));
@ -1202,8 +1212,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 3 OR a < 3 -> a <= 3 // a = 3 OR a < 3 -> a <= 3
public void testPropagateEquals_VarEq3OrVarLt3() { public void testPropagateEquals_VarEq3OrVarLt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, THREE); Equals eq = equalsOf(fa, THREE);
LessThan lt = new LessThan(EMPTY, fa, THREE); LessThan lt = lessThanOf(fa, THREE);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, lt)); Expression exp = rule.rule(new Or(EMPTY, eq, lt));
@ -1215,8 +1225,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 OR 1 < a < 3 -> 1 < a < 3 // a = 2 OR 1 < a < 3 -> 1 < a < 3
public void testPropagateEquals_VarEq2OrVarRangeGt1Lt3() { public void testPropagateEquals_VarEq2OrVarRangeGt1Lt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false); Range range = rangeOf(fa, ONE, false, THREE, false);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, range)); Expression exp = rule.rule(new Or(EMPTY, eq, range));
@ -1226,8 +1236,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 OR 2 < a < 3 -> 2 <= a < 3 // a = 2 OR 2 < a < 3 -> 2 <= a < 3
public void testPropagateEquals_VarEq2OrVarRangeGt2Lt3() { public void testPropagateEquals_VarEq2OrVarRangeGt2Lt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
Range range = new Range(EMPTY, fa, TWO, false, THREE, false); Range range = rangeOf(fa, TWO, false, THREE, false);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, range)); Expression exp = rule.rule(new Or(EMPTY, eq, range));
@ -1242,8 +1252,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 3 OR 2 < a < 3 -> 2 < a <= 3 // a = 3 OR 2 < a < 3 -> 2 < a <= 3
public void testPropagateEquals_VarEq3OrVarRangeGt2Lt3() { public void testPropagateEquals_VarEq3OrVarRangeGt2Lt3() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, THREE); Equals eq = equalsOf(fa, THREE);
Range range = new Range(EMPTY, fa, TWO, false, THREE, false); Range range = rangeOf(fa, TWO, false, THREE, false);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, range)); Expression exp = rule.rule(new Or(EMPTY, eq, range));
@ -1258,8 +1268,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 OR a != 2 -> TRUE // a = 2 OR a != 2 -> TRUE
public void testPropagateEquals_VarEq2OrVarNeq2() { public void testPropagateEquals_VarEq2OrVarNeq2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, neq)); Expression exp = rule.rule(new Or(EMPTY, eq, neq));
@ -1269,23 +1279,23 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 OR a != 5 -> a != 5 // a = 2 OR a != 5 -> a != 5
public void testPropagateEquals_VarEq2OrVarNeq5() { public void testPropagateEquals_VarEq2OrVarNeq5() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
NotEquals neq = new NotEquals(EMPTY, fa, FIVE); NotEquals neq = notEqualsOf(fa, FIVE);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, neq)); Expression exp = rule.rule(new Or(EMPTY, eq, neq));
assertEquals(NotEquals.class, exp.getClass()); assertEquals(NotEquals.class, exp.getClass());
NotEquals ne = (NotEquals) exp; NotEquals ne = (NotEquals) exp;
assertEquals(ne.right(), FIVE); assertEquals(FIVE, ne.right());
} }
// a = 2 OR 3 < a < 4 OR a > 2 OR a!= 2 -> TRUE // a = 2 OR 3 < a < 4 OR a > 2 OR a!= 2 -> TRUE
public void testPropagateEquals_VarEq2OrVarRangeGt3Lt4OrVarGt2OrVarNe2() { public void testPropagateEquals_VarEq2OrVarRangeGt3Lt4OrVarGt2OrVarNe2() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO); Equals eq = equalsOf(fa, TWO);
Range range = new Range(EMPTY, fa, THREE, false, FOUR, false); Range range = rangeOf(fa, THREE, false, FOUR, false);
GreaterThan gt = new GreaterThan(EMPTY, fa, TWO); GreaterThan gt = greaterThanOf(fa, TWO);
NotEquals neq = new NotEquals(EMPTY, fa, TWO); NotEquals neq = notEqualsOf(fa, TWO);
PropagateEquals rule = new PropagateEquals(); PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(Predicates.combineOr(Arrays.asList(eq, range, neq, gt))); Expression exp = rule.rule(Predicates.combineOr(Arrays.asList(eq, range, neq, gt)));

View File

@ -10,15 +10,17 @@ import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan;
import org.elasticsearch.xpack.sql.parser.SqlBaseParser.SingleStatementContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.SingleStatementContext;
import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue;
import java.time.ZoneId;
import java.util.Map; import java.util.Map;
class AstBuilder extends CommandBuilder { class AstBuilder extends CommandBuilder {
/** /**
* Create AST Builder * Create AST Builder
* @param params a map between '?' tokens that represent parameters and the actual parameter values * @param params a map between '?' tokens that represent parameters and the actual parameter values
* @param zoneId user specified timezone in the session
*/ */
AstBuilder(Map<Token, SqlTypedParamValue> params) { AstBuilder(Map<Token, SqlTypedParamValue> params, ZoneId zoneId) {
super(params); super(params, zoneId);
} }
@Override @Override

View File

@ -36,6 +36,7 @@ import org.elasticsearch.xpack.sql.plan.logical.command.sys.SysTables;
import org.elasticsearch.xpack.sql.plan.logical.command.sys.SysTypes; import org.elasticsearch.xpack.sql.plan.logical.command.sys.SysTypes;
import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue;
import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
@ -44,8 +45,8 @@ import java.util.Map;
abstract class CommandBuilder extends LogicalPlanBuilder { abstract class CommandBuilder extends LogicalPlanBuilder {
protected CommandBuilder(Map<Token, SqlTypedParamValue> params) { protected CommandBuilder(Map<Token, SqlTypedParamValue> params, ZoneId zoneId) {
super(params); super(params, zoneId);
} }
@Override @Override

View File

@ -119,6 +119,7 @@ import org.elasticsearch.xpack.sql.type.SqlDataTypes;
import java.time.Duration; import java.time.Duration;
import java.time.Period; import java.time.Period;
import java.time.ZoneId;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalAmount;
import java.util.ArrayList; import java.util.ArrayList;
@ -139,9 +140,11 @@ import static org.elasticsearch.xpack.sql.util.DateUtils.dateTimeOfEscapedLitera
abstract class ExpressionBuilder extends IdentifierBuilder { abstract class ExpressionBuilder extends IdentifierBuilder {
private final Map<Token, SqlTypedParamValue> params; private final Map<Token, SqlTypedParamValue> params;
private final ZoneId zoneId;
ExpressionBuilder(Map<Token, SqlTypedParamValue> params) { ExpressionBuilder(Map<Token, SqlTypedParamValue> params, ZoneId zoneId) {
this.params = params; this.params = params;
this.zoneId = zoneId;
} }
protected Expression expression(ParseTree ctx) { protected Expression expression(ParseTree ctx) {
@ -191,19 +194,19 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
switch (op.getSymbol().getType()) { switch (op.getSymbol().getType()) {
case SqlBaseParser.EQ: case SqlBaseParser.EQ:
return new Equals(source, left, right); return new Equals(source, left, right, zoneId);
case SqlBaseParser.NULLEQ: case SqlBaseParser.NULLEQ:
return new NullEquals(source, left, right); return new NullEquals(source, left, right, zoneId);
case SqlBaseParser.NEQ: case SqlBaseParser.NEQ:
return new NotEquals(source, left, right); return new NotEquals(source, left, right, zoneId);
case SqlBaseParser.LT: case SqlBaseParser.LT:
return new LessThan(source, left, right); return new LessThan(source, left, right, zoneId);
case SqlBaseParser.LTE: case SqlBaseParser.LTE:
return new LessThanOrEqual(source, left, right); return new LessThanOrEqual(source, left, right, zoneId);
case SqlBaseParser.GT: case SqlBaseParser.GT:
return new GreaterThan(source, left, right); return new GreaterThan(source, left, right, zoneId);
case SqlBaseParser.GTE: case SqlBaseParser.GTE:
return new GreaterThanOrEqual(source, left, right); return new GreaterThanOrEqual(source, left, right, zoneId);
default: default:
throw new ParsingException(source, "Unknown operator {}", source.text()); throw new ParsingException(source, "Unknown operator {}", source.text());
} }
@ -224,7 +227,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
Expression e = null; Expression e = null;
switch (pCtx.kind.getType()) { switch (pCtx.kind.getType()) {
case SqlBaseParser.BETWEEN: case SqlBaseParser.BETWEEN:
e = new Range(source, exp, expression(pCtx.lower), true, expression(pCtx.upper), true); e = new Range(source, exp, expression(pCtx.lower), true, expression(pCtx.upper), true, zoneId);
break; break;
case SqlBaseParser.IN: case SqlBaseParser.IN:
if (pCtx.query() != null) { if (pCtx.query() != null) {
@ -473,7 +476,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
for (SqlBaseParser.WhenClauseContext when : ctx.whenClause()) { for (SqlBaseParser.WhenClauseContext when : ctx.whenClause()) {
if (ctx.operand != null) { if (ctx.operand != null) {
expressions.add(new IfConditional(source(when), expressions.add(new IfConditional(source(when),
new Equals(source(when), expression(ctx.operand), expression(when.condition)), expression(when.result))); new Equals(source(when), expression(ctx.operand), expression(when.condition), zoneId), expression(when.result)));
} else { } else {
expressions.add(new IfConditional(source(when), expression(when.condition), expression(when.result))); expressions.add(new IfConditional(source(when), expression(when.condition), expression(when.result)));
} }

View File

@ -54,6 +54,7 @@ import org.elasticsearch.xpack.sql.plan.logical.With;
import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue;
import org.elasticsearch.xpack.sql.session.SingletonExecutable; import org.elasticsearch.xpack.sql.session.SingletonExecutable;
import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -63,8 +64,8 @@ import static java.util.Collections.emptyList;
abstract class LogicalPlanBuilder extends ExpressionBuilder { abstract class LogicalPlanBuilder extends ExpressionBuilder {
protected LogicalPlanBuilder(Map<Token, SqlTypedParamValue> params) { protected LogicalPlanBuilder(Map<Token, SqlTypedParamValue> params, ZoneId zoneId) {
super(params); super(params, zoneId);
} }
@Override @Override

View File

@ -28,6 +28,7 @@ import org.elasticsearch.xpack.ql.expression.Expression;
import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan;
import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue;
import java.time.ZoneId;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet; import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
@ -39,6 +40,7 @@ import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import static java.lang.String.format; import static java.lang.String.format;
import static org.elasticsearch.xpack.sql.util.DateUtils.UTC;
public class SqlParser { public class SqlParser {
@ -50,7 +52,14 @@ public class SqlParser {
* Used only in tests * Used only in tests
*/ */
public LogicalPlan createStatement(String sql) { public LogicalPlan createStatement(String sql) {
return createStatement(sql, Collections.emptyList()); return createStatement(sql, Collections.emptyList(), UTC);
}
/**
* Used only in tests
*/
public LogicalPlan createStatement(String sql, ZoneId zoneId) {
return createStatement(sql, Collections.emptyList(), zoneId);
} }
/** /**
@ -59,11 +68,11 @@ public class SqlParser {
* @param params - a list of parameters for the statement if the statement is parametrized * @param params - a list of parameters for the statement if the statement is parametrized
* @return logical plan * @return logical plan
*/ */
public LogicalPlan createStatement(String sql, List<SqlTypedParamValue> params) { public LogicalPlan createStatement(String sql, List<SqlTypedParamValue> params, ZoneId zoneId) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Parsing as statement: {}", sql); log.debug("Parsing as statement: {}", sql);
} }
return invokeParser(sql, params, SqlBaseParser::singleStatement, AstBuilder::plan); return invokeParser(sql, params, zoneId, SqlBaseParser::singleStatement, AstBuilder::plan);
} }
/** /**
@ -81,12 +90,13 @@ public class SqlParser {
log.debug("Parsing as expression: {}", expression); log.debug("Parsing as expression: {}", expression);
} }
return invokeParser(expression, params, SqlBaseParser::singleExpression, AstBuilder::expression); return invokeParser(expression, params, UTC, SqlBaseParser::singleExpression, AstBuilder::expression);
} }
private <T> T invokeParser(String sql, private <T> T invokeParser(String sql,
List<SqlTypedParamValue> params, Function<SqlBaseParser, List<SqlTypedParamValue> params,
ParserRuleContext> parseFunction, ZoneId zoneId,
Function<SqlBaseParser, ParserRuleContext> parseFunction,
BiFunction<AstBuilder, ParserRuleContext, T> visitor) { BiFunction<AstBuilder, ParserRuleContext, T> visitor) {
try { try {
SqlBaseLexer lexer = new SqlBaseLexer(new CaseInsensitiveStream(sql)); SqlBaseLexer lexer = new SqlBaseLexer(new CaseInsensitiveStream(sql));
@ -126,7 +136,7 @@ public class SqlParser {
log.info("Parse tree {} " + tree.toStringTree()); log.info("Parse tree {} " + tree.toStringTree());
} }
return visitor.apply(new AstBuilder(paramTokens), tree); return visitor.apply(new AstBuilder(paramTokens, zoneId), tree);
} catch (StackOverflowError e) { } catch (StackOverflowError e) {
throw new ParsingException("SQL statement is too large, " + throw new ParsingException("SQL statement is too large, " +
"causing stack overflow when generating the parsing tree: [{}]", sql); "causing stack overflow when generating the parsing tree: [{}]", sql);

View File

@ -96,7 +96,7 @@ public class SqlSession implements Session {
} }
private LogicalPlan doParse(String sql, List<SqlTypedParamValue> params) { private LogicalPlan doParse(String sql, List<SqlTypedParamValue> params) {
return new SqlParser().createStatement(sql, params); return new SqlParser().createStatement(sql, params, configuration.zoneId());
} }
public void analyzedPlan(LogicalPlan parsed, boolean verify, ActionListener<LogicalPlan> listener) { public void analyzedPlan(LogicalPlan parsed, boolean verify, ActionListener<LogicalPlan> listener) {

View File

@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import static org.elasticsearch.xpack.ql.TestUtils.equalsOf;
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomIntLiteral; import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomIntLiteral;
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral; import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
@ -40,7 +41,8 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
List<Expression> expressions = new ArrayList<>(noConditionals + 1); List<Expression> expressions = new ArrayList<>(noConditionals + 1);
for (int i = 0; i < noConditionals; i++) { for (int i = 0; i < noConditionals; i++) {
expressions.add(new IfConditional( expressions.add(new IfConditional(
randomSource(), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral()), randomIntLiteral())); randomSource(), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral(), randomZone()),
randomIntLiteral()));
} }
// default else // default else
@ -86,14 +88,14 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
// ELSE 'default' // ELSE 'default'
// END // END
Case c = new Case(EMPTY, Arrays.asList( Case c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), Literal.NULL), literal("default"))); new IfConditional(EMPTY, equalsOf(literal(1), literal(1)), Literal.NULL), literal("default")));
assertEquals(KEYWORD, c.dataType()); assertEquals(KEYWORD, c.dataType());
// CASE WHEN 1 = 1 THEN 'foo' // CASE WHEN 1 = 1 THEN 'foo'
// ELSE NULL // ELSE NULL
// END // END
c = new Case(EMPTY, Arrays.asList( c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), literal("foo")), new IfConditional(EMPTY, equalsOf(literal(1), literal(1)), literal("foo")),
Literal.NULL)); Literal.NULL));
assertEquals(KEYWORD, c.dataType()); assertEquals(KEYWORD, c.dataType());
@ -101,7 +103,7 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
// ELSE NULL // ELSE NULL
// END // END
c = new Case(EMPTY, Arrays.asList( c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), Literal.NULL), new IfConditional(EMPTY, equalsOf(literal(1), literal(1)), Literal.NULL),
Literal.NULL)); Literal.NULL));
assertEquals(NULL, c.dataType()); assertEquals(NULL, c.dataType());
@ -110,8 +112,8 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
// ELSE NULL // ELSE NULL
// END // END
c = new Case(EMPTY, Arrays.asList( c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), Literal.NULL), new IfConditional(EMPTY, equalsOf(literal(1), literal(1)), Literal.NULL),
new IfConditional(EMPTY, new Equals(EMPTY, literal(2), literal(2)), literal("foo")), new IfConditional(EMPTY, equalsOf(literal(2), literal(2)), literal("foo")),
Literal.NULL)); Literal.NULL));
assertEquals(KEYWORD, c.dataType()); assertEquals(KEYWORD, c.dataType());
} }
@ -133,7 +135,7 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
for (int i = 0; i < c.conditions().size(); i++) { for (int i = 0; i < c.conditions().size(); i++) {
if (i == rndIdx) { if (i == rndIdx) {
expressions.add(new IfConditional(randomValueOtherThan(c.conditions().get(i).source(), SourceTests::randomSource), expressions.add(new IfConditional(randomValueOtherThan(c.conditions().get(i).source(), SourceTests::randomSource),
new Equals(randomSource(), randomStringLiteral(), randomStringLiteral()), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral(), randomZone()),
randomValueOtherThan(c.conditions().get(i).condition(), FunctionTestUtils::randomStringLiteral))); randomValueOtherThan(c.conditions().get(i).condition(), FunctionTestUtils::randomStringLiteral)));
} else { } else {
expressions.add(c.conditions().get(i)); expressions.add(c.conditions().get(i));

View File

@ -5,6 +5,7 @@
*/ */
package org.elasticsearch.xpack.sql.expression.predicate.conditional; package org.elasticsearch.xpack.sql.expression.predicate.conditional;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expression;
import org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils; import org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals;
@ -33,7 +34,7 @@ import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource;
public class IifTests extends AbstractNodeTestCase<Iif, Expression> { public class IifTests extends AbstractNodeTestCase<Iif, Expression> {
public static Iif randomIif() { public static Iif randomIif() {
return new Iif(randomSource(), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral()), return new Iif(randomSource(), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral(), randomZone()),
randomIntLiteral(), randomIntLiteral()); randomIntLiteral(), randomIntLiteral());
} }
@ -86,7 +87,8 @@ public class IifTests extends AbstractNodeTestCase<Iif, Expression> {
Equals eq = (Equals) iif.conditions().get(0).condition(); Equals eq = (Equals) iif.conditions().get(0).condition();
expressions.add(new Equals(randomSource(), expressions.add(new Equals(randomSource(),
randomValueOtherThan(eq.left(), FunctionTestUtils::randomStringLiteral), randomValueOtherThan(eq.left(), FunctionTestUtils::randomStringLiteral),
randomValueOtherThan(eq.right(), FunctionTestUtils::randomStringLiteral))); randomValueOtherThan(eq.right(), FunctionTestUtils::randomStringLiteral),
randomValueOtherThan(eq.zoneId(), ESTestCase::randomZone)));
expressions.add(randomValueOtherThan(iif.conditions().get(0).result(), FunctionTestUtils::randomIntLiteral)); expressions.add(randomValueOtherThan(iif.conditions().get(0).result(), FunctionTestUtils::randomIntLiteral));
expressions.add(randomValueOtherThan(iif.elseResult(), FunctionTestUtils::randomIntLiteral)); expressions.add(randomValueOtherThan(iif.elseResult(), FunctionTestUtils::randomIntLiteral));
return expressions; return expressions;

View File

@ -35,8 +35,6 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equal
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThan;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThanOrEqual; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThanOrEqual;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NullEquals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NullEquals;
import org.elasticsearch.xpack.ql.expression.predicate.regex.RLike; import org.elasticsearch.xpack.ql.expression.predicate.regex.RLike;
import org.elasticsearch.xpack.ql.expression.predicate.regex.RLikePattern; import org.elasticsearch.xpack.ql.expression.predicate.regex.RLikePattern;
@ -129,6 +127,13 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.elasticsearch.xpack.ql.TestUtils.equalsOf;
import static org.elasticsearch.xpack.ql.TestUtils.greaterThanOf;
import static org.elasticsearch.xpack.ql.TestUtils.greaterThanOrEqualOf;
import static org.elasticsearch.xpack.ql.TestUtils.lessThanOf;
import static org.elasticsearch.xpack.ql.TestUtils.lessThanOrEqualOf;
import static org.elasticsearch.xpack.ql.TestUtils.notEqualsOf;
import static org.elasticsearch.xpack.ql.TestUtils.nullEqualsOf;
import static org.elasticsearch.xpack.ql.expression.Literal.FALSE; import static org.elasticsearch.xpack.ql.expression.Literal.FALSE;
import static org.elasticsearch.xpack.ql.expression.Literal.NULL; import static org.elasticsearch.xpack.ql.expression.Literal.NULL;
import static org.elasticsearch.xpack.ql.expression.Literal.TRUE; import static org.elasticsearch.xpack.ql.expression.Literal.TRUE;
@ -212,7 +217,7 @@ public class OptimizerTests extends ESTestCase {
// b // b
Alias b = new Alias(EMPTY, "b", L(10)); Alias b = new Alias(EMPTY, "b", L(10));
// WHERE a < 10 // WHERE a < 10
LogicalPlan p = new Filter(EMPTY, FROM(), new LessThan(EMPTY, a, L(10))); LogicalPlan p = new Filter(EMPTY, FROM(), lessThanOf(a, L(10)));
// SELECT // SELECT
p = new Project(EMPTY, p, Arrays.asList(a, b)); p = new Project(EMPTY, p, Arrays.asList(a, b));
// ORDER BY // ORDER BY
@ -368,7 +373,7 @@ public class OptimizerTests extends ESTestCase {
// arithmetic // arithmetic
assertNullLiteral(rule.rule(new Add(EMPTY, getFieldAttribute(), NULL))); assertNullLiteral(rule.rule(new Add(EMPTY, getFieldAttribute(), NULL)));
// comparison // comparison
assertNullLiteral(rule.rule(new GreaterThan(EMPTY, getFieldAttribute(), NULL))); assertNullLiteral(rule.rule(greaterThanOf(getFieldAttribute(), NULL)));
// regex // regex
assertNullLiteral(rule.rule(new RLike(EMPTY, NULL, new RLikePattern("123")))); assertNullLiteral(rule.rule(new RLike(EMPTY, NULL, new RLikePattern("123"))));
} }
@ -581,10 +586,10 @@ public class OptimizerTests extends ESTestCase {
// END // END
Case c = new Case(EMPTY, Arrays.asList( Case c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, getFieldAttribute(), ONE), literal("foo1")), new IfConditional(EMPTY, equalsOf(getFieldAttribute(), ONE), literal("foo1")),
new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), literal("bar1")), new IfConditional(EMPTY, equalsOf(ONE, TWO), literal("bar1")),
new IfConditional(EMPTY, new Equals(EMPTY, TWO, ONE), literal("bar2")), new IfConditional(EMPTY, equalsOf(TWO, ONE), literal("bar2")),
new IfConditional(EMPTY, new GreaterThan(EMPTY, getFieldAttribute(), ONE), literal("foo2")), literal("default"))); new IfConditional(EMPTY, greaterThanOf(getFieldAttribute(), ONE), literal("foo2")), literal("default")));
assertFalse(c.foldable()); assertFalse(c.foldable());
Expression e = new SimplifyCase().rule(c); Expression e = new SimplifyCase().rule(c);
assertEquals(Case.class, e.getClass()); assertEquals(Case.class, e.getClass());
@ -607,8 +612,8 @@ public class OptimizerTests extends ESTestCase {
// 'foo2' // 'foo2'
Case c = new Case(EMPTY, Arrays.asList( Case c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo1")), new IfConditional(EMPTY, equalsOf(ONE, TWO), literal("foo1")),
new IfConditional(EMPTY, new Equals(EMPTY, ONE, ONE), literal("foo2")), literal("default"))); new IfConditional(EMPTY, equalsOf(ONE, ONE), literal("foo2")), literal("default")));
assertFalse(c.foldable()); assertFalse(c.foldable());
SimplifyCase rule = new SimplifyCase(); SimplifyCase rule = new SimplifyCase();
@ -632,7 +637,7 @@ public class OptimizerTests extends ESTestCase {
// myField (non-foldable) // myField (non-foldable)
Case c = new Case(EMPTY, Arrays.asList( Case c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo1")), new IfConditional(EMPTY, equalsOf(ONE, TWO), literal("foo1")),
getFieldAttribute("myField"))); getFieldAttribute("myField")));
assertFalse(c.foldable()); assertFalse(c.foldable());
@ -647,7 +652,7 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyIif_ConditionTrue_FoldableResult() { public void testSimplifyIif_ConditionTrue_FoldableResult() {
SimplifyCase rule = new SimplifyCase(); SimplifyCase rule = new SimplifyCase();
Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, ONE), literal("foo"), literal("bar")); Iif iif = new Iif(EMPTY, equalsOf(ONE, ONE), literal("foo"), literal("bar"));
assertTrue(iif.foldable()); assertTrue(iif.foldable());
Expression e = rule.rule(iif); Expression e = rule.rule(iif);
@ -661,7 +666,7 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyIif_ConditionTrue_NonFoldableResult() { public void testSimplifyIif_ConditionTrue_NonFoldableResult() {
SimplifyCase rule = new SimplifyCase(); SimplifyCase rule = new SimplifyCase();
Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, ONE), getFieldAttribute("myField"), literal("bar")); Iif iif = new Iif(EMPTY, equalsOf(ONE, ONE), getFieldAttribute("myField"), literal("bar"));
assertFalse(iif.foldable()); assertFalse(iif.foldable());
Expression e = rule.rule(iif); Expression e = rule.rule(iif);
@ -676,7 +681,7 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyIif_ConditionFalse_FoldableResult() { public void testSimplifyIif_ConditionFalse_FoldableResult() {
SimplifyCase rule = new SimplifyCase(); SimplifyCase rule = new SimplifyCase();
Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo"), literal("bar")); Iif iif = new Iif(EMPTY, equalsOf(ONE, TWO), literal("foo"), literal("bar"));
assertTrue(iif.foldable()); assertTrue(iif.foldable());
Expression e = rule.rule(iif); Expression e = rule.rule(iif);
@ -690,7 +695,7 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyIif_ConditionFalse_NonFoldableResult() { public void testSimplifyIif_ConditionFalse_NonFoldableResult() {
SimplifyCase rule = new SimplifyCase(); SimplifyCase rule = new SimplifyCase();
Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo"), getFieldAttribute("myField")); Iif iif = new Iif(EMPTY, equalsOf(ONE, TWO), literal("foo"), getFieldAttribute("myField"));
assertFalse(iif.foldable()); assertFalse(iif.foldable());
Expression e = rule.rule(iif); Expression e = rule.rule(iif);
@ -711,15 +716,15 @@ public class OptimizerTests extends ESTestCase {
} }
public void testBinaryComparisonSimplification() { public void testBinaryComparisonSimplification() {
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new Equals(EMPTY, FIVE, FIVE))); assertEquals(TRUE, new BinaryComparisonSimplification().rule(equalsOf(FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new NullEquals(EMPTY, FIVE, FIVE))); assertEquals(TRUE, new BinaryComparisonSimplification().rule(nullEqualsOf(FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new NullEquals(EMPTY, NULL, NULL))); assertEquals(TRUE, new BinaryComparisonSimplification().rule(nullEqualsOf(NULL, NULL)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(new NotEquals(EMPTY, FIVE, FIVE))); assertEquals(FALSE, new BinaryComparisonSimplification().rule(notEqualsOf(FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new GreaterThanOrEqual(EMPTY, FIVE, FIVE))); assertEquals(TRUE, new BinaryComparisonSimplification().rule(greaterThanOrEqualOf(FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new LessThanOrEqual(EMPTY, FIVE, FIVE))); assertEquals(TRUE, new BinaryComparisonSimplification().rule(lessThanOrEqualOf(FIVE, FIVE)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(new GreaterThan(EMPTY, FIVE, FIVE))); assertEquals(FALSE, new BinaryComparisonSimplification().rule(greaterThanOf(FIVE, FIVE)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(new LessThan(EMPTY, FIVE, FIVE))); assertEquals(FALSE, new BinaryComparisonSimplification().rule(lessThanOf(FIVE, FIVE)));
} }
public void testNullEqualsWithNullLiteralBecomesIsNull() { public void testNullEqualsWithNullLiteralBecomesIsNull() {
@ -728,12 +733,12 @@ public class OptimizerTests extends ESTestCase {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
Source source = new Source(1, 10, "IS_NULL(a)"); Source source = new Source(1, 10, "IS_NULL(a)");
Expression e = bcSimpl.rule(swapLiteralsToRight.rule(new NullEquals(source, fa, NULL))); Expression e = bcSimpl.rule(swapLiteralsToRight.rule(new NullEquals(source, fa, NULL, randomZone())));
assertEquals(IsNull.class, e.getClass()); assertEquals(IsNull.class, e.getClass());
IsNull isNull = (IsNull) e; IsNull isNull = (IsNull) e;
assertEquals(source, isNull.source()); assertEquals(source, isNull.source());
e = bcSimpl.rule(swapLiteralsToRight.rule(new NullEquals(source, NULL, fa))); e = bcSimpl.rule(swapLiteralsToRight.rule(new NullEquals(source, NULL, fa, randomZone())));
assertEquals(IsNull.class, e.getClass()); assertEquals(IsNull.class, e.getClass());
isNull = (IsNull) e; isNull = (IsNull) e;
assertEquals(source, isNull.source()); assertEquals(source, isNull.source());
@ -764,10 +769,10 @@ public class OptimizerTests extends ESTestCase {
public void testCombineUnbalancedComparisonsMixedWithEqualsIntoRange() { public void testCombineUnbalancedComparisonsMixedWithEqualsIntoRange() {
FieldAttribute fa = getFieldAttribute(); FieldAttribute fa = getFieldAttribute();
IsNotNull isn = new IsNotNull(EMPTY, fa); IsNotNull isn = new IsNotNull(EMPTY, fa);
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, ONE); GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, ONE);
Equals eq = new Equals(EMPTY, fa, L(10)); Equals eq = equalsOf(fa, L(10));
LessThan lt = new LessThan(EMPTY, fa, FIVE); LessThan lt = lessThanOf(fa, FIVE);
And and = new And(EMPTY, new And(EMPTY, isn, gte), new And(EMPTY, lt, eq)); And and = new And(EMPTY, new And(EMPTY, isn, gte), new And(EMPTY, lt, eq));
@ -997,8 +1002,8 @@ public class OptimizerTests extends ESTestCase {
Alias bAlias = new Alias(EMPTY, "bAlias", b); Alias bAlias = new Alias(EMPTY, "bAlias", b);
Project p = new Project(EMPTY, FROM(), Arrays.asList(aAlias, bAlias)); Project p = new Project(EMPTY, FROM(), Arrays.asList(aAlias, bAlias));
Filter f = new Filter(EMPTY, p, Filter f = new Filter(EMPTY, p, new And(EMPTY, greaterThanOf(aAlias.toAttribute(), L(1)),
new And(EMPTY, new GreaterThan(EMPTY, aAlias.toAttribute(), L(1)), new GreaterThan(EMPTY, bAlias.toAttribute(), L(2)))); greaterThanOf(bAlias.toAttribute(), L(2))));
ReplaceReferenceAttributeWithSource rule = new ReplaceReferenceAttributeWithSource(); ReplaceReferenceAttributeWithSource rule = new ReplaceReferenceAttributeWithSource();
Expression condition = f.condition(); Expression condition = f.condition();

View File

@ -35,6 +35,7 @@ import java.util.function.Consumer;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.elasticsearch.action.ActionListener.wrap; import static org.elasticsearch.action.ActionListener.wrap;
import static org.elasticsearch.xpack.ql.TestUtils.UTC;
import static org.elasticsearch.xpack.sql.types.SqlTypesTests.loadMapping; import static org.elasticsearch.xpack.sql.types.SqlTypesTests.loadMapping;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyBoolean;
@ -521,7 +522,7 @@ public class SysColumnsTests extends ESTestCase {
EsIndex test = new EsIndex("test", mapping); EsIndex test = new EsIndex("test", mapping);
Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test), Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test),
new Verifier(new Metrics())); new Verifier(new Metrics()));
Command cmd = (Command) analyzer.analyze(parser.createStatement(sql, params), true); Command cmd = (Command) analyzer.analyze(parser.createStatement(sql, params, UTC), true);
IndexResolver resolver = mock(IndexResolver.class); IndexResolver resolver = mock(IndexResolver.class);
when(resolver.clusterName()).thenReturn(CLUSTER_NAME); when(resolver.clusterName()).thenReturn(CLUSTER_NAME);

View File

@ -335,7 +335,7 @@ public class SysTablesTests extends ESTestCase {
EsIndex test = new EsIndex("test", mapping); EsIndex test = new EsIndex("test", mapping);
Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test), Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test),
new Verifier(new Metrics())); new Verifier(new Metrics()));
Command cmd = (Command) analyzer.analyze(parser.createStatement(sql, params), true); Command cmd = (Command) analyzer.analyze(parser.createStatement(sql, params, cfg.zoneId()), true);
IndexResolver resolver = mock(IndexResolver.class); IndexResolver resolver = mock(IndexResolver.class);
when(resolver.clusterName()).thenReturn(CLUSTER_NAME); when(resolver.clusterName()).thenReturn(CLUSTER_NAME);

View File

@ -68,6 +68,7 @@ import org.elasticsearch.xpack.sql.types.SqlTypesTests;
import org.elasticsearch.xpack.sql.util.DateUtils; import org.elasticsearch.xpack.sql.util.DateUtils;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -87,6 +88,7 @@ import static org.elasticsearch.xpack.sql.expression.function.scalar.math.MathPr
import static org.elasticsearch.xpack.sql.planner.QueryTranslator.DATE_FORMAT; import static org.elasticsearch.xpack.sql.planner.QueryTranslator.DATE_FORMAT;
import static org.elasticsearch.xpack.sql.planner.QueryTranslator.TIME_FORMAT; import static org.elasticsearch.xpack.sql.planner.QueryTranslator.TIME_FORMAT;
import static org.elasticsearch.xpack.sql.type.SqlDataTypes.DATE; import static org.elasticsearch.xpack.sql.type.SqlDataTypes.DATE;
import static org.elasticsearch.xpack.sql.util.DateUtils.UTC;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
@ -114,20 +116,32 @@ public class QueryTranslatorTests extends ESTestCase {
} }
private LogicalPlan plan(String sql) { private LogicalPlan plan(String sql) {
return analyzer.analyze(parser.createStatement(sql), true); return plan(sql, UTC);
}
private LogicalPlan plan(String sql, ZoneId zoneId) {
return analyzer.analyze(parser.createStatement(sql, zoneId), true);
} }
private PhysicalPlan optimizeAndPlan(String sql) { private PhysicalPlan optimizeAndPlan(String sql) {
return planner.plan(optimizer.optimize(plan(sql)), true); return planner.plan(optimizer.optimize(plan(sql)), true);
} }
private QueryTranslation translate(Expression condition) {
return QueryTranslator.toQuery(condition, false);
}
private QueryTranslation translateWithAggs(Expression condition) {
return QueryTranslator.toQuery(condition, true);
}
public void testTermEqualityAnalyzer() { public void testTermEqualityAnalyzer() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE some.string = 'value'"); LogicalPlan p = plan("SELECT some.string FROM test WHERE some.string = 'value'");
assertTrue(p instanceof Project); assertTrue(p instanceof Project);
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof TermQuery); assertTrue(query instanceof TermQuery);
TermQuery tq = (TermQuery) query; TermQuery tq = (TermQuery) query;
@ -148,6 +162,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertEquals("c", a.aggregates().get(0).name()); assertEquals("c", a.aggregates().get(0).name());
assertEquals("COUNT", ((Count) ((Alias) a.aggregates().get(0)).child()).functionName()); assertEquals("COUNT", ((Count) ((Alias) a.aggregates().get(0)).child()).functionName());
} }
public void testLiteralWithGroupBy(){ public void testLiteralWithGroupBy(){
LogicalPlan p = plan("SELECT 1 as t, 2 FROM test GROUP BY int"); LogicalPlan p = plan("SELECT 1 as t, 2 FROM test GROUP BY int");
assertTrue(p instanceof Aggregate); assertTrue(p instanceof Aggregate);
@ -169,7 +184,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof TermQuery); assertTrue(query instanceof TermQuery);
TermQuery tq = (TermQuery) query; TermQuery tq = (TermQuery) query;
@ -183,7 +198,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof TermQuery); assertTrue(query instanceof TermQuery);
TermQuery tq = (TermQuery) query; TermQuery tq = (TermQuery) query;
@ -192,12 +207,13 @@ public class QueryTranslatorTests extends ESTestCase {
} }
public void testTermEqualityForDateWithLiteralDate() { public void testTermEqualityForDateWithLiteralDate() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE date = CAST('2019-08-08T12:34:56' AS DATETIME)"); ZoneId zoneId = randomZone();
LogicalPlan p = plan("SELECT some.string FROM test WHERE date = CAST('2019-08-08T12:34:56' AS DATETIME)", zoneId);
assertTrue(p instanceof Project); assertTrue(p instanceof Project);
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof RangeQuery); assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query; RangeQuery rq = (RangeQuery) query;
@ -207,15 +223,17 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(rq.includeLower()); assertTrue(rq.includeLower());
assertTrue(rq.includeUpper()); assertTrue(rq.includeUpper());
assertEquals(DATE_FORMAT, rq.format()); assertEquals(DATE_FORMAT, rq.format());
assertEquals(zoneId, rq.zoneId());
} }
public void testTermEqualityForDateWithLiteralTime() { public void testTermEqualityForDateWithLiteralTime() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE date = CAST('12:34:56' AS TIME)"); ZoneId zoneId = randomZone();
LogicalPlan p = plan("SELECT some.string FROM test WHERE date = CAST('12:34:56' AS TIME)", zoneId);
assertTrue(p instanceof Project); assertTrue(p instanceof Project);
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof RangeQuery); assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query; RangeQuery rq = (RangeQuery) query;
@ -225,6 +243,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(rq.includeLower()); assertTrue(rq.includeLower());
assertTrue(rq.includeUpper()); assertTrue(rq.includeUpper());
assertEquals(TIME_FORMAT, rq.format()); assertEquals(TIME_FORMAT, rq.format());
assertEquals(zoneId, rq.zoneId());
} }
public void testComparisonAgainstColumns() { public void testComparisonAgainstColumns() {
@ -233,50 +252,56 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QlIllegalArgumentException ex = expectThrows(QlIllegalArgumentException.class, () -> QueryTranslator.toQuery(condition, false)); QlIllegalArgumentException ex = expectThrows(QlIllegalArgumentException.class, () -> translate(condition));
assertEquals("Line 1:43: Comparisons against variables are not (currently) supported; offender [int] in [>]", ex.getMessage()); assertEquals("Line 1:43: Comparisons against variables are not (currently) supported; offender [int] in [>]", ex.getMessage());
} }
public void testDateRange() { public void testDateRange() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE date > 1969-05-13"); ZoneId zoneId = randomZone();
LogicalPlan p = plan("SELECT some.string FROM test WHERE date > 1969-05-13", zoneId);
assertTrue(p instanceof Project); assertTrue(p instanceof Project);
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof RangeQuery); assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query; RangeQuery rq = (RangeQuery) query;
assertEquals("date", rq.field()); assertEquals("date", rq.field());
assertEquals(1951, rq.lower()); assertEquals(1951, rq.lower());
assertEquals(zoneId, rq.zoneId());
} }
public void testDateRangeLiteral() { public void testDateRangeLiteral() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE date > '1969-05-13'"); ZoneId zoneId = randomZone();
LogicalPlan p = plan("SELECT some.string FROM test WHERE date > '1969-05-13'", zoneId);
assertTrue(p instanceof Project); assertTrue(p instanceof Project);
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof RangeQuery); assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query; RangeQuery rq = (RangeQuery) query;
assertEquals("date", rq.field()); assertEquals("date", rq.field());
assertEquals("1969-05-13", rq.lower()); assertEquals("1969-05-13", rq.lower());
assertEquals(zoneId, rq.zoneId());
} }
public void testDateRangeCast() { public void testDateRangeCast() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE date > CAST('1969-05-13T12:34:56Z' AS DATETIME)"); ZoneId zoneId = randomZone();
LogicalPlan p = plan("SELECT some.string FROM test WHERE date > CAST('1969-05-13T12:34:56Z' AS DATETIME)", zoneId);
assertTrue(p instanceof Project); assertTrue(p instanceof Project);
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof RangeQuery); assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query; RangeQuery rq = (RangeQuery) query;
assertEquals("date", rq.field()); assertEquals("date", rq.field());
assertEquals("1969-05-13T12:34:56.000Z", rq.lower()); assertEquals("1969-05-13T12:34:56.000Z", rq.lower());
assertEquals(zoneId, rq.zoneId());
} }
public void testDateRangeWithCurrentTimestamp() { public void testDateRangeWithCurrentTimestamp() {
@ -315,13 +340,14 @@ public class QueryTranslatorTests extends ESTestCase {
} }
private void testDateRangeWithCurrentFunctions(String function, String pattern, ZonedDateTime now) { private void testDateRangeWithCurrentFunctions(String function, String pattern, ZonedDateTime now) {
String operator = randomFrom(new String[] {">", ">=", "<", "<=", "=", "!="}); ZoneId zoneId = randomZone();
LogicalPlan p = plan("SELECT some.string FROM test WHERE date" + operator + function); String operator = randomFrom(">", ">=", "<", "<=", "=", "!=");
LogicalPlan p = plan("SELECT some.string FROM test WHERE date" + operator + function, zoneId);
assertTrue(p instanceof Project); assertTrue(p instanceof Project);
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
RangeQuery rq; RangeQuery rq;
@ -348,12 +374,13 @@ public class QueryTranslatorTests extends ESTestCase {
assertEquals(operator.equals("=") || operator.equals("!=") || operator.equals("<="), rq.includeUpper()); assertEquals(operator.equals("=") || operator.equals("!=") || operator.equals("<="), rq.includeUpper());
assertEquals(operator.equals("=") || operator.equals("!=") || operator.equals(">="), rq.includeLower()); assertEquals(operator.equals("=") || operator.equals("!=") || operator.equals(">="), rq.includeLower());
assertEquals(pattern, rq.format()); assertEquals(pattern, rq.format());
assertEquals(zoneId, rq.zoneId());
} }
private void testDateRangeWithCurrentFunctions_AndRangeOptimization(String function, String pattern, ZonedDateTime lowerValue, private void testDateRangeWithCurrentFunctions_AndRangeOptimization(String function, String pattern, ZonedDateTime lowerValue,
ZonedDateTime upperValue) { ZonedDateTime upperValue) {
String lowerOperator = randomFrom(new String[] {"<", "<="}); String lowerOperator = randomFrom("<", "<=");
String upperOperator = randomFrom(new String[] {">", ">="}); String upperOperator = randomFrom(">", ">=");
// use both date-only interval (1 DAY) and time-only interval (1 second) to cover CURRENT_TIMESTAMP and TODAY scenarios // use both date-only interval (1 DAY) and time-only interval (1 second) to cover CURRENT_TIMESTAMP and TODAY scenarios
String interval = "(INTERVAL 1 DAY + INTERVAL 1 SECOND)"; String interval = "(INTERVAL 1 DAY + INTERVAL 1 SECOND)";
@ -380,6 +407,50 @@ public class QueryTranslatorTests extends ESTestCase {
assertEquals(lowerOperator.equals("<="), rq.includeUpper()); assertEquals(lowerOperator.equals("<="), rq.includeUpper());
assertEquals(upperOperator.equals(">="), rq.includeLower()); assertEquals(upperOperator.equals(">="), rq.includeLower());
assertEquals(pattern, rq.format()); assertEquals(pattern, rq.format());
assertEquals(UTC, rq.zoneId());
}
public void testDateRangeWithESDateMath() {
ZoneId zoneId = randomZone();
String operator = randomFrom(">", ">=", "<", "<=", "=", "!=");
String dateMath = randomFrom("now", "now/d", "now/h", "now-2h", "now+2h", "now-5d", "now+5d");
LogicalPlan p = plan("SELECT some.string FROM test WHERE date" + operator + "'" + dateMath + "'", zoneId);
assertTrue(p instanceof Project);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = translate(condition);
Query query = translation.query;
if ("=".equals(operator) || "!=".equals(operator)) {
TermQuery tq;
if ("=".equals(operator)) {
assertTrue(query instanceof TermQuery);
tq = (TermQuery) query;
} else {
assertTrue(query instanceof NotQuery);
NotQuery nq = (NotQuery) query;
assertTrue(nq.child() instanceof TermQuery);
tq = (TermQuery) nq.child();
}
assertEquals("date", tq.term());
} else {
assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query;
assertEquals("date", rq.field());
if (operator.contains("<")) {
assertEquals(dateMath, rq.upper());
}
if (operator.contains(">")) {
assertEquals(dateMath, rq.lower());
}
assertEquals("<=".equals(operator), rq.includeUpper());
assertEquals(">=".equals(operator), rq.includeLower());
assertNull(rq.format());
assertEquals(zoneId, rq.zoneId());
}
} }
public void testTranslateDateAdd_WhereClause_Painless() { public void testTranslateDateAdd_WhereClause_Painless() {
@ -388,7 +459,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -405,7 +476,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -422,7 +493,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -438,7 +509,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -454,7 +525,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -470,7 +541,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -487,7 +558,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation qt = QueryTranslator.toQuery(condition, false); QueryTranslation qt = translate(condition);
assertEquals(WildcardQuery.class, qt.query.getClass()); assertEquals(WildcardQuery.class, qt.query.getClass());
WildcardQuery qsq = ((WildcardQuery) qt.query); WildcardQuery qsq = ((WildcardQuery) qt.query);
assertEquals("some.string.typical", qsq.field()); assertEquals("some.string.typical", qsq.field());
@ -499,7 +570,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation qt = QueryTranslator.toQuery(condition, false); QueryTranslation qt = translate(condition);
assertEquals(RegexQuery.class, qt.query.getClass()); assertEquals(RegexQuery.class, qt.query.getClass());
RegexQuery qsq = ((RegexQuery) qt.query); RegexQuery qsq = ((RegexQuery) qt.query);
assertEquals("some.string.typical", qsq.field()); assertEquals("some.string.typical", qsq.field());
@ -511,7 +582,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QlIllegalArgumentException ex = expectThrows(QlIllegalArgumentException.class, () -> QueryTranslator.toQuery(condition, false)); QlIllegalArgumentException ex = expectThrows(QlIllegalArgumentException.class, () -> translate(condition));
assertEquals("Scalar function [LTRIM(keyword)] not allowed (yet) as argument for LTRIM(keyword) like '%a%'", ex.getMessage()); assertEquals("Scalar function [LTRIM(keyword)] not allowed (yet) as argument for LTRIM(keyword) like '%a%'", ex.getMessage());
} }
@ -521,7 +592,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child(); p = ((Project) p).child();
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QlIllegalArgumentException ex = expectThrows(QlIllegalArgumentException.class, () -> QueryTranslator.toQuery(condition, false)); QlIllegalArgumentException ex = expectThrows(QlIllegalArgumentException.class, () -> translate(condition));
assertEquals("Scalar function [LTRIM(keyword)] not allowed (yet) as argument for LTRIM(keyword) RLIKE '.*a.*'", ex.getMessage()); assertEquals("Scalar function [LTRIM(keyword)] not allowed (yet) as argument for LTRIM(keyword) RLIKE '.*a.*'", ex.getMessage());
} }
@ -532,7 +603,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation qt = QueryTranslator.toQuery(condition, false); QueryTranslation qt = translate(condition);
assertEquals(BoolQuery.class, qt.query.getClass()); assertEquals(BoolQuery.class, qt.query.getClass());
BoolQuery bq = ((BoolQuery) qt.query); BoolQuery bq = ((BoolQuery) qt.query);
assertTrue(bq.isAnd()); assertTrue(bq.isAnd());
@ -565,7 +636,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
QueryTranslation qt = QueryTranslator.toQuery(condition, false); QueryTranslation qt = translate(condition);
assertEquals(BoolQuery.class, qt.query.getClass()); assertEquals(BoolQuery.class, qt.query.getClass());
BoolQuery bq = ((BoolQuery) qt.query); BoolQuery bq = ((BoolQuery) qt.query);
assertTrue(bq.isAnd()); assertTrue(bq.isAnd());
@ -606,7 +677,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.not(" + assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.not(" +
@ -622,7 +693,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof NotQuery); assertTrue(translation.query instanceof NotQuery);
NotQuery tq = (NotQuery) translation.query; NotQuery tq = (NotQuery) translation.query;
assertTrue(tq.child() instanceof ExistsQuery); assertTrue(tq.child() instanceof ExistsQuery);
@ -637,7 +708,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.isNull(" + assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.isNull(" +
@ -652,7 +723,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof ExistsQuery); assertTrue(translation.query instanceof ExistsQuery);
ExistsQuery eq = (ExistsQuery) translation.query; ExistsQuery eq = (ExistsQuery) translation.query;
assertEquals("{\"exists\":{\"field\":\"keyword\",\"boost\":1.0}}", assertEquals("{\"exists\":{\"field\":\"keyword\",\"boost\":1.0}}",
@ -665,7 +736,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.isNotNull(" + assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.isNotNull(" +
@ -679,7 +750,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals( assertEquals(
@ -693,7 +764,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals( assertEquals(
@ -702,6 +773,8 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int)")); assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int)"));
} }
public void testTranslateCoalesceExpression_WhereGroupByAndHaving_Painless() { public void testTranslateCoalesceExpression_WhereGroupByAndHaving_Painless() {
PhysicalPlan p = optimizeAndPlan("SELECT COALESCE(null, int) AS c, COALESCE(max(date), NULL) as m FROM test " + PhysicalPlan p = optimizeAndPlan("SELECT COALESCE(null, int) AS c, COALESCE(max(date), NULL) as m FROM test " +
"WHERE c > 10 GROUP BY c HAVING m > '2020-01-01'::date"); "WHERE c > 10 GROUP BY c HAVING m > '2020-01-01'::date");
@ -735,7 +808,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof TermsQuery); assertTrue(query instanceof TermsQuery);
TermsQuery tq = (TermsQuery) query; TermsQuery tq = (TermsQuery) query;
@ -749,7 +822,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof TermsQuery); assertTrue(query instanceof TermsQuery);
TermsQuery tq = (TermsQuery) query; TermsQuery tq = (TermsQuery) query;
@ -763,7 +836,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
Query query = translation.query; Query query = translation.query;
assertTrue(query instanceof TermsQuery); assertTrue(query instanceof TermsQuery);
TermsQuery tq = (TermsQuery) query; TermsQuery tq = (TermsQuery) query;
@ -777,7 +850,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter); assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -792,7 +865,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))", assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))",
@ -806,7 +879,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))", assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))",
@ -821,7 +894,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))", assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))",
@ -839,7 +912,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(InternalSqlScriptUtils." + assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(InternalSqlScriptUtils." +
@ -901,7 +974,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter); assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(InternalSqlScriptUtils.abs" + assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(InternalSqlScriptUtils.abs" +
@ -917,7 +990,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class)); assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(" + assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(" +
@ -934,7 +1007,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class)); assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(" + assertEquals("InternalQlScriptUtils.nullSafeFilter(" +
@ -952,7 +1025,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class)); assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery); assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -971,7 +1044,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class)); assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertTrue(translation.query instanceof GeoDistanceQuery); assertTrue(translation.query instanceof GeoDistanceQuery);
GeoDistanceQuery gq = (GeoDistanceQuery) translation.query; GeoDistanceQuery gq = (GeoDistanceQuery) translation.query;
@ -988,7 +1061,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class)); assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertThat(translation.query, instanceOf(ScriptQuery.class)); assertThat(translation.query, instanceOf(ScriptQuery.class));
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -1004,7 +1077,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class)); assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition(); Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false); QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter); assertNull(translation.aggFilter);
assertThat(translation.query, instanceOf(ScriptQuery.class)); assertThat(translation.query, instanceOf(ScriptQuery.class));
ScriptQuery sc = (ScriptQuery) translation.query; ScriptQuery sc = (ScriptQuery) translation.query;
@ -1805,7 +1878,6 @@ public class QueryTranslatorTests extends ESTestCase {
EsQueryExec eqe = (EsQueryExec) p; EsQueryExec eqe = (EsQueryExec) p;
assertTrue("Should be tracking hits", eqe.queryContainer().shouldTrackHits()); assertTrue("Should be tracking hits", eqe.queryContainer().shouldTrackHits());
assertEquals(1, eqe.output().size()); assertEquals(1, eqe.output().size());
String query = eqe.queryContainer().toString().replaceAll("\\s+", "");
assertThat(eqe.queryContainer().toString().replaceAll("\\s+", ""), containsString("\"size\":0")); assertThat(eqe.queryContainer().toString().replaceAll("\\s+", ""), containsString("\"size\":0"));
} }
@ -1879,7 +1951,7 @@ public class QueryTranslatorTests extends ESTestCase {
Expression condition = ((Filter) p).condition(); Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable()); assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true); QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query); assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter; AggFilter aggFilter = translation.aggFilter;
assertEquals( assertEquals(

View File

@ -20,6 +20,7 @@ import org.elasticsearch.xpack.ql.tree.Source;
import org.elasticsearch.xpack.ql.tree.SourceTests; import org.elasticsearch.xpack.ql.tree.SourceTests;
import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.type.EsField;
import java.time.ZoneId;
import java.util.AbstractMap.SimpleImmutableEntry; import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet; import java.util.BitSet;
@ -44,15 +45,17 @@ public class QueryContainerTests extends ESTestCase {
} }
public void testRewriteToContainsNestedFieldWhenContainsNestedField() { public void testRewriteToContainsNestedFieldWhenContainsNestedField() {
ZoneId zoneId = randomZone();
Query original = new BoolQuery(source, true, Query original = new BoolQuery(source, true,
new NestedQuery(source, path, singletonMap(name, new SimpleImmutableEntry<>(hasDocValues, format)), new NestedQuery(source, path, singletonMap(name, new SimpleImmutableEntry<>(hasDocValues, format)),
new MatchAll(source)), new MatchAll(source)),
new RangeQuery(source, randomAlphaOfLength(5), 0, randomBoolean(), 100, randomBoolean())); new RangeQuery(source, randomAlphaOfLength(5), 0, randomBoolean(), 100, randomBoolean(), zoneId));
assertSame(original, QueryContainer.rewriteToContainNestedField(original, source, path, name, format, randomBoolean())); assertSame(original, QueryContainer.rewriteToContainNestedField(original, source, path, name, format, randomBoolean()));
} }
public void testRewriteToContainsNestedFieldWhenCanAddNestedField() { public void testRewriteToContainsNestedFieldWhenCanAddNestedField() {
Query buddy = new RangeQuery(source, randomAlphaOfLength(5), 0, randomBoolean(), 100, randomBoolean()); ZoneId zoneId = randomZone();
Query buddy = new RangeQuery(source, randomAlphaOfLength(5), 0, randomBoolean(), 100, randomBoolean(), zoneId);
Query original = new BoolQuery(source, true, Query original = new BoolQuery(source, true,
new NestedQuery(source, path, emptyMap(), new MatchAll(source)), new NestedQuery(source, path, emptyMap(), new MatchAll(source)),
buddy); buddy);
@ -64,7 +67,8 @@ public class QueryContainerTests extends ESTestCase {
} }
public void testRewriteToContainsNestedFieldWhenDoesNotContainNestedFieldAndCantAdd() { public void testRewriteToContainsNestedFieldWhenDoesNotContainNestedFieldAndCantAdd() {
Query original = new RangeQuery(source, randomAlphaOfLength(5), 0, randomBoolean(), 100, randomBoolean()); ZoneId zoneId = randomZone();
Query original = new RangeQuery(source, randomAlphaOfLength(5), 0, randomBoolean(), 100, randomBoolean(), zoneId);
Query expected = new BoolQuery(source, true, Query expected = new BoolQuery(source, true,
original, original,
new NestedQuery(source, path, singletonMap(name, new SimpleImmutableEntry<>(hasDocValues, format)), new NestedQuery(source, path, singletonMap(name, new SimpleImmutableEntry<>(hasDocValues, format)),