SQL: Refactor args verification of In & conditionals (#40916)

Move verification of arguments for Conditional functions and IN
from `Verifier` to the `resolveType()` method of the functions.

(cherry picked from commit 241644aac57baee1eb128b993ee410c7d08172a5)
This commit is contained in:
Marios Trivyzas 2019-04-08 16:43:36 +02:00
parent 8eef92fafd
commit 2206491277
11 changed files with 212 additions and 253 deletions

View File

@ -26,8 +26,6 @@ import org.elasticsearch.xpack.sql.expression.function.aggregate.TopHits;
import org.elasticsearch.xpack.sql.expression.function.grouping.GroupingFunction;
import org.elasticsearch.xpack.sql.expression.function.grouping.GroupingFunctionAttribute;
import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunction;
import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalFunction;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
import org.elasticsearch.xpack.sql.plan.logical.Aggregate;
import org.elasticsearch.xpack.sql.plan.logical.Distinct;
import org.elasticsearch.xpack.sql.plan.logical.Filter;
@ -228,9 +226,6 @@ public final class Verifier {
Set<Failure> localFailures = new LinkedHashSet<>();
validateInExpression(p, localFailures);
validateConditional(p, localFailures);
checkGroupingFunctionInGroupBy(p, localFailures);
checkFilterOnAggs(p, localFailures);
checkFilterOnGrouping(p, localFailures);
@ -724,52 +719,4 @@ public final class Verifier {
fail(nested.get(0), "HAVING isn't (yet) compatible with nested fields " + new AttributeSet(nested).names()));
}
}
private static void validateInExpression(LogicalPlan p, Set<Failure> localFailures) {
p.forEachExpressions(e ->
e.forEachUp((In in) -> {
DataType dt = in.value().dataType();
for (Expression value : in.list()) {
if (areTypesCompatible(dt, value.dataType()) == false) {
localFailures.add(fail(value, "expected data type [{}], value provided is of type [{}]",
dt.typeName, value.dataType().typeName));
return;
}
}
},
In.class));
}
private static void validateConditional(LogicalPlan p, Set<Failure> localFailures) {
p.forEachExpressions(e ->
e.forEachUp((ConditionalFunction cf) -> {
DataType dt = DataType.NULL;
for (Expression child : cf.children()) {
if (dt == DataType.NULL) {
if (Expressions.isNull(child) == false) {
dt = child.dataType();
}
} else {
if (areTypesCompatible(dt, child.dataType()) == false) {
localFailures.add(fail(child, "expected data type [{}], value provided is of type [{}]",
dt.typeName, child.dataType().typeName));
return;
}
}
}
},
ConditionalFunction.class));
}
private static boolean areTypesCompatible(DataType left, DataType right) {
if (left == right) {
return true;
} else {
return
(left == DataType.NULL || right == DataType.NULL) ||
(left.isString() && right.isString()) ||
(left.isNumeric() && right.isNumeric());
}
}
}

View File

@ -262,7 +262,7 @@ public class FunctionRegistry {
for (String alias : f.aliases()) {
Object old = batchMap.put(alias, f);
if (old != null || defs.containsKey(alias)) {
throw new IllegalArgumentException("alias [" + alias + "] is used by "
throw new SqlIllegalArgumentException("alias [" + alias + "] is used by "
+ "[" + (old != null ? old : defs.get(alias).name()) + "] and [" + f.name() + "]");
}
aliases.put(alias, f.name());
@ -321,10 +321,10 @@ public class FunctionRegistry {
java.util.function.Function<Source, T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (false == children.isEmpty()) {
throw new IllegalArgumentException("expects no arguments");
throw new SqlIllegalArgumentException("expects no arguments");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.apply(source);
};
@ -341,10 +341,10 @@ public class FunctionRegistry {
ConfigurationAwareFunctionBuilder<T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (false == children.isEmpty()) {
throw new IllegalArgumentException("expects no arguments");
throw new SqlIllegalArgumentException("expects no arguments");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.build(source, cfg);
};
@ -365,10 +365,10 @@ public class FunctionRegistry {
UnaryConfigurationAwareFunctionBuilder<T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (children.size() > 1) {
throw new IllegalArgumentException("expects exactly one argument");
throw new SqlIllegalArgumentException("expects exactly one argument");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
Expression ex = children.size() == 1 ? children.get(0) : null;
return ctorRef.build(source, ex, cfg);
@ -390,10 +390,10 @@ public class FunctionRegistry {
BiFunction<Source, Expression, T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (children.size() != 1) {
throw new IllegalArgumentException("expects exactly one argument");
throw new SqlIllegalArgumentException("expects exactly one argument");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.apply(source, children.get(0));
};
@ -409,7 +409,7 @@ public class FunctionRegistry {
MultiFunctionBuilder<T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.build(source, children);
};
@ -429,7 +429,7 @@ public class FunctionRegistry {
DistinctAwareUnaryFunctionBuilder<T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (children.size() != 1) {
throw new IllegalArgumentException("expects exactly one argument");
throw new SqlIllegalArgumentException("expects exactly one argument");
}
return ctorRef.build(source, children.get(0), distinct);
};
@ -449,10 +449,10 @@ public class FunctionRegistry {
DatetimeUnaryFunctionBuilder<T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (children.size() != 1) {
throw new IllegalArgumentException("expects exactly one argument");
throw new SqlIllegalArgumentException("expects exactly one argument");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.build(source, children.get(0), cfg.zoneId());
};
@ -471,10 +471,10 @@ public class FunctionRegistry {
static <T extends Function> FunctionDefinition def(Class<T> function, DatetimeBinaryFunctionBuilder<T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (children.size() != 2) {
throw new IllegalArgumentException("expects exactly two arguments");
throw new SqlIllegalArgumentException("expects exactly two arguments");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.build(source, children.get(0), children.get(1), cfg.zoneId());
};
@ -496,13 +496,13 @@ public class FunctionRegistry {
boolean isBinaryOptionalParamFunction = function.isAssignableFrom(Round.class) || function.isAssignableFrom(Truncate.class)
|| TopHits.class.isAssignableFrom(function);
if (isBinaryOptionalParamFunction && (children.size() > 2 || children.size() < 1)) {
throw new IllegalArgumentException("expects one or two arguments");
throw new SqlIllegalArgumentException("expects one or two arguments");
} else if (!isBinaryOptionalParamFunction && children.size() != 2) {
throw new IllegalArgumentException("expects exactly two arguments");
throw new SqlIllegalArgumentException("expects exactly two arguments");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.build(source, children.get(0), children.size() == 2 ? children.get(1) : null);
};
@ -527,7 +527,7 @@ public class FunctionRegistry {
FunctionDefinition.Builder realBuilder = (uf, distinct, cfg) -> {
try {
return builder.build(uf.source(), uf.children(), distinct, cfg);
} catch (IllegalArgumentException e) {
} catch (SqlIllegalArgumentException e) {
throw new ParsingException(uf.source(), "error building [" + primaryName + "]: " + e.getMessage(), e);
}
};
@ -544,12 +544,12 @@ public class FunctionRegistry {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
boolean isLocateFunction = function.isAssignableFrom(Locate.class);
if (isLocateFunction && (children.size() > 3 || children.size() < 2)) {
throw new IllegalArgumentException("expects two or three arguments");
throw new SqlIllegalArgumentException("expects two or three arguments");
} else if (!isLocateFunction && children.size() != 3) {
throw new IllegalArgumentException("expects exactly three arguments");
throw new SqlIllegalArgumentException("expects exactly three arguments");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.build(source, children.get(0), children.get(1), children.size() == 3 ? children.get(2) : null);
};
@ -565,10 +565,10 @@ public class FunctionRegistry {
FourParametersFunctionBuilder<T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (children.size() != 4) {
throw new IllegalArgumentException("expects exactly four arguments");
throw new SqlIllegalArgumentException("expects exactly four arguments");
}
if (distinct) {
throw new IllegalArgumentException("does not support DISTINCT yet it was specified");
throw new SqlIllegalArgumentException("does not support DISTINCT yet it was specified");
}
return ctorRef.build(source, children.get(0), children.get(1), children.get(2), children.get(3));
};

View File

@ -13,7 +13,6 @@ import org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder;
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataTypeConversion;
import java.util.ArrayList;
import java.util.List;
@ -33,14 +32,6 @@ public abstract class ArbitraryConditionalFunction extends ConditionalFunction {
this.operation = operation;
}
@Override
protected TypeResolution resolveType() {
for (Expression e : children()) {
dataType = DataTypeConversion.commonType(dataType, e.dataType());
}
return TypeResolution.TYPE_RESOLVED;
}
@Override
protected Pipe makePipe() {
return new ConditionalPipe(source(), this, Expressions.pipe(children()), operation);

View File

@ -12,9 +12,14 @@ import org.elasticsearch.xpack.sql.expression.Nullability;
import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunction;
import org.elasticsearch.xpack.sql.tree.Source;
import org.elasticsearch.xpack.sql.type.DataType;
import org.elasticsearch.xpack.sql.type.DataTypeConversion;
import java.util.List;
import static org.elasticsearch.common.logging.LoggerMessageFormat.format;
import static org.elasticsearch.xpack.sql.type.DataTypes.areTypesCompatible;
import static org.elasticsearch.xpack.sql.util.StringUtils.ordinal;
/**
* Base class for conditional predicates.
*/
@ -36,6 +41,31 @@ public abstract class ConditionalFunction extends ScalarFunction {
return Expressions.foldable(children());
}
@Override
protected TypeResolution resolveType() {
DataType dt = DataType.NULL;
for (int i = 0; i < children().size(); i++) {
Expression child = children().get(i);
if (dt == DataType.NULL) {
if (Expressions.isNull(child) == false) {
dt = child.dataType();
}
} else {
if (areTypesCompatible(dt, child.dataType()) == false) {
return new TypeResolution(format(null, "{} argument of [{}] must be [{}], found value [{}] type [{}]",
ordinal(i + 1),
sourceText(),
dt.typeName,
Expressions.name(child),
child.dataType().typeName));
}
}
dataType = DataTypeConversion.commonType(dataType, child.dataType());
}
return TypeResolution.TYPE_RESOLVED;
}
@Override
public Nullability nullable() {
return Nullability.UNKNOWN;

View File

@ -39,12 +39,6 @@ public class NullIf extends ConditionalFunction {
return new NullIf(source(), newChildren.get(0), newChildren.get(1));
}
@Override
protected TypeResolution resolveType() {
dataType = children().get(0).dataType();
return TypeResolution.TYPE_RESOLVED;
}
@Override
public Object fold() {
return NullIfProcessor.apply(children().get(0).fold(), children().get(1).fold());

View File

@ -26,6 +26,8 @@ import java.util.stream.Collectors;
import static org.elasticsearch.common.logging.LoggerMessageFormat.format;
import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder;
import static org.elasticsearch.xpack.sql.type.DataTypes.areTypesCompatible;
import static org.elasticsearch.xpack.sql.util.StringUtils.ordinal;
public class In extends ScalarFunction {
@ -109,7 +111,7 @@ public class In extends ScalarFunction {
@Override
protected TypeResolution resolveType() {
TypeResolution resolution = TypeResolutions.isExact(value, functionName(), Expressions.ParamOrdinal.DEFAULT);
if (resolution != TypeResolution.TYPE_RESOLVED) {
if (resolution.unresolved()) {
return resolution;
}
@ -120,6 +122,20 @@ public class In extends ScalarFunction {
name()));
}
}
DataType dt = value.dataType();
for (int i = 0; i < list.size(); i++) {
Expression listValue = list.get(i);
if (areTypesCompatible(dt, listValue.dataType()) == false) {
return new TypeResolution(format(null, "{} argument of [{}] must be [{}], found value [{}] type [{}]",
ordinal(i + 1),
sourceText(),
dt.typeName,
Expressions.name(listValue),
listValue.dataType().typeName));
}
}
return super.resolveType();
}

View File

@ -230,4 +230,15 @@ public final class DataTypes {
}
return t.displaySize;
}
public static boolean areTypesCompatible(DataType left, DataType right) {
if (left == right) {
return true;
} else {
return
(left == DataType.NULL || right == DataType.NULL) ||
(left.isString() && right.isString()) ||
(left.isNumeric() && right.isNumeric());
}
}
}

View File

@ -23,12 +23,16 @@ import java.util.Locale;
import static java.util.stream.Collectors.toList;
public abstract class StringUtils {
public final class StringUtils {
private StringUtils() {}
public static final String EMPTY = "";
public static final String NEW_LINE = "\n";
public static final String SQL_WILDCARD = "%";
private static final String[] INTEGER_ORDINALS = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
//CamelCase to camel_case
public static String camelCaseToUnderscore(String string) {
if (!Strings.hasText(string)) {
@ -86,10 +90,6 @@ public abstract class StringUtils {
return sb.toString();
}
public static String nullAsEmpty(String string) {
return string == null ? EMPTY : string;
}
// % -> .*
// _ -> .
// escape character - can be 0 (in which case every regex gets escaped) or
@ -297,4 +297,16 @@ public abstract class StringUtils {
throw new SqlIllegalArgumentException("Cannot parse number [{}]", string);
}
}
}
public static String ordinal(int i) {
switch (i % 100) {
case 11:
case 12:
case 13:
return i + "th";
default:
return i + INTEGER_ORDINALS[i % 10];
}
}
}

View File

@ -420,46 +420,16 @@ public class VerifierErrorMessagesTests extends ESTestCase {
error("SELECT int FROM test GROUP BY int HAVING 2 < ABS(int)"));
}
public void testInWithDifferentDataTypes_SelectClause() {
assertEquals("1:17: expected data type [integer], value provided is of type [keyword]",
public void testInWithDifferentDataTypes() {
assertEquals("1:8: 2nd argument of [1 IN (2, '3', 4)] must be [integer], found value ['3'] type [keyword]",
error("SELECT 1 IN (2, '3', 4)"));
}
public void testInNestedWithDifferentDataTypes_SelectClause() {
assertEquals("1:27: expected data type [integer], value provided is of type [keyword]",
error("SELECT 1 = 1 OR 1 IN (2, '3', 4)"));
}
public void testInWithDifferentDataTypesFromLeftValue_SelectClause() {
assertEquals("1:14: expected data type [integer], value provided is of type [keyword]",
public void testInWithDifferentDataTypesFromLeftValue() {
assertEquals("1:8: 1st argument of [1 IN ('foo', 'bar')] must be [integer], found value ['foo'] type [keyword]",
error("SELECT 1 IN ('foo', 'bar')"));
}
public void testInNestedWithDifferentDataTypesFromLeftValue_SelectClause() {
assertEquals("1:29: expected data type [keyword], value provided is of type [integer]",
error("SELECT 1 = 1 OR 'foo' IN (2, 3)"));
}
public void testInWithDifferentDataTypes_WhereClause() {
assertEquals("1:52: expected data type [keyword], value provided is of type [integer]",
error("SELECT * FROM test WHERE keyword IN ('foo', 'bar', 4)"));
}
public void testInNestedWithDifferentDataTypes_WhereClause() {
assertEquals("1:63: expected data type [keyword], value provided is of type [integer]",
error("SELECT * FROM test WHERE int = 1 OR keyword IN ('foo', 'bar', 2)"));
}
public void testInWithDifferentDataTypesFromLeftValue_WhereClause() {
assertEquals("1:38: expected data type [keyword], value provided is of type [integer]",
error("SELECT * FROM test WHERE keyword IN (1, 2)"));
}
public void testInNestedWithDifferentDataTypesFromLeftValue_WhereClause() {
assertEquals("1:49: expected data type [keyword], value provided is of type [integer]",
error("SELECT * FROM test WHERE int = 1 OR keyword IN (1, 2)"));
}
public void testInWithFieldInListOfValues() {
assertEquals("1:26: Comparisons against variables are not (currently) supported; offender [int] in [int IN (1, int)]",
error("SELECT * FROM test WHERE int IN (1, int)"));
@ -615,32 +585,17 @@ public class VerifierErrorMessagesTests extends ESTestCase {
incompatibleError("SELECT languages FROM \"*\" ORDER BY SIGN(ABS(emp_no))"));
}
public void testConditionalWithDifferentDataTypes_SelectClause() {
public void testConditionalWithDifferentDataTypes() {
@SuppressWarnings("unchecked")
String function = randomFrom(IfNull.class, NullIf.class).getSimpleName();
assertEquals("1:" + (22 + function.length()) +
": expected data type [integer], value provided is of type [keyword]",
error("SELECT 1 = 1 OR " + function + "(3, '4') > 1"));
assertEquals("1:17: 2nd argument of [" + function + "(3, '4')] must be [integer], found value ['4'] type [keyword]",
error("SELECT 1 = 1 OR " + function + "(3, '4') > 1"));
@SuppressWarnings("unchecked")
String arbirtraryArgsfunction = randomFrom(Coalesce.class, Greatest.class, Least.class).getSimpleName();
assertEquals("1:" + (34 + arbirtraryArgsfunction.length()) +
": expected data type [integer], value provided is of type [keyword]",
error("SELECT 1 = 1 OR " + arbirtraryArgsfunction + "(null, null, 3, '4') > 1"));
}
public void testConditionalWithDifferentDataTypes_WhereClause() {
@SuppressWarnings("unchecked")
String function = randomFrom(IfNull.class, NullIf.class).getSimpleName();
assertEquals("1:" + (34 + function.length()) +
": expected data type [keyword], value provided is of type [integer]",
error("SELECT * FROM test WHERE " + function + "('foo', 4) > 1"));
@SuppressWarnings("unchecked")
String arbirtraryArgsfunction = randomFrom(Coalesce.class, Greatest.class, Least.class).getSimpleName();
assertEquals("1:" + (46 + arbirtraryArgsfunction.length()) +
": expected data type [keyword], value provided is of type [integer]",
error("SELECT * FROM test WHERE " + arbirtraryArgsfunction + "(null, null, 'foo', 4) > 1"));
String arbirtraryArgsFunction = randomFrom(Coalesce.class, Greatest.class, Least.class).getSimpleName();
assertEquals("1:17: 3rd argument of [" + arbirtraryArgsFunction + "(null, 3, '4')] must be [integer], " +
"found value ['4'] type [keyword]",
error("SELECT 1 = 1 OR " + arbirtraryArgsFunction + "(null, 3, '4') > 1"));
}
public void testAggsInWhere() {

View File

@ -165,13 +165,13 @@ public class FunctionRegistryTests extends ESTestCase {
public void testAliasNameIsTheSameAsAFunctionName() {
FunctionRegistry r = new FunctionRegistry(def(DummyFunction.class, DummyFunction::new, "DUMMY_FUNCTION", "ALIAS"));
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () ->
SqlIllegalArgumentException iae = expectThrows(SqlIllegalArgumentException.class, () ->
r.addToMap(def(DummyFunction2.class, DummyFunction2::new, "DUMMY_FUNCTION2", "DUMMY_FUNCTION")));
assertEquals("alias [DUMMY_FUNCTION] is used by [DUMMY_FUNCTION] and [DUMMY_FUNCTION2]", iae.getMessage());
}
public void testDuplicateAliasInTwoDifferentFunctionsFromTheSameBatch() {
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () ->
SqlIllegalArgumentException iae = expectThrows(SqlIllegalArgumentException.class, () ->
new FunctionRegistry(def(DummyFunction.class, DummyFunction::new, "DUMMY_FUNCTION", "ALIAS"),
def(DummyFunction2.class, DummyFunction2::new, "DUMMY_FUNCTION2", "ALIAS")));
assertEquals("alias [ALIAS] is used by [DUMMY_FUNCTION(ALIAS)] and [DUMMY_FUNCTION2]", iae.getMessage());
@ -179,7 +179,7 @@ public class FunctionRegistryTests extends ESTestCase {
public void testDuplicateAliasInTwoDifferentFunctionsFromTwoDifferentBatches() {
FunctionRegistry r = new FunctionRegistry(def(DummyFunction.class, DummyFunction::new, "DUMMY_FUNCTION", "ALIAS"));
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () ->
SqlIllegalArgumentException iae = expectThrows(SqlIllegalArgumentException.class, () ->
r.addToMap(def(DummyFunction2.class, DummyFunction2::new, "DUMMY_FUNCTION2", "ALIAS")));
assertEquals("alias [ALIAS] is used by [DUMMY_FUNCTION] and [DUMMY_FUNCTION2]", iae.getMessage());
}

View File

@ -108,7 +108,10 @@ 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.sql.expression.Literal.FALSE;
import static org.elasticsearch.xpack.sql.expression.Literal.NULL;
import static org.elasticsearch.xpack.sql.expression.Literal.TRUE;
import static org.elasticsearch.xpack.sql.expression.Literal.of;
import static org.elasticsearch.xpack.sql.tree.Source.EMPTY;
import static org.elasticsearch.xpack.sql.util.DateUtils.UTC;
import static org.hamcrest.Matchers.contains;
@ -174,7 +177,7 @@ public class OptimizerTests extends ESTestCase {
}
private static Literal L(Object value) {
return Literal.of(EMPTY, value);
return of(EMPTY, value);
}
private static FieldAttribute getFieldAttribute() {
@ -190,8 +193,8 @@ public class OptimizerTests extends ESTestCase {
}
public void testDuplicateFunctions() {
AggregateFunction f1 = new Count(EMPTY, Literal.TRUE, false);
AggregateFunction f2 = new Count(EMPTY, Literal.TRUE, false);
AggregateFunction f1 = new Count(EMPTY, TRUE, false);
AggregateFunction f2 = new Count(EMPTY, TRUE, false);
assertTrue(f1.functionEquals(f2));
@ -284,34 +287,34 @@ public class OptimizerTests extends ESTestCase {
}
public void testConstantFoldingBinaryComparison() {
assertEquals(Literal.FALSE, new ConstantFolding().rule(new GreaterThan(EMPTY, TWO, THREE)).canonical());
assertEquals(Literal.FALSE, new ConstantFolding().rule(new GreaterThanOrEqual(EMPTY, TWO, THREE)).canonical());
assertEquals(Literal.FALSE, new ConstantFolding().rule(new Equals(EMPTY, TWO, THREE)).canonical());
assertEquals(Literal.FALSE, new ConstantFolding().rule(new NullEquals(EMPTY, TWO, THREE)).canonical());
assertEquals(Literal.FALSE, new ConstantFolding().rule(new NullEquals(EMPTY, TWO, NULL)).canonical());
assertEquals(Literal.TRUE, new ConstantFolding().rule(new NotEquals(EMPTY, TWO, THREE)).canonical());
assertEquals(Literal.TRUE, new ConstantFolding().rule(new LessThanOrEqual(EMPTY, TWO, THREE)).canonical());
assertEquals(Literal.TRUE, new ConstantFolding().rule(new LessThan(EMPTY, TWO, THREE)).canonical());
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());
}
public void testConstantFoldingBinaryLogic() {
assertEquals(Literal.FALSE,
new ConstantFolding().rule(new And(EMPTY, new GreaterThan(EMPTY, TWO, THREE), Literal.TRUE)).canonical());
assertEquals(Literal.TRUE,
new ConstantFolding().rule(new Or(EMPTY, new GreaterThanOrEqual(EMPTY, TWO, THREE), Literal.TRUE)).canonical());
assertEquals(FALSE,
new ConstantFolding().rule(new And(EMPTY, new GreaterThan(EMPTY, TWO, THREE), TRUE)).canonical());
assertEquals(TRUE,
new ConstantFolding().rule(new Or(EMPTY, new GreaterThanOrEqual(EMPTY, TWO, THREE), TRUE)).canonical());
}
public void testConstantFoldingBinaryLogic_WithNullHandling() {
assertEquals(NULL, new ConstantFolding().rule(new And(EMPTY, NULL, Literal.TRUE)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new And(EMPTY, Literal.TRUE, NULL)).canonical());
assertEquals(Literal.FALSE, new ConstantFolding().rule(new And(EMPTY, NULL, Literal.FALSE)).canonical());
assertEquals(Literal.FALSE, new ConstantFolding().rule(new And(EMPTY, Literal.FALSE, NULL)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new And(EMPTY, NULL, TRUE)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new And(EMPTY, TRUE, NULL)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new And(EMPTY, NULL, FALSE)).canonical());
assertEquals(FALSE, new ConstantFolding().rule(new And(EMPTY, FALSE, NULL)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new And(EMPTY, NULL, NULL)).canonical());
assertEquals(Literal.TRUE, new ConstantFolding().rule(new Or(EMPTY, NULL, Literal.TRUE)).canonical());
assertEquals(Literal.TRUE, new ConstantFolding().rule(new Or(EMPTY, Literal.TRUE, NULL)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new Or(EMPTY, NULL, Literal.FALSE)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new Or(EMPTY, Literal.FALSE, NULL)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(new Or(EMPTY, NULL, TRUE)).canonical());
assertEquals(TRUE, new ConstantFolding().rule(new Or(EMPTY, TRUE, NULL)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new Or(EMPTY, NULL, FALSE)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new Or(EMPTY, FALSE, NULL)).canonical());
assertEquals(NULL, new ConstantFolding().rule(new Or(EMPTY, NULL, NULL)).canonical());
}
@ -321,25 +324,25 @@ public class OptimizerTests extends ESTestCase {
}
public void testConstantIsNotNull() {
assertEquals(Literal.FALSE, new ConstantFolding().rule(new IsNotNull(EMPTY, L(null))));
assertEquals(Literal.TRUE, new ConstantFolding().rule(new IsNotNull(EMPTY, FIVE)));
assertEquals(FALSE, new ConstantFolding().rule(new IsNotNull(EMPTY, L(null))));
assertEquals(TRUE, new ConstantFolding().rule(new IsNotNull(EMPTY, FIVE)));
}
public void testConstantNot() {
assertEquals(Literal.FALSE, new ConstantFolding().rule(new Not(EMPTY, Literal.TRUE)));
assertEquals(Literal.TRUE, new ConstantFolding().rule(new Not(EMPTY, Literal.FALSE)));
assertEquals(FALSE, new ConstantFolding().rule(new Not(EMPTY, TRUE)));
assertEquals(TRUE, new ConstantFolding().rule(new Not(EMPTY, FALSE)));
}
public void testConstantFoldingLikes() {
assertEquals(Literal.TRUE,
new ConstantFolding().rule(new Like(EMPTY, Literal.of(EMPTY, "test_emp"), new LikePattern("test%", (char) 0)))
assertEquals(TRUE,
new ConstantFolding().rule(new Like(EMPTY, of(EMPTY, "test_emp"), new LikePattern("test%", (char) 0)))
.canonical());
assertEquals(Literal.TRUE,
new ConstantFolding().rule(new RLike(EMPTY, Literal.of(EMPTY, "test_emp"), "test.emp")).canonical());
assertEquals(TRUE,
new ConstantFolding().rule(new RLike(EMPTY, of(EMPTY, "test_emp"), "test.emp")).canonical());
}
public void testConstantFoldingDatetime() {
Expression cast = new Cast(EMPTY, Literal.of(EMPTY, "2018-01-19T10:23:27Z"), DataType.DATETIME);
Expression cast = new Cast(EMPTY, of(EMPTY, "2018-01-19T10:23:27Z"), DataType.DATETIME);
assertEquals(2018, foldFunction(new Year(EMPTY, cast, UTC)));
assertEquals(1, foldFunction(new MonthOfYear(EMPTY, cast, UTC)));
assertEquals(19, foldFunction(new DayOfMonth(EMPTY, cast, UTC)));
@ -407,44 +410,44 @@ public class OptimizerTests extends ESTestCase {
public void testNullFoldingIsNull() {
FoldNull foldNull = new FoldNull();
assertEquals(true, foldNull.rule(new IsNull(EMPTY, Literal.NULL)).fold());
assertEquals(false, foldNull.rule(new IsNull(EMPTY, Literal.TRUE)).fold());
assertEquals(true, foldNull.rule(new IsNull(EMPTY, NULL)).fold());
assertEquals(false, foldNull.rule(new IsNull(EMPTY, TRUE)).fold());
}
public void testNullFoldingIsNotNull() {
FoldNull foldNull = new FoldNull();
assertEquals(true, foldNull.rule(new IsNotNull(EMPTY, Literal.TRUE)).fold());
assertEquals(false, foldNull.rule(new IsNotNull(EMPTY, Literal.NULL)).fold());
assertEquals(true, foldNull.rule(new IsNotNull(EMPTY, TRUE)).fold());
assertEquals(false, foldNull.rule(new IsNotNull(EMPTY, NULL)).fold());
}
public void testGenericNullableExpression() {
FoldNull rule = new FoldNull();
// date-time
assertNullLiteral(rule.rule(new DayName(EMPTY, Literal.NULL, randomZone())));
assertNullLiteral(rule.rule(new DayName(EMPTY, NULL, randomZone())));
// math function
assertNullLiteral(rule.rule(new Cos(EMPTY, Literal.NULL)));
assertNullLiteral(rule.rule(new Cos(EMPTY, NULL)));
// string function
assertNullLiteral(rule.rule(new Ascii(EMPTY, Literal.NULL)));
assertNullLiteral(rule.rule(new Repeat(EMPTY, getFieldAttribute(), Literal.NULL)));
assertNullLiteral(rule.rule(new Ascii(EMPTY, NULL)));
assertNullLiteral(rule.rule(new Repeat(EMPTY, getFieldAttribute(), NULL)));
// arithmetic
assertNullLiteral(rule.rule(new Add(EMPTY, getFieldAttribute(), Literal.NULL)));
assertNullLiteral(rule.rule(new Add(EMPTY, getFieldAttribute(), NULL)));
// comparison
assertNullLiteral(rule.rule(new GreaterThan(EMPTY, getFieldAttribute(), Literal.NULL)));
assertNullLiteral(rule.rule(new GreaterThan(EMPTY, getFieldAttribute(), NULL)));
// regex
assertNullLiteral(rule.rule(new RLike(EMPTY, Literal.NULL, "123")));
assertNullLiteral(rule.rule(new RLike(EMPTY, NULL, "123")));
}
public void testNullFoldingDoesNotApplyOnLogicalExpressions() {
FoldNull rule = new FoldNull();
Or or = new Or(EMPTY, Literal.NULL, Literal.TRUE);
Or or = new Or(EMPTY, NULL, TRUE);
assertEquals(or, rule.rule(or));
or = new Or(EMPTY, Literal.NULL, Literal.NULL);
or = new Or(EMPTY, NULL, NULL);
assertEquals(or, rule.rule(or));
And and = new And(EMPTY, Literal.NULL, Literal.TRUE);
And and = new And(EMPTY, NULL, TRUE);
assertEquals(and, rule.rule(and));
and = new And(EMPTY, Literal.NULL, Literal.NULL);
and = new And(EMPTY, NULL, NULL);
assertEquals(and, rule.rule(and));
}
@ -455,11 +458,11 @@ public class OptimizerTests extends ESTestCase {
Class<ConditionalFunction> clazz =
(Class<ConditionalFunction>) randomFrom(IfNull.class, NullIf.class);
Constructor<ConditionalFunction> ctor = clazz.getConstructor(Source.class, Expression.class, Expression.class);
ConditionalFunction conditionalFunction = ctor.newInstance(EMPTY, Literal.NULL, ONE);
ConditionalFunction conditionalFunction = ctor.newInstance(EMPTY, NULL, ONE);
assertEquals(conditionalFunction, rule.rule(conditionalFunction));
conditionalFunction = ctor.newInstance(EMPTY, ONE, Literal.NULL);
conditionalFunction = ctor.newInstance(EMPTY, ONE, NULL);
assertEquals(conditionalFunction, rule.rule(conditionalFunction));
conditionalFunction = ctor.newInstance(EMPTY, Literal.NULL, Literal.NULL);
conditionalFunction = ctor.newInstance(EMPTY, NULL, NULL);
assertEquals(conditionalFunction, rule.rule(conditionalFunction));
}
@ -470,14 +473,14 @@ public class OptimizerTests extends ESTestCase {
Class<ArbitraryConditionalFunction> clazz =
(Class<ArbitraryConditionalFunction>) randomFrom(Coalesce.class, Greatest.class, Least.class);
Constructor<ArbitraryConditionalFunction> ctor = clazz.getConstructor(Source.class, List.class);
ArbitraryConditionalFunction conditionalFunction = ctor.newInstance(EMPTY, Arrays.asList(Literal.NULL, ONE, TWO));
ArbitraryConditionalFunction conditionalFunction = ctor.newInstance(EMPTY, Arrays.asList(NULL, ONE, TWO));
assertEquals(conditionalFunction, rule.rule(conditionalFunction));
conditionalFunction = ctor.newInstance(EMPTY, Arrays.asList(Literal.NULL, NULL, NULL));
conditionalFunction = ctor.newInstance(EMPTY, Arrays.asList(NULL, NULL, NULL));
assertEquals(conditionalFunction, rule.rule(conditionalFunction));
}
public void testSimplifyCoalesceNulls() {
Expression e = new SimplifyConditional().rule(new Coalesce(EMPTY, asList(Literal.NULL, Literal.NULL)));
Expression e = new SimplifyConditional().rule(new Coalesce(EMPTY, asList(NULL, NULL)));
assertEquals(Coalesce.class, e.getClass());
assertEquals(0, e.children().size());
}
@ -491,51 +494,51 @@ public class OptimizerTests extends ESTestCase {
public void testSimplifyCoalesceRandomNullsWithValue() {
Expression e = new SimplifyConditional().rule(new Coalesce(EMPTY,
CollectionUtils.combine(
CollectionUtils.combine(randomListOfNulls(), Literal.TRUE, Literal.FALSE, Literal.TRUE),
CollectionUtils.combine(randomListOfNulls(), TRUE, FALSE, TRUE),
randomListOfNulls())));
assertEquals(1, e.children().size());
assertEquals(Literal.TRUE, e.children().get(0));
assertEquals(TRUE, e.children().get(0));
}
private List<Expression> randomListOfNulls() {
return asList(randomArray(1, 10, Literal[]::new, () -> Literal.NULL));
return asList(randomArray(1, 10, Literal[]::new, () -> NULL));
}
public void testSimplifyCoalesceFirstLiteral() {
Expression e = new SimplifyConditional()
.rule(new Coalesce(EMPTY,
Arrays.asList(Literal.NULL, Literal.TRUE, Literal.FALSE, new Abs(EMPTY, getFieldAttribute()))));
Arrays.asList(NULL, TRUE, FALSE, new Abs(EMPTY, getFieldAttribute()))));
assertEquals(Coalesce.class, e.getClass());
assertEquals(1, e.children().size());
assertEquals(Literal.TRUE, e.children().get(0));
assertEquals(TRUE, e.children().get(0));
}
public void testSimplifyIfNullNulls() {
Expression e = new SimplifyConditional().rule(new IfNull(EMPTY, Literal.NULL, Literal.NULL));
Expression e = new SimplifyConditional().rule(new IfNull(EMPTY, NULL, NULL));
assertEquals(IfNull.class, e.getClass());
assertEquals(0, e.children().size());
}
public void testSimplifyIfNullWithNullAndValue() {
Expression e = new SimplifyConditional().rule(new IfNull(EMPTY, Literal.NULL, ONE));
Expression e = new SimplifyConditional().rule(new IfNull(EMPTY, NULL, ONE));
assertEquals(IfNull.class, e.getClass());
assertEquals(1, e.children().size());
assertEquals(ONE, e.children().get(0));
e = new SimplifyConditional().rule(new IfNull(EMPTY, ONE, Literal.NULL));
e = new SimplifyConditional().rule(new IfNull(EMPTY, ONE, NULL));
assertEquals(IfNull.class, e.getClass());
assertEquals(1, e.children().size());
assertEquals(ONE, e.children().get(0));
}
public void testFoldNullNotAppliedOnNullIf() {
Expression orig = new NullIf(EMPTY, ONE, Literal.NULL);
Expression orig = new NullIf(EMPTY, ONE, NULL);
Expression f = new FoldNull().rule(orig);
assertEquals(orig, f);
}
public void testSimplifyGreatestNulls() {
Expression e = new SimplifyConditional().rule(new Greatest(EMPTY, asList(Literal.NULL, Literal.NULL)));
Expression e = new SimplifyConditional().rule(new Greatest(EMPTY, asList(NULL, NULL)));
assertEquals(Greatest.class, e.getClass());
assertEquals(0, e.children().size());
}
@ -556,7 +559,7 @@ public class OptimizerTests extends ESTestCase {
}
public void testSimplifyLeastNulls() {
Expression e = new SimplifyConditional().rule(new Least(EMPTY, asList(Literal.NULL, Literal.NULL)));
Expression e = new SimplifyConditional().rule(new Least(EMPTY, asList(NULL, NULL)));
assertEquals(Least.class, e.getClass());
assertEquals(0, e.children().size());
}
@ -578,9 +581,9 @@ public class OptimizerTests extends ESTestCase {
public void testConcatFoldingIsNotNull() {
FoldNull foldNull = new FoldNull();
assertEquals(1, foldNull.rule(new Concat(EMPTY, Literal.NULL, ONE)).fold());
assertEquals(1, foldNull.rule(new Concat(EMPTY, ONE, Literal.NULL)).fold());
assertEquals(StringUtils.EMPTY, foldNull.rule(new Concat(EMPTY, Literal.NULL, Literal.NULL)).fold());
assertEquals(1, foldNull.rule(new Concat(EMPTY, NULL, ONE)).fold());
assertEquals(1, foldNull.rule(new Concat(EMPTY, ONE, NULL)).fold());
assertEquals(StringUtils.EMPTY, foldNull.rule(new Concat(EMPTY, NULL, NULL)).fold());
}
//
@ -593,15 +596,15 @@ public class OptimizerTests extends ESTestCase {
}
public void testBinaryComparisonSimplification() {
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new Equals(EMPTY, FIVE, FIVE)));
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new NullEquals(EMPTY, FIVE, FIVE)));
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new NullEquals(EMPTY, NULL, NULL)));
assertEquals(Literal.FALSE, new BinaryComparisonSimplification().rule(new NotEquals(EMPTY, FIVE, FIVE)));
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new GreaterThanOrEqual(EMPTY, FIVE, FIVE)));
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new LessThanOrEqual(EMPTY, FIVE, FIVE)));
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(Literal.FALSE, new BinaryComparisonSimplification().rule(new GreaterThan(EMPTY, FIVE, FIVE)));
assertEquals(Literal.FALSE, new BinaryComparisonSimplification().rule(new LessThan(EMPTY, FIVE, FIVE)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(new GreaterThan(EMPTY, FIVE, FIVE)));
assertEquals(FALSE, new BinaryComparisonSimplification().rule(new LessThan(EMPTY, FIVE, FIVE)));
}
public void testNullEqualsWithNullLiteralBecomesIsNull() {
@ -648,25 +651,25 @@ public class OptimizerTests extends ESTestCase {
public void testBoolSimplifyOr() {
BooleanSimplification simplification = new BooleanSimplification();
assertEquals(Literal.TRUE, simplification.rule(new Or(EMPTY, Literal.TRUE, Literal.TRUE)));
assertEquals(Literal.TRUE, simplification.rule(new Or(EMPTY, Literal.TRUE, DUMMY_EXPRESSION)));
assertEquals(Literal.TRUE, simplification.rule(new Or(EMPTY, DUMMY_EXPRESSION, Literal.TRUE)));
assertEquals(TRUE, simplification.rule(new Or(EMPTY, TRUE, TRUE)));
assertEquals(TRUE, simplification.rule(new Or(EMPTY, TRUE, DUMMY_EXPRESSION)));
assertEquals(TRUE, simplification.rule(new Or(EMPTY, DUMMY_EXPRESSION, TRUE)));
assertEquals(Literal.FALSE, simplification.rule(new Or(EMPTY, Literal.FALSE, Literal.FALSE)));
assertEquals(DUMMY_EXPRESSION, simplification.rule(new Or(EMPTY, Literal.FALSE, DUMMY_EXPRESSION)));
assertEquals(DUMMY_EXPRESSION, simplification.rule(new Or(EMPTY, DUMMY_EXPRESSION, Literal.FALSE)));
assertEquals(FALSE, simplification.rule(new Or(EMPTY, FALSE, FALSE)));
assertEquals(DUMMY_EXPRESSION, simplification.rule(new Or(EMPTY, FALSE, DUMMY_EXPRESSION)));
assertEquals(DUMMY_EXPRESSION, simplification.rule(new Or(EMPTY, DUMMY_EXPRESSION, FALSE)));
}
public void testBoolSimplifyAnd() {
BooleanSimplification simplification = new BooleanSimplification();
assertEquals(Literal.TRUE, simplification.rule(new And(EMPTY, Literal.TRUE, Literal.TRUE)));
assertEquals(DUMMY_EXPRESSION, simplification.rule(new And(EMPTY, Literal.TRUE, DUMMY_EXPRESSION)));
assertEquals(DUMMY_EXPRESSION, simplification.rule(new And(EMPTY, DUMMY_EXPRESSION, Literal.TRUE)));
assertEquals(TRUE, simplification.rule(new And(EMPTY, TRUE, TRUE)));
assertEquals(DUMMY_EXPRESSION, simplification.rule(new And(EMPTY, TRUE, DUMMY_EXPRESSION)));
assertEquals(DUMMY_EXPRESSION, simplification.rule(new And(EMPTY, DUMMY_EXPRESSION, TRUE)));
assertEquals(Literal.FALSE, simplification.rule(new And(EMPTY, Literal.FALSE, Literal.FALSE)));
assertEquals(Literal.FALSE, simplification.rule(new And(EMPTY, Literal.FALSE, DUMMY_EXPRESSION)));
assertEquals(Literal.FALSE, simplification.rule(new And(EMPTY, DUMMY_EXPRESSION, Literal.FALSE)));
assertEquals(FALSE, simplification.rule(new And(EMPTY, FALSE, FALSE)));
assertEquals(FALSE, simplification.rule(new And(EMPTY, FALSE, DUMMY_EXPRESSION)));
assertEquals(FALSE, simplification.rule(new And(EMPTY, DUMMY_EXPRESSION, FALSE)));
}
public void testBoolCommonFactorExtraction() {
@ -710,7 +713,7 @@ public class OptimizerTests extends ESTestCase {
public void testCombineBinaryComparisonsNotComparable() {
FieldAttribute fa = getFieldAttribute();
LessThanOrEqual lte = new LessThanOrEqual(EMPTY, fa, SIX);
LessThan lt = new LessThan(EMPTY, fa, Literal.FALSE);
LessThan lt = new LessThan(EMPTY, fa, FALSE);
CombineBinaryComparisons rule = new CombineBinaryComparisons();
And and = new And(EMPTY, lte, lt);
@ -790,7 +793,7 @@ public class OptimizerTests extends ESTestCase {
CombineBinaryComparisons rule = new CombineBinaryComparisons();
// TRUE AND a != 5 AND 4 < a <= 7
Expression exp = rule.rule(new And(EMPTY, gte, new And(EMPTY, Literal.TRUE, new And(EMPTY, gt, new And(EMPTY, ne, lte)))));
Expression exp = rule.rule(new And(EMPTY, gte, new And(EMPTY, TRUE, new And(EMPTY, gt, new And(EMPTY, ne, lte)))));
assertEquals(And.class, exp.getClass());
And and = ((And) exp);
assertEquals(Range.class, and.right().getClass());
@ -943,7 +946,7 @@ public class OptimizerTests extends ESTestCase {
FieldAttribute fa = getFieldAttribute();
GreaterThan gt1 = new GreaterThan(EMPTY, fa, ONE);
GreaterThan gt2 = new GreaterThan(EMPTY, fa, Literal.FALSE);
GreaterThan gt2 = new GreaterThan(EMPTY, fa, FALSE);
Or or = new Or(EMPTY, gt1, gt2);
@ -1056,7 +1059,7 @@ public class OptimizerTests extends ESTestCase {
FieldAttribute fa = getFieldAttribute();
Range r1 = new Range(EMPTY, fa, TWO, false, THREE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, Literal.FALSE, false);
Range r2 = new Range(EMPTY, fa, ONE, false, FALSE, false);
Or or = new Or(EMPTY, r1, r2);
@ -1194,7 +1197,7 @@ public class OptimizerTests extends ESTestCase {
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, eq2));
assertEquals(Literal.FALSE, rule.rule(exp));
assertEquals(FALSE, rule.rule(exp));
}
// a <=> 1 AND a <=> 2 -> FALSE
@ -1205,7 +1208,7 @@ public class OptimizerTests extends ESTestCase {
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, eq2));
assertEquals(Literal.FALSE, rule.rule(exp));
assertEquals(FALSE, rule.rule(exp));
}
// 1 < a < 10 AND a == 10 -> FALSE
@ -1216,7 +1219,7 @@ public class OptimizerTests extends ESTestCase {
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, r));
assertEquals(Literal.FALSE, rule.rule(exp));
assertEquals(FALSE, rule.rule(exp));
}
// 1 < a < 10 AND a <=> 10 -> FALSE
@ -1227,7 +1230,7 @@ public class OptimizerTests extends ESTestCase {
PropagateEquals rule = new PropagateEquals();
Expression exp = rule.rule(new And(EMPTY, eq1, r));
assertEquals(Literal.FALSE, rule.rule(exp));
assertEquals(FALSE, rule.rule(exp));
}
public void testTranslateMinToFirst() {