Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2ffa01f
Full Text Functions support for Lookup Join
julian-elastic Oct 7, 2025
b139388
Update docs/changelog/136104.yaml
julian-elastic Oct 7, 2025
f018cac
Merge branch 'main' into rightFTF
julian-elastic Oct 10, 2025
3095216
Add new UTs, fix failing UTs
julian-elastic Oct 10, 2025
124f2fa
Bugfix, add UTs for all FTFs
julian-elastic Oct 10, 2025
4d524e2
Fix failing UT
julian-elastic Oct 10, 2025
65351c7
Merge branch 'main' into rightFTF
julian-elastic Oct 10, 2025
965d801
Minor fixes
julian-elastic Oct 10, 2025
b467ea8
Bugfix
julian-elastic Oct 10, 2025
868cca1
Merge branch 'main' into rightFTF
julian-elastic Oct 13, 2025
a1c0989
Perf Improvements
julian-elastic Oct 13, 2025
c69f5bf
Merge branch 'main' into rightFTF
julian-elastic Oct 13, 2025
4d4a049
Address code review comments
julian-elastic Oct 16, 2025
49296aa
Merge branch 'main' into rightFTF
julian-elastic Oct 16, 2025
895b948
Add more UTs
julian-elastic Oct 16, 2025
6917da2
Fix failing UT
julian-elastic Oct 16, 2025
7ba0ed1
Add a new transport version
julian-elastic Oct 16, 2025
e7d3751
Merge branch 'main' into rightFTF
julian-elastic Oct 16, 2025
b2f44e4
Address code review comments
julian-elastic Oct 17, 2025
8bca38a
Allow for Mutable Analyzer Context for testing purposes
julian-elastic Oct 20, 2025
a9b1ceb
Fix transport version
julian-elastic Oct 20, 2025
b8254c1
Merge branch 'main' into rightFTF
julian-elastic Oct 20, 2025
5b99f18
Fix failing UT
julian-elastic Oct 20, 2025
45dbf66
Merge branch 'main' into rightFTF
julian-elastic Oct 23, 2025
520fc04
Merge branch 'main' into rightFTF
julian-elastic Oct 23, 2025
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog/136104.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 136104
summary: Add support for Full Text Functions and Lucene pushable conditions on fields from the Lookup Index for Lookup Join
area: ES|QL
type: enhancement
issues: [ ]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
9201000
2 changes: 1 addition & 1 deletion server/src/main/resources/transport/upper_bounds/9.3.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
inference_cached_tokens,9200000
esql_lookup_join_full_text_function,9201000
Original file line number Diff line number Diff line change
Expand Up @@ -861,11 +861,22 @@ private Map<String, Object> lookupExplosion(
}
}
if (lookupEntries != lookupEntriesToKeep) {
// add a filter to reduce the number of matches
// we add both a Lucene pushable filter and a non-pushable filter
// this is to make sure that even if there are non-pushable filters the pushable filters is still applied
query.append(" | WHERE ABS(filter_key) > -1 AND filter_key < ").append(lookupEntriesToKeep);

boolean applyAsExpressionJoinFilter = expressionBasedJoin && randomBoolean();
// we randomly add the filter after the join or as part of the join
// in both cases we should have the same amount of results
if (applyAsExpressionJoinFilter == false) {
// add a filter after the join to reduce the number of matches
// we add both a Lucene pushable filter and a non-pushable filter
// this is to make sure that even if there are non-pushable filters the pushable filters is still applied
query.append(" | WHERE ABS(filter_key) > -1 AND filter_key < ").append(lookupEntriesToKeep);
} else {
// apply the filter as part of the join
// then we filter out the rows that do not match the filter after
// so the number of rows is the same as in the field based join case
// and can get the same number of rows for verification purposes
query.append(" AND filter_key < ").append(lookupEntriesToKeep);
query.append(" | WHERE filter_key IS NOT NULL ");
}
}
query.append(" | STATS COUNT(location) | LIMIT 100\"}");
return responseAsMap(query(query.toString(), null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ private void testLookupJoinFieldLevelSecurityHelper(boolean useExpressionJoin) t
ResponseException error = expectThrows(ResponseException.class, () -> runESQLCommand("fls_user4_1", query));
assertThat(error.getResponse().getStatusLine().getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST));
if (useExpressionJoin) {
assertThat(error.getMessage(), containsString("Unsupported join filter expression:value_left == value"));
assertThat(error.getMessage(), containsString("Unknown column [value], did you mean [value_left]?"));
} else {
assertThat(error.getMessage(), containsString("Unknown column [value] in right side of join"));
}
Expand Down Expand Up @@ -902,7 +902,7 @@ private void testLookupJoinFieldLevelSecurityOnAliasHelper(boolean useExpression
ResponseException error = expectThrows(ResponseException.class, () -> runESQLCommand("fls_user4_1_alias", query));
assertThat(error.getResponse().getStatusLine().getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST));
if (useExpressionJoin) {
assertThat(error.getMessage(), containsString("Unsupported join filter expression:value_left == value"));
assertThat(error.getMessage(), containsString("Unknown column [value], did you mean [value_left]?"));
} else {
assertThat(error.getMessage(), containsString("Unknown column [value] in right side of join"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,9 @@ public class CsvTestsDataLoader {
private static final TestDataset DATE_NANOS_UNION_TYPES = new TestDataset("date_nanos_union_types");
private static final TestDataset COUNTRIES_BBOX = new TestDataset("countries_bbox");
private static final TestDataset COUNTRIES_BBOX_WEB = new TestDataset("countries_bbox_web");
private static final TestDataset AIRPORT_CITY_BOUNDARIES = new TestDataset("airport_city_boundaries");
private static final TestDataset AIRPORT_CITY_BOUNDARIES = new TestDataset("airport_city_boundaries").withSetting(
"lookup-settings.json"
);
private static final TestDataset CARTESIAN_MULTIPOLYGONS = new TestDataset("cartesian_multipolygons");
private static final TestDataset CARTESIAN_MULTIPOLYGONS_NO_DOC_VALUES = new TestDataset("cartesian_multipolygons_no_doc_values")
.withData("cartesian_multipolygons.csv");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContent;
import org.elasticsearch.xpack.esql.action.EsqlQueryResponse;
import org.elasticsearch.xpack.esql.analysis.AnalyzerContext;
import org.elasticsearch.xpack.esql.analysis.AnalyzerSettings;
import org.elasticsearch.xpack.esql.analysis.EnrichResolution;
import org.elasticsearch.xpack.esql.analysis.MutableAnalyzerContext;
import org.elasticsearch.xpack.esql.analysis.Verifier;
import org.elasticsearch.xpack.esql.core.expression.Alias;
import org.elasticsearch.xpack.esql.core.expression.Attribute;
Expand Down Expand Up @@ -449,7 +449,7 @@ public static TransportVersion randomMinimumVersion() {
}

// TODO: make this even simpler, remove the enrichResolution for tests that do not require it (most tests)
public static AnalyzerContext testAnalyzerContext(
public static MutableAnalyzerContext testAnalyzerContext(
Configuration configuration,
EsqlFunctionRegistry functionRegistry,
Map<IndexPattern, IndexResolution> indexResolutions,
Expand All @@ -462,15 +462,15 @@ public static AnalyzerContext testAnalyzerContext(
/**
* Analyzer context for a random (but compatible) minimum transport version.
*/
public static AnalyzerContext testAnalyzerContext(
public static MutableAnalyzerContext testAnalyzerContext(
Configuration configuration,
EsqlFunctionRegistry functionRegistry,
Map<IndexPattern, IndexResolution> indexResolutions,
Map<String, IndexResolution> lookupResolution,
EnrichResolution enrichResolution,
InferenceResolution inferenceResolution
) {
return new AnalyzerContext(
return new MutableAnalyzerContext(
configuration,
functionRegistry,
indexResolutions,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.esql.analysis;

import org.elasticsearch.TransportVersion;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.TransportVersionUtils;
import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry;
import org.elasticsearch.xpack.esql.index.IndexResolution;
import org.elasticsearch.xpack.esql.inference.InferenceResolution;
import org.elasticsearch.xpack.esql.plan.IndexPattern;
import org.elasticsearch.xpack.esql.session.Configuration;

import java.util.Map;

/**
* A mutable version of AnalyzerContext that allows temporarily changing the transport version.
* This is useful for testing scenarios where different transport versions need to be tested.
*/
public class MutableAnalyzerContext extends AnalyzerContext {
private TransportVersion currentVersion;

public MutableAnalyzerContext(
Configuration configuration,
EsqlFunctionRegistry functionRegistry,
Map<IndexPattern, IndexResolution> indexResolution,
Map<String, IndexResolution> lookupResolution,
EnrichResolution enrichResolution,
InferenceResolution inferenceResolution,
TransportVersion minimumVersion
) {
super(configuration, functionRegistry, indexResolution, lookupResolution, enrichResolution, inferenceResolution, minimumVersion);
this.currentVersion = minimumVersion;
}

@Override
public TransportVersion minimumVersion() {
return currentVersion;
}

/**
* Temporarily set the transport version to a random version between the passed-in version and the latest,
* and return an AutoCloseable to restore it.
* Usage:
* try (var restore = context.setTemporaryTransportVersionOnOrAfter(minVersion)) {...}
*/
public RestoreTransportVersion setTemporaryTransportVersionOnOrAfter(TransportVersion minVersion) {
TransportVersion oldVersion = this.currentVersion;
// Set to a random version between minVersion and current
this.currentVersion = TransportVersionUtils.randomVersionBetween(ESTestCase.random(), minVersion, TransportVersion.current());
return new RestoreTransportVersion(oldVersion);
}

/**
* AutoCloseable that restores the original transport version when closed.
*/
public class RestoreTransportVersion implements AutoCloseable {
private final TransportVersion originalVersion;

private RestoreTransportVersion(TransportVersion originalVersion) {
this.originalVersion = originalVersion;
}

@Override
public void close() {
MutableAnalyzerContext.this.currentVersion = originalVersion;
}
}
}
Loading