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 static java.lang.String.format;
import static org.elasticsearch.xpack.ql.type.DateUtils.UTC;
public class EqlParser {
@ -41,7 +42,7 @@ public class EqlParser {
* Parses an EQL statement into execution plan
*/
public LogicalPlan createStatement(String eql) {
return createStatement(eql, new ParserParams());
return createStatement(eql, new ParserParams(UTC));
}
public LogicalPlan createStatement(String eql, ParserParams params) {
@ -52,7 +53,7 @@ public class EqlParser {
}
public Expression createExpression(String expression) {
return createExpression(expression, new ParserParams());
return createExpression(expression, new ParserParams(UTC));
}
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.util.StringUtils;
import java.time.ZoneId;
import java.util.List;
import static java.util.Collections.emptyList;
@ -52,6 +53,12 @@ import static java.util.Collections.emptyList;
public class ExpressionBuilder extends IdentifierBuilder {
protected final ParserParams params;
public ExpressionBuilder(ParserParams params) {
this.params = params;
}
protected Expression expression(ParseTree ctx) {
return typedParsing(ctx, Expression.class);
}
@ -115,20 +122,21 @@ public class ExpressionBuilder extends IdentifierBuilder {
TerminalNode op = (TerminalNode) ctx.comparisonOperator().getChild(0);
Source source = source(ctx);
ZoneId zoneId = params.zoneId();
switch (op.getSymbol().getType()) {
case EqlBaseParser.EQ:
return new Equals(source, left, right);
return new Equals(source, left, right, zoneId);
case EqlBaseParser.NEQ:
return new NotEquals(source, left, right);
return new NotEquals(source, left, right, zoneId);
case EqlBaseParser.LT:
return new LessThan(source, left, right);
return new LessThan(source, left, right, zoneId);
case EqlBaseParser.LTE:
return new LessThanOrEqual(source, left, right);
return new LessThanOrEqual(source, left, right, zoneId);
case EqlBaseParser.GT:
return new GreaterThan(source, left, right);
return new GreaterThan(source, left, right, zoneId);
case EqlBaseParser.GTE:
return new GreaterThanOrEqual(source, left, right);
return new GreaterThanOrEqual(source, left, right, zoneId);
default:
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 {
private final ParserParams params;
private final UnresolvedRelation RELATION = new UnresolvedRelation(Source.EMPTY, null, "", false, "");
public LogicalPlanBuilder(ParserParams params) {
this.params = params;
super(params);
}
@Override
@ -56,7 +55,7 @@ public abstract class LogicalPlanBuilder extends ExpressionBuilder {
Literal eventValue = new Literal(eventSource, eventName, DataTypes.KEYWORD);
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);
}
@ -214,4 +213,4 @@ public abstract class LogicalPlanBuilder extends ExpressionBuilder {
text(numberCtx));
}
}
}
}

View File

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

View File

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

View File

@ -26,6 +26,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import static java.util.Collections.singletonList;
import static org.elasticsearch.xpack.ql.type.DateUtils.UTC;
public class LogicalPlanTests extends ESTestCase {
@ -56,7 +57,7 @@ public class LogicalPlanTests extends ESTestCase {
}
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);
Expression fullExpression = expr("myCustomEvent == 'process' and process_name == 'net.exe'");
@ -126,4 +127,4 @@ public class LogicalPlanTests extends ESTestCase {
assertEquals(new TimeValue(2, TimeUnit.SECONDS), maxSpan);
}
}
}

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.DataTypes;
import java.time.ZoneId;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@ -35,20 +36,22 @@ public class Range extends ScalarFunction {
private final Expression value, lower, upper;
private final boolean includeLower, includeUpper;
private final ZoneId zoneId;
public Range(Source source, Expression value, Expression lower, boolean includeLower, Expression upper, boolean includeUpper) {
super(source, asList(value, lower, upper));
public Range(Source src, Expression value, Expression lower, boolean inclLower, Expression upper, boolean inclUpper, ZoneId zoneId) {
super(src, asList(value, lower, upper));
this.value = value;
this.lower = lower;
this.upper = upper;
this.includeLower = includeLower;
this.includeUpper = includeUpper;
this.includeLower = inclLower;
this.includeUpper = inclUpper;
this.zoneId = zoneId;
}
@Override
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
@ -56,7 +59,7 @@ public class Range extends ScalarFunction {
if (newChildren.size() != 3) {
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() {
@ -79,6 +82,10 @@ public class Range extends ScalarFunction {
return includeUpper;
}
public ZoneId zoneId() {
return zoneId;
}
@Override
public boolean foldable() {
if (lower.foldable() && upper.foldable()) {
@ -160,7 +167,7 @@ public class Range extends ScalarFunction {
@Override
public int hashCode() {
return Objects.hash(includeLower, includeUpper, value, lower, upper);
return Objects.hash(includeLower, includeUpper, value, lower, upper, zoneId);
}
@Override
@ -178,6 +185,7 @@ public class Range extends ScalarFunction {
&& Objects.equals(includeUpper, other.includeUpper)
&& Objects.equals(value, other.value)
&& 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.DataTypes;
import java.time.ZoneId;
// marker class to indicate operations that rely on values
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);
this.zoneId = zoneId;
}
public ZoneId zoneId() {
return zoneId;
}
@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.Source;
import java.time.ZoneId;
public class Equals extends BinaryComparison implements Negatable<BinaryComparison> {
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
protected NodeInfo<Equals> info() {
return NodeInfo.create(this, Equals::new, left(), right());
return NodeInfo.create(this, Equals::new, left(), right(), zoneId());
}
@Override
protected Equals replaceChildren(Expression newLeft, Expression newRight) {
return new Equals(source(), newLeft, newRight);
return new Equals(source(), newLeft, newRight, zoneId());
}
@Override
public Equals swapLeftAndRight() {
return new Equals(source(), right(), left());
return new Equals(source(), right(), left(), zoneId());
}
@Override
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.Source;
import java.time.ZoneId;
public class GreaterThan extends BinaryComparison implements Negatable<BinaryComparison> {
public GreaterThan(Source source, Expression left, Expression right) {
super(source, left, right, BinaryComparisonOperation.GT);
public GreaterThan(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.GT, zoneId);
}
@Override
protected NodeInfo<GreaterThan> info() {
return NodeInfo.create(this, GreaterThan::new, left(), right());
return NodeInfo.create(this, GreaterThan::new, left(), right(), zoneId());
}
@Override
protected GreaterThan replaceChildren(Expression newLeft, Expression newRight) {
return new GreaterThan(source(), newLeft, newRight);
return new GreaterThan(source(), newLeft, newRight, zoneId());
}
@Override
public LessThan swapLeftAndRight() {
return new LessThan(source(), right(), left());
return new LessThan(source(), right(), left(), zoneId());
}
@Override
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.Source;
import java.time.ZoneId;
public class GreaterThanOrEqual extends BinaryComparison implements Negatable<BinaryComparison> {
public GreaterThanOrEqual(Source source, Expression left, Expression right) {
super(source, left, right, BinaryComparisonOperation.GTE);
public GreaterThanOrEqual(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.GTE, zoneId);
}
@Override
protected NodeInfo<GreaterThanOrEqual> info() {
return NodeInfo.create(this, GreaterThanOrEqual::new, left(), right());
return NodeInfo.create(this, GreaterThanOrEqual::new, left(), right(), zoneId());
}
@Override
protected GreaterThanOrEqual replaceChildren(Expression newLeft, Expression newRight) {
return new GreaterThanOrEqual(source(), newLeft, newRight);
return new GreaterThanOrEqual(source(), newLeft, newRight, zoneId());
}
@Override
public LessThanOrEqual swapLeftAndRight() {
return new LessThanOrEqual(source(), right(), left());
return new LessThanOrEqual(source(), right(), left(), zoneId());
}
@Override
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.Source;
import java.time.ZoneId;
public class LessThan extends BinaryComparison implements Negatable<BinaryComparison> {
public LessThan(Source source, Expression left, Expression right) {
super(source, left, right, BinaryComparisonOperation.LT);
public LessThan(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.LT, zoneId);
}
@Override
protected NodeInfo<LessThan> info() {
return NodeInfo.create(this, LessThan::new, left(), right());
return NodeInfo.create(this, LessThan::new, left(), right(), zoneId());
}
@Override
protected LessThan replaceChildren(Expression newLeft, Expression newRight) {
return new LessThan(source(), newLeft, newRight);
return new LessThan(source(), newLeft, newRight, zoneId());
}
@Override
public GreaterThan swapLeftAndRight() {
return new GreaterThan(source(), right(), left());
return new GreaterThan(source(), right(), left(), zoneId());
}
@Override
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.Source;
import java.time.ZoneId;
public class LessThanOrEqual extends BinaryComparison implements Negatable<BinaryComparison> {
public LessThanOrEqual(Source source, Expression left, Expression right) {
super(source, left, right, BinaryComparisonOperation.LTE);
public LessThanOrEqual(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.LTE, zoneId);
}
@Override
protected NodeInfo<LessThanOrEqual> info() {
return NodeInfo.create(this, LessThanOrEqual::new, left(), right());
return NodeInfo.create(this, LessThanOrEqual::new, left(), right(), zoneId());
}
@Override
protected LessThanOrEqual replaceChildren(Expression newLeft, Expression newRight) {
return new LessThanOrEqual(source(), newLeft, newRight);
return new LessThanOrEqual(source(), newLeft, newRight, zoneId());
}
@Override
public GreaterThanOrEqual swapLeftAndRight() {
return new GreaterThanOrEqual(source(), right(), left());
return new GreaterThanOrEqual(source(), right(), left(), zoneId());
}
@Override
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.Source;
import java.time.ZoneId;
public class NotEquals extends BinaryComparison implements Negatable<BinaryComparison> {
public NotEquals(Source source, Expression left, Expression right) {
super(source, left, right, BinaryComparisonOperation.NEQ);
public NotEquals(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.NEQ, zoneId);
}
@Override
protected NodeInfo<NotEquals> info() {
return NodeInfo.create(this, NotEquals::new, left(), right());
return NodeInfo.create(this, NotEquals::new, left(), right(), zoneId());
}
@Override
protected NotEquals replaceChildren(Expression newLeft, Expression newRight) {
return new NotEquals(source(), newLeft, newRight);
return new NotEquals(source(), newLeft, newRight, zoneId());
}
@Override
public NotEquals swapLeftAndRight() {
return new NotEquals(source(), right(), left());
return new NotEquals(source(), right(), left(), zoneId());
}
@Override
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.Source;
import java.time.ZoneId;
/**
* Implements the MySQL {@code <=>} operator
*/
public class NullEquals extends BinaryComparison {
public NullEquals(Source source, Expression left, Expression right) {
super(source, left, right, BinaryComparisonOperation.NULLEQ);
public NullEquals(Source source, Expression left, Expression right, ZoneId zoneId) {
super(source, left, right, BinaryComparisonOperation.NULLEQ, zoneId);
}
@Override
protected NodeInfo<NullEquals> info() {
return NodeInfo.create(this, NullEquals::new, left(), right());
return NodeInfo.create(this, NullEquals::new, left(), right(), zoneId());
}
@Override
protected NullEquals replaceChildren(Expression newLeft, Expression newRight) {
return new NullEquals(source(), newLeft, newRight);
return new NullEquals(source(), newLeft, newRight, zoneId());
}
@Override
public NullEquals swapLeftAndRight() {
return new NullEquals(source(), right(), left());
return new NullEquals(source(), right(), left(), zoneId());
}
@Override

View File

@ -446,14 +446,14 @@ public final class OptimizerRules {
if (lowerComp != null && lowerComp == 0) {
if (!range.includeLower()) { // a = 2 OR 2 < a < ? -> 2 <= a < ?
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 < ?
removeEquals = true; // update range with lower equality instead or simply superfluous
break;
} else if (upperComp != null && upperComp == 0) {
if (!range.includeUpper()) { // a = 2 OR ? < a < 2 -> ? < a <= 2
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
removeEquals = true; // update range with upper equality instead
break;
@ -481,7 +481,7 @@ public final class OptimizerRules {
if (comp < 0) { // a = 1 OR a > 2 -> nop
continue;
} 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) :
// a = 3 OR a > 2 -> a > 2; a = 2 OR a => 2 -> a => 2
@ -492,7 +492,7 @@ public final class OptimizerRules {
continue;
}
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
removeEquals = true; // update range with equality instead or simply superfluous
break;
@ -598,7 +598,7 @@ public final class OptimizerRules {
ranges.add(new Range(and.source(), main.left(),
main.right(), main instanceof GreaterThanOrEqual,
other.right(), other instanceof LessThanOrEqual));
other.right(), other instanceof LessThanOrEqual, main.zoneId()));
changed = true;
step = 0;
@ -612,7 +612,7 @@ public final class OptimizerRules {
ranges.add(new Range(and.source(), main.left(),
other.right(), other instanceof GreaterThanOrEqual,
main.right(), main instanceof LessThanOrEqual));
main.right(), main instanceof LessThanOrEqual, main.zoneId()));
changed = true;
step = 0;
@ -739,7 +739,8 @@ public final class OptimizerRules {
lower ? main.lower() : other.lower(),
lower ? main.includeLower() : other.includeLower(),
upper ? main.upper() : other.upper(),
upper ? main.includeUpper() : other.includeUpper()));
upper ? main.includeUpper() : other.includeUpper(),
main.zoneId()));
}
// range was comparable
@ -755,7 +756,8 @@ public final class OptimizerRules {
lower ? main.lower() : other.lower(),
lower ? main.includeLower() : other.includeLower(),
upper ? main.upper() : other.upper(),
upper ? main.includeUpper() : other.includeUpper()));
upper ? main.includeUpper() : other.includeUpper(),
main.zoneId()));
return true;
}
@ -790,7 +792,7 @@ public final class OptimizerRules {
ranges.add(i,
new Range(other.source(), other.value(),
main.right(), lowerEq ? false : main instanceof GreaterThanOrEqual,
other.upper(), other.includeUpper()));
other.upper(), other.includeUpper(), other.zoneId()));
}
// found a match
@ -810,7 +812,7 @@ public final class OptimizerRules {
ranges.remove(i);
ranges.add(i, new Range(other.source(), other.value(),
other.lower(), other.includeLower(),
main.right(), upperEq ? false : main instanceof LessThanOrEqual));
main.right(), upperEq ? false : main instanceof LessThanOrEqual, other.zoneId()));
}
// found a match
@ -924,7 +926,7 @@ public final class OptimizerRules {
if (comp <= 0) {
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(),
range.includeUpper()));
range.includeUpper(), range.zoneId()));
}
// else: !.includeLower() : a != 2 AND 2 < a < 3 -> 2 < a < 3; or:
// 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 == 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(),
range.upper(), false));
range.upper(), false, range.zoneId()));
}
// else: !.includeUpper() : a != 4 AND 2 < a < 4 -> 2 < a < 4
// 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 == 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(),
false));
false, range.zoneId()));
}
// else: !.includeUpper() : a != 3 AND ?? < a < 3 -> ?? < a < 3
// else: comp > 0 : a != 3 and ?? < a < 2 -> ?? < a < 2
@ -979,7 +981,7 @@ public final class OptimizerRules {
if (comp != null) {
if (comp >= 0) {
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)
return true;
} // else: comp < 0 : a != 2 AND a </<= 3 -> nop
@ -989,7 +991,7 @@ public final class OptimizerRules {
if (comp != null) {
if (comp <= 0) {
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)
return true;
} // 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 java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAccessor;
import java.util.Arrays;
@ -59,6 +60,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME;
public final class ExpressionTranslators {
@ -250,17 +252,21 @@ public final class ExpressionTranslators {
isDateLiteralComparison = true;
}
ZoneId zoneId = null;
if (bc.left().dataType() == DATETIME) {
zoneId = bc.zoneId();
}
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) {
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) {
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) {
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.left() instanceof FieldAttribute) {
@ -271,7 +277,7 @@ public final class ExpressionTranslators {
Query query;
if (isDateLiteralComparison) {
// 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 {
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(),
upper.get(), r.includeUpper(), format.get()));
upper.get(), r.includeUpper(), format.get(), r.zoneId()));
return query;
}

View File

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

View File

@ -6,7 +6,16 @@
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.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.tree.Source;
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.randomZone;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
public final class TestUtils {
@ -49,4 +59,36 @@ public final class TestUtils {
}
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.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.tree.Source.EMPTY;
@ -40,54 +47,54 @@ public class BinaryComparisonProcessorTests extends AbstractWireSerializingTestC
}
public void testEq() {
assertEquals(true, new Equals(EMPTY, l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, new Equals(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, equalsOf(l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, equalsOf(l(3), l(4)).makePipe().asProcessor().process(null));
}
public void testNullEq() {
assertEquals(true, new NullEquals(EMPTY, l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, new NullEquals(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, new NullEquals(EMPTY, NULL, NULL).makePipe().asProcessor().process(null));
assertEquals(false, new NullEquals(EMPTY, l(4), NULL).makePipe().asProcessor().process(null));
assertEquals(false, new NullEquals(EMPTY, NULL, l(4)).makePipe().asProcessor().process(null));
assertEquals(true, nullEqualsOf(l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, nullEqualsOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, nullEqualsOf(NULL, NULL).makePipe().asProcessor().process(null));
assertEquals(false, nullEqualsOf(l(4), NULL).makePipe().asProcessor().process(null));
assertEquals(false, nullEqualsOf(NULL, l(4)).makePipe().asProcessor().process(null));
}
public void testNEq() {
assertEquals(false, new NotEquals(EMPTY, l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, new NotEquals(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, notEqualsOf(l(4), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, notEqualsOf(l(3), l(4)).makePipe().asProcessor().process(null));
}
public void testGt() {
assertEquals(true, new GreaterThan(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(false, new GreaterThan(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, new GreaterThan(EMPTY, l(3), l(3)).makePipe().asProcessor().process(null));
assertEquals(true, greaterThanOf(l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(false, greaterThanOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, greaterThanOf(l(3), l(3)).makePipe().asProcessor().process(null));
}
public void testGte() {
assertEquals(true, new GreaterThanOrEqual(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(false, new GreaterThanOrEqual(EMPTY, 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(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(false, greaterThanOrEqualOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, greaterThanOrEqualOf(l(3), l(3)).makePipe().asProcessor().process(null));
}
public void testLt() {
assertEquals(false, new LessThan(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(true, new LessThan(EMPTY, 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(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(true, lessThanOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(false, lessThanOf(l(3), l(3)).makePipe().asProcessor().process(null));
}
public void testLte() {
assertEquals(false, new LessThanOrEqual(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(true, new LessThanOrEqual(EMPTY, l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, new LessThanOrEqual(EMPTY, l(3), l(3)).makePipe().asProcessor().process(null));
assertEquals(false, lessThanOrEqualOf(l(4), l(3)).makePipe().asProcessor().process(null));
assertEquals(true, lessThanOrEqualOf(l(3), l(4)).makePipe().asProcessor().process(null));
assertEquals(true, lessThanOrEqualOf(l(3), l(3)).makePipe().asProcessor().process(null));
}
public void testHandleNull() {
assertNull(new Equals(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new NotEquals(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new GreaterThan(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new GreaterThanOrEqual(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new LessThan(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new LessThanOrEqual(EMPTY, NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(equalsOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(notEqualsOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(greaterThanOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(greaterThanOrEqualOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(lessThanOf(NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(lessThanOrEqualOf(NULL, l(3)).makePipe().asProcessor().process(null));
}
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.EsField;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
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.rangeOf;
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.TRUE;
@ -144,21 +153,21 @@ public class OptimizerRulesTests extends ESTestCase {
}
public void testConstantFoldingBinaryComparison() {
assertEquals(FALSE, new ConstantFolding().rule(new GreaterThan(EMPTY, TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new GreaterThanOrEqual(EMPTY, TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new Equals(EMPTY, TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new NullEquals(EMPTY, TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new NullEquals(EMPTY, TWO, NULL)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(new NotEquals(EMPTY, TWO, THREE)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(new LessThanOrEqual(EMPTY, TWO, THREE)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(new LessThan(EMPTY, TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(greaterThanOf(TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(greaterThanOrEqualOf(TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(equalsOf(TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(nullEqualsOf(TWO, THREE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(nullEqualsOf(TWO, NULL)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(notEqualsOf(TWO, THREE)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(lessThanOrEqualOf(TWO, THREE)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(lessThanOf(TWO, THREE)).canonical());
}
public void testConstantFoldingBinaryLogic() {
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,
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() {
@ -176,8 +185,8 @@ public class OptimizerRulesTests extends ESTestCase {
}
public void testConstantFoldingRange() {
assertEquals(true, new ConstantFolding().rule(new Range(EMPTY, FIVE, FIVE, true, L(10), false)).fold());
assertEquals(false, new ConstantFolding().rule(new Range(EMPTY, FIVE, FIVE, false, L(10), false)).fold());
assertEquals(true, new ConstantFolding().rule(rangeOf(FIVE, FIVE, true, L(10), false)).fold());
assertEquals(false, new ConstantFolding().rule(rangeOf(FIVE, FIVE, false, L(10), false)).fold());
}
public void testConstantNot() {
@ -211,14 +220,14 @@ public class OptimizerRulesTests extends ESTestCase {
public void testLiteralsOnTheRight() {
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);
Equals eq = (Equals) result;
assertEquals(a, eq.left());
assertEquals(FIVE, eq.right());
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);
NullEquals nullEquals= (NullEquals) result;
assertEquals(a, nullEquals.left());
@ -271,7 +280,7 @@ public class OptimizerRulesTests extends ESTestCase {
public void testFoldExcludingRangeToFalse() {
FieldAttribute fa = getFieldAttribute();
Range r = new Range(EMPTY, fa, SIX, false, FIVE, true);
Range r = rangeOf(fa, SIX, false, FIVE, true);
assertTrue(r.foldable());
assertEquals(Boolean.FALSE, r.fold());
}
@ -280,7 +289,7 @@ public class OptimizerRulesTests extends ESTestCase {
public void testFoldExcludingRangeWithDifferentTypesToFalse() {
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());
assertEquals(Boolean.FALSE, r.fold());
}
@ -289,8 +298,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsNotComparable() {
FieldAttribute fa = getFieldAttribute();
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, SIX);
LessThan lt = new LessThan(EMPTY, fa, FALSE);
LessThanOrEqual lte = lessThanOrEqualOf(fa, SIX);
LessThan lt = lessThanOf(fa, FALSE);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
And and = new And(EMPTY, lte, lt);
@ -301,8 +310,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a <= 6 AND a < 5 -> a < 5
public void testCombineBinaryComparisonsUpper() {
FieldAttribute fa = getFieldAttribute();
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, SIX);
LessThan lt = new LessThan(EMPTY, fa, FIVE);
LessThanOrEqual lte = lessThanOrEqualOf(fa, SIX);
LessThan lt = lessThanOf(fa, FIVE);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -315,8 +324,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 6 <= a AND 5 < a -> 6 <= a
public void testCombineBinaryComparisonsLower() {
FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, SIX);
GreaterThan gt = new GreaterThan(EMPTY, fa, FIVE);
GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, SIX);
GreaterThan gt = greaterThanOf(fa, FIVE);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -329,8 +338,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 5 <= a AND 5 < a -> 5 < a
public void testCombineBinaryComparisonsInclude() {
FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, FIVE);
GreaterThan gt = new GreaterThan(EMPTY, fa, FIVE);
GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, FIVE);
GreaterThan gt = greaterThanOf(fa, FIVE);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -344,8 +353,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsAndRangeLower() {
FieldAttribute fa = getFieldAttribute();
GreaterThan gt = new GreaterThan(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, TWO, true, THREE, false);
GreaterThan gt = greaterThanOf(fa, TWO);
Range range = rangeOf(fa, TWO, true, THREE, false);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression exp = rule.rule(new And(EMPTY, gt, range));
@ -361,8 +370,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsAndRangeUpper() {
FieldAttribute fa = getFieldAttribute();
LessThan lt = new LessThan(EMPTY, fa, FOUR);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false);
LessThan lt = lessThanOf(fa, FOUR);
Range range = rangeOf(fa, ONE, false, THREE, false);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression exp = rule.rule(new And(EMPTY, range, lt));
@ -378,8 +387,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsAndRangeUpperEqual() {
FieldAttribute fa = getFieldAttribute();
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false);
LessThanOrEqual lte = lessThanOrEqualOf(fa, TWO);
Range range = rangeOf(fa, ONE, false, THREE, false);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
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
public void testCombineMultipleBinaryComparisons() {
FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, THREE);
GreaterThan gt = new GreaterThan(EMPTY, fa, FOUR);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, L(7));
LessThan lt = new LessThan(EMPTY, fa, SIX);
GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, THREE);
GreaterThan gt = greaterThanOf(fa, FOUR);
LessThanOrEqual lte = lessThanOrEqualOf(fa, L(7));
LessThan lt = lessThanOf(fa, SIX);
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
public void testCombineMixedMultipleBinaryComparisons() {
FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, THREE);
GreaterThan gt = new GreaterThan(EMPTY, fa, FOUR);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, L(7));
Expression ne = new Not(EMPTY, new Equals(EMPTY, fa, FIVE));
GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, THREE);
GreaterThan gt = greaterThanOf(fa, FOUR);
LessThanOrEqual lte = lessThanOrEqualOf(fa, L(7));
Expression ne = new Not(EMPTY, equalsOf(fa, FIVE));
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -435,8 +444,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 1 <= a AND a < 5 -> 1 <= a < 5
public void testCombineComparisonsIntoRange() {
FieldAttribute fa = getFieldAttribute();
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, ONE);
LessThan lt = new LessThan(EMPTY, fa, FIVE);
GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, ONE);
LessThan lt = lessThanOf(fa, FIVE);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression exp = rule.rule(new And(EMPTY, gte, lt));
@ -455,19 +464,20 @@ public class OptimizerRulesTests extends ESTestCase {
FieldAttribute fb = getFieldAttribute("b");
FieldAttribute fc = getFieldAttribute("c");
GreaterThan agt1 = new GreaterThan(EMPTY, fa, ONE);
LessThan alt3 = new LessThan(EMPTY, fa, THREE);
GreaterThan bgt2 = new GreaterThan(EMPTY, fb, TWO);
LessThan blt4 = new LessThan(EMPTY, fb, FOUR);
LessThan clt4 = new LessThan(EMPTY, fc, FOUR);
ZoneId zoneId = randomZone();
GreaterThan agt1 = new GreaterThan(EMPTY, fa, ONE, zoneId);
LessThan alt3 = new LessThan(EMPTY, fa, THREE, zoneId);
GreaterThan bgt2 = new GreaterThan(EMPTY, fb, TWO, zoneId);
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));
CombineBinaryComparisons rule = new CombineBinaryComparisons();
Expression outputAnd = rule.rule(inputAnd);
Range agt1lt3 = new Range(EMPTY, fa, ONE, false, THREE, false);
Range bgt2lt4 = new Range(EMPTY, fb, TWO, false, FOUR, false);
Range agt1lt3 = new Range(EMPTY, fa, ONE, false, THREE, false, zoneId);
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
Expression expectedAnd = Predicates.combineAnd(Arrays.asList(clt4, agt1lt3, bgt2lt4));
@ -479,8 +489,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionOfIncludedRange() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, FOUR, false);
Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = rangeOf(fa, ONE, false, FOUR, false);
And and = new And(EMPTY, r1, r2);
@ -493,8 +503,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionOfNonOverlappingBoundaries() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, TWO, false);
Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = rangeOf(fa, ONE, false, TWO, false);
And and = new And(EMPTY, r1, r2);
@ -513,8 +523,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionOfUpperEqualsOverlappingBoundaries() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, true);
Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = rangeOf(fa, TWO, false, THREE, true);
And and = new And(EMPTY, r1, r2);
@ -527,8 +537,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionOverlappingUpperBoundary() {
FieldAttribute fa = getFieldAttribute();
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r1 = new Range(EMPTY, fa, ONE, false, THREE, false);
Range r2 = rangeOf(fa, TWO, false, THREE, false);
Range r1 = rangeOf(fa, ONE, false, THREE, false);
And and = new And(EMPTY, r1, r2);
@ -541,8 +551,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunctionWithDifferentUpperLimitInclusion() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, ONE, false, THREE, false);
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, true);
Range r1 = rangeOf(fa, ONE, false, THREE, false);
Range r2 = rangeOf(fa, TWO, false, THREE, true);
And and = new And(EMPTY, r1, r2);
@ -560,8 +570,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testRangesOverlappingConjunctionNoLowerBoundary() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, L(0), false, ONE, true);
Range r2 = new Range(EMPTY, fa, L(0), true, TWO, false);
Range r1 = rangeOf(fa, L(0), false, ONE, true);
Range r2 = rangeOf(fa, L(0), true, TWO, false);
And and = new And(EMPTY, r1, r2);
@ -574,8 +584,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt3Lt5() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, THREE, false, FIVE, false);
NotEquals neq = notEqualsOf(fa, TWO);
Range range = rangeOf(fa, THREE, false, FIVE, false);
And and = new And(EMPTY, range, neq);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -592,8 +602,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt0Lt1() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, L(0), false, ONE, false);
NotEquals neq = notEqualsOf(fa, TWO);
Range range = rangeOf(fa, L(0), false, ONE, false);
And and = new And(EMPTY, neq, range);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -610,8 +620,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGte2Lt3() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, TWO, true, THREE, false);
NotEquals neq = notEqualsOf(fa, TWO);
Range range = rangeOf(fa, TWO, true, THREE, false);
And and = new And(EMPTY, neq, range);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -628,8 +638,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq3AndRangeGt2Lte3() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, THREE);
Range range = new Range(EMPTY, fa, TWO, false, THREE, true);
NotEquals neq = notEqualsOf(fa, THREE);
Range range = rangeOf(fa, TWO, false, THREE, true);
And and = new And(EMPTY, neq, range);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -646,8 +656,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndRangeGt1Lt3() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false);
NotEquals neq = notEqualsOf(fa, TWO);
Range range = rangeOf(fa, ONE, false, THREE, false);
And and = new And(EMPTY, neq, range);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -659,8 +669,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndGt3() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, THREE);
NotEquals neq = notEqualsOf(fa, TWO);
GreaterThan gt = greaterThanOf(fa, THREE);
And and = new And(EMPTY, neq, gt);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -672,8 +682,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndGte2() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, TWO);
NotEquals neq = notEqualsOf(fa, TWO);
GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, TWO);
And and = new And(EMPTY, neq, gte);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -687,8 +697,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndGte1() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, ONE);
NotEquals neq = notEqualsOf(fa, TWO);
GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, ONE);
And and = new And(EMPTY, neq, gte);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -700,8 +710,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndLte3() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, THREE);
NotEquals neq = notEqualsOf(fa, TWO);
LessThanOrEqual lte = lessThanOrEqualOf(fa, THREE);
And and = new And(EMPTY, neq, lte);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -713,8 +723,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndLte2() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, TWO);
NotEquals neq = notEqualsOf(fa, TWO);
LessThanOrEqual lte = lessThanOrEqualOf(fa, TWO);
And and = new And(EMPTY, neq, lte);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -728,8 +738,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsConjunction_Neq2AndLte1() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, ONE);
NotEquals neq = notEqualsOf(fa, TWO);
LessThanOrEqual lte = lessThanOrEqualOf(fa, ONE);
And and = new And(EMPTY, neq, lte);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
@ -742,8 +752,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionNotComparable() {
FieldAttribute fa = getFieldAttribute();
GreaterThan gt1 = new GreaterThan(EMPTY, fa, ONE);
GreaterThan gt2 = new GreaterThan(EMPTY, fa, FALSE);
GreaterThan gt1 = greaterThanOf(fa, ONE);
GreaterThan gt2 = greaterThanOf(fa, FALSE);
Or or = new Or(EMPTY, gt1, gt2);
@ -757,9 +767,9 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionLowerBound() {
FieldAttribute fa = getFieldAttribute();
GreaterThan gt1 = new GreaterThan(EMPTY, fa, ONE);
GreaterThan gt2 = new GreaterThan(EMPTY, fa, TWO);
GreaterThan gt3 = new GreaterThan(EMPTY, fa, THREE);
GreaterThan gt1 = greaterThanOf(fa, ONE);
GreaterThan gt2 = greaterThanOf(fa, TWO);
GreaterThan gt3 = greaterThanOf(fa, THREE);
Or or = new Or(EMPTY, gt1, new Or(EMPTY, gt2, gt3));
@ -775,9 +785,9 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionIncludeLowerBounds() {
FieldAttribute fa = getFieldAttribute();
GreaterThan gt1 = new GreaterThan(EMPTY, fa, ONE);
GreaterThan gt2 = new GreaterThan(EMPTY, fa, TWO);
GreaterThanOrEqual gte3 = new GreaterThanOrEqual(EMPTY, fa, THREE);
GreaterThan gt1 = greaterThanOf(fa, ONE);
GreaterThan gt2 = greaterThanOf(fa, TWO);
GreaterThanOrEqual gte3 = greaterThanOrEqualOf(fa, THREE);
Or or = new Or(EMPTY, new Or(EMPTY, gt1, gt2), gte3);
@ -793,9 +803,9 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionUpperBound() {
FieldAttribute fa = getFieldAttribute();
LessThan lt1 = new LessThan(EMPTY, fa, ONE);
LessThan lt2 = new LessThan(EMPTY, fa, TWO);
LessThan lt3 = new LessThan(EMPTY, fa, THREE);
LessThan lt1 = lessThanOf(fa, ONE);
LessThan lt2 = lessThanOf(fa, TWO);
LessThan lt3 = lessThanOf(fa, THREE);
Or or = new Or(EMPTY, new Or(EMPTY, lt1, lt2), lt3);
@ -811,9 +821,9 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionIncludeUpperBounds() {
FieldAttribute fa = getFieldAttribute();
LessThan lt1 = new LessThan(EMPTY, fa, ONE);
LessThan lt2 = new LessThan(EMPTY, fa, TWO);
LessThanOrEqual lte2 = new LessThanOrEqual(EMPTY, fa, TWO);
LessThan lt1 = lessThanOf(fa, ONE);
LessThan lt2 = lessThanOf(fa, TWO);
LessThanOrEqual lte2 = lessThanOrEqualOf(fa, TWO);
Or or = new Or(EMPTY, lt2, new Or(EMPTY, lte2, lt1));
@ -829,11 +839,11 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionOfLowerAndUpperBounds() {
FieldAttribute fa = getFieldAttribute();
LessThan lt1 = new LessThan(EMPTY, fa, ONE);
LessThan lt2 = new LessThan(EMPTY, fa, TWO);
LessThan lt1 = lessThanOf(fa, ONE);
LessThan lt2 = lessThanOf(fa, TWO);
GreaterThan gt3 = new GreaterThan(EMPTY, fa, THREE);
GreaterThan gt4 = new GreaterThan(EMPTY, fa, FOUR);
GreaterThan gt3 = greaterThanOf(fa, THREE);
GreaterThan gt4 = greaterThanOf(fa, FOUR);
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() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, FALSE, false);
Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = rangeOf(fa, ONE, false, FALSE, false);
Or or = new Or(EMPTY, r1, r2);
@ -870,8 +880,8 @@ public class OptimizerRulesTests extends ESTestCase {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, FOUR, false);
Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = rangeOf(fa, ONE, false, FOUR, false);
Or or = new Or(EMPTY, r1, r2);
@ -890,8 +900,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionOfNonOverlappingBoundaries() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, TWO, false);
Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = rangeOf(fa, ONE, false, TWO, false);
Or or = new Or(EMPTY, r1, r2);
@ -904,8 +914,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsDisjunctionOfUpperEqualsOverlappingBoundaries() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, true);
Range r1 = rangeOf(fa, TWO, false, THREE, false);
Range r2 = rangeOf(fa, TWO, false, THREE, true);
Or or = new Or(EMPTY, r1, r2);
@ -918,8 +928,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsOverlappingUpperBoundary() {
FieldAttribute fa = getFieldAttribute();
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r1 = new Range(EMPTY, fa, ONE, false, THREE, false);
Range r2 = rangeOf(fa, TWO, false, THREE, false);
Range r1 = rangeOf(fa, ONE, false, THREE, false);
Or or = new Or(EMPTY, r1, r2);
@ -932,8 +942,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testCombineBinaryComparisonsWithDifferentUpperLimitInclusion() {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, ONE, false, THREE, false);
Range r2 = new Range(EMPTY, fa, TWO, false, THREE, true);
Range r1 = rangeOf(fa, ONE, false, THREE, false);
Range r2 = rangeOf(fa, TWO, false, THREE, true);
Or or = new Or(EMPTY, r1, r2);
@ -948,9 +958,9 @@ public class OptimizerRulesTests extends ESTestCase {
FieldAttribute fb = getFieldAttribute("b");
FieldAttribute fc = getFieldAttribute("c");
Expression a1 = new Equals(EMPTY, fa, ONE);
Expression a2 = new Equals(EMPTY, fa, TWO);
And common = new And(EMPTY, new Equals(EMPTY, fb, THREE), new Equals(EMPTY, fc, FOUR));
Expression a1 = equalsOf(fa, ONE);
Expression a2 = equalsOf(fa, TWO);
And common = new And(EMPTY, equalsOf(fb, THREE), equalsOf(fc, FOUR));
And left = new And(EMPTY, a1, common);
And right = new And(EMPTY, a2, common);
Or or = new Or(EMPTY, left, right);
@ -963,8 +973,8 @@ public class OptimizerRulesTests extends ESTestCase {
public void testRangesOverlappingNoLowerBoundary() {
FieldAttribute fa = getFieldAttribute();
Range r2 = new Range(EMPTY, fa, L(0), false, TWO, false);
Range r1 = new Range(EMPTY, fa, L(0), false, ONE, true);
Range r2 = rangeOf(fa, L(0), false, TWO, false);
Range r1 = rangeOf(fa, L(0), false, ONE, true);
Or or = new Or(EMPTY, r1, r2);
@ -979,8 +989,8 @@ public class OptimizerRulesTests extends ESTestCase {
// 1 <= a < 10 AND a == 1 -> a == 1
public void testEliminateRangeByEqualsInInterval() {
FieldAttribute fa = getFieldAttribute();
Equals eq1 = new Equals(EMPTY, fa, ONE);
Range r = new Range(EMPTY, fa, ONE, true, L(10), false);
Equals eq1 = equalsOf(fa, ONE);
Range r = rangeOf(fa, ONE, true, L(10), false);
PropagateEquals rule = new PropagateEquals();
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
public void testEliminateRangeByNullEqualsInInterval() {
FieldAttribute fa = getFieldAttribute();
NullEquals eq1 = new NullEquals(EMPTY, fa, ONE);
Range r = new Range(EMPTY, fa, ONE, true, L(10), false);
NullEquals eq1 = nullEqualsOf(fa, ONE);
Range r = rangeOf(fa, ONE, true, L(10), false);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, r));
@ -1006,8 +1016,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a == 1 AND a == 2 -> FALSE
public void testDualEqualsConjunction() {
FieldAttribute fa = getFieldAttribute();
Equals eq1 = new Equals(EMPTY, fa, ONE);
Equals eq2 = new Equals(EMPTY, fa, TWO);
Equals eq1 = equalsOf(fa, ONE);
Equals eq2 = equalsOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, eq2));
@ -1017,8 +1027,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a <=> 1 AND a <=> 2 -> FALSE
public void testDualNullEqualsConjunction() {
FieldAttribute fa = getFieldAttribute();
NullEquals eq1 = new NullEquals(EMPTY, fa, ONE);
NullEquals eq2 = new NullEquals(EMPTY, fa, TWO);
NullEquals eq1 = nullEqualsOf(fa, ONE);
NullEquals eq2 = nullEqualsOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
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
public void testEliminateRangeByEqualsOutsideInterval() {
FieldAttribute fa = getFieldAttribute();
Equals eq1 = new Equals(EMPTY, fa, L(10));
Range r = new Range(EMPTY, fa, ONE, false, L(10), false);
Equals eq1 = equalsOf(fa, L(10));
Range r = rangeOf(fa, ONE, false, L(10), false);
PropagateEquals rule = new PropagateEquals();
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
public void testEliminateRangeByNullEqualsOutsideInterval() {
FieldAttribute fa = getFieldAttribute();
NullEquals eq1 = new NullEquals(EMPTY, fa, L(10));
Range r = new Range(EMPTY, fa, ONE, false, L(10), false);
NullEquals eq1 = nullEqualsOf(fa, L(10));
Range r = rangeOf(fa, ONE, false, L(10), false);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, r));
@ -1050,8 +1060,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a != 3 AND a = 3 -> FALSE
public void testPropagateEquals_VarNeq3AndVarEq3() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, THREE);
Equals eq = new Equals(EMPTY, fa, THREE);
NotEquals neq = notEqualsOf(fa, THREE);
Equals eq = equalsOf(fa, THREE);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarNeq4AndVarEq3() {
FieldAttribute fa = getFieldAttribute();
NotEquals neq = new NotEquals(EMPTY, fa, FOUR);
Equals eq = new Equals(EMPTY, fa, THREE);
NotEquals neq = notEqualsOf(fa, FOUR);
Equals eq = equalsOf(fa, THREE);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, neq, eq));
@ -1073,8 +1083,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a < 2 -> FALSE
public void testPropagateEquals_VarEq2AndVarLt2() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
LessThan lt = new LessThan(EMPTY, fa, TWO);
Equals eq = equalsOf(fa, TWO);
LessThan lt = lessThanOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2AndVarLte2() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
LessThanOrEqual lt = new LessThanOrEqual(EMPTY, fa, TWO);
Equals eq = equalsOf(fa, TWO);
LessThanOrEqual lt = lessThanOrEqualOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, lt));
@ -1095,8 +1105,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a <= 1 -> FALSE
public void testPropagateEquals_VarEq2AndVarLte1() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
LessThanOrEqual lt = new LessThanOrEqual(EMPTY, fa, ONE);
Equals eq = equalsOf(fa, TWO);
LessThanOrEqual lt = lessThanOrEqualOf(fa, ONE);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, lt));
@ -1106,8 +1116,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a > 2 -> FALSE
public void testPropagateEquals_VarEq2AndVarGt2() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, TWO);
Equals eq = equalsOf(fa, TWO);
GreaterThan gt = greaterThanOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2AndVarGte2() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
GreaterThanOrEqual gte = new GreaterThanOrEqual(EMPTY, fa, TWO);
Equals eq = equalsOf(fa, TWO);
GreaterThanOrEqual gte = greaterThanOrEqualOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq, gte));
@ -1128,8 +1138,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 AND a > 3 -> FALSE
public void testPropagateEquals_VarEq2AndVarLt3() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, THREE);
Equals eq = equalsOf(fa, TWO);
GreaterThan gt = greaterThanOf(fa, THREE);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2AndVarLt3AndVarGt1AndVarNeq4() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
LessThan lt = new LessThan(EMPTY, fa, THREE);
GreaterThan gt = new GreaterThan(EMPTY, fa, ONE);
NotEquals neq = new NotEquals(EMPTY, fa, FOUR);
Equals eq = equalsOf(fa, TWO);
LessThan lt = lessThanOf(fa, THREE);
GreaterThan gt = greaterThanOf(fa, ONE);
NotEquals neq = notEqualsOf(fa, FOUR);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2AndVarRangeGt1Lt3AndVarGt0AndVarNeq4() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false);
GreaterThan gt = new GreaterThan(EMPTY, fa, L(0));
NotEquals neq = new NotEquals(EMPTY, fa, FOUR);
Equals eq = equalsOf(fa, TWO);
Range range = rangeOf(fa, ONE, false, THREE, false);
GreaterThan gt = greaterThanOf(fa, L(0));
NotEquals neq = notEqualsOf(fa, FOUR);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2OrVarGt1() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, ONE);
Equals eq = equalsOf(fa, TWO);
GreaterThan gt = greaterThanOf(fa, ONE);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2OrVarGte2() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
GreaterThan gt = new GreaterThan(EMPTY, fa, TWO);
Equals eq = equalsOf(fa, TWO);
GreaterThan gt = greaterThanOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2OrVarLt3() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
LessThan lt = new LessThan(EMPTY, fa, THREE);
Equals eq = equalsOf(fa, TWO);
LessThan lt = lessThanOf(fa, THREE);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq3OrVarLt3() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, THREE);
LessThan lt = new LessThan(EMPTY, fa, THREE);
Equals eq = equalsOf(fa, THREE);
LessThan lt = lessThanOf(fa, THREE);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2OrVarRangeGt1Lt3() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, ONE, false, THREE, false);
Equals eq = equalsOf(fa, TWO);
Range range = rangeOf(fa, ONE, false, THREE, false);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2OrVarRangeGt2Lt3() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, TWO, false, THREE, false);
Equals eq = equalsOf(fa, TWO);
Range range = rangeOf(fa, TWO, false, THREE, false);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq3OrVarRangeGt2Lt3() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, THREE);
Range range = new Range(EMPTY, fa, TWO, false, THREE, false);
Equals eq = equalsOf(fa, THREE);
Range range = rangeOf(fa, TWO, false, THREE, false);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, range));
@ -1258,8 +1268,8 @@ public class OptimizerRulesTests extends ESTestCase {
// a = 2 OR a != 2 -> TRUE
public void testPropagateEquals_VarEq2OrVarNeq2() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
Equals eq = equalsOf(fa, TWO);
NotEquals neq = notEqualsOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
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
public void testPropagateEquals_VarEq2OrVarNeq5() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
NotEquals neq = new NotEquals(EMPTY, fa, FIVE);
Equals eq = equalsOf(fa, TWO);
NotEquals neq = notEqualsOf(fa, FIVE);
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new Or(EMPTY, eq, neq));
assertEquals(NotEquals.class, exp.getClass());
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
public void testPropagateEquals_VarEq2OrVarRangeGt3Lt4OrVarGt2OrVarNe2() {
FieldAttribute fa = getFieldAttribute();
Equals eq = new Equals(EMPTY, fa, TWO);
Range range = new Range(EMPTY, fa, THREE, false, FOUR, false);
GreaterThan gt = new GreaterThan(EMPTY, fa, TWO);
NotEquals neq = new NotEquals(EMPTY, fa, TWO);
Equals eq = equalsOf(fa, TWO);
Range range = rangeOf(fa, THREE, false, FOUR, false);
GreaterThan gt = greaterThanOf(fa, TWO);
NotEquals neq = notEqualsOf(fa, TWO);
PropagateEquals rule = new PropagateEquals();
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.proto.SqlTypedParamValue;
import java.time.ZoneId;
import java.util.Map;
class AstBuilder extends CommandBuilder {
/**
* Create AST Builder
* @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) {
super(params);
AstBuilder(Map<Token, SqlTypedParamValue> params, ZoneId zoneId) {
super(params, zoneId);
}
@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.proto.SqlTypedParamValue;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
@ -44,8 +45,8 @@ import java.util.Map;
abstract class CommandBuilder extends LogicalPlanBuilder {
protected CommandBuilder(Map<Token, SqlTypedParamValue> params) {
super(params);
protected CommandBuilder(Map<Token, SqlTypedParamValue> params, ZoneId zoneId) {
super(params, zoneId);
}
@Override

View File

@ -119,6 +119,7 @@ import org.elasticsearch.xpack.sql.type.SqlDataTypes;
import java.time.Duration;
import java.time.Period;
import java.time.ZoneId;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAmount;
import java.util.ArrayList;
@ -139,9 +140,11 @@ import static org.elasticsearch.xpack.sql.util.DateUtils.dateTimeOfEscapedLitera
abstract class ExpressionBuilder extends IdentifierBuilder {
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.zoneId = zoneId;
}
protected Expression expression(ParseTree ctx) {
@ -191,19 +194,19 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
switch (op.getSymbol().getType()) {
case SqlBaseParser.EQ:
return new Equals(source, left, right);
return new Equals(source, left, right, zoneId);
case SqlBaseParser.NULLEQ:
return new NullEquals(source, left, right);
return new NullEquals(source, left, right, zoneId);
case SqlBaseParser.NEQ:
return new NotEquals(source, left, right);
return new NotEquals(source, left, right, zoneId);
case SqlBaseParser.LT:
return new LessThan(source, left, right);
return new LessThan(source, left, right, zoneId);
case SqlBaseParser.LTE:
return new LessThanOrEqual(source, left, right);
return new LessThanOrEqual(source, left, right, zoneId);
case SqlBaseParser.GT:
return new GreaterThan(source, left, right);
return new GreaterThan(source, left, right, zoneId);
case SqlBaseParser.GTE:
return new GreaterThanOrEqual(source, left, right);
return new GreaterThanOrEqual(source, left, right, zoneId);
default:
throw new ParsingException(source, "Unknown operator {}", source.text());
}
@ -224,7 +227,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
Expression e = null;
switch (pCtx.kind.getType()) {
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;
case SqlBaseParser.IN:
if (pCtx.query() != null) {
@ -473,7 +476,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
for (SqlBaseParser.WhenClauseContext when : ctx.whenClause()) {
if (ctx.operand != null) {
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 {
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.session.SingletonExecutable;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@ -63,8 +64,8 @@ import static java.util.Collections.emptyList;
abstract class LogicalPlanBuilder extends ExpressionBuilder {
protected LogicalPlanBuilder(Map<Token, SqlTypedParamValue> params) {
super(params);
protected LogicalPlanBuilder(Map<Token, SqlTypedParamValue> params, ZoneId zoneId) {
super(params, zoneId);
}
@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.sql.proto.SqlTypedParamValue;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
@ -39,6 +40,7 @@ import java.util.function.BiFunction;
import java.util.function.Function;
import static java.lang.String.format;
import static org.elasticsearch.xpack.sql.util.DateUtils.UTC;
public class SqlParser {
@ -50,7 +52,14 @@ public class SqlParser {
* Used only in tests
*/
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
* @return logical plan
*/
public LogicalPlan createStatement(String sql, List<SqlTypedParamValue> params) {
public LogicalPlan createStatement(String sql, List<SqlTypedParamValue> params, ZoneId zoneId) {
if (log.isDebugEnabled()) {
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);
}
return invokeParser(expression, params, SqlBaseParser::singleExpression, AstBuilder::expression);
return invokeParser(expression, params, UTC, SqlBaseParser::singleExpression, AstBuilder::expression);
}
private <T> T invokeParser(String sql,
List<SqlTypedParamValue> params, Function<SqlBaseParser,
ParserRuleContext> parseFunction,
List<SqlTypedParamValue> params,
ZoneId zoneId,
Function<SqlBaseParser, ParserRuleContext> parseFunction,
BiFunction<AstBuilder, ParserRuleContext, T> visitor) {
try {
SqlBaseLexer lexer = new SqlBaseLexer(new CaseInsensitiveStream(sql));
@ -126,7 +136,7 @@ public class SqlParser {
log.info("Parse tree {} " + tree.toStringTree());
}
return visitor.apply(new AstBuilder(paramTokens), tree);
return visitor.apply(new AstBuilder(paramTokens, zoneId), tree);
} catch (StackOverflowError e) {
throw new ParsingException("SQL statement is too large, " +
"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) {
return new SqlParser().createStatement(sql, params);
return new SqlParser().createStatement(sql, params, configuration.zoneId());
}
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.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.randomStringLiteral;
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);
for (int i = 0; i < noConditionals; i++) {
expressions.add(new IfConditional(
randomSource(), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral()), randomIntLiteral()));
randomSource(), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral(), randomZone()),
randomIntLiteral()));
}
// default else
@ -86,14 +88,14 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
// ELSE 'default'
// END
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());
// CASE WHEN 1 = 1 THEN 'foo'
// ELSE NULL
// END
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));
assertEquals(KEYWORD, c.dataType());
@ -101,7 +103,7 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
// ELSE NULL
// END
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));
assertEquals(NULL, c.dataType());
@ -110,8 +112,8 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
// ELSE NULL
// END
c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), Literal.NULL),
new IfConditional(EMPTY, new Equals(EMPTY, literal(2), literal(2)), literal("foo")),
new IfConditional(EMPTY, equalsOf(literal(1), literal(1)), Literal.NULL),
new IfConditional(EMPTY, equalsOf(literal(2), literal(2)), literal("foo")),
Literal.NULL));
assertEquals(KEYWORD, c.dataType());
}
@ -133,7 +135,7 @@ public class CaseTests extends AbstractNodeTestCase<Case, Expression> {
for (int i = 0; i < c.conditions().size(); i++) {
if (i == rndIdx) {
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)));
} else {
expressions.add(c.conditions().get(i));

View File

@ -5,6 +5,7 @@
*/
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.function.scalar.FunctionTestUtils;
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 static Iif randomIif() {
return new Iif(randomSource(), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral()),
return new Iif(randomSource(), new Equals(randomSource(), randomStringLiteral(), randomStringLiteral(), randomZone()),
randomIntLiteral(), randomIntLiteral());
}
@ -86,7 +87,8 @@ public class IifTests extends AbstractNodeTestCase<Iif, Expression> {
Equals eq = (Equals) iif.conditions().get(0).condition();
expressions.add(new Equals(randomSource(),
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.elseResult(), FunctionTestUtils::randomIntLiteral));
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.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.expression.predicate.regex.RLike;
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.emptyMap;
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.NULL;
import static org.elasticsearch.xpack.ql.expression.Literal.TRUE;
@ -212,7 +217,7 @@ public class OptimizerTests extends ESTestCase {
// b
Alias b = new Alias(EMPTY, "b", L(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
p = new Project(EMPTY, p, Arrays.asList(a, b));
// ORDER BY
@ -368,7 +373,7 @@ public class OptimizerTests extends ESTestCase {
// arithmetic
assertNullLiteral(rule.rule(new Add(EMPTY, getFieldAttribute(), NULL)));
// comparison
assertNullLiteral(rule.rule(new GreaterThan(EMPTY, getFieldAttribute(), NULL)));
assertNullLiteral(rule.rule(greaterThanOf(getFieldAttribute(), NULL)));
// regex
assertNullLiteral(rule.rule(new RLike(EMPTY, NULL, new RLikePattern("123"))));
}
@ -581,10 +586,10 @@ public class OptimizerTests extends ESTestCase {
// END
Case c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, getFieldAttribute(), ONE), literal("foo1")),
new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), literal("bar1")),
new IfConditional(EMPTY, new Equals(EMPTY, TWO, ONE), literal("bar2")),
new IfConditional(EMPTY, new GreaterThan(EMPTY, getFieldAttribute(), ONE), literal("foo2")), literal("default")));
new IfConditional(EMPTY, equalsOf(getFieldAttribute(), ONE), literal("foo1")),
new IfConditional(EMPTY, equalsOf(ONE, TWO), literal("bar1")),
new IfConditional(EMPTY, equalsOf(TWO, ONE), literal("bar2")),
new IfConditional(EMPTY, greaterThanOf(getFieldAttribute(), ONE), literal("foo2")), literal("default")));
assertFalse(c.foldable());
Expression e = new SimplifyCase().rule(c);
assertEquals(Case.class, e.getClass());
@ -607,8 +612,8 @@ public class OptimizerTests extends ESTestCase {
// 'foo2'
Case c = new Case(EMPTY, Arrays.asList(
new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo1")),
new IfConditional(EMPTY, new Equals(EMPTY, ONE, ONE), literal("foo2")), literal("default")));
new IfConditional(EMPTY, equalsOf(ONE, TWO), literal("foo1")),
new IfConditional(EMPTY, equalsOf(ONE, ONE), literal("foo2")), literal("default")));
assertFalse(c.foldable());
SimplifyCase rule = new SimplifyCase();
@ -632,7 +637,7 @@ public class OptimizerTests extends ESTestCase {
// myField (non-foldable)
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")));
assertFalse(c.foldable());
@ -647,7 +652,7 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyIif_ConditionTrue_FoldableResult() {
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());
Expression e = rule.rule(iif);
@ -661,7 +666,7 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyIif_ConditionTrue_NonFoldableResult() {
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());
Expression e = rule.rule(iif);
@ -676,7 +681,7 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyIif_ConditionFalse_FoldableResult() {
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());
Expression e = rule.rule(iif);
@ -690,7 +695,7 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyIif_ConditionFalse_NonFoldableResult() {
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());
Expression e = rule.rule(iif);
@ -711,15 +716,15 @@ public class OptimizerTests extends ESTestCase {
}
public void testBinaryComparisonSimplification() {
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new Equals(EMPTY, FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new NullEquals(EMPTY, FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new NullEquals(EMPTY, NULL, NULL)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(new NotEquals(EMPTY, FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new GreaterThanOrEqual(EMPTY, FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(new LessThanOrEqual(EMPTY, FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(equalsOf(FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(nullEqualsOf(FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(nullEqualsOf(NULL, NULL)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(notEqualsOf(FIVE, FIVE)));
assertEquals(TRUE, new BinaryComparisonSimplification().rule(greaterThanOrEqualOf(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(new LessThan(EMPTY, FIVE, FIVE)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(greaterThanOf(FIVE, FIVE)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(lessThanOf(FIVE, FIVE)));
}
public void testNullEqualsWithNullLiteralBecomesIsNull() {
@ -728,12 +733,12 @@ public class OptimizerTests extends ESTestCase {
FieldAttribute fa = getFieldAttribute();
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());
IsNull isNull = (IsNull) e;
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());
isNull = (IsNull) e;
assertEquals(source, isNull.source());
@ -764,10 +769,10 @@ public class OptimizerTests extends ESTestCase {
public void testCombineUnbalancedComparisonsMixedWithEqualsIntoRange() {
FieldAttribute fa = getFieldAttribute();
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));
LessThan lt = new LessThan(EMPTY, fa, FIVE);
Equals eq = equalsOf(fa, L(10));
LessThan lt = lessThanOf(fa, FIVE);
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);
Project p = new Project(EMPTY, FROM(), Arrays.asList(aAlias, bAlias));
Filter f = new Filter(EMPTY, p,
new And(EMPTY, new GreaterThan(EMPTY, aAlias.toAttribute(), L(1)), new GreaterThan(EMPTY, bAlias.toAttribute(), L(2))));
Filter f = new Filter(EMPTY, p, new And(EMPTY, greaterThanOf(aAlias.toAttribute(), L(1)),
greaterThanOf(bAlias.toAttribute(), L(2))));
ReplaceReferenceAttributeWithSource rule = new ReplaceReferenceAttributeWithSource();
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.singletonList;
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.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
@ -521,7 +522,7 @@ public class SysColumnsTests extends ESTestCase {
EsIndex test = new EsIndex("test", mapping);
Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test),
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);
when(resolver.clusterName()).thenReturn(CLUSTER_NAME);

View File

@ -335,7 +335,7 @@ public class SysTablesTests extends ESTestCase {
EsIndex test = new EsIndex("test", mapping);
Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test),
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);
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.junit.BeforeClass;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collection;
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.TIME_FORMAT;
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.Matchers.endsWith;
import static org.hamcrest.Matchers.instanceOf;
@ -114,20 +116,32 @@ public class QueryTranslatorTests extends ESTestCase {
}
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) {
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() {
LogicalPlan p = plan("SELECT some.string FROM test WHERE some.string = 'value'");
assertTrue(p instanceof Project);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof TermQuery);
TermQuery tq = (TermQuery) query;
@ -148,6 +162,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertEquals("c", a.aggregates().get(0).name());
assertEquals("COUNT", ((Count) ((Alias) a.aggregates().get(0)).child()).functionName());
}
public void testLiteralWithGroupBy(){
LogicalPlan p = plan("SELECT 1 as t, 2 FROM test GROUP BY int");
assertTrue(p instanceof Aggregate);
@ -169,7 +184,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof TermQuery);
TermQuery tq = (TermQuery) query;
@ -183,7 +198,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof TermQuery);
TermQuery tq = (TermQuery) query;
@ -192,12 +207,13 @@ public class QueryTranslatorTests extends ESTestCase {
}
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);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query;
@ -207,15 +223,17 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(rq.includeLower());
assertTrue(rq.includeUpper());
assertEquals(DATE_FORMAT, rq.format());
assertEquals(zoneId, rq.zoneId());
}
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);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query;
@ -225,6 +243,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(rq.includeLower());
assertTrue(rq.includeUpper());
assertEquals(TIME_FORMAT, rq.format());
assertEquals(zoneId, rq.zoneId());
}
public void testComparisonAgainstColumns() {
@ -233,50 +252,56 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child();
assertTrue(p instanceof Filter);
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());
}
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);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query;
assertEquals("date", rq.field());
assertEquals(1951, rq.lower());
assertEquals(zoneId, rq.zoneId());
}
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);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query;
assertEquals("date", rq.field());
assertEquals("1969-05-13", rq.lower());
assertEquals(zoneId, rq.zoneId());
}
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);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof RangeQuery);
RangeQuery rq = (RangeQuery) query;
assertEquals("date", rq.field());
assertEquals("1969-05-13T12:34:56.000Z", rq.lower());
assertEquals(zoneId, rq.zoneId());
}
public void testDateRangeWithCurrentTimestamp() {
@ -315,13 +340,14 @@ public class QueryTranslatorTests extends ESTestCase {
}
private void testDateRangeWithCurrentFunctions(String function, String pattern, ZonedDateTime now) {
String operator = randomFrom(new String[] {">", ">=", "<", "<=", "=", "!="});
LogicalPlan p = plan("SELECT some.string FROM test WHERE date" + operator + function);
ZoneId zoneId = randomZone();
String operator = randomFrom(">", ">=", "<", "<=", "=", "!=");
LogicalPlan p = plan("SELECT some.string FROM test WHERE date" + operator + function, zoneId);
assertTrue(p instanceof Project);
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
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.includeLower());
assertEquals(pattern, rq.format());
assertEquals(zoneId, rq.zoneId());
}
private void testDateRangeWithCurrentFunctions_AndRangeOptimization(String function, String pattern, ZonedDateTime lowerValue,
ZonedDateTime upperValue) {
String lowerOperator = randomFrom(new String[] {"<", "<="});
String upperOperator = randomFrom(new String[] {">", ">="});
String lowerOperator = randomFrom("<", "<=");
String upperOperator = randomFrom(">", ">=");
// 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)";
@ -380,6 +407,50 @@ public class QueryTranslatorTests extends ESTestCase {
assertEquals(lowerOperator.equals("<="), rq.includeUpper());
assertEquals(upperOperator.equals(">="), rq.includeLower());
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() {
@ -388,7 +459,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
@ -405,7 +476,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
@ -422,7 +493,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
@ -438,7 +509,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
@ -454,7 +525,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
@ -470,7 +541,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
@ -487,7 +558,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation qt = QueryTranslator.toQuery(condition, false);
QueryTranslation qt = translate(condition);
assertEquals(WildcardQuery.class, qt.query.getClass());
WildcardQuery qsq = ((WildcardQuery) qt.query);
assertEquals("some.string.typical", qsq.field());
@ -499,7 +570,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child();
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation qt = QueryTranslator.toQuery(condition, false);
QueryTranslation qt = translate(condition);
assertEquals(RegexQuery.class, qt.query.getClass());
RegexQuery qsq = ((RegexQuery) qt.query);
assertEquals("some.string.typical", qsq.field());
@ -511,7 +582,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child();
assertTrue(p instanceof Filter);
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());
}
@ -521,7 +592,7 @@ public class QueryTranslatorTests extends ESTestCase {
p = ((Project) p).child();
assertTrue(p instanceof Filter);
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());
}
@ -532,7 +603,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation qt = QueryTranslator.toQuery(condition, false);
QueryTranslation qt = translate(condition);
assertEquals(BoolQuery.class, qt.query.getClass());
BoolQuery bq = ((BoolQuery) qt.query);
assertTrue(bq.isAnd());
@ -565,7 +636,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
QueryTranslation qt = QueryTranslator.toQuery(condition, false);
QueryTranslation qt = translate(condition);
assertEquals(BoolQuery.class, qt.query.getClass());
BoolQuery bq = ((BoolQuery) qt.query);
assertTrue(bq.isAnd());
@ -606,7 +677,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.not(" +
@ -622,7 +693,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof NotQuery);
NotQuery tq = (NotQuery) translation.query;
assertTrue(tq.child() instanceof ExistsQuery);
@ -637,7 +708,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.isNull(" +
@ -652,7 +723,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof ExistsQuery);
ExistsQuery eq = (ExistsQuery) translation.query;
assertEquals("{\"exists\":{\"field\":\"keyword\",\"boost\":1.0}}",
@ -665,7 +736,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.isNotNull(" +
@ -679,7 +750,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals(
@ -693,7 +764,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals(
@ -702,6 +773,8 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(aggFilter.scriptTemplate().params().toString(), startsWith("[{a=max(int)"));
}
public void testTranslateCoalesceExpression_WhereGroupByAndHaving_Painless() {
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");
@ -735,7 +808,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof TermsQuery);
TermsQuery tq = (TermsQuery) query;
@ -749,7 +822,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof TermsQuery);
TermsQuery tq = (TermsQuery) query;
@ -763,7 +836,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
Query query = translation.query;
assertTrue(query instanceof TermsQuery);
TermsQuery tq = (TermsQuery) query;
@ -777,7 +850,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p.children().get(0) instanceof Filter);
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
@ -792,7 +865,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))",
@ -806,7 +879,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))",
@ -821,7 +894,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.in(params.a0, params.v0))",
@ -839,7 +912,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(InternalSqlScriptUtils." +
@ -901,7 +974,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertTrue(p instanceof Filter);
Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(InternalSqlScriptUtils.abs" +
@ -917,7 +990,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(" +
@ -934,7 +1007,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
assertEquals("InternalQlScriptUtils.nullSafeFilter(" +
@ -952,7 +1025,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof ScriptQuery);
ScriptQuery sc = (ScriptQuery) translation.query;
@ -971,7 +1044,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertTrue(translation.query instanceof GeoDistanceQuery);
GeoDistanceQuery gq = (GeoDistanceQuery) translation.query;
@ -988,7 +1061,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertThat(translation.query, instanceOf(ScriptQuery.class));
ScriptQuery sc = (ScriptQuery) translation.query;
@ -1004,7 +1077,7 @@ public class QueryTranslatorTests extends ESTestCase {
assertThat(p.children().get(0), instanceOf(Filter.class));
Expression condition = ((Filter) p.children().get(0)).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, false);
QueryTranslation translation = translate(condition);
assertNull(translation.aggFilter);
assertThat(translation.query, instanceOf(ScriptQuery.class));
ScriptQuery sc = (ScriptQuery) translation.query;
@ -1139,7 +1212,7 @@ public class QueryTranslatorTests extends ESTestCase {
endsWith("\"date_histogram\":{\"field\":\"date\",\"missing_bucket\":true,\"value_type\":\"date\",\"order\":\"asc\","
+ "\"calendar_interval\":\"1y\",\"time_zone\":\"Z\"}}}]}}}"));
}
public void testGroupByOneMonthHistogramQueryTranslator() {
PhysicalPlan p = optimizeAndPlan("SELECT HISTOGRAM(date, INTERVAL 1 MONTH) AS h FROM test GROUP BY h");
assertEquals(EsQueryExec.class, p.getClass());
@ -1151,7 +1224,7 @@ public class QueryTranslatorTests extends ESTestCase {
endsWith("\"date_histogram\":{\"field\":\"date\",\"missing_bucket\":true,\"value_type\":\"date\",\"order\":\"asc\","
+ "\"calendar_interval\":\"1M\",\"time_zone\":\"Z\"}}}]}}}"));
}
public void testGroupByMoreMonthsHistogramQueryTranslator() {
PhysicalPlan p = optimizeAndPlan("SELECT HISTOGRAM(date, INTERVAL 5 MONTH) AS h FROM test GROUP BY h");
assertEquals(EsQueryExec.class, p.getClass());
@ -1175,7 +1248,7 @@ public class QueryTranslatorTests extends ESTestCase {
endsWith("\"date_histogram\":{\"field\":\"date\",\"missing_bucket\":true,\"value_type\":\"date\",\"order\":\"asc\","
+ "\"calendar_interval\":\"1d\",\"time_zone\":\"Z\"}}}]}}}"));
}
public void testGroupByMoreDaysHistogramQueryTranslator() {
PhysicalPlan p = optimizeAndPlan("SELECT HISTOGRAM(date, INTERVAL '1 5' DAY TO HOUR) AS h FROM test GROUP BY h");
assertEquals(EsQueryExec.class, p.getClass());
@ -1805,7 +1878,6 @@ public class QueryTranslatorTests extends ESTestCase {
EsQueryExec eqe = (EsQueryExec) p;
assertTrue("Should be tracking hits", eqe.queryContainer().shouldTrackHits());
assertEquals(1, eqe.output().size());
String query = eqe.queryContainer().toString().replaceAll("\\s+", "");
assertThat(eqe.queryContainer().toString().replaceAll("\\s+", ""), containsString("\"size\":0"));
}
@ -1879,7 +1951,7 @@ public class QueryTranslatorTests extends ESTestCase {
Expression condition = ((Filter) p).condition();
assertFalse(condition.foldable());
QueryTranslation translation = QueryTranslator.toQuery(condition, true);
QueryTranslation translation = translateWithAggs(condition);
assertNull(translation.query);
AggFilter aggFilter = translation.aggFilter;
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.type.EsField;
import java.time.ZoneId;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Arrays;
import java.util.BitSet;
@ -44,15 +45,17 @@ public class QueryContainerTests extends ESTestCase {
}
public void testRewriteToContainsNestedFieldWhenContainsNestedField() {
ZoneId zoneId = randomZone();
Query original = new BoolQuery(source, true,
new NestedQuery(source, path, singletonMap(name, new SimpleImmutableEntry<>(hasDocValues, format)),
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()));
}
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,
new NestedQuery(source, path, emptyMap(), new MatchAll(source)),
buddy);
@ -64,7 +67,8 @@ public class QueryContainerTests extends ESTestCase {
}
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,
original,
new NestedQuery(source, path, singletonMap(name, new SimpleImmutableEntry<>(hasDocValues, format)),