Skip to content

Commit 009a81c

Browse files
Integrate with ExpressionQuery, fix merge errors
1 parent 7d1920b commit 009a81c

File tree

5 files changed

+392
-1201
lines changed

5 files changed

+392
-1201
lines changed

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ static TransportVersion def(int id) {
330330
public static final TransportVersion ESQL_SERIALIZE_TIMESERIES_FIELD_TYPE = def(9_114_0_00);
331331
public static final TransportVersion ML_INFERENCE_IBM_WATSONX_COMPLETION_ADDED = def(9_115_0_00);
332332
public static final TransportVersion ESQL_FIXED_INDEX_LIKE = def(9_116_0_00);
333+
public static final TransportVersion ESQL_RLIKE_LIST = def(9_117_0_00);
334+
333335
/*
334336
* STOP! READ THIS FIRST! No, really,
335337
* ____ _____ ___ ____ _ ____ _____ _ ____ _____ _ _ ___ ____ _____ ___ ____ ____ _____ _

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,7 @@ public enum Cap {
12281228
/**
12291229
* Support for the RLIKE operator with a list of regexes.
12301230
*/
1231-
RLIKE_WITH_LIST_OF_PATTERNS
1231+
RLIKE_WITH_LIST_OF_PATTERNS,
12321232

12331233
/**
12341234
* FUSE command

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/RLikeList.java

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,31 @@
77

88
package org.elasticsearch.xpack.esql.expression.function.scalar.string.regex;
99

10+
import org.apache.lucene.search.MultiTermQuery;
11+
import org.apache.lucene.util.automaton.Automaton;
12+
import org.apache.lucene.util.automaton.CharacterRunAutomaton;
13+
import org.elasticsearch.TransportVersion;
14+
import org.elasticsearch.TransportVersions;
1015
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1116
import org.elasticsearch.common.io.stream.StreamInput;
1217
import org.elasticsearch.common.io.stream.StreamOutput;
18+
import org.elasticsearch.index.mapper.MappedFieldType;
19+
import org.elasticsearch.index.query.SearchExecutionContext;
1320
import org.elasticsearch.xpack.esql.core.expression.Expression;
1421
import org.elasticsearch.xpack.esql.core.expression.FieldAttribute;
1522
import org.elasticsearch.xpack.esql.core.expression.predicate.regex.RLikePattern;
1623
import org.elasticsearch.xpack.esql.core.expression.predicate.regex.RLikePatternList;
17-
import org.elasticsearch.xpack.esql.core.querydsl.query.EsqlAutomatonQuery;
1824
import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
1925
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
2026
import org.elasticsearch.xpack.esql.core.tree.Source;
2127
import org.elasticsearch.xpack.esql.expression.function.Param;
28+
import org.elasticsearch.xpack.esql.io.stream.ExpressionQuery;
2229
import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
2330
import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.LucenePushdownPredicates;
2431
import org.elasticsearch.xpack.esql.planner.TranslatorHandler;
2532

2633
import java.io.IOException;
34+
import java.util.function.Supplier;
2735
import java.util.stream.Collectors;
2836

2937
public class RLikeList extends RegexMatch<RLikePatternList> {
@@ -33,6 +41,30 @@ public class RLikeList extends RegexMatch<RLikePatternList> {
3341
RLikeList::new
3442
);
3543

44+
Supplier<Automaton> automatonSupplier = new Supplier<>() {
45+
Automaton cached;
46+
47+
@Override
48+
public Automaton get() {
49+
if (cached == null) {
50+
cached = pattern().createAutomaton(caseInsensitive());
51+
}
52+
return cached;
53+
}
54+
};
55+
56+
Supplier<CharacterRunAutomaton> characterRunAutomatonSupplier = new Supplier<>() {
57+
CharacterRunAutomaton cached;
58+
59+
@Override
60+
public CharacterRunAutomaton get() {
61+
if (cached == null) {
62+
cached = new CharacterRunAutomaton(automatonSupplier.get());
63+
}
64+
return cached;
65+
}
66+
};
67+
3668
/**
3769
* The documentation for this function is in RLike, and shown to the users as `RLIKE` in the docs.
3870
*/
@@ -75,39 +107,62 @@ public String getWriteableName() {
75107
return ENTRY.name;
76108
}
77109

110+
@Override
111+
protected NodeInfo<RLikeList> info() {
112+
return NodeInfo.create(this, RLikeList::new, field(), pattern(), caseInsensitive());
113+
}
114+
78115
@Override
79116
protected RLikeList replaceChild(Expression newChild) {
80117
return new RLikeList(source(), newChild, pattern(), caseInsensitive());
81118
}
82119

120+
/**
121+
* Returns {@link Translatable#YES} if the field is pushable, otherwise {@link Translatable#NO}.
122+
*/
83123
@Override
84124
public Translatable translatable(LucenePushdownPredicates pushdownPredicates) {
85-
return pushdownPredicates.isPushableAttribute(field()) ? Translatable.YES : Translatable.NO;
125+
if (supportsPushdown(pushdownPredicates.minTransportVersion())) {
126+
return pushdownPredicates.isPushableAttribute(field()) ? Translatable.YES : Translatable.NO;
127+
} else {
128+
// The ExpressionQuery we use isn't serializable to all nodes in the cluster.
129+
return Translatable.NO;
130+
}
86131
}
87132

88-
/**
89-
* Returns a {@link Query} that matches the field against the provided patterns.
90-
* For now, we only support a single pattern in the list for pushdown.
91-
*/
92133
@Override
93134
public Query asQuery(LucenePushdownPredicates pushdownPredicates, TranslatorHandler handler) {
94135
var field = field();
95136
LucenePushdownPredicates.checkIsPushableAttribute(field);
96137
return translateField(handler.nameOf(field instanceof FieldAttribute fa ? fa.exactAttribute() : field));
97138
}
98139

99-
private Query translateField(String targetFieldName) {
100-
return new EsqlAutomatonQuery(source(), targetFieldName, pattern().createAutomaton(caseInsensitive()), getAutomatonDescription());
140+
private boolean supportsPushdown(TransportVersion version) {
141+
return version == null || version.onOrAfter(TransportVersions.ESQL_RLIKE_LIST);
101142
}
102143

103144
@Override
104-
protected NodeInfo<? extends Expression> info() {
105-
return NodeInfo.create(this, RLikeList::new, field(), pattern(), caseInsensitive());
145+
public org.apache.lucene.search.Query asLuceneQuery(
146+
MappedFieldType fieldType,
147+
MultiTermQuery.RewriteMethod constantScoreRewrite,
148+
SearchExecutionContext context
149+
) {
150+
return fieldType.automatonQuery(
151+
automatonSupplier,
152+
characterRunAutomatonSupplier,
153+
constantScoreRewrite,
154+
context,
155+
getLuceneQueryDescription()
156+
);
106157
}
107158

108-
private String getAutomatonDescription() {
159+
private String getLuceneQueryDescription() {
109160
// we use the information used to create the automaton to describe the query here
110161
String patternDesc = pattern().patternList().stream().map(RLikePattern::pattern).collect(Collectors.joining("\", \""));
111162
return "RLIKE(\"" + patternDesc + "\"), caseInsensitive=" + caseInsensitive();
112163
}
164+
165+
private Query translateField(String targetFieldName) {
166+
return new ExpressionQuery(source(), targetFieldName, this);
167+
}
113168
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp

Lines changed: 1 addition & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)