Skip to content

Commit 7c4c0b7

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 53d2c47 commit 7c4c0b7

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
@@ -56,17 +56,14 @@
5656
import org.elasticsearch.xpack.core.rollup.RollupField;
5757
import org.elasticsearch.xpack.core.rollup.action.RollupJobCaps;
5858
import org.elasticsearch.xpack.core.rollup.action.RollupSearchAction;
59-
import org.elasticsearch.xpack.core.rollup.job.DateHistogramGroupConfig;
6059
import org.elasticsearch.xpack.rollup.Rollup;
6160
import org.elasticsearch.xpack.rollup.RollupJobIdentifierUtils;
6261
import org.elasticsearch.xpack.rollup.RollupRequestTranslator;
6362
import org.elasticsearch.xpack.rollup.RollupResponseTranslator;
64-
import org.joda.time.DateTimeZone;
6563

6664
import java.io.IOException;
6765
import java.util.ArrayList;
6866
import java.util.Arrays;
69-
import java.util.Collections;
7067
import java.util.HashSet;
7168
import java.util.List;
7269
import java.util.Objects;
@@ -286,11 +283,8 @@ static QueryBuilder rewriteQuery(QueryBuilder builder, Set<RollupJobCaps> jobCap
286283
} else if (builder.getWriteableName().equals(RangeQueryBuilder.NAME)) {
287284
RangeQueryBuilder range = (RangeQueryBuilder) builder;
288285
String fieldName = range.fieldName();
289-
// Many range queries don't include the timezone because the default is UTC, but the query
290-
// builder will return null so we need to set it here
291-
String timeZone = range.timeZone() == null ? DateTimeZone.UTC.toString() : range.timeZone();
292286

293-
String rewrittenFieldName = rewriteFieldName(jobCaps, RangeQueryBuilder.NAME, fieldName, timeZone);
287+
String rewrittenFieldName = rewriteFieldName(jobCaps, RangeQueryBuilder.NAME, fieldName);
294288
RangeQueryBuilder rewritten = new RangeQueryBuilder(rewrittenFieldName)
295289
.from(range.from())
296290
.to(range.to())
@@ -306,12 +300,12 @@ static QueryBuilder rewriteQuery(QueryBuilder builder, Set<RollupJobCaps> jobCap
306300
} else if (builder.getWriteableName().equals(TermQueryBuilder.NAME)) {
307301
TermQueryBuilder term = (TermQueryBuilder) builder;
308302
String fieldName = term.fieldName();
309-
String rewrittenFieldName = rewriteFieldName(jobCaps, TermQueryBuilder.NAME, fieldName, null);
303+
String rewrittenFieldName = rewriteFieldName(jobCaps, TermQueryBuilder.NAME, fieldName);
310304
return new TermQueryBuilder(rewrittenFieldName, term.value());
311305
} else if (builder.getWriteableName().equals(TermsQueryBuilder.NAME)) {
312306
TermsQueryBuilder terms = (TermsQueryBuilder) builder;
313307
String fieldName = terms.fieldName();
314-
String rewrittenFieldName = rewriteFieldName(jobCaps, TermQueryBuilder.NAME, fieldName, null);
308+
String rewrittenFieldName = rewriteFieldName(jobCaps, TermQueryBuilder.NAME, fieldName);
315309
return new TermsQueryBuilder(rewrittenFieldName, terms.values());
316310
} else if (builder.getWriteableName().equals(MatchAllQueryBuilder.NAME)) {
317311
// no-op
@@ -321,11 +315,7 @@ static QueryBuilder rewriteQuery(QueryBuilder builder, Set<RollupJobCaps> jobCap
321315
}
322316
}
323317

324-
private static String rewriteFieldName(Set<RollupJobCaps> jobCaps,
325-
String builderName,
326-
String fieldName,
327-
String timeZone) {
328-
List<String> incompatibleTimeZones = timeZone == null ? Collections.emptyList() : new ArrayList<>();
318+
private static String rewriteFieldName(Set<RollupJobCaps> jobCaps, String builderName, String fieldName) {
329319
List<String> rewrittenFieldNames = jobCaps.stream()
330320
// We only care about job caps that have the query's target field
331321
.filter(caps -> caps.getFieldCaps().keySet().contains(fieldName))
@@ -335,17 +325,7 @@ private static String rewriteFieldName(Set<RollupJobCaps> jobCaps,
335325
// For now, we only allow filtering on grouping fields
336326
.filter(agg -> {
337327
String type = (String)agg.get(RollupField.AGG);
338-
339-
// If the cap is for a date_histo, and the query is a range, the timezones need to match
340-
if (type.equals(DateHistogramAggregationBuilder.NAME) && timeZone != null) {
341-
boolean matchingTZ = ((String)agg.get(DateHistogramGroupConfig.TIME_ZONE))
342-
.equalsIgnoreCase(timeZone);
343-
if (matchingTZ == false) {
344-
incompatibleTimeZones.add((String)agg.get(DateHistogramGroupConfig.TIME_ZONE));
345-
}
346-
return matchingTZ;
347-
}
348-
// Otherwise just make sure it's one of the three groups
328+
// make sure it's one of the three groups
349329
return type.equals(TermsAggregationBuilder.NAME)
350330
|| type.equals(DateHistogramAggregationBuilder.NAME)
351331
|| type.equals(HistogramAggregationBuilder.NAME);
@@ -363,14 +343,8 @@ private static String rewriteFieldName(Set<RollupJobCaps> jobCaps,
363343
.distinct()
364344
.collect(ArrayList::new, List::addAll, List::addAll);
365345
if (rewrittenFieldNames.isEmpty()) {
366-
if (incompatibleTimeZones.isEmpty()) {
367-
throw new IllegalArgumentException("Field [" + fieldName + "] in [" + builderName
346+
throw new IllegalArgumentException("Field [" + fieldName + "] in [" + builderName
368347
+ "] query is not available in selected rollup indices, cannot query.");
369-
} else {
370-
throw new IllegalArgumentException("Field [" + fieldName + "] in [" + builderName
371-
+ "] query was found in rollup indices, but requested timezone is not compatible. Options include: "
372-
+ incompatibleTimeZones);
373-
}
374348
} else if (rewrittenFieldNames.size() > 1) {
375349
throw new IllegalArgumentException("Ambiguous field name resolution when mapping to rolled fields. Field name [" +
376350
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("CET"), 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)