Skip to content

Commit 286cb26

Browse files
committed
Deal with internally created IN in a different way for EQL
1 parent f5b1263 commit 286cb26

File tree

3 files changed

+46
-11
lines changed
  • x-pack/plugin

3 files changed

+46
-11
lines changed

x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/optimizer/Optimizer.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BinaryComparisonSimplification;
4545
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BooleanFunctionEqualsElimination;
4646
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.BooleanSimplification;
47-
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.CombineDisjunctionsToIn;
4847
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.ConstantFolding;
4948
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.LiteralsOnTheRight;
5049
import org.elasticsearch.xpack.ql.optimizer.OptimizerRules.OptimizerRule;
@@ -252,6 +251,14 @@ protected Expression maybeSimplifyNegatable(Expression e) {
252251

253252
}
254253

254+
static class CombineDisjunctionsToIn extends org.elasticsearch.xpack.ql.optimizer.OptimizerRules.CombineDisjunctionsToIn {
255+
256+
@Override
257+
protected boolean shouldValidateIn() {
258+
return true;
259+
}
260+
}
261+
255262
static class PruneFilters extends org.elasticsearch.xpack.ql.optimizer.OptimizerRules.PruneFilters {
256263

257264
@Override

x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/In.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ protected TypeResolution resolveType() {
177177
return super.resolveType();
178178
}
179179

180+
public TypeResolution validateInTypes() {
181+
return resolveType();
182+
}
183+
180184
@Override
181185
public int hashCode() {
182186
return Objects.hash(value, list);

x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/optimizer/OptimizerRules.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,8 +1203,8 @@ private static boolean notEqualsIsRemovableFromConjunction(NotEquals notEquals,
12031203
* 2. a == 1 OR a IN (2) becomes a IN (1, 2)
12041204
* 3. a IN (1) OR a IN (2) becomes a IN (1, 2)
12051205
*
1206-
* This rule does NOT check for type compatibility as that phase has been
1207-
* already be verified in the analyzer.
1206+
* By default (see {@link #shouldValidateIn()}), this rule does NOT check for type compatibility as that phase has
1207+
* already been verified in the analyzer, but this behavior can be changed by subclasses.
12081208
*/
12091209
public static class CombineDisjunctionsToIn extends OptimizerExpressionRule<Or> {
12101210
public CombineDisjunctionsToIn() {
@@ -1214,7 +1214,7 @@ public CombineDisjunctionsToIn() {
12141214
@Override
12151215
protected Expression rule(Or or) {
12161216
Expression e = or;
1217-
// look only at equals and In
1217+
// look only at Equals and In
12181218
List<Expression> exps = splitOr(e);
12191219

12201220
Map<Expression, Set<Expression>> found = new LinkedHashMap<>();
@@ -1223,7 +1223,7 @@ protected Expression rule(Or or) {
12231223

12241224
for (Expression exp : exps) {
12251225
if (exp instanceof Equals eq) {
1226-
// consider only equals against foldables
1226+
// consider only Equals against foldables
12271227
if (eq.right().foldable()) {
12281228
found.computeIfAbsent(eq.left(), k -> new LinkedHashSet<>()).add(eq.right());
12291229
} else {
@@ -1243,10 +1243,30 @@ protected Expression rule(Or or) {
12431243
}
12441244

12451245
if (found.isEmpty() == false) {
1246-
// combine equals alongside the existing ors
1246+
// combine Equals alongside the existing ORs
12471247
final ZoneId finalZoneId = zoneId;
12481248
found.forEach(
1249-
(k, v) -> { ors.add(v.size() == 1 ? createEquals(k, v, finalZoneId) : createIn(k, new ArrayList<>(v), finalZoneId)); }
1249+
(k, v) -> {
1250+
if (v.size() == 1) {
1251+
ors.add(createEquals(k, v.iterator().next(), finalZoneId));
1252+
} else {
1253+
In in = createIn(k, new ArrayList<>(v), finalZoneId);
1254+
// IN has its own particularities when it comes to type resolution and not all implementations
1255+
// double check the validity of an internally created IN (like the one created here). EQL is one where the IN
1256+
// implementation is like this mechanism here has been specifically created for it
1257+
if (shouldValidateIn()) {
1258+
Expression.TypeResolution resolution = in.validateInTypes();
1259+
if (resolution.unresolved()) {
1260+
// if the created In is not valid, fall back to regular Equals combined with ORs
1261+
in.list().forEach(inValue -> ors.add(createEquals(k, inValue, finalZoneId)));
1262+
} else {
1263+
ors.add(in);
1264+
}
1265+
} else {
1266+
ors.add(in);
1267+
}
1268+
}
1269+
}
12501270
);
12511271

12521272
Expression combineOr = combineOr(ors);
@@ -1261,13 +1281,17 @@ protected Expression rule(Or or) {
12611281
return e;
12621282
}
12631283

1264-
protected Equals createEquals(Expression k, Set<Expression> v, ZoneId finalZoneId) {
1265-
return new Equals(k.source(), k, v.iterator().next(), finalZoneId);
1266-
}
1267-
12681284
protected In createIn(Expression key, List<Expression> values, ZoneId zoneId) {
12691285
return new In(key.source(), key, values, zoneId);
12701286
}
1287+
1288+
protected boolean shouldValidateIn() {
1289+
return false;
1290+
}
1291+
1292+
private Equals createEquals(Expression key, Expression value, ZoneId finalZoneId) {
1293+
return new Equals(key.source(), key, value, finalZoneId);
1294+
}
12711295
}
12721296

12731297
public static class PushDownAndCombineFilters extends OptimizerRule<Filter> {

0 commit comments

Comments
 (0)