Skip to content

Commit aa30c2e

Browse files
committed
Remove timezone validation on rollup range queries (#40647)
We enforced the timezone of range queries when using the rollup search endpoint, but this validation is not needed. Since rollup dates are stored in UTC, and range queries are always converted to UTC (even if specifying a `time_zone`) the validation is not needed and can prevent legitimate queries from running.
1 parent fcc5ad9 commit aa30c2e

File tree

2 files changed

+10
-37
lines changed

2 files changed

+10
-37
lines changed

x-pack/plugin/rollup/src/main/java/org/elasticsearch/xpack/rollup/action/TransportRollupSearchAction.java

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,14 @@
5757
import org.elasticsearch.xpack.core.rollup.RollupField;
5858
import org.elasticsearch.xpack.core.rollup.action.RollupJobCaps;
5959
import org.elasticsearch.xpack.core.rollup.action.RollupSearchAction;
60-
import org.elasticsearch.xpack.core.rollup.job.DateHistogramGroupConfig;
6160
import org.elasticsearch.xpack.rollup.Rollup;
6261
import org.elasticsearch.xpack.rollup.RollupJobIdentifierUtils;
6362
import org.elasticsearch.xpack.rollup.RollupRequestTranslator;
6463
import org.elasticsearch.xpack.rollup.RollupResponseTranslator;
65-
import org.joda.time.DateTimeZone;
6664

6765
import java.io.IOException;
6866
import java.util.ArrayList;
6967
import java.util.Arrays;
70-
import java.util.Collections;
7168
import java.util.HashSet;
7269
import java.util.List;
7370
import java.util.Objects;
@@ -295,11 +292,8 @@ static QueryBuilder rewriteQuery(QueryBuilder builder, Set<RollupJobCaps> jobCap
295292
} else if (builder.getWriteableName().equals(RangeQueryBuilder.NAME)) {
296293
RangeQueryBuilder range = (RangeQueryBuilder) builder;
297294
String fieldName = range.fieldName();
298-
// Many range queries don't include the timezone because the default is UTC, but the query
299-
// builder will return null so we need to set it here
300-
String timeZone = range.timeZone() == null ? DateTimeZone.UTC.toString() : range.timeZone();
301295

302-
String rewrittenFieldName = rewriteFieldName(jobCaps, RangeQueryBuilder.NAME, fieldName, timeZone);
296+
String rewrittenFieldName = rewriteFieldName(jobCaps, RangeQueryBuilder.NAME, fieldName);
303297
RangeQueryBuilder rewritten = new RangeQueryBuilder(rewrittenFieldName)
304298
.from(range.from())
305299
.to(range.to())
@@ -315,12 +309,12 @@ static QueryBuilder rewriteQuery(QueryBuilder builder, Set<RollupJobCaps> jobCap
315309
} else if (builder.getWriteableName().equals(TermQueryBuilder.NAME)) {
316310
TermQueryBuilder term = (TermQueryBuilder) builder;
317311
String fieldName = term.fieldName();
318-
String rewrittenFieldName = rewriteFieldName(jobCaps, TermQueryBuilder.NAME, fieldName, null);
312+
String rewrittenFieldName = rewriteFieldName(jobCaps, TermQueryBuilder.NAME, fieldName);
319313
return new TermQueryBuilder(rewrittenFieldName, term.value());
320314
} else if (builder.getWriteableName().equals(TermsQueryBuilder.NAME)) {
321315
TermsQueryBuilder terms = (TermsQueryBuilder) builder;
322316
String fieldName = terms.fieldName();
323-
String rewrittenFieldName = rewriteFieldName(jobCaps, TermQueryBuilder.NAME, fieldName, null);
317+
String rewrittenFieldName = rewriteFieldName(jobCaps, TermQueryBuilder.NAME, fieldName);
324318
return new TermsQueryBuilder(rewrittenFieldName, terms.values());
325319
} else if (builder.getWriteableName().equals(MatchAllQueryBuilder.NAME)) {
326320
// no-op
@@ -330,11 +324,7 @@ static QueryBuilder rewriteQuery(QueryBuilder builder, Set<RollupJobCaps> jobCap
330324
}
331325
}
332326

333-
private static String rewriteFieldName(Set<RollupJobCaps> jobCaps,
334-
String builderName,
335-
String fieldName,
336-
String timeZone) {
337-
List<String> incompatibleTimeZones = timeZone == null ? Collections.emptyList() : new ArrayList<>();
327+
private static String rewriteFieldName(Set<RollupJobCaps> jobCaps, String builderName, String fieldName) {
338328
List<String> rewrittenFieldNames = jobCaps.stream()
339329
// We only care about job caps that have the query's target field
340330
.filter(caps -> caps.getFieldCaps().keySet().contains(fieldName))
@@ -344,17 +334,7 @@ private static String rewriteFieldName(Set<RollupJobCaps> jobCaps,
344334
// For now, we only allow filtering on grouping fields
345335
.filter(agg -> {
346336
String type = (String)agg.get(RollupField.AGG);
347-
348-
// If the cap is for a date_histo, and the query is a range, the timezones need to match
349-
if (type.equals(DateHistogramAggregationBuilder.NAME) && timeZone != null) {
350-
boolean matchingTZ = ((String)agg.get(DateHistogramGroupConfig.TIME_ZONE))
351-
.equalsIgnoreCase(timeZone);
352-
if (matchingTZ == false) {
353-
incompatibleTimeZones.add((String)agg.get(DateHistogramGroupConfig.TIME_ZONE));
354-
}
355-
return matchingTZ;
356-
}
357-
// Otherwise just make sure it's one of the three groups
337+
// make sure it's one of the three groups
358338
return type.equals(TermsAggregationBuilder.NAME)
359339
|| type.equals(DateHistogramAggregationBuilder.NAME)
360340
|| type.equals(HistogramAggregationBuilder.NAME);
@@ -372,14 +352,8 @@ private static String rewriteFieldName(Set<RollupJobCaps> jobCaps,
372352
.distinct()
373353
.collect(ArrayList::new, List::addAll, List::addAll);
374354
if (rewrittenFieldNames.isEmpty()) {
375-
if (incompatibleTimeZones.isEmpty()) {
376-
throw new IllegalArgumentException("Field [" + fieldName + "] in [" + builderName
355+
throw new IllegalArgumentException("Field [" + fieldName + "] in [" + builderName
377356
+ "] query is not available in selected rollup indices, cannot query.");
378-
} else {
379-
throw new IllegalArgumentException("Field [" + fieldName + "] in [" + builderName
380-
+ "] query was found in rollup indices, but requested timezone is not compatible. Options include: "
381-
+ incompatibleTimeZones);
382-
}
383357
} else if (rewrittenFieldNames.size() > 1) {
384358
throw new IllegalArgumentException("Ambiguous field name resolution when mapping to rolled fields. Field name [" +
385359
fieldName + "] was mapped to: [" + Strings.collectionToDelimitedString(rewrittenFieldNames, ",") + "].");

x-pack/plugin/rollup/src/test/java/org/elasticsearch/xpack/rollup/action/SearchActionTests.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,15 @@ public void testRangeNullTimeZone() {
140140
assertThat(((RangeQueryBuilder)rewritten).fieldName(), equalTo("foo.date_histogram.timestamp"));
141141
}
142142

143-
public void testRangeWrongTZ() {
143+
public void testRangeDifferentTZ() {
144144
final GroupConfig groupConfig = new GroupConfig(new DateHistogramGroupConfig("foo", new DateHistogramInterval("1h"), null, "UTC"));
145145
final RollupJobConfig config = new RollupJobConfig("foo", "index", "rollup", "*/5 * * * * ?", 10, groupConfig, emptyList(), null);
146146
RollupJobCaps cap = new RollupJobCaps(config);
147147
Set<RollupJobCaps> caps = new HashSet<>();
148148
caps.add(cap);
149-
Exception e = expectThrows(IllegalArgumentException.class,
150-
() -> TransportRollupSearchAction.rewriteQuery(new RangeQueryBuilder("foo").gt(1).timeZone("EST"), caps));
151-
assertThat(e.getMessage(), equalTo("Field [foo] in [range] query was found in rollup indices, but requested timezone is not " +
152-
"compatible. Options include: [UTC]"));
149+
QueryBuilder rewritten = TransportRollupSearchAction.rewriteQuery(new RangeQueryBuilder("foo").gt(1).timeZone("CET"), caps);
150+
assertThat(rewritten, instanceOf(RangeQueryBuilder.class));
151+
assertThat(((RangeQueryBuilder)rewritten).fieldName(), equalTo("foo.date_histogram.timestamp"));
153152
}
154153

155154
public void testTermQuery() {

0 commit comments

Comments
 (0)