Skip to content

Commit 611902f

Browse files
committed
ESQL: Pass FoldContext to Translatable expressions
1 parent f563012 commit 611902f

File tree

37 files changed

+121
-88
lines changed

37 files changed

+121
-88
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/capabilities/TranslationAware.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package org.elasticsearch.xpack.esql.capabilities;
99

1010
import org.elasticsearch.xpack.esql.core.expression.Expression;
11+
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
1112
import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
1213
import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.LucenePushdownPredicates;
1314
import org.elasticsearch.xpack.esql.planner.TranslatorHandler;
@@ -27,11 +28,11 @@ public interface TranslationAware {
2728
* If during translation a child needs to be translated first, the handler needs to be used even if the child implements this
2829
* interface as well. This is to ensure that the child is wrapped in a SingleValueQuery if necessary.
2930
* <p>So use this:</p>
30-
* <p>{@code Query childQuery = handler.asQuery(child);}</p>
31+
* <p>{@code Query childQuery = handler.asQuery(child, foldContext);}</p>
3132
* <p>and <b>not</b> this:</p>
32-
* <p>{@code Query childQuery = child.asQuery(handler);}</p>
33+
* <p>{@code Query childQuery = child.asQuery(handler, foldContext);}</p>
3334
*/
34-
Query asQuery(TranslatorHandler handler);
35+
Query asQuery(TranslatorHandler handler, FoldContext foldContext);
3536

3637
/**
3738
* Subinterface for expressions that can only process single values (and null out on MVs).

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/execution/PlanExecutor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public void esql(
9494
});
9595
// Wrap it in a listener so that if we have any exceptions during execution, the listener picks it up
9696
// and all the metrics are properly updated
97-
ActionListener.run(executeListener, l -> session.execute(request, executionInfo, planRunner, l));
97+
ActionListener.run(executeListener, l -> session.execute(request, foldContext, executionInfo, planRunner, l));
9898
}
9999

100100
public IndexResolver indexResolver() {

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ public Expression query() {
108108
*
109109
* @return query expression as an object
110110
*/
111-
public Object queryAsObject() {
112-
Object queryAsObject = query().fold(FoldContext.small() /* TODO remove me */);
111+
public Object queryAsObject(FoldContext foldContext) {
112+
Object queryAsObject = query().fold(foldContext);
113113
return BytesRefs.toString(queryAsObject);
114114
}
115115

@@ -148,15 +148,15 @@ public boolean translatable(LucenePushdownPredicates pushdownPredicates) {
148148
}
149149

150150
@Override
151-
public Query asQuery(TranslatorHandler handler) {
152-
return queryBuilder != null ? new TranslationAwareExpressionQuery(source(), queryBuilder) : translate(handler);
151+
public Query asQuery(TranslatorHandler handler, FoldContext foldContext) {
152+
return queryBuilder != null ? new TranslationAwareExpressionQuery(source(), queryBuilder) : translate(handler, foldContext);
153153
}
154154

155155
public QueryBuilder queryBuilder() {
156156
return queryBuilder;
157157
}
158158

159-
protected abstract Query translate(TranslatorHandler handler);
159+
protected abstract Query translate(TranslatorHandler handler, FoldContext foldContext);
160160

161161
public abstract Expression replaceQueryBuilder(QueryBuilder queryBuilder);
162162

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Kql.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.common.io.stream.StreamOutput;
1414
import org.elasticsearch.index.query.QueryBuilder;
1515
import org.elasticsearch.xpack.esql.core.expression.Expression;
16+
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
1617
import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
1718
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
1819
import org.elasticsearch.xpack.esql.core.tree.Source;
@@ -89,8 +90,8 @@ protected NodeInfo<? extends Expression> info() {
8990
}
9091

9192
@Override
92-
protected Query translate(TranslatorHandler handler) {
93-
return new KqlQuery(source(), Objects.toString(queryAsObject()));
93+
protected Query translate(TranslatorHandler handler, FoldContext foldContext) {
94+
return new KqlQuery(source(), Objects.toString(queryAsObject(foldContext)));
9495
}
9596

9697
@Override

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,8 +452,8 @@ public BiConsumer<LogicalPlan, Failures> postAnalysisPlanVerification() {
452452
}
453453

454454
@Override
455-
public Object queryAsObject() {
456-
Object queryAsObject = query().fold(FoldContext.small() /* TODO remove me */);
455+
public Object queryAsObject(FoldContext foldContext) {
456+
Object queryAsObject = query().fold(foldContext);
457457

458458
// Convert BytesRef to string for string-based values
459459
if (queryAsObject instanceof BytesRef bytesRef) {
@@ -478,7 +478,7 @@ public Object queryAsObject() {
478478
}
479479

480480
@Override
481-
protected Query translate(TranslatorHandler handler) {
481+
protected Query translate(TranslatorHandler handler, FoldContext foldContext) {
482482
var fieldAttribute = fieldAsFieldAttribute();
483483
Check.notNull(fieldAttribute, "Match must have a field attribute as the first argument");
484484
String fieldName = fieldAttribute.name();
@@ -487,7 +487,7 @@ protected Query translate(TranslatorHandler handler) {
487487
fieldName = multiTypeEsField.getName();
488488
}
489489
// Make query lenient so mixed field types can be queried when a field type is incompatible with the value provided
490-
return new MatchQuery(source(), fieldName, queryAsObject(), matchQueryOptions());
490+
return new MatchQuery(source(), fieldName, queryAsObject(foldContext), matchQueryOptions());
491491
}
492492

493493
private FieldAttribute fieldAsFieldAttribute() {

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryBuilderResolver.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.index.query.QueryBuilder;
1313
import org.elasticsearch.index.query.QueryRewriteContext;
1414
import org.elasticsearch.index.query.Rewriteable;
15+
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
1516
import org.elasticsearch.xpack.esql.core.util.Holder;
1617
import org.elasticsearch.xpack.esql.plan.logical.EsRelation;
1718
import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;
@@ -26,22 +27,27 @@
2627
/**
2728
* Some {@link FullTextFunction} implementations such as {@link org.elasticsearch.xpack.esql.expression.function.fulltext.Match}
2829
* will be translated to a {@link QueryBuilder} that require a rewrite phase on the coordinator.
29-
* {@link QueryBuilderResolver#resolveQueryBuilders(LogicalPlan, TransportActionServices, ActionListener)} will rewrite the plan by
30+
* {@link QueryBuilderResolver#resolveQueryBuilders(LogicalPlan, FoldContext, TransportActionServices, ActionListener)} will rewrite the plan by
3031
* replacing {@link FullTextFunction} expression with new ones that hold rewritten {@link QueryBuilder}s.
3132
*/
3233
public final class QueryBuilderResolver {
3334

3435
private QueryBuilderResolver() {}
3536

36-
public static void resolveQueryBuilders(LogicalPlan plan, TransportActionServices services, ActionListener<LogicalPlan> listener) {
37+
public static void resolveQueryBuilders(
38+
LogicalPlan plan,
39+
FoldContext foldContext,
40+
TransportActionServices services,
41+
ActionListener<LogicalPlan> listener
42+
) {
3743
var hasFullTextFunctions = plan.anyMatch(p -> {
3844
Holder<Boolean> hasFullTextFunction = new Holder<>(false);
3945
p.forEachExpression(FullTextFunction.class, unused -> hasFullTextFunction.set(true));
4046
return hasFullTextFunction.get();
4147
});
4248
if (hasFullTextFunctions) {
4349
Rewriteable.rewriteAndFetch(
44-
new FullTextFunctionsRewritable(plan),
50+
new FullTextFunctionsRewritable(plan, foldContext),
4551
queryRewriteContext(services, indexNames(plan)),
4652
listener.delegateFailureAndWrap((l, r) -> l.onResponse(r.plan))
4753
);
@@ -69,14 +75,16 @@ private static Set<String> indexNames(LogicalPlan plan) {
6975
return indexNames;
7076
}
7177

72-
private record FullTextFunctionsRewritable(LogicalPlan plan) implements Rewriteable<QueryBuilderResolver.FullTextFunctionsRewritable> {
78+
private record FullTextFunctionsRewritable(LogicalPlan plan, FoldContext foldContext)
79+
implements
80+
Rewriteable<QueryBuilderResolver.FullTextFunctionsRewritable> {
7381
@Override
7482
public FullTextFunctionsRewritable rewrite(QueryRewriteContext ctx) throws IOException {
7583
Holder<IOException> exceptionHolder = new Holder<>();
7684
Holder<Boolean> updated = new Holder<>(false);
7785
LogicalPlan newPlan = plan.transformExpressionsDown(FullTextFunction.class, f -> {
7886
QueryBuilder builder = f.queryBuilder(), initial = builder;
79-
builder = builder == null ? f.asQuery(TranslatorHandler.TRANSLATOR_HANDLER).asBuilder() : builder;
87+
builder = builder == null ? f.asQuery(TranslatorHandler.TRANSLATOR_HANDLER, foldContext).asBuilder() : builder;
8088
try {
8189
builder = builder.rewrite(ctx);
8290
} catch (IOException e) {
@@ -89,7 +97,7 @@ public FullTextFunctionsRewritable rewrite(QueryRewriteContext ctx) throws IOExc
8997
if (exceptionHolder.get() != null) {
9098
throw exceptionHolder.get();
9199
}
92-
return updated.get() ? new FullTextFunctionsRewritable(newPlan) : this;
100+
return updated.get() ? new FullTextFunctionsRewritable(newPlan, foldContext) : this;
93101
}
94102
}
95103
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryString.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.common.io.stream.StreamOutput;
1414
import org.elasticsearch.index.query.QueryBuilder;
1515
import org.elasticsearch.xpack.esql.core.expression.Expression;
16+
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
1617
import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
1718
import org.elasticsearch.xpack.esql.core.querydsl.query.QueryStringQuery;
1819
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
@@ -101,8 +102,8 @@ protected NodeInfo<? extends Expression> info() {
101102
}
102103

103104
@Override
104-
protected Query translate(TranslatorHandler handler) {
105-
return new QueryStringQuery(source(), Objects.toString(queryAsObject()), Map.of(), Map.of());
105+
protected Query translate(TranslatorHandler handler, FoldContext foldContext) {
106+
return new QueryStringQuery(source(), Objects.toString(queryAsObject(foldContext)), Map.of(), Map.of());
106107
}
107108

108109
@Override

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Term.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.elasticsearch.xpack.esql.common.Failures;
1818
import org.elasticsearch.xpack.esql.core.expression.Expression;
1919
import org.elasticsearch.xpack.esql.core.expression.FieldAttribute;
20+
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
2021
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
2122
import org.elasticsearch.xpack.esql.core.querydsl.query.Query;
2223
import org.elasticsearch.xpack.esql.core.querydsl.query.TermQuery;
@@ -140,8 +141,8 @@ protected TypeResolutions.ParamOrdinal queryParamOrdinal() {
140141
}
141142

142143
@Override
143-
protected Query translate(TranslatorHandler handler) {
144-
return new TermQuery(source(), ((FieldAttribute) field()).name(), queryAsObject());
144+
protected Query translate(TranslatorHandler handler, FoldContext foldContext) {
145+
return new TermQuery(source(), ((FieldAttribute) field()).name(), queryAsObject(foldContext));
145146
}
146147

147148
@Override

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ip/CIDRMatch.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,12 @@ public boolean translatable(LucenePushdownPredicates pushdownPredicates) {
184184
}
185185

186186
@Override
187-
public Query asQuery(TranslatorHandler handler) {
187+
public Query asQuery(TranslatorHandler handler, FoldContext foldContext) {
188188
var fa = LucenePushdownPredicates.checkIsFieldAttribute(ipField);
189189
Check.isTrue(Expressions.foldable(matches), "Expected foldable matches, but got [{}]", matches);
190190

191191
String targetFieldName = handler.nameOf(fa.exactAttribute());
192-
Set<Object> set = new LinkedHashSet<>(Expressions.fold(FoldContext.small() /* TODO remove me */, matches));
192+
Set<Object> set = new LinkedHashSet<>(Expressions.fold(foldContext, matches));
193193

194194
return new TermsQuery(source(), targetFieldName, set);
195195
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialRelatesFunction.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,13 @@ public boolean translatable(LucenePushdownPredicates pushdownPredicates) {
183183
}
184184

185185
@Override
186-
public Query asQuery(TranslatorHandler handler) {
186+
public Query asQuery(TranslatorHandler handler, FoldContext foldContext) {
187187
if (left().foldable()) {
188188
checkSpatialRelatesFunction(left(), queryRelation());
189-
return translate(handler, right(), left());
189+
return translate(handler, foldContext, right(), left());
190190
} else {
191191
checkSpatialRelatesFunction(right(), queryRelation());
192-
return translate(handler, left(), right());
192+
return translate(handler, foldContext, left(), right());
193193
}
194194

195195
}
@@ -205,12 +205,17 @@ private static void checkSpatialRelatesFunction(Expression constantExpression, S
205205
);
206206
}
207207

208-
private Query translate(TranslatorHandler handler, Expression spatialExpression, Expression constantExpression) {
208+
private Query translate(
209+
TranslatorHandler handler,
210+
FoldContext foldContext,
211+
Expression spatialExpression,
212+
Expression constantExpression
213+
) {
209214
TypedAttribute attribute = LucenePushdownPredicates.checkIsPushableAttribute(spatialExpression);
210215
String name = handler.nameOf(attribute);
211216

212217
try {
213-
Geometry shape = SpatialRelatesUtils.makeGeometryFromLiteral(FoldContext.small() /* TODO remove me */, constantExpression);
218+
Geometry shape = SpatialRelatesUtils.makeGeometryFromLiteral(foldContext, constantExpression);
214219
return new SpatialRelatesQuery(source(), name, queryRelation(), shape, attribute.dataType());
215220
} catch (IllegalArgumentException e) {
216221
throw new QlIllegalArgumentException(e.getMessage(), e);

0 commit comments

Comments
 (0)