|
@@ -12,6 +12,7 @@ import org.elasticsearch.test.ESTestCase;
|
|
|
import org.elasticsearch.xpack.eql.analysis.Analyzer;
|
|
|
import org.elasticsearch.xpack.eql.analysis.PostAnalyzer;
|
|
|
import org.elasticsearch.xpack.eql.analysis.PreAnalyzer;
|
|
|
+import org.elasticsearch.xpack.eql.expression.function.scalar.string.StartsWith;
|
|
|
import org.elasticsearch.xpack.eql.expression.function.scalar.string.ToString;
|
|
|
import org.elasticsearch.xpack.eql.parser.EqlParser;
|
|
|
import org.elasticsearch.xpack.eql.plan.logical.AbstractJoin;
|
|
@@ -576,6 +577,113 @@ public class OptimizerTests extends ESTestCase {
|
|
|
assertEquals(ruleBCondition, filterCondition(query2.child().children().get(0)));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * sequence
|
|
|
+ * 1. filter startsWith(a, "foo") by a
|
|
|
+ * 2. filter X by a
|
|
|
+ * ==
|
|
|
+ * 1. filter startsWith(a, "foo") by a
|
|
|
+ * 2. filter startsWith(a, "foo") by a
|
|
|
+ * \filter X
|
|
|
+ */
|
|
|
+ public void testKeyConstraintWithFunction() {
|
|
|
+ Attribute a = key("a");
|
|
|
+
|
|
|
+ Expression keyCondition = startsWithExp(a, new Literal(EMPTY, "foo", DataTypes.KEYWORD));
|
|
|
+ Expression filter = equalsExpression();
|
|
|
+
|
|
|
+ KeyedFilter rule1 = keyedFilter(basicFilter(keyCondition), a);
|
|
|
+ KeyedFilter rule2 = keyedFilter(basicFilter(filter), a);
|
|
|
+
|
|
|
+ AbstractJoin j = randomSequenceOrSample(rule1, rule2);
|
|
|
+
|
|
|
+ List<KeyedFilter> queries = j.queries();
|
|
|
+ assertEquals(rule1, queries.get(0));
|
|
|
+ assertEquals(keyCondition, filterCondition(queries.get(1).child()));
|
|
|
+ assertEquals(filterCondition(rule2.child()), filterCondition(queries.get(1).child().children().get(0)));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * sequence
|
|
|
+ * 1. filter startsWith(a, b) by a
|
|
|
+ * 2. filter X by a
|
|
|
+ * ==
|
|
|
+ * same
|
|
|
+ */
|
|
|
+ public void testKeyConstraintWithNonKey() {
|
|
|
+ Attribute a = key("a");
|
|
|
+
|
|
|
+ Expression keyCondition = startsWithExp(a, key("b"));
|
|
|
+ Expression filter = equalsExpression();
|
|
|
+
|
|
|
+ KeyedFilter rule1 = keyedFilter(basicFilter(keyCondition), a);
|
|
|
+ KeyedFilter rule2 = keyedFilter(basicFilter(filter), a);
|
|
|
+
|
|
|
+ AbstractJoin j = randomSequenceOrSample(rule1, rule2);
|
|
|
+
|
|
|
+ List<KeyedFilter> queries = j.queries();
|
|
|
+ assertEquals(rule1, queries.get(0));
|
|
|
+ assertEquals(rule2, queries.get(1));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * sequence
|
|
|
+ * 1. filter startsWith(a, b) and c > 10 by a, c
|
|
|
+ * 2. filter X by a, c
|
|
|
+ * ==
|
|
|
+ * 1. filter startsWith(a, b) and c > 10 by a, c
|
|
|
+ * 2. filter c > 10 by a, c
|
|
|
+ * \filter X
|
|
|
+ */
|
|
|
+ public void testKeyConstraintWithNonKeyPartialPropagation() {
|
|
|
+ Attribute a = key("a");
|
|
|
+ Attribute b = key("b");
|
|
|
+ Attribute c = key("c");
|
|
|
+
|
|
|
+ GreaterThan gtExp = gtExpression(c);
|
|
|
+ Expression keyCondition = new And(EMPTY, startsWithExp(a, b), gtExp);
|
|
|
+ Expression filter = equalsExpression();
|
|
|
+
|
|
|
+ KeyedFilter rule1 = keyedFilter(basicFilter(keyCondition), a, c);
|
|
|
+ KeyedFilter rule2 = keyedFilter(basicFilter(filter), a, c);
|
|
|
+
|
|
|
+ AbstractJoin j = randomSequenceOrSample(rule1, rule2);
|
|
|
+
|
|
|
+ List<KeyedFilter> queries = j.queries();
|
|
|
+ assertEquals(rule1, queries.get(0));
|
|
|
+ assertEquals(gtExp, filterCondition(queries.get(1).child()));
|
|
|
+ assertEquals(filterCondition(rule2.child()), filterCondition(queries.get(1).child().children().get(0)));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * sequence
|
|
|
+ * 1. filter startsWith(a, b) by a, c
|
|
|
+ * 2. filter X and c > 10 by a, c
|
|
|
+ * ==
|
|
|
+ * 1. filter c > 10 by a, c
|
|
|
+ * \filter startsWith(a, b)
|
|
|
+ * 2. filter X and c > 10 by a, c
|
|
|
+ */
|
|
|
+ public void testKeyConstraintWithNonKeyPartialReversePropagation() {
|
|
|
+ Attribute a = key("a");
|
|
|
+ Attribute b = key("b");
|
|
|
+ Attribute c = key("c");
|
|
|
+
|
|
|
+ GreaterThan gtExp = gtExpression(c);
|
|
|
+ Expression keyCondition = startsWithExp(a, b);
|
|
|
+ Expression filter = new And(EMPTY, equalsExpression(), gtExp);
|
|
|
+
|
|
|
+ KeyedFilter rule1 = keyedFilter(basicFilter(keyCondition), a, c);
|
|
|
+ KeyedFilter rule2 = keyedFilter(basicFilter(filter), a, c);
|
|
|
+
|
|
|
+ AbstractJoin j = randomSequenceOrSample(rule1, rule2);
|
|
|
+
|
|
|
+ List<KeyedFilter> queries = j.queries();
|
|
|
+ assertEquals(gtExp, filterCondition(queries.get(0).child()));
|
|
|
+ assertEquals(filterCondition(rule1.child()), filterCondition(queries.get(0).child().children().get(0)));
|
|
|
+ assertEquals(rule2, queries.get(1));
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Key conditions inside a disjunction (OR) are ignored
|
|
|
* <p>
|
|
@@ -817,4 +925,8 @@ public class OptimizerTests extends ESTestCase {
|
|
|
private static GreaterThan gtExpression(Attribute b) {
|
|
|
return new GreaterThan(EMPTY, b, new Literal(EMPTY, 1, INTEGER), UTC);
|
|
|
}
|
|
|
+
|
|
|
+ private static StartsWith startsWithExp(Expression a, Expression b) {
|
|
|
+ return new StartsWith(EMPTY, a, b, randomBoolean());
|
|
|
+ }
|
|
|
}
|