Skip to content

Commit 3eac180

Browse files
committed
whitelist supported processing commands
1 parent aec02c3 commit 3eac180

File tree

1 file changed

+44
-3
lines changed
  • x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/approximate

1 file changed

+44
-3
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/approximate/Approximate.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,26 @@
4545
import org.elasticsearch.xpack.esql.plan.logical.Dissect;
4646
import org.elasticsearch.xpack.esql.plan.logical.Drop;
4747
import org.elasticsearch.xpack.esql.plan.logical.Enrich;
48+
import org.elasticsearch.xpack.esql.plan.logical.EsRelation;
4849
import org.elasticsearch.xpack.esql.plan.logical.Eval;
4950
import org.elasticsearch.xpack.esql.plan.logical.Filter;
5051
import org.elasticsearch.xpack.esql.plan.logical.Grok;
5152
import org.elasticsearch.xpack.esql.plan.logical.Insist;
5253
import org.elasticsearch.xpack.esql.plan.logical.Keep;
5354
import org.elasticsearch.xpack.esql.plan.logical.LeafPlan;
55+
import org.elasticsearch.xpack.esql.plan.logical.Limit;
5456
import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;
57+
import org.elasticsearch.xpack.esql.plan.logical.MvExpand;
5558
import org.elasticsearch.xpack.esql.plan.logical.OrderBy;
5659
import org.elasticsearch.xpack.esql.plan.logical.Project;
60+
import org.elasticsearch.xpack.esql.plan.logical.RegexExtract;
5761
import org.elasticsearch.xpack.esql.plan.logical.Rename;
62+
import org.elasticsearch.xpack.esql.plan.logical.Row;
5863
import org.elasticsearch.xpack.esql.plan.logical.Sample;
64+
import org.elasticsearch.xpack.esql.plan.logical.TopN;
5965
import org.elasticsearch.xpack.esql.plan.logical.UnaryPlan;
66+
import org.elasticsearch.xpack.esql.plan.logical.inference.Completion;
67+
import org.elasticsearch.xpack.esql.plan.logical.inference.Rerank;
6068
import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject;
6169
import org.elasticsearch.xpack.esql.session.Result;
6270

@@ -75,10 +83,14 @@
7583
* A query is currently suitable for approximation if:
7684
* <ul>
7785
* <li> it contains exactly one {@code STATS} command
86+
* <li> the other commands are from the supported set
87+
* ({@link Approximate#SUPPORTED_COMMANDS}); this contains almost all
88+
* unary commands, but no {@code FORK} or {@code JOIN}.
7889
* <li> the aggregate functions are from the supported set
7990
* ({@link Approximate#SUPPORTED_SINGLE_VALUED_AGGS} and
8091
* {@link Approximate#SUPPORTED_MULTIVALUED_AGGS})
8192
* <li> it contains only unary commands (so no {@code FORK} or {@code JOIN})
93+
* <li> it doesn't contain a forbidden command (
8294
* </ul>
8395
* Some of these restrictions may be lifted in the future.
8496
* <p>
@@ -114,6 +126,35 @@ public interface LogicalPlanRunner {
114126
void run(LogicalPlan plan, ActionListener<Result> listener);
115127
}
116128

129+
/**
130+
* These processing commands are supported.
131+
*/
132+
private static final Set<Class<? extends LogicalPlan>> SUPPORTED_COMMANDS = Set.of(
133+
Aggregate.class,
134+
ChangePoint.class,
135+
Completion.class,
136+
Dissect.class,
137+
Drop.class,
138+
Enrich.class,
139+
EsqlProject.class,
140+
EsRelation.class,
141+
Eval.class,
142+
Filter.class,
143+
Grok.class,
144+
Insist.class,
145+
Keep.class,
146+
Limit.class,
147+
MvExpand.class,
148+
OrderBy.class,
149+
Project.class,
150+
RegexExtract.class,
151+
Rename.class,
152+
Rerank.class,
153+
Row.class,
154+
Sample.class,
155+
TopN.class
156+
);
157+
117158
/**
118159
* These commands preserve all rows, making it easy to predict the number of output rows.
119160
*/
@@ -209,9 +250,9 @@ private boolean verifyPlan() throws VerificationException {
209250
List.of(Failure.fail(logicalPlan.collectLeaves().getFirst(), "query without [STATS] cannot be approximated"))
210251
);
211252
}
212-
// Only unary plans are supported for now (no FORK or JOIN).
253+
// Verify that all commands are supported.
213254
logicalPlan.forEachUp(plan -> {
214-
if (plan instanceof LeafPlan == false && plan instanceof UnaryPlan == false) {
255+
if (SUPPORTED_COMMANDS.contains(plan.getClass()) == false) {
215256
throw new VerificationException(
216257
List.of(Failure.fail(plan, "query with [" + plan.nodeName().toUpperCase(Locale.ROOT) + "] cannot be approximated"))
217258
);
@@ -239,7 +280,7 @@ private boolean verifyPlan() throws VerificationException {
239280
}
240281
return aggFn;
241282
});
242-
} else if (ROW_PRESERVING_COMMANDS.contains(plan.getClass()) == false) {
283+
} else if (plan instanceof LeafPlan == false && ROW_PRESERVING_COMMANDS.contains(plan.getClass()) == false) {
243284
// Keep track of whether the plan until the STATS preserves all rows.
244285
preservesRows.set(false);
245286
}

0 commit comments

Comments
 (0)