Skip to content

Commit 7bc4a87

Browse files
Address feedback
1 parent 98aa887 commit 7bc4a87

File tree

2 files changed

+38
-29
lines changed
  • x-pack/plugin
    • esql-core/src/main/java/org/elasticsearch/xpack/esql/core/tree
    • esql/src/main/java/org/elasticsearch/xpack/esql/session

2 files changed

+38
-29
lines changed

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/tree/Node.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88

99
import org.elasticsearch.common.io.stream.NamedWriteable;
1010
import org.elasticsearch.xpack.esql.core.QlIllegalArgumentException;
11+
import org.elasticsearch.xpack.esql.core.util.Holder;
1112

1213
import java.util.ArrayList;
1314
import java.util.BitSet;
1415
import java.util.Iterator;
1516
import java.util.List;
1617
import java.util.Objects;
18+
import java.util.function.BiConsumer;
1719
import java.util.function.Consumer;
1820
import java.util.function.Function;
1921
import java.util.function.Predicate;
@@ -65,28 +67,33 @@ public List<T> children() {
6567
}
6668

6769
@SuppressWarnings("unchecked")
68-
public boolean forEachDownMayReturnEarly(Function<? super T, Boolean> action) {
69-
if (action.apply((T) this) == false) {
70+
void forEachDownMayReturnEarly(BiConsumer<? super T, Holder<Boolean>> action, Holder<Boolean> breakEarly) {
71+
action.accept((T) this, breakEarly);
72+
if (breakEarly.get()) {
7073
// Early return.
71-
return false;
74+
return;
7275
}
7376
// please do not refactor it to a for-each loop to avoid
7477
// allocating iterator that performs concurrent modification checks and extra stack frames
7578
for (int c = 0, size = children.size(); c < size; c++) {
76-
if (children.get(c).forEachDownMayReturnEarly(action) == false) {
77-
return false;
79+
children.get(c).forEachDownMayReturnEarly(action, breakEarly);
80+
if (breakEarly.get()) {
81+
// Early return.
82+
return;
7883
}
7984
}
80-
return true;
8185
}
8286

83-
@SuppressWarnings("unchecked")
87+
public boolean forEachDownMayReturnEarly(BiConsumer<? super T, Holder<Boolean>> action) {
88+
var breakEarly = new Holder<>(false);
89+
forEachDownMayReturnEarly(action, breakEarly);
90+
return breakEarly.get();
91+
}
92+
8493
public void forEachDown(Consumer<? super T> action) {
85-
forEachDownMayReturnEarly(p -> {
86-
action.accept(p);
87-
// No early return.
88-
return true;
89-
});
94+
boolean result = forEachDownMayReturnEarly((p, breakFlag) -> { action.accept(p); });
95+
// We should be breaking early here...
96+
assert result == false;
9097
}
9198

9299
@SuppressWarnings("unchecked")

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/FieldNameUtils.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
import java.util.HashSet;
5050
import java.util.List;
5151
import java.util.Set;
52-
import java.util.function.Function;
52+
import java.util.function.BiConsumer;
5353
import java.util.stream.Collectors;
5454

5555
import static org.elasticsearch.xpack.esql.core.util.StringUtils.WILDCARD;
@@ -107,31 +107,36 @@ public static PreAnalysisResult resolveFieldNames(LogicalPlan parsed, EnrichReso
107107
Set<String> wildcardJoinIndices = new java.util.HashSet<>();
108108

109109
var canRemoveAliases = new Holder<>(true);
110-
var needsAllFields = new Holder<>(false);
111110

112-
var processingLambda = new Holder<Function<LogicalPlan, Boolean>>();
113-
processingLambda.set((LogicalPlan p) -> {// go over each plan top-down
111+
var processingLambda = new Holder<BiConsumer<LogicalPlan, Holder<Boolean>>>();
112+
processingLambda.set((LogicalPlan p, Holder<Boolean> breakEarly) -> {// go over each plan top-down
114113
if (p instanceof Fork fork) {
115-
// Early return from forEachDown. We will iterate over the children manually.
114+
// Early return from forEachDown. We will iterate over the children manually and end the recursion via forEachDown early.
116115
var forkRefsResult = AttributeSet.builder();
117116
forkRefsResult.addAll(referencesBuilder.get());
118117

119-
for (var child : fork.children()) {
118+
for (var fork_child : fork.children()) {
120119
referencesBuilder.set(AttributeSet.builder());
121-
var return_result = child.forEachDownMayReturnEarly(processingLambda.get());
122-
// No nested Forks for now...
123-
assert return_result;
120+
var nested_early_return = fork_child.forEachDownMayReturnEarly(processingLambda.get());
121+
// This assert is just for good measure. FORKs within FORKs is yet not supported.
122+
assert nested_early_return == false;
123+
124+
// See below, no references, means we should return all fields (*).
124125
if (referencesBuilder.get().isEmpty()) {
125-
needsAllFields.set(true);
126-
// Early return.
127-
return false;
126+
projectAll.set(true);
127+
// Return early, we'll be returning all references no matter what the remainder of the query is.
128+
breakEarly.set(true);
129+
return;
128130
}
129131
forkRefsResult.addAll(referencesBuilder.get());
130132
}
131133

132134
forkRefsResult.removeIf(attr -> attr.name().equals(Fork.FORK_FIELD));
133135
referencesBuilder.set(forkRefsResult);
134-
return false;
136+
137+
// Return early, we've already explored all fork branches.
138+
breakEarly.set(true);
139+
return;
135140
} else if (p instanceof RegexExtract re) { // for Grok and Dissect
136141
// keep the inputs needed by Grok/Dissect
137142
referencesBuilder.get().addAll(re.input().references());
@@ -210,13 +215,10 @@ public static PreAnalysisResult resolveFieldNames(LogicalPlan parsed, EnrichReso
210215
.removeIf(attr -> matchByName(attr, ne.name(), keepRefs.contains(attr) || dropWildcardRefs.contains(attr)));
211216
});
212217
}
213-
214-
// No early return.
215-
return true;
216218
});
217219
parsed.forEachDownMayReturnEarly(processingLambda.get());
218220

219-
if (needsAllFields.get()) {
221+
if (projectAll.get()) {
220222
return new PreAnalysisResult(enrichResolution, IndexResolver.ALL_FIELDS, Set.of());
221223
}
222224

0 commit comments

Comments
 (0)