SQL: Introduce NotEquals node to simplify expressions (#35234)

Add NotEquals node in parser to simplify expressions so that <value1> != <value2> is
no longer translated internally to NOT(<value1> = <value2>)

Closes: #35210
Fixes: #35233
This commit is contained in:
Marios Trivyzas 2018-11-05 22:23:07 +01:00 committed by GitHub
parent f72ef9b5fd
commit 9ac7af6b3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 169 additions and 44 deletions

View File

@ -129,6 +129,10 @@ aggCountAndHaving
SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING COUNT(*) > 10 ORDER BY gender;
aggCountAndHavingEquality
SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING COUNT(*) = 10 ORDER BY gender;
aggCountAndHavingNotEquals
SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING COUNT(*) != 10 ORDER BY gender;
aggCountAndHavingNegateEquality
SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING NOT COUNT(*) = 10 ORDER BY gender;
aggCountOnColumnAndHaving
SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING COUNT(gender) > 10 ORDER BY gender;
aggCountOnColumnAndWildcardAndHaving

View File

@ -232,21 +232,13 @@ SELECT POSITION('x',LCASE("first_name")) pos, "first_name" FROM "test_emp" WHERE
pos:i | first_name:s
---------------+---------------
4 |Guoxiang
null |null
null |null
null |null
null |null
null |null
null |null
null |null
null |null
null |null
null |null
1 |Xinglin
1 |Xinglin
;
selectPositionWithLcaseAndConditionWithGroupByAndOrderBy
SELECT POSITION('m',LCASE("first_name")), COUNT(*) pos FROM "test_emp" WHERE POSITION('m',LCASE("first_name")) != 0 GROUP BY POSITION('m',LCASE("first_name")) ORDER BY POSITION('m',LCASE("first_name")) DESC;
SELECT POSITION('m',LCASE("first_name")), COUNT(*) pos FROM "test_emp"
WHERE POSITION('m',LCASE("first_name")) != 0
GROUP BY POSITION('m',LCASE("first_name")) ORDER BY POSITION('m',LCASE("first_name")) DESC;
POSITION(m,LCASE(first_name)):i| pos:l
-------------------------------+---------------
@ -256,7 +248,6 @@ POSITION(m,LCASE(first_name)):i| pos:l
3 |6
2 |1
1 |9
null |10
;
selectInsertWithPositionAndCondition

View File

@ -1,4 +1,48 @@
//
// SELECT with = and !=
//
equalsSelectClause
SELECT CAST(4 = 4 AS STRING), CAST(NOT 4 = 4 AS STRING), CAST(3 = 4 AS STRING), CAST(NOT 3 = 4 AS STRING), CAST(1 = null AS STRING), CAST(NOT null = 1 AS STRING);
CAST(4 == 4 AS VARCHAR):s | CAST(NOT(4 == 4) AS VARCHAR):s | CAST(3 == 4 AS VARCHAR):s | CAST(NOT(3 == 4) AS VARCHAR):s | CAST(1 == null AS VARCHAR):s | CAST(NOT(null == 1) AS VARCHAR):s
----------------------------+---------------------------------+----------------------------+---------------------------------+-------------------------------+-----------------------------------
true |false |false |true |null |null
;
notEqualsSelectClause
SELECT CAST(4 != 4 AS STRING), CAST(NOT 4 != 4 AS STRING), CAST(3 != 4 AS STRING), CAST(NOT 3 != 4 AS STRING), CAST(1 != null AS STRING), CAST(NOT 1 != null AS STRING);
CAST(4 != 4 AS VARCHAR):s | CAST(NOT(4 != 4) AS VARCHAR):s | CAST(3 != 4 AS VARCHAR):s | CAST(NOT(3 != 4) AS VARCHAR):s | CAST(1 != null AS VARCHAR):s | CAST(NOT(1 != null) AS VARCHAR):s
----------------------------+---------------------------------+----------------------------+---------------------------------+-------------------------------+-----------------------------------
false |true |true |false |null |null
;
equalSelectClauseWithTableColumns
SELECT CAST(languages = 2 AS STRING), CAST(NOT languages = 2 AS STRING), CAST(languages = null AS STRING), CAST(NOT languages = null AS STRING)
FROM "test_emp" WHERE emp_no IN(10018, 10019, 10020) ORDER BY emp_no;
CAST((languages) == 2 AS VARCHAR):s | CAST(NOT((languages) == 2) AS VARCHAR):s | CAST((languages) == null AS VARCHAR):s | CAST(NOT((languages) == null) AS VARCHAR):s
--------------------------------------+-------------------------------------------+-----------------------------------------+---------------------------------------------
true |false |null |null
false |true |null |null
null |null |null |null
;
notEqualsAndNotEqualsSelectClauseWithTableColumns
SELECT CAST(languages != 2 AS STRING), CAST(NOT languages != 2 AS STRING), CAST(languages != null AS STRING), CAST(NOT languages != null AS STRING)
FROM "test_emp" WHERE emp_no IN(10018, 10019, 10020) ORDER BY emp_no;
CAST((languages) != 2 AS VARCHAR):s | CAST(NOT((languages) != 2) AS VARCHAR):s | CAST((languages) != null AS VARCHAR):s | CAST(NOT((languages) != null) AS VARCHAR):s
--------------------------------------+-------------------------------------------+-----------------------------------------+---------------------------------------------
false |true |null |null
true |false |null |null
null |null |null |null
;
//
// SELECT with IN
//
inWithLiterals
SELECT 1 IN (1, 2, 3), 1 IN (2, 3);

View File

@ -40,6 +40,7 @@ import java.util.Map;
* Acts as a registry of the various static methods used <b>internally</b> by the scalar functions
* (to simplify the whitelist definition).
*/
@SuppressWarnings("unused")
public final class InternalSqlScriptUtils {
private InternalSqlScriptUtils() {}
@ -52,7 +53,7 @@ public final class InternalSqlScriptUtils {
public static <T> Object docValue(Map<String, ScriptDocValues<T>> doc, String fieldName) {
if (doc.containsKey(fieldName)) {
ScriptDocValues<T> docValues = doc.get(fieldName);
if (docValues.size() > 0) {
if (!docValues.isEmpty()) {
return docValues.get(0);
}
}
@ -83,6 +84,10 @@ public final class InternalSqlScriptUtils {
return BinaryComparisonOperation.EQ.apply(left, right);
}
public static Boolean neq(Object left, Object right) {
return BinaryComparisonOperation.NEQ.apply(left, right);
}
public static Boolean lt(Object left, Object right) {
return BinaryComparisonOperation.LT.apply(left, right);
}

View File

@ -19,6 +19,7 @@ public class BinaryComparisonProcessor extends FunctionalBinaryProcessor<Object,
public enum BinaryComparisonOperation implements PredicateBiFunction<Object, Object, Boolean> {
EQ(Comparisons::eq, "=="),
NEQ(Comparisons::neq, "!="),
GT(Comparisons::gt, ">"),
GTE(Comparisons::gte, ">="),
LT(Comparisons::lt, "<"),
@ -62,4 +63,4 @@ public class BinaryComparisonProcessor extends FunctionalBinaryProcessor<Object,
public String getWriteableName() {
return NAME;
}
}
}

View File

@ -19,6 +19,11 @@ public final class Comparisons {
return i == null ? null : i.intValue() == 0;
}
static Boolean neq(Object l, Object r) {
Integer i = compare(l, r);
return i == null ? null : i.intValue() != 0;
}
static Boolean lt(Object l, Object r) {
Integer i = compare(l, r);
return i == null ? null : i.intValue() < 0;
@ -50,6 +55,9 @@ public final class Comparisons {
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
static Integer compare(Object l, Object r) {
if (l == null || r == null) {
return null;
}
// typical number comparison
if (l instanceof Number && r instanceof Number) {
return compare((Number) l, (Number) r);

View File

@ -6,11 +6,12 @@
package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison;
import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation;
import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
public class Equals extends BinaryComparison {
public class Equals extends BinaryComparison implements BinaryOperator.Negateable {
public Equals(Location location, Expression left, Expression right) {
super(location, left, right, BinaryComparisonOperation.EQ);
@ -30,4 +31,9 @@ public class Equals extends BinaryComparison {
public Equals swapLeftAndRight() {
return new Equals(location(), right(), left());
}
@Override
public BinaryOperator<?, ?, ?, ?> negate() {
return new NotEquals(location(), left(), right());
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison;
import org.elasticsearch.xpack.sql.expression.Expression;
import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation;
import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.tree.NodeInfo;
public class NotEquals extends BinaryComparison implements BinaryOperator.Negateable {
public NotEquals(Location location, Expression left, Expression right) {
super(location, left, right, BinaryComparisonOperation.NEQ);
}
@Override
protected NodeInfo<NotEquals> info() {
return NodeInfo.create(this, NotEquals::new, left(), right());
}
@Override
protected NotEquals replaceChildren(Expression newLeft, Expression newRight) {
return new NotEquals(location(), newLeft, newRight);
}
@Override
public NotEquals swapLeftAndRight() {
return new NotEquals(location(), right(), left());
}
@Override
public BinaryOperator<?, ?, ?, ?> negate() {
return new Equals(location(), left(), right());
}
}

View File

@ -52,6 +52,7 @@ import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Grea
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThan;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThanOrEqual;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.sql.plan.logical.Aggregate;
import org.elasticsearch.xpack.sql.plan.logical.EsRelation;
import org.elasticsearch.xpack.sql.plan.logical.Filter;
@ -1313,7 +1314,7 @@ public class Optimizer extends RuleExecutor<LogicalPlan> {
}
// false for equality
if (bc instanceof GreaterThan || bc instanceof LessThan) {
if (bc instanceof NotEquals || bc instanceof GreaterThan || bc instanceof LessThan) {
if (!l.nullable() && !r.nullable() && l.semanticEquals(r)) {
return FALSE;
}

View File

@ -44,6 +44,7 @@ import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Grea
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThanOrEqual;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThan;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThanOrEqual;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.sql.expression.predicate.regex.Like;
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike;
@ -165,7 +166,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
case SqlBaseParser.EQ:
return new Equals(loc, left, right);
case SqlBaseParser.NEQ:
return new Not(loc, new Equals(loc, left, right));
return new NotEquals(loc, left, right);
case SqlBaseParser.LT:
return new LessThan(loc, left, right);
case SqlBaseParser.LTE:

View File

@ -31,7 +31,6 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunction;
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeFunction;
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeHistogramFunction;
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
import org.elasticsearch.xpack.sql.expression.predicate.IsNotNull;
import org.elasticsearch.xpack.sql.expression.predicate.Range;
import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MatchQueryPredicate;
@ -44,8 +43,10 @@ import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Bina
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Equals;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThan;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThanOrEqual;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThan;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThanOrEqual;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.sql.expression.predicate.regex.Like;
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike;
@ -536,16 +537,15 @@ final class QueryTranslator {
//
// Agg context means HAVING -> PipelineAggs
//
ScriptTemplate script = bc.asScript();
if (onAggs) {
aggFilter = new AggFilter(at.id().toString(), script);
aggFilter = new AggFilter(at.id().toString(), bc.asScript());
}
else {
// query directly on the field
if (at instanceof FieldAttribute) {
query = wrapIfNested(translateQuery(bc), ne);
} else {
query = new ScriptQuery(at.location(), script);
query = new ScriptQuery(at.location(), bc.asScript());
}
}
return new QueryTranslation(query, aggFilter);
@ -576,7 +576,7 @@ final class QueryTranslator {
if (bc instanceof LessThanOrEqual) {
return new RangeQuery(loc, name, null, false, value, true, format);
}
if (bc instanceof Equals) {
if (bc instanceof Equals || bc instanceof NotEquals) {
if (bc.left() instanceof FieldAttribute) {
FieldAttribute fa = (FieldAttribute) bc.left();
// equality should always be against an exact match
@ -585,7 +585,11 @@ final class QueryTranslator {
name = fa.exactAttribute().name();
}
}
return new TermQuery(loc, name, value);
Query query = new TermQuery(loc, name, value);
if (bc instanceof NotEquals) {
query = new NotQuery(loc, query);
}
return query;
}
throw new SqlIllegalArgumentException("Don't know how to translate binary comparison [{}] in [{}]", bc.right().nodeString(),
@ -655,11 +659,10 @@ final class QueryTranslator {
//
// Agg context means HAVING -> PipelineAggs
//
ScriptTemplate script = r.asScript();
Attribute at = ((NamedExpression) e).toAttribute();
if (onAggs) {
aggFilter = new AggFilter(at.id().toString(), script);
aggFilter = new AggFilter(at.id().toString(), r.asScript());
} else {
// typical range; no scripting involved
if (at instanceof FieldAttribute) {
@ -669,7 +672,7 @@ final class QueryTranslator {
}
// scripted query
else {
query = new ScriptQuery(at.location(), script);
query = new ScriptQuery(at.location(), r.asScript());
}
}
return new QueryTranslation(query, aggFilter);

View File

@ -9,10 +9,10 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.sort.NestedSortBuilder;
import org.elasticsearch.xpack.sql.tree.Location;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import java.util.Objects;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
public class NotQuery extends Query {
private final Query child;

View File

@ -20,6 +20,7 @@ class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalS
# Comparison
#
Boolean eq(Object, Object)
Boolean neq(Object, Object)
Boolean lt(Object, Object)
Boolean lte(Object, Object)
Boolean gt(Object, Object)

View File

@ -11,12 +11,6 @@ import org.elasticsearch.test.AbstractWireSerializingTestCase;
import org.elasticsearch.xpack.sql.expression.Literal;
import org.elasticsearch.xpack.sql.expression.function.scalar.Processors;
import org.elasticsearch.xpack.sql.expression.gen.processor.ConstantProcessor;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Equals;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThan;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThanOrEqual;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThan;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThanOrEqual;
import static org.elasticsearch.xpack.sql.tree.Location.EMPTY;
@ -48,6 +42,11 @@ public class BinaryComparisonProcessorTests extends AbstractWireSerializingTestC
assertEquals(false, new Equals(EMPTY, l(3), 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));
}
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));
@ -73,14 +72,15 @@ public class BinaryComparisonProcessorTests extends AbstractWireSerializingTestC
}
public void testHandleNull() {
assertNull(new Equals(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
assertNull(new GreaterThan(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
assertNull(new GreaterThanOrEqual(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
assertNull(new LessThan(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
assertNull(new LessThanOrEqual(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
assertNull(new Equals(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new NotEquals(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new GreaterThan(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new GreaterThanOrEqual(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new LessThan(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
assertNull(new LessThanOrEqual(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
}
private static Literal l(Object value) {
return Literal.of(EMPTY, value);
}
}
}

View File

@ -35,7 +35,6 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.math.Floor;
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Ascii;
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Repeat;
import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
import org.elasticsearch.xpack.sql.expression.predicate.IsNotNull;
import org.elasticsearch.xpack.sql.expression.predicate.Range;
import org.elasticsearch.xpack.sql.expression.predicate.logical.And;
@ -49,8 +48,10 @@ import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Sub;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Equals;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThan;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThanOrEqual;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThan;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThanOrEqual;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.sql.expression.predicate.regex.Like;
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike;
@ -265,6 +266,7 @@ public class OptimizerTests extends ESTestCase {
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.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());
}
@ -406,11 +408,12 @@ public class OptimizerTests extends ESTestCase {
private void assertNullLiteral(Expression expression) {
assertEquals(Literal.class, expression.getClass());
assertNull(((Literal) expression).fold());
assertNull(expression.fold());
}
public void testBinaryComparisonSimplification() {
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new Equals(EMPTY, FIVE, FIVE)));
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)));

View File

@ -14,6 +14,8 @@ import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Add;
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mul;
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Neg;
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Sub;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Equals;
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.sql.type.DataType;
import static org.hamcrest.core.StringStartsWith.startsWith;
@ -158,6 +160,22 @@ public class ExpressionTests extends ESTestCase {
assertEquals("2", ((Literal) sub2.children().get(1)).name());
}
public void testEquals() {
Expression expr = parser.createExpression("a = 10");
assertEquals(Equals.class, expr.getClass());
Equals eq = (Equals) expr;
assertEquals("(a) == 10", eq.name());
assertEquals(2, eq.children().size());
}
public void testNotEquals() {
Expression expr = parser.createExpression("a != 10");
assertEquals(NotEquals.class, expr.getClass());
NotEquals neq = (NotEquals) expr;
assertEquals("(a) != 10", neq.name());
assertEquals(2, neq.children().size());
}
public void testCastWithUnquotedDataType() {
Expression expr = parser.createExpression("CAST(10*2 AS long)");
assertEquals(Cast.class, expr.getClass());

View File

@ -34,7 +34,7 @@ import java.util.Map;
import java.util.TimeZone;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.core.StringStartsWith.startsWith;
import static org.hamcrest.Matchers.startsWith;
public class QueryTranslatorTests extends ESTestCase {