mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-23 13:26:02 +00:00
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:
parent
8a23da429a
commit
cc21468559
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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)),
|
||||
|
Loading…
x
Reference in New Issue
Block a user