mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-17 10:25:15 +00:00
* Simplify equals/not-equals TRUE/FALSE expressions, by returning them as is (TRUE variant) or negating them (FALSE variant) (cherry picked from commit 17858afbe6da5fa0b3ecfc537cabb337e4baaffe)
This commit is contained in:
parent
8e570300eb
commit
980f175222
@ -15,6 +15,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Binar
|
||||
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals;
|
||||
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals;
|
||||
import org.elasticsearch.xpack.ql.expression.predicate.regex.Like;
|
||||
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BooleanEqualsSimplification;
|
||||
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BooleanLiteralsOnTheRight;
|
||||
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BooleanSimplification;
|
||||
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.CombineBinaryComparisons;
|
||||
@ -47,6 +48,7 @@ public class Optimizer extends RuleExecutor<LogicalPlan> {
|
||||
// boolean
|
||||
new BooleanSimplification(),
|
||||
new BooleanLiteralsOnTheRight(),
|
||||
new BooleanEqualsSimplification(),
|
||||
// needs to occur before BinaryComparison combinations
|
||||
new ReplaceWildcards(),
|
||||
new ReplaceNullChecks(),
|
||||
|
@ -13,48 +13,57 @@
|
||||
|
||||
|
||||
basic
|
||||
process where true;
|
||||
process where true
|
||||
;
|
||||
null
|
||||
;
|
||||
|
||||
singleNumericFilterEquals
|
||||
process where serial_event_id = 1;
|
||||
process where serial_event_id = 1
|
||||
;
|
||||
"term":{"serial_event_id":{"value":1
|
||||
;
|
||||
|
||||
singleNumericFilterLess
|
||||
process where serial_event_id < 4;
|
||||
process where serial_event_id < 4
|
||||
;
|
||||
"range":{"serial_event_id":{"from":null,"to":4,"include_lower":false,"include_upper":false
|
||||
;
|
||||
|
||||
singleNumericFilterLessEquals
|
||||
process where serial_event_id <= 4;
|
||||
process where serial_event_id <= 4
|
||||
;
|
||||
"range":{"serial_event_id":{"from":null,"to":4,"include_lower":false,"include_upper":true
|
||||
;
|
||||
|
||||
singleNumericFilterGreater
|
||||
process where serial_event_id > 4;
|
||||
process where serial_event_id > 4
|
||||
;
|
||||
"range":{"serial_event_id":{"from":4,"to":null,"include_lower":false,"include_upper":false
|
||||
;
|
||||
|
||||
singleNumericFilterGreaterEquals
|
||||
process where serial_event_id >= 4;
|
||||
process where serial_event_id >= 4
|
||||
;
|
||||
"range":{"serial_event_id":{"from":4,"to":null,"include_lower":true,"include_upper":false
|
||||
;
|
||||
|
||||
mixedTypeFilter
|
||||
process where process_name == "notepad.exe" or (serial_event_id < 4.5 and serial_event_id >= 3.1);
|
||||
process where process_name == "notepad.exe" or (serial_event_id < 4.5 and serial_event_id >= 3.1)
|
||||
;
|
||||
"term":{"process_name":{"value":"notepad.exe"
|
||||
"range":{"serial_event_id":{"from":3.1,"to":4.5,"include_lower":true,"include_upper":false
|
||||
;
|
||||
|
||||
notFilter
|
||||
process where not (exit_code > -1);
|
||||
process where not (exit_code > -1)
|
||||
;
|
||||
"range":{"exit_code":{"from":null,"to":-1,"include_lower":false,"include_upper":true
|
||||
;
|
||||
|
||||
inFilter
|
||||
process where process_name in ("python.exe", "SMSS.exe", "explorer.exe");
|
||||
process where process_name in ("python.exe", "SMSS.exe", "explorer.exe")
|
||||
;
|
||||
"terms":{"process_name":["python.exe","SMSS.exe","explorer.exe"],
|
||||
;
|
||||
|
||||
@ -65,6 +74,46 @@ process where process_path == "*\\red_ttp\\wininit.*" and opcode in (0,1,2,3)
|
||||
{"terms":{"opcode":[0,1,2,3]
|
||||
;
|
||||
|
||||
functionEqualsTrue
|
||||
process where cidrMatch(source_address, "10.0.0.0/8") == true
|
||||
;
|
||||
{"bool":{"must":[{"term":{"event.category":{"value":"process"
|
||||
{"term":{"source_address":{"value":"10.0.0.0/8"
|
||||
;
|
||||
|
||||
functionEqualsFalse
|
||||
process where cidrMatch(source_address, "10.0.0.0/8") == false
|
||||
;
|
||||
{"bool":{"must":[{"term":{"event.category":{"value":"process"
|
||||
{"bool":{"must_not":[{"term":{"source_address":{"value":"10.0.0.0/8"
|
||||
;
|
||||
|
||||
functionNotEqualsTrue
|
||||
process where cidrMatch(source_address, "10.0.0.0/8") != true
|
||||
;
|
||||
{"bool":{"must":[{"term":{"event.category":{"value":"process"
|
||||
{"bool":{"must_not":[{"term":{"source_address":{"value":"10.0.0.0/8"
|
||||
;
|
||||
|
||||
functionNotEqualsFalse
|
||||
process where cidrMatch(source_address, "10.0.0.0/8") != false
|
||||
;
|
||||
{"bool":{"must":[{"term":{"event.category":{"value":"process"
|
||||
{"term":{"source_address":{"value":"10.0.0.0/8"
|
||||
;
|
||||
|
||||
twoFunctionsEqualsBooleanLiterals
|
||||
process where endsWith(process_path, 'x') == true and endsWith(process_path, 'yx') == false
|
||||
;
|
||||
{"bool":{"must":[{"term":{"event.category":{"value":"process",
|
||||
{"bool":{"must":[{"script":{"script":{"source":"InternalQlScriptUtils.nullSafeFilter(
|
||||
InternalEqlScriptUtils.endsWith(InternalQlScriptUtils.docValue(doc,params.v0),params.v1))","lang":"painless",
|
||||
"params":{"v0":"process_path","v1":"x"}}
|
||||
{"script":{"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.not(
|
||||
InternalEqlScriptUtils.endsWith(InternalQlScriptUtils.docValue(doc,params.v0),params.v1)))","lang":"painless",
|
||||
"params":{"v0":"process_path","v1":"yx"}}
|
||||
;
|
||||
|
||||
endsWithFunction
|
||||
process where endsWith(user_name, 'c')
|
||||
;
|
||||
@ -114,7 +163,8 @@ InternalQlScriptUtils.docValue(doc,params.v0),params.v1))"
|
||||
;
|
||||
|
||||
stringFunction
|
||||
process where string(pid) == "123";
|
||||
process where string(pid) == "123"
|
||||
;
|
||||
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.eq(
|
||||
InternalEqlScriptUtils.string(InternalQlScriptUtils.docValue(doc,params.v0)),params.v1))",
|
||||
"params":{"v0":"pid","v1":"123"}
|
||||
|
@ -62,6 +62,34 @@ public final class OptimizerRules {
|
||||
return e.foldable() ? Literal.of(e) : e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This rule must always be placed after {@link BooleanLiteralsOnTheRight}, since it looks at TRUE/FALSE literals' existence
|
||||
* on the right hand-side of the {@link Equals}/{@link NotEquals} expressions.
|
||||
*/
|
||||
public static final class BooleanEqualsSimplification extends OptimizerExpressionRule {
|
||||
|
||||
public BooleanEqualsSimplification() {
|
||||
super(TransformDirection.UP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression rule(Expression e) {
|
||||
if (e instanceof Equals || e instanceof NotEquals) {
|
||||
// for expression "==" or "!=" TRUE/FALSE, return the expression itself or its negated variant
|
||||
BinaryComparison bc = (BinaryComparison) e;
|
||||
|
||||
if (TRUE.equals(bc.right())) {
|
||||
return e instanceof Equals ? bc.left() : new Not(bc.left().source(), bc.left());
|
||||
}
|
||||
if (FALSE.equals(bc.right())) {
|
||||
return e instanceof Equals ? new Not(bc.left().source(), bc.left()) : bc.left();
|
||||
}
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class BooleanSimplification extends OptimizerExpressionRule {
|
||||
|
||||
@ -255,7 +283,7 @@ public final class OptimizerRules {
|
||||
if (comp != null) {
|
||||
// var cannot be equal to two different values at the same time
|
||||
if (comp != 0) {
|
||||
return new Literal(and.source(), Boolean.FALSE, DataTypes.BOOLEAN);
|
||||
return new Literal(and.source(), Boolean.FALSE, DataTypes.BOOLEAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -263,7 +291,7 @@ public final class OptimizerRules {
|
||||
equals.add(otherEq);
|
||||
} else {
|
||||
exps.add(otherEq);
|
||||
}
|
||||
}
|
||||
} else if (ex instanceof GreaterThan || ex instanceof GreaterThanOrEqual ||
|
||||
ex instanceof LessThan || ex instanceof LessThanOrEqual) {
|
||||
BinaryComparison bc = (BinaryComparison) ex;
|
||||
|
@ -34,6 +34,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.regex.Like;
|
||||
import org.elasticsearch.xpack.ql.expression.predicate.regex.LikePattern;
|
||||
import org.elasticsearch.xpack.ql.expression.predicate.regex.RLike;
|
||||
import org.elasticsearch.xpack.ql.expression.predicate.regex.RLikePattern;
|
||||
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BooleanEqualsSimplification;
|
||||
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BooleanLiteralsOnTheRight;
|
||||
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BooleanSimplification;
|
||||
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.CombineBinaryComparisons;
|
||||
@ -272,6 +273,22 @@ public class OptimizerRulesTests extends ESTestCase {
|
||||
assertEquals(expected, simplification.rule(actual));
|
||||
}
|
||||
|
||||
public void testBoolEqualsSimplification() {
|
||||
BooleanEqualsSimplification s = new BooleanEqualsSimplification();
|
||||
|
||||
assertEquals(DUMMY_EXPRESSION, s.rule(new Equals(EMPTY, DUMMY_EXPRESSION, TRUE)));
|
||||
assertEquals(new Not(EMPTY, DUMMY_EXPRESSION), s.rule(new Equals(EMPTY, DUMMY_EXPRESSION, FALSE)));
|
||||
|
||||
assertEquals(new Not(EMPTY, DUMMY_EXPRESSION), s.rule(notEqualsOf(DUMMY_EXPRESSION, TRUE)));
|
||||
assertEquals(DUMMY_EXPRESSION, s.rule(notEqualsOf(DUMMY_EXPRESSION, FALSE)));
|
||||
|
||||
assertEquals(NULL, s.rule(new Equals(EMPTY, NULL, TRUE)));
|
||||
assertEquals(new Not(EMPTY, NULL), s.rule(new Equals(EMPTY, NULL, FALSE)));
|
||||
|
||||
assertEquals(new Not(EMPTY, NULL), s.rule(notEqualsOf(NULL, TRUE)));
|
||||
assertEquals(NULL, s.rule(notEqualsOf(NULL, FALSE)));
|
||||
}
|
||||
|
||||
//
|
||||
// Range optimization
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user