Skip to content
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
d777561
Add check that remote enrich stays on remote side
smalyshev Sep 4, 2025
a93438f
Merge branch 'main' into remote-enrich-check
smalyshev Sep 8, 2025
b6244e5
Make it more generic
smalyshev Sep 9, 2025
a787ae8
[CI] Auto commit changes from spotless
Sep 9, 2025
6d638be
Verifier refactor
smalyshev Sep 9, 2025
95ef823
Merge branch 'main' into remote-enrich-check
smalyshev Sep 9, 2025
2490f60
Merge branch 'main' into remote-enrich-check
smalyshev Sep 12, 2025
4e16026
Fix the fix for https://github.com/elastic/elasticsearch/issues/118531
smalyshev Sep 12, 2025
e3324c0
Merge branch 'main' into remote-enrich-check
smalyshev Sep 17, 2025
dd7dd79
Remove old hacks
smalyshev Sep 17, 2025
31df078
Replace remote Enrich hack with proper handling of remote Enrich
smalyshev Sep 17, 2025
8dde748
Don't stop for ANY enrich
smalyshev Sep 17, 2025
d053fe4
Add TopN handling
smalyshev Sep 18, 2025
9b185e8
Merge branch 'main' into entich-remote-unhack
smalyshev Sep 18, 2025
93c827d
Oops, forgot the file
smalyshev Sep 18, 2025
a78a2c8
fix multiple topNs
smalyshev Sep 18, 2025
ea421ca
fix tests
smalyshev Sep 18, 2025
e70043e
test fixes
smalyshev Sep 19, 2025
9edcd72
Ban Limit + MvExpand before remote Enrich
smalyshev Sep 19, 2025
7c6c9b1
Update docs/changelog/135051.yaml
smalyshev Sep 19, 2025
3f2e2e9
spotless
smalyshev Sep 19, 2025
3d909ce
Move check pre optimizer
smalyshev Sep 19, 2025
ddc5815
Merge branch 'remote-enrich-limit' into entich-remote-unhack
smalyshev Sep 19, 2025
587ae4c
fix tests
smalyshev Sep 19, 2025
f9686e5
[CI] Update transport version definitions
Sep 20, 2025
30146a1
test fixes
smalyshev Sep 22, 2025
8dc2101
[CI] Update transport version definitions
Sep 22, 2025
77acee7
Merge branch 'main' into entich-remote-unhack
smalyshev Sep 22, 2025
346d17f
Update x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/…
smalyshev Sep 22, 2025
54d3aec
fix merge
smalyshev Sep 22, 2025
3d51a5c
test fixes
smalyshev Sep 22, 2025
f2e9fde
spotless
smalyshev Sep 22, 2025
f762627
Fix tests
smalyshev Sep 22, 2025
9bbdb26
Cleanup
smalyshev Sep 22, 2025
10581b8
Fix test
smalyshev Sep 22, 2025
47694c4
[CI] Auto commit changes from spotless
Sep 23, 2025
0a7cc56
Add project handling
smalyshev Sep 23, 2025
3c6e699
[CI] Update transport version definitions
Sep 23, 2025
6eb2468
Add two topN test
smalyshev Sep 23, 2025
0c1ee72
Merge branch 'main' into entich-remote-unhack
smalyshev Sep 23, 2025
abc1a7d
Clean up plan/optimizer structure
smalyshev Sep 24, 2025
da237a2
Introduce CardinalityExpanding
smalyshev Sep 24, 2025
809e528
Switch to CardinalityPreserving
smalyshev Sep 24, 2025
605b0c8
Block multiple TopN handling as it's semantically unsound
smalyshev Sep 24, 2025
6b7838e
Remove todo
smalyshev Sep 24, 2025
810e795
[Build] Update checkstyle from 10.3 to 11.0.1
breskeby Sep 24, 2025
0ae16c2
Merge branch 'pr/135381' into entich-remote-unhack
smalyshev Sep 24, 2025
819760e
Remove exclusion
smalyshev Sep 24, 2025
7baa484
Merge branch 'main' into entich-remote-unhack
smalyshev Sep 24, 2025
1bd78e6
Add missing dependency verification
breskeby Sep 24, 2025
0b70d07
Merge branch 'pr/135381' into entich-remote-unhack
smalyshev Sep 24, 2025
ec179e1
[Build] update eclipse formatter used by spotless
breskeby Sep 24, 2025
e1e4f21
Merge branch 'pr/135382' into entich-remote-unhack
smalyshev Sep 24, 2025
62f72b1
spotless
smalyshev Sep 24, 2025
3ab2bf7
Merge branch 'main' into entich-remote-unhack
smalyshev Sep 25, 2025
15f9cbf
cleanup
smalyshev Sep 25, 2025
616021d
Cleanups
smalyshev Sep 25, 2025
255bce5
clean test
smalyshev Sep 25, 2025
c8a109b
moar tests
smalyshev Sep 25, 2025
7b28e9f
oops typo
smalyshev Sep 25, 2025
3af3540
Merge branch 'main' into entich-remote-unhack
smalyshev Sep 25, 2025
00bc8b7
Merge branch 'main' into entich-remote-unhack
smalyshev Oct 3, 2025
6df9352
Feedback, pass 1
smalyshev Oct 3, 2025
3f58415
More feedback
smalyshev Oct 3, 2025
8c0c305
Remove limit optimization - data node optimizer will take care of it
smalyshev Oct 3, 2025
2145a40
moar tests
smalyshev Oct 3, 2025
74c8a9d
avoid forbidden lore
smalyshev Oct 3, 2025
69c2225
More tests
smalyshev Oct 4, 2025
e9160a5
TopN tests
smalyshev Oct 6, 2025
9b40f1d
Merge branch 'main' into entich-remote-unhack
smalyshev Oct 6, 2025
4c052ec
fix test
smalyshev Oct 7, 2025
2c67a57
Refine CoordinatorOnly interface for rules
alex-spies Oct 7, 2025
File filter

Filter by extension

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/135051.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 135051
summary: Ban Limit + `MvExpand` before remote Enrich
area: ES|QL
type: enhancement
issues: []
2 changes: 1 addition & 1 deletion server/src/main/resources/transport/upper_bounds/8.18.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
initial_elasticsearch_8_18_6,8840008
initial_elasticsearch_8_18_8,8840010
2 changes: 1 addition & 1 deletion server/src/main/resources/transport/upper_bounds/8.19.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
initial_elasticsearch_8_19_3,8841067
initial_elasticsearch_8_19_5,8841069
2 changes: 1 addition & 1 deletion server/src/main/resources/transport/upper_bounds/9.0.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
initial_elasticsearch_9_0_6,9000015
initial_elasticsearch_9_0_8,9000017
2 changes: 1 addition & 1 deletion server/src/main/resources/transport/upper_bounds/9.1.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
initial_elasticsearch_9_1_4,9112007
initial_elasticsearch_9_1_5,9112008
2 changes: 1 addition & 1 deletion server/src/main/resources/transport/upper_bounds/9.2.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ml_inference_endpoint_cache,9157000
inference_results_map_with_cluster_alias,9166000
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import org.elasticsearch.core.Tuple;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.xpack.esql.VerificationException;
import org.elasticsearch.xpack.esql.plan.logical.Enrich;

Expand All @@ -27,6 +28,7 @@
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;

@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug")
public class CrossClusterEnrichIT extends AbstractEnrichBasedCrossClusterTestCase {

@Override
Expand Down Expand Up @@ -402,6 +404,33 @@ public void testTopNThenEnrichRemote() {
assertThat(executionInfo.clusterAliases(), equalTo(Set.of("", "c1", "c2")));
assertCCSExecutionInfoDetails(executionInfo);
}

// No renames, no KEEP - this is required to verify that ENRICH does not break sort with fields it overrides
query = """
FROM *:events,events
| eval ip= TO_STR(host)
| SORT timestamp, user, ip
| LIMIT 5
| ENRICH _remote:hosts
""";
try (EsqlQueryResponse resp = runQuery(query, requestIncludeMeta)) {
assertThat(
getValuesList(resp),
equalTo(
List.of(
List.of("192.168.1.2", 1L, "andres", "192.168.1.2", "Windows"),
List.of("192.168.1.3", 1L, "matthew", "192.168.1.3", "MacOS"),
Arrays.asList("192.168.1.25", 1L, "park", (String) null, (String) null),
List.of("192.168.1.5", 2L, "akio", "192.168.1.5", "Android"),
List.of("192.168.1.6", 2L, "sergio", "192.168.1.6", "iOS")
)
)
);
EsqlExecutionInfo executionInfo = resp.getExecutionInfo();
assertThat(executionInfo.includeCCSMetadata(), equalTo(responseExpectMeta));
assertThat(executionInfo.clusterAliases(), equalTo(Set.of("", "c1", "c2")));
assertCCSExecutionInfoDetails(executionInfo);
}
}

public void testLimitThenEnrichRemote() {
Expand Down Expand Up @@ -466,6 +495,19 @@ public void testEnrichCoordinatorThenEnrichRemote() {
assertThat(error.getMessage(), containsString("ENRICH with remote policy can't be executed after [ENRICH _COORDINATOR"));
}

public void testEnrichAfterMvExpandLimit() {
String query = String.format(Locale.ROOT, """
FROM *:events,events
| SORT timestamp
| LIMIT 2
| eval ip= TO_STR(host)
| MV_EXPAND host
| %s
""", enrichHosts(Enrich.Mode.REMOTE));
var error = expectThrows(VerificationException.class, () -> runQuery(query, randomBoolean()).close());
assertThat(error.getMessage(), containsString("MV_EXPAND after LIMIT is incompatible with remote ENRICH"));
}

private static void assertCCSExecutionInfoDetails(EsqlExecutionInfo executionInfo) {
assertThat(executionInfo.overallTook().millis(), greaterThanOrEqualTo(0L));
assertTrue(executionInfo.isCrossClusterSearch());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
* {@link org.elasticsearch.xpack.esql.stats.SearchStats} which provides access to metadata about the index.
*
* <p>NB: This class also reapplies all the rules from {@link LogicalPlanOptimizer#operators(boolean)}
* and {@link LogicalPlanOptimizer#cleanup()}
* and {@link LogicalPlanOptimizer#cleanup(boolean)}
*/
public class LocalLogicalPlanOptimizer extends ParameterizedRuleExecutor<LogicalPlan, LocalLogicalOptimizerContext> {

private final LogicalVerifier verifier = LogicalVerifier.INSTANCE;
private final LogicalVerifier verifier = LogicalVerifier.LOCAL_INSTANCE;

private static final List<Batch<LogicalPlan>> RULES = arrayAsArrayList(
new Batch<>(
Expand All @@ -53,7 +53,7 @@ public class LocalLogicalPlanOptimizer extends ParameterizedRuleExecutor<Logical
new ReplaceDateTruncBucketWithRoundTo()
),
localOperators(),
cleanup()
cleanup(true)
);

public LocalLogicalPlanOptimizer(LocalLogicalOptimizerContext localLogicalOptimizerContext) {
Expand Down Expand Up @@ -90,7 +90,7 @@ private static Batch<LogicalPlan> localOperators() {

public LogicalPlan localOptimize(LogicalPlan plan) {
LogicalPlan optimized = execute(plan);
Failures failures = verifier.verify(optimized, true, plan.output());
Failures failures = verifier.verify(optimized, plan.output());
if (failures.hasFailures()) {
throw new VerificationException(failures);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class LocalPhysicalPlanOptimizer extends ParameterizedRuleExecutor<Physic

private static final List<Batch<PhysicalPlan>> RULES = rules(true);

private final PhysicalVerifier verifier = PhysicalVerifier.INSTANCE;
private final PhysicalVerifier verifier = PhysicalVerifier.LOCAL_INSTANCE;

public LocalPhysicalPlanOptimizer(LocalPhysicalOptimizerContext context) {
super(context);
Expand All @@ -47,7 +47,7 @@ public PhysicalPlan localOptimize(PhysicalPlan plan) {
}

PhysicalPlan verify(PhysicalPlan optimizedPlan, List<Attribute> expectedOutputAttributes) {
Failures failures = verifier.verify(optimizedPlan, true, expectedOutputAttributes);
Failures failures = verifier.verify(optimizedPlan, expectedOutputAttributes);
if (failures.hasFailures()) {
throw new VerificationException(failures);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.elasticsearch.xpack.esql.optimizer.rules.logical.ConstantFolding;
import org.elasticsearch.xpack.esql.optimizer.rules.logical.ExtractAggregateCommonFilter;
import org.elasticsearch.xpack.esql.optimizer.rules.logical.FoldNull;
import org.elasticsearch.xpack.esql.optimizer.rules.logical.HoistRemoteEnrichLimit;
import org.elasticsearch.xpack.esql.optimizer.rules.logical.HoistRemoteEnrichTopN;
import org.elasticsearch.xpack.esql.optimizer.rules.logical.LiteralsOnTheRight;
import org.elasticsearch.xpack.esql.optimizer.rules.logical.PartiallyFoldCase;
import org.elasticsearch.xpack.esql.optimizer.rules.logical.PropagateEmptyRelation;
Expand Down Expand Up @@ -89,19 +91,19 @@
* time), combining expressions, dropping redundant clauses, and some normalization such as putting literals on the right whenever
* possible. These rules are run in a loop until none of the rules make any changes to the plan (there is also a safety shut off
* after many iterations, although hitting that is considered a bug)</li>
* <li>{@link LogicalPlanOptimizer#cleanup()} Which can replace sorts+limit with a TopN</li>
* <li>{@link LogicalPlanOptimizer#cleanup(boolean)} Which can replace sorts+limit with a TopN</li>
* </ul>
*
* <p>Note that the {@link LogicalPlanOptimizer#operators(boolean)} and {@link LogicalPlanOptimizer#cleanup()} steps are reapplied at the
* {@link LocalLogicalPlanOptimizer} layer.</p>
* <p>Note that the {@link LogicalPlanOptimizer#operators(boolean)} and {@link LogicalPlanOptimizer#cleanup(boolean)} steps are reapplied
* at the {@link LocalLogicalPlanOptimizer} layer.</p>
*/
public class LogicalPlanOptimizer extends ParameterizedRuleExecutor<LogicalPlan, LogicalOptimizerContext> {

private static final List<RuleExecutor.Batch<LogicalPlan>> RULES = List.of(
substitutions(),
operators(false),
new Batch<>("Skip Compute", new SkipQueryOnLimitZero()),
cleanup(),
cleanup(false),
new Batch<>("Set as Optimized", Limiter.ONCE, new SetAsOptimized())
);

Expand All @@ -114,7 +116,7 @@ public LogicalPlanOptimizer(LogicalOptimizerContext optimizerContext) {
public LogicalPlan optimize(LogicalPlan verified) {
var optimized = execute(verified);

Failures failures = verifier.verify(optimized, false, verified.output());
Failures failures = verifier.verify(optimized, verified.output());
if (failures.hasFailures()) {
throw new VerificationException(failures);
}
Expand Down Expand Up @@ -165,6 +167,7 @@ protected static Batch<LogicalPlan> substitutions() {
protected static Batch<LogicalPlan> operators(boolean local) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Hey, we have 3 mechanisms now that convey whether a rule should be run on the coordinator, the data node, or behave differently depending on global/local: this boolean parameter, the CoordinatorOnly interface, and the method LocalLogicalPlanOptimizer#localOperators which does some special filtering on its own.

I like the CoordinatorOnly interface, but'd prefer we settle on 1 mechanism if possible.

Maybe rather than a CoordinatorOnly interface, we should have a DifferentOnDataNode interface (yes, the name is horrible, I didn't have much time to think :D ) with a method localVersion (or so) that either gives the data node version of the optimizer rule (applies to CombineProjections and PropagateEmptyRelation) or null (applies to all rules marked CoordinatorOnly in this PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made LocalLogicalPlanOptimizer#localOperators respect the CoordinatorOnly marker, so that's the same thing now, except for rule that work on both sides, but differently (PropagateEmptyRelation). I agree that it could be refined further but not sure the best way yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't mind, I'd like to push a small refactoring that consolidates the 3 methods for adjusting rules to the local optimizer into one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed 2c67a57. Feel free to revert if you don't like it, though :)

return new Batch<>(
"Operator Optimization",
new HoistRemoteEnrichLimit(local),
new CombineProjections(local),
new CombineEvals(),
new PruneEmptyPlans(),
Expand Down Expand Up @@ -209,7 +212,13 @@ protected static Batch<LogicalPlan> operators(boolean local) {
);
}

protected static Batch<LogicalPlan> cleanup() {
return new Batch<>("Clean Up", new ReplaceLimitAndSortAsTopN(), new ReplaceRowAsLocalRelation(), new PropgateUnmappedFields());
protected static Batch<LogicalPlan> cleanup(boolean local) {
return new Batch<>(
"Clean Up",
new ReplaceLimitAndSortAsTopN(),
new HoistRemoteEnrichTopN(local),
new ReplaceRowAsLocalRelation(),
new PropgateUnmappedFields()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,18 @@
import org.elasticsearch.xpack.esql.capabilities.PostOptimizationVerificationAware;
import org.elasticsearch.xpack.esql.common.Failures;
import org.elasticsearch.xpack.esql.optimizer.rules.PlanConsistencyChecker;
import org.elasticsearch.xpack.esql.plan.logical.Enrich;
import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;

public final class LogicalVerifier extends PostOptimizationPhasePlanVerifier<LogicalPlan> {
public static final LogicalVerifier LOCAL_INSTANCE = new LogicalVerifier(true);
public static final LogicalVerifier INSTANCE = new LogicalVerifier(false);

public static final LogicalVerifier INSTANCE = new LogicalVerifier();

private LogicalVerifier() {}

@Override
boolean skipVerification(LogicalPlan optimizedPlan, boolean skipRemoteEnrichVerification) {
if (skipRemoteEnrichVerification) {
// AwaitsFix https://github.com/elastic/elasticsearch/issues/118531
var enriches = optimizedPlan.collectFirstChildren(Enrich.class::isInstance);
if (enriches.isEmpty() == false && ((Enrich) enriches.get(0)).mode() == Enrich.Mode.REMOTE) {
return true;
}
}
return false;
private LogicalVerifier(boolean isLocal) {
super(isLocal);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public PhysicalPlan optimize(PhysicalPlan plan) {
}

PhysicalPlan verify(PhysicalPlan optimizedPlan, List<Attribute> expectedOutputAttributes) {
Failures failures = verifier.verify(optimizedPlan, false, expectedOutputAttributes);
Failures failures = verifier.verify(optimizedPlan, expectedOutputAttributes);
if (failures.hasFailures()) {
throw new VerificationException(failures);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,19 @@
import org.elasticsearch.xpack.esql.core.expression.Attribute;
import org.elasticsearch.xpack.esql.core.expression.Expressions;
import org.elasticsearch.xpack.esql.optimizer.rules.PlanConsistencyChecker;
import org.elasticsearch.xpack.esql.plan.logical.Enrich;
import org.elasticsearch.xpack.esql.plan.physical.EnrichExec;
import org.elasticsearch.xpack.esql.plan.logical.ExecutesOn;
import org.elasticsearch.xpack.esql.plan.physical.FieldExtractExec;
import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;

import static org.elasticsearch.xpack.esql.common.Failure.fail;

/** Physical plan verifier. */
public final class PhysicalVerifier extends PostOptimizationPhasePlanVerifier<PhysicalPlan> {
public static final PhysicalVerifier LOCAL_INSTANCE = new PhysicalVerifier(true);
public static final PhysicalVerifier INSTANCE = new PhysicalVerifier(false);

public static final PhysicalVerifier INSTANCE = new PhysicalVerifier();

private PhysicalVerifier() {}

@Override
boolean skipVerification(PhysicalPlan optimizedPlan, boolean skipRemoteEnrichVerification) {
if (skipRemoteEnrichVerification) {
// AwaitsFix https://github.com/elastic/elasticsearch/issues/118531
var enriches = optimizedPlan.collectFirstChildren(EnrichExec.class::isInstance);
if (enriches.isEmpty() == false && ((EnrichExec) enriches.get(0)).mode() == Enrich.Mode.REMOTE) {
return true;
}
}
return false;
private PhysicalVerifier(boolean isLocal) {
super(isLocal);
}

@Override
Expand All @@ -54,6 +43,19 @@ void checkPlanConsistency(PhysicalPlan optimizedPlan, Failures failures, Failure
);
}
}

// This check applies only for general physical plans (isLocal == false)
if (isLocal == false && p instanceof ExecutesOn ex && ex.executesOn() == ExecutesOn.ExecuteLocation.REMOTE) {
failures.add(
fail(
p,
"Physical plan contains remote executing operation [{}] in local part. "
+ "This usually means this command is incompatible with some of the preceding commands.",
p.nodeName()
)
);
}

PlanConsistencyChecker.checkPlan(p, depFailures);

if (failures.hasFailures() == false) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,17 @@
*/
public abstract class PostOptimizationPhasePlanVerifier<P extends QueryPlan<P>> {

// Are we verifying the global plan (coordinator) or a local plan (data node)?
protected final boolean isLocal;

protected PostOptimizationPhasePlanVerifier(boolean isLocal) {
this.isLocal = isLocal;
}

/** Verifies the optimized plan */
public Failures verify(P optimizedPlan, boolean skipRemoteEnrichVerification, List<Attribute> expectedOutputAttributes) {
public Failures verify(P optimizedPlan, List<Attribute> expectedOutputAttributes) {
Failures failures = new Failures();
Failures depFailures = new Failures();
if (skipVerification(optimizedPlan, skipRemoteEnrichVerification)) {
return failures;
}

checkPlanConsistency(optimizedPlan, failures, depFailures);

Expand All @@ -47,8 +51,6 @@ public Failures verify(P optimizedPlan, boolean skipRemoteEnrichVerification, Li
return failures;
}

abstract boolean skipVerification(P optimizedPlan, boolean skipRemoteEnrichVerification);

abstract void checkPlanConsistency(P optimizedPlan, Failures failures, Failures depFailures);

private static void verifyOutputNotChanged(QueryPlan<?> optimizedPlan, List<Attribute> expectedOutputAttributes, Failures failures) {
Expand All @@ -67,7 +69,7 @@ private static void verifyOutputNotChanged(QueryPlan<?> optimizedPlan, List<Attr
.stream()
.anyMatch(x -> x.name().equals(ProjectAwayColumns.ALL_FIELDS_PROJECTED));
// LookupJoinExec represents the lookup index with EsSourceExec and this is turned into EsQueryExec by
// ReplaceSourceAttributes. Because InsertFieldExtractions doesn't apply to lookup indices, the
// ReplaceSourceAttributes. Because InsertFieldExtraction doesn't apply to lookup indices, the
// right hand side will only have the EsQueryExec providing the _doc attribute and nothing else.
// We perform an optimizer run on every fragment. LookupJoinExec also contains such a fragment,
// and currently it only contains an EsQueryExec after optimization.
Expand Down
Loading