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:
parent
f72ef9b5fd
commit
9ac7af6b3e
|
@ -129,6 +129,10 @@ aggCountAndHaving
|
||||||
SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING COUNT(*) > 10 ORDER BY gender;
|
SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING COUNT(*) > 10 ORDER BY gender;
|
||||||
aggCountAndHavingEquality
|
aggCountAndHavingEquality
|
||||||
SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING COUNT(*) = 10 ORDER BY gender;
|
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
|
aggCountOnColumnAndHaving
|
||||||
SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING COUNT(gender) > 10 ORDER BY gender;
|
SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING COUNT(gender) > 10 ORDER BY gender;
|
||||||
aggCountOnColumnAndWildcardAndHaving
|
aggCountOnColumnAndWildcardAndHaving
|
||||||
|
|
|
@ -232,21 +232,13 @@ SELECT POSITION('x',LCASE("first_name")) pos, "first_name" FROM "test_emp" WHERE
|
||||||
pos:i | first_name:s
|
pos:i | first_name:s
|
||||||
---------------+---------------
|
---------------+---------------
|
||||||
4 |Guoxiang
|
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
|
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
|
POSITION(m,LCASE(first_name)):i| pos:l
|
||||||
-------------------------------+---------------
|
-------------------------------+---------------
|
||||||
|
@ -256,7 +248,6 @@ POSITION(m,LCASE(first_name)):i| pos:l
|
||||||
3 |6
|
3 |6
|
||||||
2 |1
|
2 |1
|
||||||
1 |9
|
1 |9
|
||||||
null |10
|
|
||||||
;
|
;
|
||||||
|
|
||||||
selectInsertWithPositionAndCondition
|
selectInsertWithPositionAndCondition
|
||||||
|
|
|
@ -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
|
// SELECT with IN
|
||||||
|
//
|
||||||
inWithLiterals
|
inWithLiterals
|
||||||
SELECT 1 IN (1, 2, 3), 1 IN (2, 3);
|
SELECT 1 IN (1, 2, 3), 1 IN (2, 3);
|
||||||
|
|
||||||
|
|
|
@ -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
|
* Acts as a registry of the various static methods used <b>internally</b> by the scalar functions
|
||||||
* (to simplify the whitelist definition).
|
* (to simplify the whitelist definition).
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public final class InternalSqlScriptUtils {
|
public final class InternalSqlScriptUtils {
|
||||||
|
|
||||||
private InternalSqlScriptUtils() {}
|
private InternalSqlScriptUtils() {}
|
||||||
|
@ -52,7 +53,7 @@ public final class InternalSqlScriptUtils {
|
||||||
public static <T> Object docValue(Map<String, ScriptDocValues<T>> doc, String fieldName) {
|
public static <T> Object docValue(Map<String, ScriptDocValues<T>> doc, String fieldName) {
|
||||||
if (doc.containsKey(fieldName)) {
|
if (doc.containsKey(fieldName)) {
|
||||||
ScriptDocValues<T> docValues = doc.get(fieldName);
|
ScriptDocValues<T> docValues = doc.get(fieldName);
|
||||||
if (docValues.size() > 0) {
|
if (!docValues.isEmpty()) {
|
||||||
return docValues.get(0);
|
return docValues.get(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,6 +84,10 @@ public final class InternalSqlScriptUtils {
|
||||||
return BinaryComparisonOperation.EQ.apply(left, right);
|
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) {
|
public static Boolean lt(Object left, Object right) {
|
||||||
return BinaryComparisonOperation.LT.apply(left, right);
|
return BinaryComparisonOperation.LT.apply(left, right);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ public class BinaryComparisonProcessor extends FunctionalBinaryProcessor<Object,
|
||||||
public enum BinaryComparisonOperation implements PredicateBiFunction<Object, Object, Boolean> {
|
public enum BinaryComparisonOperation implements PredicateBiFunction<Object, Object, Boolean> {
|
||||||
|
|
||||||
EQ(Comparisons::eq, "=="),
|
EQ(Comparisons::eq, "=="),
|
||||||
|
NEQ(Comparisons::neq, "!="),
|
||||||
GT(Comparisons::gt, ">"),
|
GT(Comparisons::gt, ">"),
|
||||||
GTE(Comparisons::gte, ">="),
|
GTE(Comparisons::gte, ">="),
|
||||||
LT(Comparisons::lt, "<"),
|
LT(Comparisons::lt, "<"),
|
||||||
|
|
|
@ -19,6 +19,11 @@ public final class Comparisons {
|
||||||
return i == null ? null : i.intValue() == 0;
|
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) {
|
static Boolean lt(Object l, Object r) {
|
||||||
Integer i = compare(l, r);
|
Integer i = compare(l, r);
|
||||||
return i == null ? null : i.intValue() < 0;
|
return i == null ? null : i.intValue() < 0;
|
||||||
|
@ -50,6 +55,9 @@ public final class Comparisons {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
static Integer compare(Object l, Object r) {
|
static Integer compare(Object l, Object r) {
|
||||||
|
if (l == null || r == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// typical number comparison
|
// typical number comparison
|
||||||
if (l instanceof Number && r instanceof Number) {
|
if (l instanceof Number && r instanceof Number) {
|
||||||
return compare((Number) l, (Number) r);
|
return compare((Number) l, (Number) r);
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison;
|
package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
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.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
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) {
|
public Equals(Location location, Expression left, Expression right) {
|
||||||
super(location, left, right, BinaryComparisonOperation.EQ);
|
super(location, left, right, BinaryComparisonOperation.EQ);
|
||||||
|
@ -30,4 +31,9 @@ public class Equals extends BinaryComparison {
|
||||||
public Equals swapLeftAndRight() {
|
public Equals swapLeftAndRight() {
|
||||||
return new Equals(location(), right(), left());
|
return new Equals(location(), right(), left());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BinaryOperator<?, ?, ?, ?> negate() {
|
||||||
|
return new NotEquals(location(), left(), right());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.In;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThan;
|
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.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.Aggregate;
|
||||||
import org.elasticsearch.xpack.sql.plan.logical.EsRelation;
|
import org.elasticsearch.xpack.sql.plan.logical.EsRelation;
|
||||||
import org.elasticsearch.xpack.sql.plan.logical.Filter;
|
import org.elasticsearch.xpack.sql.plan.logical.Filter;
|
||||||
|
@ -1313,7 +1314,7 @@ public class Optimizer extends RuleExecutor<LogicalPlan> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// false for equality
|
// 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)) {
|
if (!l.nullable() && !r.nullable() && l.semanticEquals(r)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.GreaterThanOrEqual;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThan;
|
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.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.Like;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
|
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike;
|
import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike;
|
||||||
|
@ -165,7 +166,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
|
||||||
case SqlBaseParser.EQ:
|
case SqlBaseParser.EQ:
|
||||||
return new Equals(loc, left, right);
|
return new Equals(loc, left, right);
|
||||||
case SqlBaseParser.NEQ:
|
case SqlBaseParser.NEQ:
|
||||||
return new Not(loc, new Equals(loc, left, right));
|
return new NotEquals(loc, left, right);
|
||||||
case SqlBaseParser.LT:
|
case SqlBaseParser.LT:
|
||||||
return new LessThan(loc, left, right);
|
return new LessThan(loc, left, right);
|
||||||
case SqlBaseParser.LTE:
|
case SqlBaseParser.LTE:
|
||||||
|
|
|
@ -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.DateTimeFunction;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeHistogramFunction;
|
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.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.IsNotNull;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.Range;
|
import org.elasticsearch.xpack.sql.expression.predicate.Range;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MatchQueryPredicate;
|
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.Equals;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThan;
|
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.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.LessThan;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThanOrEqual;
|
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.Like;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
|
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike;
|
import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike;
|
||||||
|
@ -536,16 +537,15 @@ final class QueryTranslator {
|
||||||
//
|
//
|
||||||
// Agg context means HAVING -> PipelineAggs
|
// Agg context means HAVING -> PipelineAggs
|
||||||
//
|
//
|
||||||
ScriptTemplate script = bc.asScript();
|
|
||||||
if (onAggs) {
|
if (onAggs) {
|
||||||
aggFilter = new AggFilter(at.id().toString(), script);
|
aggFilter = new AggFilter(at.id().toString(), bc.asScript());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// query directly on the field
|
// query directly on the field
|
||||||
if (at instanceof FieldAttribute) {
|
if (at instanceof FieldAttribute) {
|
||||||
query = wrapIfNested(translateQuery(bc), ne);
|
query = wrapIfNested(translateQuery(bc), ne);
|
||||||
} else {
|
} else {
|
||||||
query = new ScriptQuery(at.location(), script);
|
query = new ScriptQuery(at.location(), bc.asScript());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new QueryTranslation(query, aggFilter);
|
return new QueryTranslation(query, aggFilter);
|
||||||
|
@ -576,7 +576,7 @@ final class QueryTranslator {
|
||||||
if (bc instanceof LessThanOrEqual) {
|
if (bc instanceof LessThanOrEqual) {
|
||||||
return new RangeQuery(loc, name, null, false, value, true, format);
|
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) {
|
if (bc.left() instanceof FieldAttribute) {
|
||||||
FieldAttribute fa = (FieldAttribute) bc.left();
|
FieldAttribute fa = (FieldAttribute) bc.left();
|
||||||
// equality should always be against an exact match
|
// equality should always be against an exact match
|
||||||
|
@ -585,7 +585,11 @@ final class QueryTranslator {
|
||||||
name = fa.exactAttribute().name();
|
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(),
|
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
|
// Agg context means HAVING -> PipelineAggs
|
||||||
//
|
//
|
||||||
ScriptTemplate script = r.asScript();
|
|
||||||
Attribute at = ((NamedExpression) e).toAttribute();
|
Attribute at = ((NamedExpression) e).toAttribute();
|
||||||
|
|
||||||
if (onAggs) {
|
if (onAggs) {
|
||||||
aggFilter = new AggFilter(at.id().toString(), script);
|
aggFilter = new AggFilter(at.id().toString(), r.asScript());
|
||||||
} else {
|
} else {
|
||||||
// typical range; no scripting involved
|
// typical range; no scripting involved
|
||||||
if (at instanceof FieldAttribute) {
|
if (at instanceof FieldAttribute) {
|
||||||
|
@ -669,7 +672,7 @@ final class QueryTranslator {
|
||||||
}
|
}
|
||||||
// scripted query
|
// scripted query
|
||||||
else {
|
else {
|
||||||
query = new ScriptQuery(at.location(), script);
|
query = new ScriptQuery(at.location(), r.asScript());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new QueryTranslation(query, aggFilter);
|
return new QueryTranslation(query, aggFilter);
|
||||||
|
|
|
@ -9,10 +9,10 @@ import org.elasticsearch.index.query.QueryBuilder;
|
||||||
import org.elasticsearch.search.sort.NestedSortBuilder;
|
import org.elasticsearch.search.sort.NestedSortBuilder;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
|
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
||||||
|
|
||||||
public class NotQuery extends Query {
|
public class NotQuery extends Query {
|
||||||
private final Query child;
|
private final Query child;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalS
|
||||||
# Comparison
|
# Comparison
|
||||||
#
|
#
|
||||||
Boolean eq(Object, Object)
|
Boolean eq(Object, Object)
|
||||||
|
Boolean neq(Object, Object)
|
||||||
Boolean lt(Object, Object)
|
Boolean lt(Object, Object)
|
||||||
Boolean lte(Object, Object)
|
Boolean lte(Object, Object)
|
||||||
Boolean gt(Object, Object)
|
Boolean gt(Object, Object)
|
||||||
|
|
|
@ -11,12 +11,6 @@ import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||||
import org.elasticsearch.xpack.sql.expression.Literal;
|
import org.elasticsearch.xpack.sql.expression.Literal;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.Processors;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.Processors;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.processor.ConstantProcessor;
|
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;
|
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));
|
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() {
|
public void testGt() {
|
||||||
assertEquals(true, new GreaterThan(EMPTY, l(4), l(3)).makePipe().asProcessor().process(null));
|
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(4)).makePipe().asProcessor().process(null));
|
||||||
|
@ -73,11 +72,12 @@ public class BinaryComparisonProcessorTests extends AbstractWireSerializingTestC
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testHandleNull() {
|
public void testHandleNull() {
|
||||||
assertNull(new Equals(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
|
assertNull(new Equals(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
|
||||||
assertNull(new GreaterThan(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
|
assertNull(new NotEquals(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
|
||||||
assertNull(new GreaterThanOrEqual(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
|
assertNull(new GreaterThan(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
|
||||||
assertNull(new LessThan(EMPTY, l(null), l(3)).makePipe().asProcessor().process(null));
|
assertNull(new GreaterThanOrEqual(EMPTY, Literal.NULL, l(3)).makePipe().asProcessor().process(null));
|
||||||
assertNull(new LessThanOrEqual(EMPTY, l(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) {
|
private static Literal l(Object value) {
|
||||||
|
|
|
@ -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.Ascii;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Repeat;
|
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.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.IsNotNull;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.Range;
|
import org.elasticsearch.xpack.sql.expression.predicate.Range;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.logical.And;
|
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.Equals;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThan;
|
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.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.LessThan;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThanOrEqual;
|
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.Like;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
|
import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike;
|
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 GreaterThan(EMPTY, TWO, THREE)).canonical());
|
||||||
assertEquals(Literal.FALSE, new ConstantFolding().rule(new GreaterThanOrEqual(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 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 LessThanOrEqual(EMPTY, TWO, THREE)).canonical());
|
||||||
assertEquals(Literal.TRUE, new ConstantFolding().rule(new LessThan(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) {
|
private void assertNullLiteral(Expression expression) {
|
||||||
assertEquals(Literal.class, expression.getClass());
|
assertEquals(Literal.class, expression.getClass());
|
||||||
assertNull(((Literal) expression).fold());
|
assertNull(expression.fold());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBinaryComparisonSimplification() {
|
public void testBinaryComparisonSimplification() {
|
||||||
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new Equals(EMPTY, FIVE, FIVE)));
|
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 GreaterThanOrEqual(EMPTY, FIVE, FIVE)));
|
||||||
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new LessThanOrEqual(EMPTY, FIVE, FIVE)));
|
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new LessThanOrEqual(EMPTY, FIVE, FIVE)));
|
||||||
|
|
||||||
|
|
|
@ -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.Mul;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Neg;
|
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.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 org.elasticsearch.xpack.sql.type.DataType;
|
||||||
|
|
||||||
import static org.hamcrest.core.StringStartsWith.startsWith;
|
import static org.hamcrest.core.StringStartsWith.startsWith;
|
||||||
|
@ -158,6 +160,22 @@ public class ExpressionTests extends ESTestCase {
|
||||||
assertEquals("2", ((Literal) sub2.children().get(1)).name());
|
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() {
|
public void testCastWithUnquotedDataType() {
|
||||||
Expression expr = parser.createExpression("CAST(10*2 AS long)");
|
Expression expr = parser.createExpression("CAST(10*2 AS long)");
|
||||||
assertEquals(Cast.class, expr.getClass());
|
assertEquals(Cast.class, expr.getClass());
|
||||||
|
|
|
@ -34,7 +34,7 @@ import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.endsWith;
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
import static org.hamcrest.core.StringStartsWith.startsWith;
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
|
|
||||||
public class QueryTranslatorTests extends ESTestCase {
|
public class QueryTranslatorTests extends ESTestCase {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue