Skip to content

Commit 318c807

Browse files
authored
Translate start/end to filter on @timestamp (#138412)
1 parent 398fc50 commit 318c807

File tree

2 files changed

+28
-29
lines changed

2 files changed

+28
-29
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/promql/TranslatePromqlToTimeSeriesAggregate.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
import org.elasticsearch.xpack.esql.expression.predicate.logical.And;
2828
import org.elasticsearch.xpack.esql.expression.predicate.nulls.IsNotNull;
2929
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.Equals;
30+
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.GreaterThanOrEqual;
3031
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.In;
32+
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.LessThanOrEqual;
3133
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.NotEquals;
3234
import org.elasticsearch.xpack.esql.expression.promql.function.PromqlFunctionRegistry;
3335
import org.elasticsearch.xpack.esql.optimizer.rules.logical.OptimizerRules;
@@ -98,16 +100,28 @@ protected LogicalPlan rule(PromqlCommand promqlCommand) {
98100
LogicalPlan promqlPlan = promqlCommand.promqlPlan();
99101

100102
// first replace the Placeholder relation with the child plan
101-
promqlPlan = promqlPlan.transformUp(PlaceholderRelation.class, pr -> promqlCommand.child());
103+
promqlPlan = promqlPlan.transformUp(PlaceholderRelation.class, pr -> withTimestampFilter(promqlCommand, promqlCommand.child()));
102104

103-
// Translate based on plan type
104-
return translate(promqlCommand, promqlPlan);
105+
// Translate based on plan type by converting the plan bottom-up
106+
return map(promqlCommand, promqlPlan).plan();
105107
}
106108

107-
private LogicalPlan translate(PromqlCommand promqlCommand, LogicalPlan promqlPlan) {
108-
// convert the plan bottom-up
109-
MapResult result = map(promqlCommand, promqlPlan);
110-
return result.plan();
109+
private static LogicalPlan withTimestampFilter(PromqlCommand promqlCommand, LogicalPlan plan) {
110+
// start and end are either both set or both null
111+
if (promqlCommand.start().value() != null && promqlCommand.end().value() != null) {
112+
Source promqlSource = promqlCommand.source();
113+
Expression timestamp = promqlCommand.timestamp();
114+
plan = new Filter(
115+
promqlSource,
116+
plan,
117+
new And(
118+
promqlSource,
119+
new GreaterThanOrEqual(promqlSource, timestamp, promqlCommand.start()),
120+
new LessThanOrEqual(promqlSource, timestamp, promqlCommand.end())
121+
)
122+
);
123+
}
124+
return plan;
111125
}
112126

113127
private record MapResult(LogicalPlan plan, Map<String, Expression> extras) {}

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/promql/PromqlLogicalPlanOptimizerTests.java

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.xpack.esql.analysis.Analyzer;
1515
import org.elasticsearch.xpack.esql.analysis.AnalyzerContext;
1616
import org.elasticsearch.xpack.esql.core.expression.Alias;
17+
import org.elasticsearch.xpack.esql.core.expression.FieldAttribute;
1718
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
1819
import org.elasticsearch.xpack.esql.core.expression.predicate.regex.RegexMatch;
1920
import org.elasticsearch.xpack.esql.core.tree.Source;
@@ -41,7 +42,6 @@
4142
import java.time.Duration;
4243
import java.time.Instant;
4344
import java.time.temporal.ChronoUnit;
44-
import java.util.List;
4545
import java.util.Map;
4646
import java.util.Set;
4747

@@ -57,8 +57,6 @@
5757
// @TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug tests")
5858
public class PromqlLogicalPlanOptimizerTests extends AbstractLogicalPlanOptimizerTests {
5959

60-
private static final String PARAM_FORMATTING = "%1$s";
61-
6260
private static Analyzer tsAnalyzer;
6361

6462
@BeforeClass
@@ -93,7 +91,6 @@ public void testExplainPromql() {
9391
)
9492
""");
9593

96-
logger.trace(plan);
9794
}
9895

9996
public void testExplainPromqlSimple() {
@@ -106,7 +103,6 @@ public void testExplainPromqlSimple() {
106103
| STATS AVG(AVG_OVER_TIME(network.bytes_in)) BY TBUCKET(1h)
107104
""");
108105

109-
logger.trace(plan);
110106
}
111107

112108
/**
@@ -144,8 +140,6 @@ public void testAvgAvgOverTimeOutput() {
144140
| LIMIT 1000
145141
""");
146142

147-
logger.trace(plan);
148-
149143
var project = as(plan, Project.class);
150144
assertThat(project.projections(), hasSize(3));
151145

@@ -240,7 +234,6 @@ public void testTSAvgAvgOverTimeOutput() {
240234
| LIMIT 1000
241235
""");
242236

243-
logger.trace(plan);
244237
}
245238

246239
/**
@@ -270,9 +263,6 @@ public void testTSAvgWithoutByDimension() {
270263
| STATS avg(avg_over_time(network.bytes_in)) BY TBUCKET(1h)
271264
| LIMIT 1000
272265
""");
273-
274-
logger.trace(plan);
275-
276266
}
277267

278268
/**
@@ -306,7 +296,6 @@ public void testPromqlAvgWithoutByDimension() {
306296
| LIMIT 1000
307297
""");
308298

309-
logger.trace(plan);
310299
}
311300

312301
/**
@@ -337,7 +326,6 @@ public void testRangeSelector() {
337326
| promql step 1h ( max by (pod) (avg_over_time(network.bytes_in[1h])) )
338327
""");
339328

340-
logger.trace(plan);
341329
}
342330

343331
@AwaitsFix(bugUrl = "Invalid call to dataType on an unresolved object ?RATE_$1")
@@ -353,7 +341,6 @@ avg by (pod) (rate(network.bytes_in[1h]))
353341
""";
354342

355343
var plan = planPromql(testQuery);
356-
logger.trace(plan);
357344
}
358345

359346
/**
@@ -385,8 +372,10 @@ public void testStartEndStep() {
385372
""";
386373

387374
var plan = planPromql(testQuery);
388-
List<LogicalPlan> collect = plan.collect(Bucket.class::isInstance);
389-
logger.trace(plan);
375+
var filters = plan.collect(Filter.class::isInstance);
376+
assertThat(filters, hasSize(1));
377+
var filter = (Filter) filters.getFirst();
378+
assertThat(filter.condition().collect(e -> e instanceof FieldAttribute a && a.name().equals("@timestamp")), hasSize(2));
390379
}
391380

392381
/**
@@ -427,7 +416,6 @@ max by (pod) (avg_over_time(network.bytes_in{pod=~"host-0|host-1|host-2"}[5m]))
427416
assertThat(filters, hasSize(1));
428417
var filter = (Filter) filters.getFirst();
429418
assertThat(filter.condition().anyMatch(In.class::isInstance), equalTo(true));
430-
logger.trace(plan);
431419
}
432420

433421
public void testLabelSelectorPrefix() {
@@ -448,7 +436,6 @@ avg by (pod) (avg_over_time(network.bytes_in{pod=~"host-.*"}[5m]))
448436
var filter = (Filter) filters.getFirst();
449437
assertThat(filter.condition().anyMatch(StartsWith.class::isInstance), equalTo(true));
450438
assertThat(filter.condition().anyMatch(NotEquals.class::isInstance), equalTo(false));
451-
logger.trace(plan);
452439
}
453440

454441
public void testLabelSelectorProperPrefix() {
@@ -518,7 +505,6 @@ sum by (host.name, mountpoint) (last_over_time(system.filesystem.usage{state=~"u
518505
""";
519506

520507
var plan = planPromql(testQuery);
521-
logger.trace(plan);
522508
}
523509

524510
@AwaitsFix(bugUrl = "only aggregations across timeseries are supported at this time (found [foo or bar])")
@@ -539,7 +525,6 @@ public void testGrammar() {
539525
""";
540526

541527
var plan = planPromql(testQuery);
542-
logger.trace(plan);
543528
}
544529

545530
// public void testPromqlArithmetricOperators() {
@@ -567,9 +552,9 @@ protected LogicalPlan planPromql(String query) {
567552
query = query.replace("$now-1h", '"' + Instant.now().minus(1, ChronoUnit.HOURS).toString() + '"');
568553
query = query.replace("$now", '"' + Instant.now().toString() + '"');
569554
var analyzed = tsAnalyzer.analyze(parser.createStatement(query));
570-
logger.trace(analyzed);
555+
logger.trace("analyzed plan:\n{}", analyzed);
571556
var optimized = logicalOptimizer.optimize(analyzed);
572-
logger.trace(optimized);
557+
logger.trace("optimized plan:\n{}", optimized);
573558
return optimized;
574559
}
575560
}

0 commit comments

Comments
 (0)