diff --git a/x-pack/plugin/esql/compute/ann/src/main/java/org/elasticsearch/compute/ann/Aggregator.java b/x-pack/plugin/esql/compute/ann/src/main/java/org/elasticsearch/compute/ann/Aggregator.java index cdff28acecdbe..cebd78c828295 100644 --- a/x-pack/plugin/esql/compute/ann/src/main/java/org/elasticsearch/compute/ann/Aggregator.java +++ b/x-pack/plugin/esql/compute/ann/src/main/java/org/elasticsearch/compute/ann/Aggregator.java @@ -54,9 +54,4 @@ * into a warning and turn into a null value. */ Class[] warnExceptions() default {}; - - /** - * If {@code true} then the @timestamp LongVector will be appended to the input blocks of the aggregation function. - */ - boolean includeTimestamps() default false; } diff --git a/x-pack/plugin/esql/compute/ann/src/main/java/org/elasticsearch/compute/ann/GroupingAggregator.java b/x-pack/plugin/esql/compute/ann/src/main/java/org/elasticsearch/compute/ann/GroupingAggregator.java index 03565ab92667d..22d387ccf0f88 100644 --- a/x-pack/plugin/esql/compute/ann/src/main/java/org/elasticsearch/compute/ann/GroupingAggregator.java +++ b/x-pack/plugin/esql/compute/ann/src/main/java/org/elasticsearch/compute/ann/GroupingAggregator.java @@ -27,9 +27,4 @@ * into a warning and turn into a null value. */ Class[] warnExceptions() default {}; - - /** - * {@code true} if this is a time-series aggregation - */ - boolean timeseries() default false; } diff --git a/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/AggregatorImplementer.java b/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/AggregatorImplementer.java index d775a46109214..83fd3459f9dee 100644 --- a/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/AggregatorImplementer.java +++ b/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/AggregatorImplementer.java @@ -37,6 +37,7 @@ import static org.elasticsearch.compute.gen.Methods.requireAnyArgs; import static org.elasticsearch.compute.gen.Methods.requireAnyType; import static org.elasticsearch.compute.gen.Methods.requireArgs; +import static org.elasticsearch.compute.gen.Methods.requireArgsStartsWith; import static org.elasticsearch.compute.gen.Methods.requireName; import static org.elasticsearch.compute.gen.Methods.requirePrimitiveOrImplements; import static org.elasticsearch.compute.gen.Methods.requireStaticMethod; @@ -87,8 +88,7 @@ public AggregatorImplementer( Elements elements, TypeElement declarationType, IntermediateState[] interStateAnno, - List warnExceptions, - boolean includeTimestampVector + List warnExceptions ) { this.declarationType = declarationType; this.warnExceptions = warnExceptions; @@ -105,8 +105,18 @@ public AggregatorImplementer( declarationType, aggState.declaredType().isPrimitive() ? requireType(aggState.declaredType()) : requireVoidType(), requireName("combine"), - combineArgs(aggState, includeTimestampVector) + requireArgsStartsWith(requireType(aggState.declaredType()), requireAnyType("")) ); + switch (combine.getParameters().size()) { + case 2 -> includeTimestampVector = false; + case 3 -> { + if (false == TypeName.get(combine.getParameters().get(1).asType()).equals(TypeName.LONG)) { + throw new IllegalArgumentException("combine/3's second parameter must be long but was: " + combine); + } + includeTimestampVector = true; + } + default -> throw new IllegalArgumentException("combine must have 2 or 3 parameters but was: " + combine); + } // TODO support multiple parameters this.aggParam = AggregationParameter.create(combine.getParameters().getLast().asType()); @@ -121,19 +131,6 @@ public AggregatorImplementer( (declarationType.getSimpleName() + "AggregatorFunction").replace("AggregatorAggregator", "Aggregator") ); this.intermediateState = Arrays.stream(interStateAnno).map(IntermediateStateDesc::newIntermediateStateDesc).toList(); - this.includeTimestampVector = includeTimestampVector; - } - - private static Methods.ArgumentMatcher combineArgs(AggregationState aggState, boolean includeTimestampVector) { - if (includeTimestampVector) { - return requireArgs( - requireType(aggState.declaredType()), - requireType(TypeName.LONG), // @timestamp - requireAnyType("") - ); - } else { - return requireArgs(requireType(aggState.declaredType()), requireAnyType("")); - } } ClassName implementation() { diff --git a/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/AggregatorProcessor.java b/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/AggregatorProcessor.java index 0b3b10c92b96c..ddfc0db91bfac 100644 --- a/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/AggregatorProcessor.java +++ b/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/AggregatorProcessor.java @@ -87,13 +87,7 @@ public boolean process(Set set, RoundEnvironment roundEnv ); if (aggClass.getAnnotation(Aggregator.class) != null) { IntermediateState[] intermediateState = aggClass.getAnnotation(Aggregator.class).value(); - implementer = new AggregatorImplementer( - env.getElementUtils(), - aggClass, - intermediateState, - warnExceptionsTypes, - aggClass.getAnnotation(Aggregator.class).includeTimestamps() - ); + implementer = new AggregatorImplementer(env.getElementUtils(), aggClass, intermediateState, warnExceptionsTypes); write(aggClass, "aggregator", implementer.sourceFile(), env); } GroupingAggregatorImplementer groupingAggregatorImplementer = null; @@ -106,8 +100,7 @@ public boolean process(Set set, RoundEnvironment roundEnv env.getElementUtils(), aggClass, intermediateState, - warnExceptionsTypes, - aggClass.getAnnotation(GroupingAggregator.class).timeseries() + warnExceptionsTypes ); write(aggClass, "grouping aggregator", groupingAggregatorImplementer.sourceFile(), env); } diff --git a/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/GroupingAggregatorImplementer.java b/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/GroupingAggregatorImplementer.java index 6042915f70aee..c4b343c4c6017 100644 --- a/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/GroupingAggregatorImplementer.java +++ b/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/GroupingAggregatorImplementer.java @@ -40,6 +40,7 @@ import static org.elasticsearch.compute.gen.Methods.requireAnyArgs; import static org.elasticsearch.compute.gen.Methods.requireAnyType; import static org.elasticsearch.compute.gen.Methods.requireArgs; +import static org.elasticsearch.compute.gen.Methods.requireArgsStartsWith; import static org.elasticsearch.compute.gen.Methods.requireName; import static org.elasticsearch.compute.gen.Methods.requirePrimitiveOrImplements; import static org.elasticsearch.compute.gen.Methods.requireStaticMethod; @@ -98,8 +99,7 @@ public GroupingAggregatorImplementer( Elements elements, TypeElement declarationType, IntermediateState[] interStateAnno, - List warnExceptions, - boolean timseries + List warnExceptions ) { this.declarationType = declarationType; this.warnExceptions = warnExceptions; @@ -116,8 +116,18 @@ public GroupingAggregatorImplementer( declarationType, aggState.declaredType().isPrimitive() ? requireType(aggState.declaredType()) : requireVoidType(), requireName("combine"), - combineArgs(aggState, timseries) + combineArgs(aggState) ); + switch (combine.getParameters().size()) { + case 2, 3 -> timseries = false; + case 4 -> { + if (false == TypeName.get(combine.getParameters().get(2).asType()).equals(TypeName.LONG)) { + throw new IllegalArgumentException("combine/4's third parameter must be long but was: " + combine); + } + timseries = true; + } + default -> throw new IllegalArgumentException("combine must have 2, 3, or 4 parameters but was: " + combine); + } // TODO support multiple parameters this.aggParam = AggregationParameter.create(combine.getParameters().getLast().asType()); @@ -135,21 +145,13 @@ public GroupingAggregatorImplementer( this.intermediateState = Arrays.stream(interStateAnno) .map(AggregatorImplementer.IntermediateStateDesc::newIntermediateStateDesc) .toList(); - this.timseries = timseries; } - private static Methods.ArgumentMatcher combineArgs(AggregationState aggState, boolean includeTimestampVector) { + private static Methods.ArgumentMatcher combineArgs(AggregationState aggState) { if (aggState.declaredType().isPrimitive()) { return requireArgs(requireType(aggState.declaredType()), requireAnyType("")); - } else if (includeTimestampVector) { - return requireArgs( - requireType(aggState.declaredType()), - requireType(TypeName.INT), - requireType(TypeName.LONG), // @timestamp - requireAnyType("") - ); } else { - return requireArgs( + return requireArgsStartsWith( requireType(aggState.declaredType()), requireType(TypeName.INT), requireAnyType("") diff --git a/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/Methods.java b/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/Methods.java index c2d076eee611a..dfa2283f14224 100644 --- a/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/Methods.java +++ b/x-pack/plugin/esql/compute/gen/src/main/java/org/elasticsearch/compute/gen/Methods.java @@ -123,6 +123,13 @@ static ArgumentMatcher requireArgs(TypeMatcher... argTypes) { ); } + static ArgumentMatcher requireArgsStartsWith(TypeMatcher... argTypes) { + return new ArgumentMatcher( + args -> args.size() >= argTypes.length && IntStream.range(0, argTypes.length).allMatch(i -> argTypes[i].test(args.get(i))), + Stream.of(argTypes).map(TypeMatcher::toString).collect(joining(", ")) + ", ..." + ); + } + record NameMatcher(Set names) implements Predicate { @Override public boolean test(String name) { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeDoubleAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeDoubleAggregator.java index 3c3ca7f6cb2d9..41e880c069e27 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeDoubleAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeDoubleAggregator.java @@ -24,7 +24,6 @@ * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "DOUBLE_BLOCK") } ) public class FirstOverTimeDoubleAggregator { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeFloatAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeFloatAggregator.java index 407c6f9d2ff6d..cbf6251f40546 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeFloatAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeFloatAggregator.java @@ -24,7 +24,6 @@ * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "FLOAT_BLOCK") } ) public class FirstOverTimeFloatAggregator { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeIntAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeIntAggregator.java index d006907f1800e..20df3c0a3a267 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeIntAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeIntAggregator.java @@ -24,7 +24,6 @@ * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "INT_BLOCK") } ) public class FirstOverTimeIntAggregator { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeLongAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeLongAggregator.java index 62f9a46ef9ed7..084e3889e9ddf 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeLongAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/FirstOverTimeLongAggregator.java @@ -22,7 +22,6 @@ * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "LONG_BLOCK") } ) public class FirstOverTimeLongAggregator { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeDoubleAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeDoubleAggregator.java index 91373a508784c..7d6c8a6c9ec2f 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeDoubleAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeDoubleAggregator.java @@ -24,7 +24,6 @@ * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "DOUBLE_BLOCK") } ) public class LastOverTimeDoubleAggregator { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeFloatAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeFloatAggregator.java index 4bb863ad6474f..cf35765ed3395 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeFloatAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeFloatAggregator.java @@ -24,7 +24,6 @@ * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "FLOAT_BLOCK") } ) public class LastOverTimeFloatAggregator { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeIntAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeIntAggregator.java index ee2cc6f3049b2..78c664a37ee0c 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeIntAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeIntAggregator.java @@ -24,7 +24,6 @@ * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "INT_BLOCK") } ) public class LastOverTimeIntAggregator { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeLongAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeLongAggregator.java index d32144ef1fc19..5acac93f6bbe6 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeLongAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/LastOverTimeLongAggregator.java @@ -22,7 +22,6 @@ * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "LONG_BLOCK") } ) public class LastOverTimeLongAggregator { diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateDoubleAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateDoubleAggregator.java index 92f8886712d35..830e2e113c5ab 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateDoubleAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateDoubleAggregator.java @@ -29,7 +29,6 @@ * This class is generated. Edit `X-RateAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "DOUBLE_BLOCK"), diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateFloatAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateFloatAggregator.java index eb8d6a194e6e5..dbb9681225fdb 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateFloatAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateFloatAggregator.java @@ -30,7 +30,6 @@ * This class is generated. Edit `X-RateAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "FLOAT_BLOCK"), diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateIntAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateIntAggregator.java index fdacd473264a6..5a9010b9a00e6 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateIntAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateIntAggregator.java @@ -30,7 +30,6 @@ * This class is generated. Edit `X-RateAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "INT_BLOCK"), diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateLongAggregator.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateLongAggregator.java index ea9f7802656fb..0a1d91b29b36f 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateLongAggregator.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/aggregation/RateLongAggregator.java @@ -29,7 +29,6 @@ * This class is generated. Edit `X-RateAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "LONG_BLOCK"), diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/X-RateAggregator.java.st b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/X-RateAggregator.java.st index 639c7d4ab1831..748fc6b99a5ab 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/X-RateAggregator.java.st +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/X-RateAggregator.java.st @@ -34,7 +34,6 @@ import org.elasticsearch.core.Releasables; * This class is generated. Edit `X-RateAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "$TYPE$_BLOCK"), diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/X-ValueOverTimeAggregator.java.st b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/X-ValueOverTimeAggregator.java.st index 31633b151fa39..b517443ce8736 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/X-ValueOverTimeAggregator.java.st +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/X-ValueOverTimeAggregator.java.st @@ -28,7 +28,6 @@ import org.elasticsearch.core.Releasables; * This class is generated. Edit `X-ValueOverTimeAggregator.java.st` instead. */ @GroupingAggregator( - timeseries = true, value = { @IntermediateState(name = "timestamps", type = "LONG_BLOCK"), @IntermediateState(name = "values", type = "$TYPE$_BLOCK") } ) public class $Occurrence$OverTime$Type$Aggregator {