From 54d4da81d3fd3d2b62387cabac3f55d3f56f6d0a Mon Sep 17 00:00:00 2001 From: Larisa Motova Date: Mon, 22 Sep 2025 07:24:55 -1000 Subject: [PATCH 1/5] [ES|QL] Enable aggregate_metric_double outside of snapshots --- .../esql/_snippets/functions/types/absent.md | 1 + .../functions/types/absent_over_time.md | 1 + .../esql/_snippets/functions/types/avg.md | 1 + .../functions/types/avg_over_time.md | 1 + .../esql/_snippets/functions/types/count.md | 1 + .../functions/types/count_over_time.md | 1 + .../esql/_snippets/functions/types/max.md | 1 + .../functions/types/max_over_time.md | 1 + .../esql/_snippets/functions/types/min.md | 1 + .../functions/types/min_over_time.md | 1 + .../esql/_snippets/functions/types/present.md | 1 + .../functions/types/present_over_time.md | 1 + .../esql/_snippets/functions/types/sum.md | 1 + .../functions/types/sum_over_time.md | 1 + .../types/to_aggregate_metric_double.md | 12 +++ .../_snippets/functions/types/to_string.md | 1 + .../_snippets/operators/types/is_not_null.md | 1 + .../esql/_snippets/operators/types/is_null.md | 1 + .../kibana/definition/functions/absent.json | 12 +++ .../functions/absent_over_time.json | 12 +++ .../esql/kibana/definition/functions/avg.json | 12 +++ .../definition/functions/avg_over_time.json | 12 +++ .../kibana/definition/functions/count.json | 12 +++ .../definition/functions/count_over_time.json | 12 +++ .../esql/kibana/definition/functions/max.json | 12 +++ .../definition/functions/max_over_time.json | 12 +++ .../esql/kibana/definition/functions/min.json | 12 +++ .../definition/functions/min_over_time.json | 12 +++ .../kibana/definition/functions/present.json | 12 +++ .../functions/present_over_time.json | 12 +++ .../esql/kibana/definition/functions/sum.json | 12 +++ .../definition/functions/sum_over_time.json | 12 +++ .../functions/to_aggregate_metric_double.json | 63 ++++++++++++++- .../definition/functions/to_string.json | 12 +++ .../definition/operators/is_not_null.json | 12 +++ .../kibana/definition/operators/is_null.json | 12 +++ .../xpack/downsample/DownsampleIT.java | 6 +- .../esql/core/expression/TypeResolutions.java | 29 +++++++ .../esql/core/plugin/EsqlCorePlugin.java | 1 - .../xpack/esql/core/type/DataType.java | 1 - .../xpack/esql/qa/single_node/RestEsqlIT.java | 6 +- .../rest/generative/GenerativeRestTest.java | 2 +- .../src/main/resources/convert.csv-spec | 8 +- .../k8s-timeseries-absent-over-time.csv-spec | 4 +- .../k8s-timeseries-avg-over-time.csv-spec | 10 +-- .../k8s-timeseries-count-over-time.csv-spec | 6 +- .../k8s-timeseries-max-over-time.csv-spec | 10 +-- .../k8s-timeseries-min-over-time.csv-spec | 10 +-- .../k8s-timeseries-present-over-time.csv-spec | 4 +- .../k8s-timeseries-sum-over-time.csv-spec | 10 +-- .../src/main/resources/stats.csv-spec | 10 +-- .../xpack/esql/action/EsqlCapabilities.java | 37 ++++++--- .../expression/function/aggregate/Avg.java | 8 +- .../function/aggregate/AvgOverTime.java | 2 +- .../expression/function/aggregate/Sample.java | 7 +- .../expression/function/aggregate/Values.java | 2 +- .../function/scalar/conditional/Case.java | 12 ++- ...ingFromAggregateMetricDoubleEvaluator.java | 5 ++ .../function/scalar/multivalue/MvAppend.java | 6 +- .../scalar/multivalue/MvContains.java | 6 +- .../function/scalar/multivalue/MvCount.java | 4 +- .../function/scalar/multivalue/MvDedupe.java | 4 +- .../function/scalar/multivalue/MvFirst.java | 4 +- .../function/scalar/multivalue/MvLast.java | 4 +- .../function/scalar/multivalue/MvMax.java | 4 +- .../function/scalar/multivalue/MvMin.java | 4 +- .../function/scalar/multivalue/MvSlice.java | 4 +- .../xpack/esql/analysis/AnalyzerTests.java | 5 +- .../function/AbstractAggregationTestCase.java | 1 + .../function/MultiRowTestCaseSupplier.java | 81 +++++++++++++++++++ .../expression/function/TestCaseSupplier.java | 41 ++++++++++ .../function/aggregate/AbsentTests.java | 2 + .../function/aggregate/AvgTests.java | 20 ++++- .../function/aggregate/CountTests.java | 20 ++++- .../function/aggregate/MaxTests.java | 42 ++++++++-- .../function/aggregate/MinTests.java | 42 ++++++++-- .../function/aggregate/PresentTests.java | 2 + .../function/aggregate/SampleErrorTests.java | 4 +- .../function/aggregate/SumTests.java | 34 ++++++-- .../function/aggregate/ValuesErrorTests.java | 8 +- .../scalar/conditional/CaseErrorTests.java | 6 ++ .../convert/ToAggregateMetricDoubleTests.java | 7 ++ .../scalar/convert/ToStringTests.java | 7 ++ .../scalar/multivalue/MvAppendErrorTests.java | 6 ++ .../multivalue/MvContainsErrorTests.java | 6 ++ .../scalar/multivalue/MvCountErrorTests.java | 7 +- .../scalar/multivalue/MvDedupeErrorTests.java | 7 +- .../scalar/multivalue/MvFirstErrorTests.java | 7 +- .../scalar/multivalue/MvLastErrorTests.java | 7 +- .../scalar/multivalue/MvMaxErrorTests.java | 9 ++- .../scalar/multivalue/MvMinErrorTests.java | 9 ++- .../scalar/multivalue/MvSliceErrorTests.java | 5 ++ .../operator/comparison/EqualsErrorTests.java | 4 +- .../comparison/NotEqualsErrorTests.java | 4 +- ...IgnoreNullMetricsPhysicalPlannerTests.java | 6 +- .../test/esql/160_union_types.yml | 2 +- .../rest-api-spec/test/esql/40_tsdb.yml | 26 +++--- .../rest-api-spec/test/esql/46_downsample.yml | 20 ++--- 98 files changed, 814 insertions(+), 159 deletions(-) create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/to_aggregate_metric_double.md diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/absent.md b/docs/reference/query-languages/esql/_snippets/functions/types/absent.md index 626f34b097399..109575169eb59 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/absent.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/absent.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | boolean | | boolean | boolean | | cartesian_point | boolean | | cartesian_shape | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/absent_over_time.md b/docs/reference/query-languages/esql/_snippets/functions/types/absent_over_time.md index 626f34b097399..109575169eb59 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/absent_over_time.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/absent_over_time.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | boolean | | boolean | boolean | | cartesian_point | boolean | | cartesian_shape | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/avg.md b/docs/reference/query-languages/esql/_snippets/functions/types/avg.md index e204309f17bb1..d27a904332436 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/avg.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/avg.md @@ -4,6 +4,7 @@ | number | result | | --- | --- | +| aggregate_metric_double | double | | double | double | | integer | double | | long | double | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/avg_over_time.md b/docs/reference/query-languages/esql/_snippets/functions/types/avg_over_time.md index e204309f17bb1..d27a904332436 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/avg_over_time.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/avg_over_time.md @@ -4,6 +4,7 @@ | number | result | | --- | --- | +| aggregate_metric_double | double | | double | double | | integer | double | | long | double | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/count.md b/docs/reference/query-languages/esql/_snippets/functions/types/count.md index 175336bd98374..0cf690e810426 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/count.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/count.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | long | | boolean | long | | cartesian_point | long | | cartesian_shape | long | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/count_over_time.md b/docs/reference/query-languages/esql/_snippets/functions/types/count_over_time.md index 175336bd98374..0cf690e810426 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/count_over_time.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/count_over_time.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | long | | boolean | long | | cartesian_point | long | | cartesian_shape | long | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/max.md b/docs/reference/query-languages/esql/_snippets/functions/types/max.md index 3e79cc241a965..9ff4654e9b8c1 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/max.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/max.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | double | | boolean | boolean | | date | date | | date_nanos | date_nanos | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/max_over_time.md b/docs/reference/query-languages/esql/_snippets/functions/types/max_over_time.md index 3e79cc241a965..9ff4654e9b8c1 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/max_over_time.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/max_over_time.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | double | | boolean | boolean | | date | date | | date_nanos | date_nanos | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/min.md b/docs/reference/query-languages/esql/_snippets/functions/types/min.md index 3e79cc241a965..9ff4654e9b8c1 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/min.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/min.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | double | | boolean | boolean | | date | date | | date_nanos | date_nanos | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/min_over_time.md b/docs/reference/query-languages/esql/_snippets/functions/types/min_over_time.md index 3e79cc241a965..9ff4654e9b8c1 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/min_over_time.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/min_over_time.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | double | | boolean | boolean | | date | date | | date_nanos | date_nanos | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/present.md b/docs/reference/query-languages/esql/_snippets/functions/types/present.md index 626f34b097399..109575169eb59 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/present.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/present.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | boolean | | boolean | boolean | | cartesian_point | boolean | | cartesian_shape | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/present_over_time.md b/docs/reference/query-languages/esql/_snippets/functions/types/present_over_time.md index 626f34b097399..109575169eb59 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/present_over_time.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/present_over_time.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | boolean | | boolean | boolean | | cartesian_point | boolean | | cartesian_shape | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/sum.md b/docs/reference/query-languages/esql/_snippets/functions/types/sum.md index 01801c5c25b70..962f012aa445a 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/sum.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/sum.md @@ -4,6 +4,7 @@ | number | result | | --- | --- | +| aggregate_metric_double | double | | double | double | | integer | long | | long | long | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/sum_over_time.md b/docs/reference/query-languages/esql/_snippets/functions/types/sum_over_time.md index 28eaca7ce6c61..dce89b1781d85 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/sum_over_time.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/sum_over_time.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | double | | double | double | | integer | long | | long | long | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/to_aggregate_metric_double.md b/docs/reference/query-languages/esql/_snippets/functions/types/to_aggregate_metric_double.md new file mode 100644 index 0000000000000..1738fcb47e3e0 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/to_aggregate_metric_double.md @@ -0,0 +1,12 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| number | result | +| --- | --- | +| aggregate_metric_double | aggregate_metric_double | +| double | aggregate_metric_double | +| integer | aggregate_metric_double | +| long | aggregate_metric_double | +| unsigned_long | aggregate_metric_double | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/to_string.md b/docs/reference/query-languages/esql/_snippets/functions/types/to_string.md index 77fd3adaf8c56..295a2f70fe2bb 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/to_string.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | keyword | | boolean | keyword | | cartesian_point | keyword | | cartesian_shape | keyword | diff --git a/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md b/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md index 0a1179d8b1218..f13d2c67648c7 100644 --- a/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md +++ b/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | boolean | | boolean | boolean | | cartesian_point | boolean | | cartesian_shape | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md b/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md index 0a1179d8b1218..f13d2c67648c7 100644 --- a/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md +++ b/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md @@ -4,6 +4,7 @@ | field | result | | --- | --- | +| aggregate_metric_double | boolean | | boolean | boolean | | cartesian_point | boolean | | cartesian_shape | boolean | diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/absent.json b/docs/reference/query-languages/esql/kibana/definition/functions/absent.json index 281dd189f9cba..aa52950cebd1a 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/absent.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/absent.json @@ -4,6 +4,18 @@ "name" : "absent", "description" : "Returns true if the input expression yields no non-null values within the current aggregation context. Otherwise it returns false.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "Expression that outputs values to be checked for absence." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/absent_over_time.json b/docs/reference/query-languages/esql/kibana/definition/functions/absent_over_time.json index 879918c653dda..5285538b87a8e 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/absent_over_time.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/absent_over_time.json @@ -4,6 +4,18 @@ "name" : "absent_over_time", "description" : "Calculates the absence of a field in the output result over time range.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/avg.json b/docs/reference/query-languages/esql/kibana/definition/functions/avg.json index 9af4ac38896c9..aa90ce69b4c18 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/avg.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/avg.json @@ -4,6 +4,18 @@ "name" : "avg", "description" : "The average of a numeric field.", "signatures" : [ + { + "params" : [ + { + "name" : "number", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "Expression that outputs values to average." + } + ], + "variadic" : false, + "returnType" : "double" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/avg_over_time.json b/docs/reference/query-languages/esql/kibana/definition/functions/avg_over_time.json index 5f449bb6459f5..12b861bc01e22 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/avg_over_time.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/avg_over_time.json @@ -4,6 +4,18 @@ "name" : "avg_over_time", "description" : "Calculates the average over time of a numeric field.", "signatures" : [ + { + "params" : [ + { + "name" : "number", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "Expression that outputs values to average." + } + ], + "variadic" : false, + "returnType" : "double" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/count.json b/docs/reference/query-languages/esql/kibana/definition/functions/count.json index 4510ef427fbda..7c9d570069cff 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/count.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/count.json @@ -4,6 +4,18 @@ "name" : "count", "description" : "Returns the total number (count) of input values.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : true, + "description" : "Expression that outputs values to be counted. If omitted, equivalent to `COUNT(*)` (the number of rows)." + } + ], + "variadic" : false, + "returnType" : "long" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/count_over_time.json b/docs/reference/query-languages/esql/kibana/definition/functions/count_over_time.json index efdc885ee1265..846c074fb62f7 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/count_over_time.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/count_over_time.json @@ -4,6 +4,18 @@ "name" : "count_over_time", "description" : "Calculates the count over time value of a field.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "long" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/max.json b/docs/reference/query-languages/esql/kibana/definition/functions/max.json index e30651b6f3842..844448f1e7755 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/max.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/max.json @@ -4,6 +4,18 @@ "name" : "max", "description" : "The maximum value of a field.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "double" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/max_over_time.json b/docs/reference/query-languages/esql/kibana/definition/functions/max_over_time.json index 340e6543a4e3f..6552ef6d941ca 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/max_over_time.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/max_over_time.json @@ -4,6 +4,18 @@ "name" : "max_over_time", "description" : "Calculates the maximum over time value of a field.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "double" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/min.json b/docs/reference/query-languages/esql/kibana/definition/functions/min.json index e9569a85c6c26..8c90393a0bc36 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/min.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/min.json @@ -4,6 +4,18 @@ "name" : "min", "description" : "The minimum value of a field.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "double" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/min_over_time.json b/docs/reference/query-languages/esql/kibana/definition/functions/min_over_time.json index ab34295c27765..062bd0757508d 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/min_over_time.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/min_over_time.json @@ -4,6 +4,18 @@ "name" : "min_over_time", "description" : "Calculates the minimum over time value of a field.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "double" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/present.json b/docs/reference/query-languages/esql/kibana/definition/functions/present.json index d75d787b4762c..0dc48a0bed330 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/present.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/present.json @@ -4,6 +4,18 @@ "name" : "present", "description" : "Returns true if the input expression yields any non-null values within the current aggregation context. Otherwise it returns false.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "Expression that outputs values to be checked for presence." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/present_over_time.json b/docs/reference/query-languages/esql/kibana/definition/functions/present_over_time.json index 87a66d4a49ef5..b22a6fa705197 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/present_over_time.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/present_over_time.json @@ -4,6 +4,18 @@ "name" : "present_over_time", "description" : "Calculates the presence of a field in the output result over time range.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/sum.json b/docs/reference/query-languages/esql/kibana/definition/functions/sum.json index bb071eac9c627..5549f37d47e44 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/sum.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/sum.json @@ -4,6 +4,18 @@ "name" : "sum", "description" : "The sum of a numeric expression.", "signatures" : [ + { + "params" : [ + { + "name" : "number", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "double" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/sum_over_time.json b/docs/reference/query-languages/esql/kibana/definition/functions/sum_over_time.json index 2888b2caded55..3e7ef74e5c8a4 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/sum_over_time.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/sum_over_time.json @@ -4,6 +4,18 @@ "name" : "sum_over_time", "description" : "Calculates the sum over time value of a field.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "double" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/to_aggregate_metric_double.json b/docs/reference/query-languages/esql/kibana/definition/functions/to_aggregate_metric_double.json index 64ae79a76061e..a18f5cc04578e 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/to_aggregate_metric_double.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/to_aggregate_metric_double.json @@ -3,7 +3,68 @@ "type" : "scalar", "name" : "to_aggregate_metric_double", "description" : "Encode a numeric to an aggregate_metric_double.", - "signatures" : [ ], + "signatures" : [ + { + "params" : [ + { + "name" : "number", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "aggregate_metric_double" + }, + { + "params" : [ + { + "name" : "number", + "type" : "double", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "aggregate_metric_double" + }, + { + "params" : [ + { + "name" : "number", + "type" : "integer", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "aggregate_metric_double" + }, + { + "params" : [ + { + "name" : "number", + "type" : "long", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "aggregate_metric_double" + }, + { + "params" : [ + { + "name" : "number", + "type" : "unsigned_long", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "aggregate_metric_double" + } + ], "examples" : [ "ROW x = 3892095203\n| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)", "ROW x = [5032, 11111, 40814]\n| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)" diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/to_string.json b/docs/reference/query-languages/esql/kibana/definition/functions/to_string.json index 7e81f967db12e..7837fa4c8990c 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/to_string.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/to_string.json @@ -4,6 +4,18 @@ "name" : "to_string", "description" : "Converts an input value into a string.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json b/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json index c3cc8fae2a14e..76d442723d5a9 100644 --- a/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json +++ b/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json @@ -6,6 +6,18 @@ "description" : "Returns `false` if the value is `NULL`, `true` otherwise.", "note" : "If a field is only in some documents it will be `NULL` in the documents that did not contain it.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json b/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json index 08c98810ddede..e60f5e6290404 100644 --- a/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json +++ b/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json @@ -6,6 +6,18 @@ "description" : "Returns `true` if the value is `NULL`, `false` otherwise.", "note" : "If a field is only in some documents it will be `NULL` in the documents that did not contain it.", "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "aggregate_metric_double", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/x-pack/plugin/downsample/src/internalClusterTest/java/org/elasticsearch/xpack/downsample/DownsampleIT.java b/x-pack/plugin/downsample/src/internalClusterTest/java/org/elasticsearch/xpack/downsample/DownsampleIT.java index fb8639320523c..9fc8fdfca9830 100644 --- a/x-pack/plugin/downsample/src/internalClusterTest/java/org/elasticsearch/xpack/downsample/DownsampleIT.java +++ b/x-pack/plugin/downsample/src/internalClusterTest/java/org/elasticsearch/xpack/downsample/DownsampleIT.java @@ -36,7 +36,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.xpack.downsample.DownsampleDataStreamTests.TIMEOUT; -import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.AGGREGATE_METRIC_DOUBLE_IMPLICIT_CASTING_IN_AGGS; +import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.AGGREGATE_METRIC_DOUBLE_V0; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; @@ -225,11 +225,11 @@ public void testAggMetricInEsqlTSAfterDownsampling() throws Exception { }; bulkIndex(dataStreamName, nextSourceSupplier, 100); - // check that TS command is available + // check that aggregate metric double is available var response = clusterAdmin().nodesCapabilities( new NodesCapabilitiesRequest().method(RestRequest.Method.POST) .path("/_query") - .capabilities(AGGREGATE_METRIC_DOUBLE_IMPLICIT_CASTING_IN_AGGS.capabilityName()) + .capabilities(AGGREGATE_METRIC_DOUBLE_V0.capabilityName()) ).actionGet(); assumeTrue("Require aggregate_metric_double casting", response.isSupported().orElse(Boolean.FALSE)); diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java index c0ca5d18dc63d..75028cd801862 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java @@ -18,6 +18,7 @@ import static org.elasticsearch.common.logging.LoggerMessageFormat.format; import static org.elasticsearch.xpack.esql.core.expression.Expressions.name; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT; +import static org.elasticsearch.xpack.esql.core.type.DataType.AGGREGATE_METRIC_DOUBLE; import static org.elasticsearch.xpack.esql.core.type.DataType.BOOLEAN; import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; import static org.elasticsearch.xpack.esql.core.type.DataType.IP; @@ -79,6 +80,34 @@ public static TypeResolution isRepresentableExceptCounters(Expression e, String return isType(e, DataType::isRepresentable, operationName, paramOrd, "any type except counter types"); } + public static TypeResolution isRepresentableExceptCountersAndAggregateMetricDouble( + Expression e, + String operationName, + ParamOrdinal paramOrd + ) { + return isType( + e, + (t) -> t != AGGREGATE_METRIC_DOUBLE && DataType.isRepresentable(t), + operationName, + paramOrd, + "any type except counter types and aggregate metric double" + ); + } + + public static TypeResolution isRepresentableExceptCountersAndSpatialAndAggregateMetricDouble( + Expression e, + String operationName, + ParamOrdinal paramOrd + ) { + return isType( + e, + (t) -> t != AGGREGATE_METRIC_DOUBLE && isSpatialOrGrid(t) == false && DataType.isRepresentable(t), + operationName, + paramOrd, + "any type except counter and spatial types and aggregate metric double" + ); + } + public static TypeResolution isRepresentableExceptCountersAndSpatial(Expression e, String operationName, ParamOrdinal paramOrd) { return isType( e, diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java index b9f55f7985e84..53607f96f0b36 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java @@ -13,6 +13,5 @@ public class EsqlCorePlugin extends Plugin implements ExtensiblePlugin { - public static final FeatureFlag AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG = new FeatureFlag("esql_aggregate_metric_double"); public static final FeatureFlag DENSE_VECTOR_FEATURE_FLAG = new FeatureFlag("esql_dense_vector"); } diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java index 7a7d5e15e5a9e..dd0d7ad0a4a05 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java @@ -349,7 +349,6 @@ public enum DataType implements Writeable { * */ public static final Map UNDER_CONSTRUCTION = Map.ofEntries( - Map.entry(AGGREGATE_METRIC_DOUBLE, EsqlCorePlugin.AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), Map.entry(DENSE_VECTOR, EsqlCorePlugin.DENSE_VECTOR_FEATURE_FLAG) ); diff --git a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java index 0e26663579c88..21418ec533663 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java @@ -27,7 +27,7 @@ import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.xcontent.json.JsonXContent; -import org.elasticsearch.xpack.esql.core.plugin.EsqlCorePlugin; +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.qa.rest.RestEsqlTestCase; import org.elasticsearch.xpack.esql.tools.ProfileParser; @@ -743,7 +743,7 @@ public void testSuggestedCast() throws IOException { } """) ); - if (EsqlCorePlugin.AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG.isEnabled()) { + if (EsqlCapabilities.Cap.AGGREGATE_METRIC_DOUBLE_V0.isEnabled()) { typesAndValues = new HashMap<>(typesAndValues); typesAndValues.put(DataType.AGGREGATE_METRIC_DOUBLE, """ { @@ -761,7 +761,7 @@ public void testSuggestedCast() throws IOException { shouldBeSupported.remove(DataType.DOC_DATA_TYPE); shouldBeSupported.remove(DataType.TSID_DATA_TYPE); shouldBeSupported.remove(DataType.DENSE_VECTOR); - if (EsqlCorePlugin.AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG.isEnabled() == false) { + if (EsqlCapabilities.Cap.AGGREGATE_METRIC_DOUBLE_V0.isEnabled() == false) { shouldBeSupported.remove(DataType.AGGREGATE_METRIC_DOUBLE); } for (DataType type : shouldBeSupported) { diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeRestTest.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeRestTest.java index c1634bf9885fb..bd9f9add8ea09 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeRestTest.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeRestTest.java @@ -71,7 +71,7 @@ public abstract class GenerativeRestTest extends ESRestTestCase implements Query "Expecting at most \\[.*\\] columns, got \\[.*\\]", // https://github.com/elastic/elasticsearch/issues/129561 // TS-command tests - "time-series .* the first aggregation .* is not allowed", + "time-series.*the first aggregation.*is not allowed", "count_star .* can't be used with TS command", "time_series aggregate.* can only be used with the TS command", "Invalid call to dataType on an unresolved object \\?LASTOVERTIME", // https://github.com/elastic/elasticsearch/issues/134791 diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/convert.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/convert.csv-spec index 0ca39652cbd42..cfb9dbcfb69f2 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/convert.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/convert.csv-spec @@ -455,7 +455,7 @@ emp_no:integer | birth_date:datetime ; convertToAggregateMetricDouble -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 //tag::toAggregateMetricDouble[] ROW x = 3892095203 | EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x) @@ -469,7 +469,7 @@ x:long | agg_metric:aggregate_metric_double ; convertToAggregateMetricDoubleMv -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 //tag::toAggregateMetricDoubleMv[] ROW x = [5032, 11111, 40814] | EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x) @@ -484,7 +484,7 @@ x:integer | agg_metric:aggregate_metric_double convertToAggregateMetricDoubleCastingOperatorFromDouble required_capability: suggested_cast -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 ROW x = 29384.1256 | EVAL agg_metric = x::aggregate_metric_double ; @@ -495,7 +495,7 @@ x:double | agg_metric:aggregate_metric_double convertToAggregateMetricDoubleCastingOperatorFromInt required_capability: suggested_cast -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 ROW x = 55555 | EVAL agg_metric = x::aggregate_metric_double ; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-absent-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-absent-over-time.csv-spec index 0ad2659b49714..e96d5e74d1c3a 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-absent-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-absent-over-time.csv-spec @@ -165,7 +165,7 @@ false | staging | 2024-05-10T00:20:00.000Z absent_over_time_of_aggregate_metric_double required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS is_present = max(absent_over_time(network.eth0.tx)) BY cluster, time_bucket = tbucket(10 minute) | SORT time_bucket, cluster | LIMIT 10; is_present:boolean | cluster:keyword | time_bucket:datetime @@ -271,7 +271,7 @@ false | staging | 2024-05-10T00:20:00.000Z absent_over_time_older_than_10d required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | WHERE cluster == "qa" AND @timestamp < now() - 10 day | STATS is_present = max(absent_over_time(network.eth0.rx)) BY pod, time_bucket = tbucket(10 minute) | SORT time_bucket, pod | LIMIT 5; is_present:boolean | pod:keyword | time_bucket:datetime diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-avg-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-avg-over-time.csv-spec index cd219e59fb241..d3c0fd2cf6db2 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-avg-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-avg-over-time.csv-spec @@ -54,7 +54,7 @@ clients:double | cluster:keyword | time_bucket:datetime avg_over_time_of_aggregate_metric_double required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(avg_over_time(network.eth0.tx)) BY time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket | LIMIT 10; tx:double | time_bucket:datetime 4362.2 | 2024-05-09T23:30:00.000Z @@ -64,7 +64,7 @@ tx:double | time_bucket:datetime avg_over_time_of_aggregate_metric_double_grouping required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(avg_over_time(network.eth0.tx)) BY cluster, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, cluster | LIMIT 10; tx:double | cluster:keyword | time_bucket:datetime @@ -113,7 +113,7 @@ tx:double | cluster:keyword | time_bucket:datetime avg_over_time_older_than_10d required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | WHERE cluster == "qa" AND @timestamp < now() - 10 day | STATS cost = avg(avg_over_time(network.eth0.rx)) BY pod, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, pod | LIMIT 5; cost:double | pod:keyword | time_bucket:datetime @@ -192,7 +192,7 @@ events:double | pod:keyword | time_bucket:datetime avg_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 -required_capability: aggregate_metric_double_implicit_casting_in_aggs +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(avg_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; bytes:double | time_bucket:datetime @@ -206,7 +206,7 @@ bytes:double | time_bucket:datetime avg_over_time_aggregate_metric_double_implicit_casting_grouping required_capability: ts_command_v0 -required_capability: aggregate_metric_double_implicit_casting_in_aggs +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(avg_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; bytes:double | pod:keyword | time_bucket:datetime diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-count-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-count-over-time.csv-spec index 7b7f9cd8472fb..901997aedcf9a 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-count-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-count-over-time.csv-spec @@ -144,7 +144,7 @@ pod:long | cluster:keyword | time_bucket:datetime count_over_time_of_aggregate_metric_double required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(count_over_time(network.eth0.tx)) BY cluster, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, cluster | LIMIT 10; tx:long | cluster:keyword | time_bucket:datetime @@ -241,7 +241,7 @@ tx:long | cluster:keyword | time_bucket:datetime count_over_time_older_than_10d required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | WHERE cluster == "qa" AND @timestamp < now() - 10 day | STATS cost = avg(count_over_time(network.eth0.rx)) BY pod, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, pod | LIMIT 5; cost:double | pod:keyword | time_bucket:datetime @@ -321,7 +321,7 @@ events:long | pod:keyword | time_bucket:datetime count_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 -required_capability: aggregate_metric_double_implicit_casting_in_aggs +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(count_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes, pod, time_bucket | LIMIT 10 ; bytes:long | pod:keyword | time_bucket:datetime diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-max-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-max-over-time.csv-spec index 966437cd357c7..559f5610ae87f 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-max-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-max-over-time.csv-spec @@ -290,7 +290,7 @@ one | staging | 2024-05-10T00:03:00.000Z max_over_time_of_aggregate_metric_double required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(max_over_time(network.eth0.tx)) BY time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket | LIMIT 10; tx:double | time_bucket:datetime 6053.0 | 2024-05-09T23:30:00.000Z @@ -300,7 +300,7 @@ tx:double | time_bucket:datetime max_over_time_of_aggregate_metric_double_grouping required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(max_over_time(network.eth0.tx)) BY cluster, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, cluster | LIMIT 10; tx:double | cluster:keyword | time_bucket:datetime @@ -333,7 +333,7 @@ tx:long | cluster:keyword | time_bucket:datetime max_over_time_older_than_10h required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | WHERE cluster == "qa" AND @timestamp < now() - 10 day | STATS cost = avg(max_over_time(network.eth0.rx)) BY pod, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, pod | LIMIT 5; cost:double | pod:keyword | time_bucket:datetime @@ -429,7 +429,7 @@ events:long | pod:keyword | time_bucket:datetime max_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 -required_capability: aggregate_metric_double_implicit_casting_in_aggs +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(max_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; bytes:double | time_bucket:datetime @@ -443,7 +443,7 @@ bytes:double | time_bucket:datetime max_over_time_aggregate_metric_double_implicit_casting_grouping required_capability: ts_command_v0 -required_capability: aggregate_metric_double_implicit_casting_in_aggs +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(max_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; bytes:double | pod:keyword | time_bucket:datetime diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-min-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-min-over-time.csv-spec index 6a27b1ba3d0fb..01e46e10d05fa 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-min-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-min-over-time.csv-spec @@ -283,7 +283,7 @@ one | staging | 2024-05-10T00:03:00.000Z min_over_time_of_aggregate_metric_double required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(min_over_time(network.eth0.tx)) BY time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket | LIMIT 10; tx:double | time_bucket:datetime @@ -294,7 +294,7 @@ tx:double | time_bucket:datetime min_over_time_of_aggregate_metric_double_grouping required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(min_over_time(network.eth0.tx)) BY cluster, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, cluster | LIMIT 10; tx:double | cluster:keyword | time_bucket:datetime @@ -327,7 +327,7 @@ tx:long | cluster:keyword | time_bucket:datetime min_over_time_older_than_10h required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | WHERE cluster == "qa" AND @timestamp < now() - 10 day | STATS cost = avg(min_over_time(network.eth0.rx)) BY pod, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, pod | LIMIT 5; cost:double | pod:keyword | time_bucket:datetime @@ -407,7 +407,7 @@ events:long | pod:keyword | time_bucket:datetime min_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 -required_capability: aggregate_metric_double_implicit_casting_in_aggs +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(min_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes, time_bucket | LIMIT 10 ; bytes:double | time_bucket:datetime @@ -421,7 +421,7 @@ bytes:double | time_bucket:datetime min_over_time_aggregate_metric_double_implicit_casting_grouping required_capability: ts_command_v0 -required_capability: aggregate_metric_double_implicit_casting_in_aggs +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(min_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes, pod, time_bucket | LIMIT 10 ; bytes:double | pod:keyword | time_bucket:datetime diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-present-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-present-over-time.csv-spec index 48cd8d39dab79..a19edd95652b1 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-present-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-present-over-time.csv-spec @@ -153,7 +153,7 @@ true | staging | 2024-05-10T00:20:00.000Z present_over_time_of_aggregate_metric_double required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS is_present = max(present_over_time(network.eth0.tx)) BY cluster, time_bucket = tbucket(10 minute) | SORT time_bucket, cluster | LIMIT 10; is_present:boolean | cluster:keyword | time_bucket:datetime @@ -250,7 +250,7 @@ true | staging | 2024-05-10T00:20:00.000Z present_over_time_older_than_10d required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | WHERE cluster == "qa" AND @timestamp < now() - 10 day | STATS is_present = max(present_over_time(network.eth0.rx)) BY pod, time_bucket = tbucket(10 minute) | SORT time_bucket, pod | LIMIT 5; is_present:boolean | pod:keyword | time_bucket:datetime diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-sum-over-time.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-sum-over-time.csv-spec index cbd2369056a92..cea9ef27c656f 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-sum-over-time.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-sum-over-time.csv-spec @@ -53,7 +53,7 @@ clients:double | cluster:keyword | time_bucket:datetime sum_over_time_of_aggregate_metric_double required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(sum_over_time(network.eth0.tx)) BY time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket | LIMIT 10; tx:double | time_bucket:datetime @@ -64,7 +64,7 @@ tx:double | time_bucket:datetime sum_over_time_of_aggregate_metric_double_grouping required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | STATS tx = sum(sum_over_time(network.eth0.tx)) BY cluster, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, cluster | LIMIT 10; tx:double | cluster:keyword | time_bucket:datetime @@ -97,7 +97,7 @@ tx:long | cluster:keyword | time_bucket:datetime sum_over_time_older_than_10d required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s-downsampled | WHERE cluster == "qa" AND @timestamp < now() - 10 day | STATS cost = avg(sum_over_time(network.eth0.rx)) BY pod, time_bucket = bucket(@timestamp, 10minute) | SORT time_bucket, pod | LIMIT 5; cost:double | pod:keyword | time_bucket:datetime @@ -176,7 +176,7 @@ events:long | pod:keyword | time_bucket:datetime sum_over_time_aggregate_metric_double_implicit_casting required_capability: ts_command_v0 -required_capability: aggregate_metric_double +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(sum_over_time(network.eth0.rx)) by time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, time_bucket | LIMIT 10 ; bytes:double | time_bucket:datetime @@ -190,7 +190,7 @@ bytes:double | time_bucket:datetime sum_over_time_aggregate_metric_double_implicit_casting_grouping required_capability: ts_command_v0 -required_capability: aggregate_metric_double_implicit_casting_in_aggs +required_capability: aggregate_metric_double_v0 TS k8s* | STATS bytes = sum(sum_over_time(network.eth0.rx)) by pod, time_bucket = bucket(@timestamp, 10minute) | SORT bytes desc, pod, time_bucket | LIMIT 10 ; bytes:double | pod:keyword | time_bucket:datetime diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats.csv-spec index 5ceb8d92f6dda..a386b638b46e7 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/stats.csv-spec @@ -3162,7 +3162,7 @@ m:datetime | x:integer | d:boolean sumWithConditions required_capability: stats_with_filtered_surrogate_fixed -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 FROM employees | EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(1) @@ -3197,7 +3197,7 @@ w_avg1:double | w_avg2:double | w_avg3:double | w_avg4:double | w_avg5:double | maxWithConditions required_capability: stats_with_filtered_surrogate_fixed -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 ROW x = [1, 2, 3, 4, 5] | MV_EXPAND x @@ -3214,7 +3214,7 @@ max1:double | max2:double | max3:integer | max4:integer minWithConditions required_capability: stats_with_filtered_surrogate_fixed -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 ROW x = [1, 2, 3, 4, 5] | MV_EXPAND x @@ -3231,7 +3231,7 @@ min1:double | min2:double | min3:integer | min4:integer countWithConditions required_capability: stats_with_filtered_surrogate_fixed -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 ROW x = [1, 2, 3, 4, 5] | MV_EXPAND x @@ -3267,7 +3267,7 @@ count1:long | count2:long | count3:long | count4:long avgWithConditions required_capability: stats_with_filtered_surrogate_fixed -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 ROW x = [1, 2, 3, 4, 5] | MV_EXPAND x diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 6d6ba59abac19..2c79657a13a99 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -20,8 +20,6 @@ import java.util.Locale; import java.util.Set; -import static org.elasticsearch.xpack.esql.core.plugin.EsqlCorePlugin.AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG; - /** * A {@link Set} of "capabilities" supported by the {@link RestEsqlQueryAction} * and {@link RestEsqlAsyncQueryAction} APIs. These are exposed over the @@ -933,53 +931,68 @@ public enum Cap { /** * Support for aggregate_metric_double type */ - AGGREGATE_METRIC_DOUBLE(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE, /** * Support for partial subset of metrics in aggregate_metric_double type */ - AGGREGATE_METRIC_DOUBLE_PARTIAL_SUBMETRICS(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_PARTIAL_SUBMETRICS, /** * Support for rendering aggregate_metric_double type */ - AGGREGATE_METRIC_DOUBLE_RENDERING(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_RENDERING, /** * Support for to_aggregate_metric_double function */ - AGGREGATE_METRIC_DOUBLE_CONVERT_TO(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_CONVERT_TO, /** * Support for sorting when aggregate_metric_doubles are present */ - AGGREGATE_METRIC_DOUBLE_SORTING(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_SORTING, /** * Support avg with aggregate metric doubles */ - AGGREGATE_METRIC_DOUBLE_AVG(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_AVG, /** * Support for implicit casting of aggregate metric double when run in aggregations */ - AGGREGATE_METRIC_DOUBLE_IMPLICIT_CASTING_IN_AGGS(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_IMPLICIT_CASTING_IN_AGGS, /** * Fixes bug when aggregate metric double is encoded as a single nul value but decoded as * AggregateMetricDoubleBlock (expecting 4 values) in TopN. */ - AGGREGATE_METRIC_DOUBLE_SORTING_FIXED(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_SORTING_FIXED, /** * Stop erroring out when trying to apply MV_EXPAND on aggregate metric double. */ - AGGREGATE_METRIC_DOUBLE_MV_EXPAND(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_MV_EXPAND, /** * Registering AggregateMetricDoubleLiteral as a NamedWritable. */ - AGGREGATE_METRIC_DOUBLE_LITERAL_REGISTERED(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG), + @Deprecated + AGGREGATE_METRIC_DOUBLE_LITERAL_REGISTERED, + + /** + * Enable aggregate_metric_double in non-snapshot builds + */ + AGGREGATE_METRIC_DOUBLE_V0, /** * Support change point detection "CHANGE_POINT". diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Avg.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Avg.java index f9f5bcf23ce7d..5616b0947077c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Avg.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Avg.java @@ -71,7 +71,7 @@ public Expression summationMode() { protected Expression.TypeResolution resolveType() { return isType( field(), - dt -> dt.isNumeric() && dt != DataType.UNSIGNED_LONG || dt == AGGREGATE_METRIC_DOUBLE, + dt -> (dt.isNumeric() && dt != DataType.UNSIGNED_LONG) || dt == AGGREGATE_METRIC_DOUBLE, sourceText(), DEFAULT, "aggregate_metric_double or numeric except unsigned_long or counter types" @@ -115,12 +115,12 @@ public Avg withFilter(Expression filter) { public Expression surrogate() { var s = source(); var field = field(); - if (field.foldable()) { - return new MvAvg(s, field); - } if (field.dataType() == AGGREGATE_METRIC_DOUBLE) { return new Div(s, new Sum(s, field, filter(), summationMode).surrogate(), new Count(s, field, filter()).surrogate()); } + if (field.foldable()) { + return new MvAvg(s, field); + } return new Div(s, new Sum(s, field, filter(), summationMode), new Count(s, field, filter()), dataType()); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgOverTime.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgOverTime.java index b1c92c3f6dafd..942d5551ea9e5 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgOverTime.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgOverTime.java @@ -49,7 +49,7 @@ public AvgOverTime( Source source, @Param( name = "number", - type = { "double", "integer", "long" }, + type = { "aggregate_metric_double", "double", "integer", "long" }, description = "Expression that outputs values to average." ) Expression field ) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java index 1ed7e439a9f06..19bb06064d9e9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java @@ -40,7 +40,7 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNotNull; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCounters; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; import static org.elasticsearch.xpack.esql.expression.Foldables.TypeResolutionValidator.forPostOptimizationValidation; import static org.elasticsearch.xpack.esql.expression.Foldables.TypeResolutionValidator.forPreOptimizationValidation; @@ -126,8 +126,9 @@ protected TypeResolution resolveType() { if (childrenResolved() == false) { return new TypeResolution("Unresolved children"); } - var typeResolution = isRepresentableExceptCounters(field(), sourceText(), FIRST).and(isNotNull(limitField(), sourceText(), SECOND)) - .and(isType(limitField(), dt -> dt == DataType.INTEGER, sourceText(), SECOND, "integer")); + var typeResolution = isRepresentableExceptCountersAndAggregateMetricDouble(field(), sourceText(), FIRST).and( + isNotNull(limitField(), sourceText(), SECOND) + ).and(isType(limitField(), dt -> dt == DataType.INTEGER, sourceText(), SECOND, "integer")); if (typeResolution.unresolved()) { return typeResolution; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java index 863a9d2d2d58d..ac9fb5f2b0a23 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java @@ -165,7 +165,7 @@ public DataType dataType() { @Override protected TypeResolution resolveType() { - return TypeResolutions.isRepresentableExceptCounters(field(), sourceText(), DEFAULT); + return TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble(field(), sourceText(), DEFAULT); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/Case.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/Case.java index 3f5cfea2e7443..9701671f22e33 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/Case.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/Case.java @@ -46,6 +46,7 @@ import java.util.stream.Stream; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; +import static org.elasticsearch.xpack.esql.core.type.DataType.AGGREGATE_METRIC_DOUBLE; import static org.elasticsearch.xpack.esql.core.type.DataType.NULL; public final class Case extends EsqlScalarFunction { @@ -202,12 +203,19 @@ protected TypeResolution resolveType() { private TypeResolution resolveValueType(Expression value, int position) { if (dataType == null || dataType == NULL) { + boolean originalWasNull = dataType == NULL; dataType = value.dataType().noText(); - return TypeResolution.TYPE_RESOLVED; + return TypeResolutions.isType( + value, + t -> t != AGGREGATE_METRIC_DOUBLE, + sourceText(), + TypeResolutions.ParamOrdinal.fromIndex(position), + originalWasNull ? NULL.typeName() : "any but aggregate_metric_double" + ); } return TypeResolutions.isType( value, - t -> t.noText() == dataType, + t -> t.noText() == dataType && t != AGGREGATE_METRIC_DOUBLE, sourceText(), TypeResolutions.ParamOrdinal.fromIndex(position), dataType.typeName() diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringFromAggregateMetricDoubleEvaluator.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringFromAggregateMetricDoubleEvaluator.java index 2d8ffbd34b649..99576de84af9f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringFromAggregateMetricDoubleEvaluator.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringFromAggregateMetricDoubleEvaluator.java @@ -90,5 +90,10 @@ public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field) { public EvalOperator.ExpressionEvaluator get(DriverContext context) { return new ToStringFromAggregateMetricDoubleEvaluator(source, field.get(context), context); } + + @Override + public String toString() { + return "ToStringFromAggregateMetricDoubleEvaluator[field=" + field + "]"; + } } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppend.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppend.java index a950fca954101..670fcba569060 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppend.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppend.java @@ -40,7 +40,7 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCounters; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; /** @@ -148,14 +148,14 @@ protected TypeResolution resolveType() { return new TypeResolution("Unresolved children"); } - TypeResolution resolution = isRepresentableExceptCounters(field1, sourceText(), FIRST); + TypeResolution resolution = isRepresentableExceptCountersAndAggregateMetricDouble(field1, sourceText(), FIRST); if (resolution.unresolved()) { return resolution; } dataType = field1.dataType().noText(); if (dataType == DataType.NULL) { dataType = field2.dataType().noText(); - return isRepresentableExceptCounters(field2, sourceText(), SECOND); + return isRepresentableExceptCountersAndAggregateMetricDouble(field2, sourceText(), SECOND); } return isType(field2, t -> t.noText() == dataType, sourceText(), SECOND, dataType.typeName()); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContains.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContains.java index 052dac0d68b1c..3ec100c0b7e42 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContains.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContains.java @@ -44,7 +44,7 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCounters; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; /** @@ -147,12 +147,12 @@ protected TypeResolution resolveType() { return new TypeResolution("Unresolved children"); } - TypeResolution resolution = isRepresentableExceptCounters(left(), sourceText(), FIRST); + TypeResolution resolution = isRepresentableExceptCountersAndAggregateMetricDouble(left(), sourceText(), FIRST); if (resolution.unresolved()) { return resolution; } if (left().dataType() == DataType.NULL) { - return isRepresentableExceptCounters(right(), sourceText(), SECOND); + return isRepresentableExceptCountersAndAggregateMetricDouble(right(), sourceText(), SECOND); } return isType(right(), t -> t.noText() == left().dataType().noText(), sourceText(), SECOND, left().dataType().noText().typeName()); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCount.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCount.java index aa6049207fa05..07f51da0de859 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCount.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCount.java @@ -26,7 +26,7 @@ import java.util.List; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCounters; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble; /** * Reduce a multivalued field to a single valued field containing the count of values. @@ -79,7 +79,7 @@ public String getWriteableName() { @Override protected TypeResolution resolveFieldType() { - return isRepresentableExceptCounters(field(), sourceText(), DEFAULT); + return isRepresentableExceptCountersAndAggregateMetricDouble(field(), sourceText(), DEFAULT); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupe.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupe.java index c7b7ea0523a45..51559d9cf2dc3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupe.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupe.java @@ -23,7 +23,7 @@ import java.util.List; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCounters; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble; /** * Removes duplicate values from a multivalued field. @@ -95,7 +95,7 @@ public String getWriteableName() { @Override protected TypeResolution resolveFieldType() { - return isRepresentableExceptCounters(field(), sourceText(), DEFAULT); + return isRepresentableExceptCountersAndAggregateMetricDouble(field(), sourceText(), DEFAULT); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirst.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirst.java index 7afcf0a1641cc..723208e2dcc42 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirst.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirst.java @@ -31,7 +31,7 @@ import java.util.List; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCounters; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble; /** * Reduce a multivalued field to a single valued field containing the minimum value. @@ -110,7 +110,7 @@ public String getWriteableName() { @Override protected TypeResolution resolveFieldType() { - return isRepresentableExceptCounters(field(), sourceText(), DEFAULT); + return isRepresentableExceptCountersAndAggregateMetricDouble(field(), sourceText(), DEFAULT); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLast.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLast.java index bbcc6367784d4..cbd7476fa8016 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLast.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLast.java @@ -31,7 +31,7 @@ import java.util.List; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCounters; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble; /** * Reduce a multivalued field to a single valued field containing the minimum value. @@ -110,7 +110,7 @@ public String getWriteableName() { @Override protected TypeResolution resolveFieldType() { - return isRepresentableExceptCounters(field(), sourceText(), DEFAULT); + return isRepresentableExceptCountersAndAggregateMetricDouble(field(), sourceText(), DEFAULT); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMax.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMax.java index fc8281188c067..8dfae4d99b89e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMax.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMax.java @@ -26,7 +26,7 @@ import java.util.List; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndSpatial; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndSpatialAndAggregateMetricDouble; /** * Reduce a multivalued field to a single valued field containing the maximum value. @@ -68,7 +68,7 @@ public String getWriteableName() { @Override protected TypeResolution resolveFieldType() { - return isRepresentableExceptCountersAndSpatial(field(), sourceText(), DEFAULT); + return isRepresentableExceptCountersAndSpatialAndAggregateMetricDouble(field(), sourceText(), DEFAULT); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMin.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMin.java index 36dac6658aa5a..439452f8c4b79 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMin.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMin.java @@ -26,7 +26,7 @@ import java.util.List; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndSpatial; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndSpatialAndAggregateMetricDouble; /** * Reduce a multivalued field to a single valued field containing the minimum value. @@ -68,7 +68,7 @@ public String getWriteableName() { @Override protected TypeResolution resolveFieldType() { - return isRepresentableExceptCountersAndSpatial(field(), sourceText(), DEFAULT); + return isRepresentableExceptCountersAndSpatialAndAggregateMetricDouble(field(), sourceText(), DEFAULT); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSlice.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSlice.java index 4ad3426b94719..323b56dd0cfe8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSlice.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSlice.java @@ -42,7 +42,7 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.THIRD; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCounters; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndAggregateMetricDouble; import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToInt; @@ -168,7 +168,7 @@ protected TypeResolution resolveType() { return new TypeResolution("Unresolved children"); } - TypeResolution resolution = isRepresentableExceptCounters(field, sourceText(), FIRST); + TypeResolution resolution = isRepresentableExceptCountersAndAggregateMetricDouble(field, sourceText(), FIRST); if (resolution.unresolved()) { return resolution; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java index a1c348000dc5b..9f60da1c1d67b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java @@ -37,7 +37,6 @@ import org.elasticsearch.xpack.esql.core.expression.NamedExpression; import org.elasticsearch.xpack.esql.core.expression.ReferenceAttribute; import org.elasticsearch.xpack.esql.core.expression.UnresolvedAttribute; -import org.elasticsearch.xpack.esql.core.plugin.EsqlCorePlugin; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.core.type.EsField; @@ -3373,7 +3372,7 @@ public void testResolveAggregateMetricDouble() { assertThat(plan.output(), hasSize(1)); assertThat( plan.output().getFirst().dataType(), - equalTo(EsqlCorePlugin.AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG.isEnabled() ? AGGREGATE_METRIC_DOUBLE : UNSUPPORTED) + equalTo(EsqlCapabilities.Cap.AGGREGATE_METRIC_DOUBLE_V0.isEnabled() ? AGGREGATE_METRIC_DOUBLE : UNSUPPORTED) ); } { @@ -4649,7 +4648,7 @@ private void verifyNameAndType(String actualName, DataType actualType, String ex public void testImplicitCastingForAggregateMetricDouble() { assumeTrue( "aggregate metric double implicit casting must be available", - EsqlCapabilities.Cap.AGGREGATE_METRIC_DOUBLE_IMPLICIT_CASTING_IN_AGGS.isEnabled() + EsqlCapabilities.Cap.AGGREGATE_METRIC_DOUBLE_V0.isEnabled() ); Map mapping = Map.of( "@timestamp", diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractAggregationTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractAggregationTestCase.java index 5958ded41fd55..69b6ff4ff30d1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractAggregationTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractAggregationTestCase.java @@ -559,6 +559,7 @@ protected static String standardAggregatorName(String prefix, DataType type) { case INTEGER, COUNTER_INTEGER -> "Int"; case IP -> "Ip"; case DATETIME, DATE_NANOS, LONG, COUNTER_LONG, UNSIGNED_LONG, GEOHASH, GEOTILE, GEOHEX -> "Long"; + case AGGREGATE_METRIC_DOUBLE -> "AggregateMetricDouble"; case NULL -> "Null"; default -> throw new UnsupportedOperationException("name for [" + type + "]"); }; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/MultiRowTestCaseSupplier.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/MultiRowTestCaseSupplier.java index 03b0ea4fe449f..93f650398a605 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/MultiRowTestCaseSupplier.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/MultiRowTestCaseSupplier.java @@ -11,6 +11,7 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.Strings; import org.elasticsearch.common.network.InetAddresses; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; import org.elasticsearch.geometry.Geometry; @@ -30,6 +31,8 @@ import java.util.function.Supplier; import static org.elasticsearch.test.ESTestCase.randomBoolean; +import static org.elasticsearch.test.ESTestCase.randomDoubleBetween; +import static org.elasticsearch.test.ESTestCase.randomIntBetween; import static org.elasticsearch.test.ESTestCase.randomList; import static org.elasticsearch.xpack.esql.core.util.NumericUtils.UNSIGNED_LONG_MAX; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; @@ -548,6 +551,84 @@ public static List tsidCases(int minRows, int maxRows) { return cases; } + public static List aggregateMetricDoubleCases(int minRows, int maxRows, double min, double max) { + List cases = new ArrayList<>(); + + if (0 <= max && 0 >= min) { + addSuppliers( + cases, + minRows, + maxRows, + "0 aggregate metric double with positive count", + DataType.AGGREGATE_METRIC_DOUBLE, + () -> new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + 0.0, + 0.0, + 0.0, + ESTestCase.randomIntBetween(1, Integer.MAX_VALUE) + ) + ); + addSuppliers( + cases, + minRows, + maxRows, + "0 aggregate metric double with count 0", + DataType.AGGREGATE_METRIC_DOUBLE, + () -> new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(0.0, 0.0, 0.0, 0) + ); + } + + addSuppliers(cases, minRows, maxRows, "random aggregate metric double", DataType.AGGREGATE_METRIC_DOUBLE, () -> { + var v1 = randomDoubleBetween(min, max, true); + var v2 = randomDoubleBetween(min, max, true); + double generatedMin = Math.min(v1, v2); + double generatedMax = Math.max(v1, v2); + int count = randomIntBetween(1, Integer.MAX_VALUE); + double sum = generateAggregateMetricDoubleSum(generatedMin, generatedMax); + return new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(generatedMin, generatedMax, sum, count); + }); + + if (min < 0) { + addSuppliers(cases, minRows, maxRows, "entirely negative aggregate metric double", DataType.AGGREGATE_METRIC_DOUBLE, () -> { + var v1 = randomDoubleBetween(min, 0, true); + var v2 = randomDoubleBetween(min, 0, true); + double generatedMin = Math.min(v1, v2); + double generatedMax = Math.max(v1, v2); + int count = randomIntBetween(1, Integer.MAX_VALUE); + double sum = generateAggregateMetricDoubleSum(generatedMin, generatedMax); + return new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(generatedMin, generatedMax, sum, count); + }); + } + if (max > 0) { + addSuppliers(cases, minRows, maxRows, "entirely positive aggregate metric double", DataType.AGGREGATE_METRIC_DOUBLE, () -> { + var v1 = randomDoubleBetween(0, max, false); + var v2 = randomDoubleBetween(0, max, false); + double generatedMin = Math.min(v1, v2); + double generatedMax = Math.max(v1, v2); + int count = randomIntBetween(1, Integer.MAX_VALUE); + double sum = generateAggregateMetricDoubleSum(generatedMin, generatedMax); + return new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(generatedMin, generatedMax, sum, count); + }); + } + if (min < 0 && max > 0) { + addSuppliers(cases, minRows, maxRows, "negative and positive aggregate metric double", DataType.AGGREGATE_METRIC_DOUBLE, () -> { + var generatedMin = randomDoubleBetween(min, 0, true); + var generatedMax = randomDoubleBetween(0, max, false); + int count = randomIntBetween(1, Integer.MAX_VALUE); + double sum = generateAggregateMetricDoubleSum(generatedMin, generatedMax); + return new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(generatedMin, generatedMax, sum, count); + }); + } + return cases; + } + + private static double generateAggregateMetricDoubleSum(double min, double max) { + if ((max >= 0 && min >= 0) || (max <= 0 && min <= 0)) { + return min + max + randomDoubleBetween(min, max, true); + } + return randomDoubleBetween(min, max, true); + } + private static void addSuppliers( List cases, int minRows, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java index 930bfc7cf7203..7ff4cfb72bdab 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.time.DateUtils; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; import org.elasticsearch.geometry.Point; @@ -53,7 +54,9 @@ import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import static org.elasticsearch.test.ESTestCase.randomDouble; import static org.elasticsearch.test.ESTestCase.randomIntBetween; +import static org.elasticsearch.test.ESTestCase.randomNonNegativeInt; import static org.elasticsearch.xpack.esql.core.util.NumericUtils.UNSIGNED_LONG_MAX; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; @@ -820,6 +823,23 @@ public static void forUnaryVersion( ); } + public static void forUnaryAggregateMetricDouble( + List suppliers, + String expectedEvaluatorToString, + DataType expectedType, + Function expectedValue, + List warnings + ) { + unary( + suppliers, + expectedEvaluatorToString, + aggregateMetricDoubleCases(), + expectedType, + v -> expectedValue.apply((AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) v), + warnings + ); + } + private static void unaryNumeric( List suppliers, String expectedEvaluatorToString, @@ -1437,6 +1457,27 @@ public static List versionCases(String prefix) { ); } + /** + * Generate cases for {@link DataType#AGGREGATE_METRIC_DOUBLE}. + *

+ * For multi-row parameters, see {@link MultiRowTestCaseSupplier#aggregateMetricDoubleCases}. + *

+ */ + public static List aggregateMetricDoubleCases() { + return List.of( + new TypedDataSupplier( + "", + () -> new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + randomDouble(), + randomDouble(), + randomDouble(), + randomNonNegativeInt() + ), + DataType.AGGREGATE_METRIC_DOUBLE + ) + ); + } + public static String getCastEvaluator(String original, DataType current, DataType target) { if (current == target) { return original; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbsentTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbsentTests.java index 839c588f4cf08..401a5c3e2f515 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbsentTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AbsentTests.java @@ -43,6 +43,7 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.longCases(1, 1000, Long.MIN_VALUE, Long.MAX_VALUE, true), MultiRowTestCaseSupplier.ulongCases(1, 1000, BigInteger.ZERO, UNSIGNED_LONG_MAX, true), MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true), + MultiRowTestCaseSupplier.aggregateMetricDoubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE), MultiRowTestCaseSupplier.dateCases(1, 1000), MultiRowTestCaseSupplier.dateNanosCases(1, 1000), MultiRowTestCaseSupplier.booleanCases(1, 1000), @@ -60,6 +61,7 @@ public static Iterable parameters() { // No rows for (var dataType : List.of( + DataType.AGGREGATE_METRIC_DOUBLE, DataType.BOOLEAN, DataType.CARTESIAN_POINT, DataType.CARTESIAN_SHAPE, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgTests.java index 75d95c3eeac96..74c1540ad423e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgTests.java @@ -10,6 +10,7 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -37,7 +38,8 @@ public static Iterable parameters() { Stream.of( MultiRowTestCaseSupplier.intCases(1, 1000, Integer.MIN_VALUE, Integer.MAX_VALUE, true), MultiRowTestCaseSupplier.longCases(1, 1000, Long.MIN_VALUE, Long.MAX_VALUE, true), - MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true) + MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true), + MultiRowTestCaseSupplier.aggregateMetricDoubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE) ).flatMap(List::stream).map(AvgTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); suppliers.add( @@ -70,7 +72,12 @@ private static TestCaseSupplier makeSupplier(TestCaseSupplier.TypedDataSupplier if (fieldData.size() == 1) { // For single elements, we directly return them to avoid precision issues - expected = ((Number) fieldData.get(0)).doubleValue(); + if (fieldSupplier.type() == DataType.AGGREGATE_METRIC_DOUBLE) { + var aggMetric = (AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) fieldData.get(0); + expected = aggMetric.sum() / (aggMetric.count().doubleValue()); + } else { + expected = ((Number) fieldData.get(0)).doubleValue(); + } } else if (fieldData.size() > 1) { expected = switch (fieldTypedData.type().widenSmallNumeric()) { case INTEGER -> fieldData.stream() @@ -82,6 +89,15 @@ private static TestCaseSupplier makeSupplier(TestCaseSupplier.TypedDataSupplier .map(v -> (Double) v) .collect(Collectors.summarizingDouble(Double::doubleValue)) .getAverage(); + case AGGREGATE_METRIC_DOUBLE -> { + double sum = fieldData.stream() + .mapToDouble(v -> ((AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) v).sum()) + .sum(); + double count = fieldData.stream() + .mapToInt(v -> ((AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) v).count()) + .sum(); + yield count == 0 ? null : sum / count; + } default -> throw new IllegalStateException("Unexpected value: " + fieldTypedData.type()); }; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java index cb635935c93e0..48e09e2743e0a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java @@ -10,6 +10,7 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -43,6 +44,7 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.longCases(1, 1000, Long.MIN_VALUE, Long.MAX_VALUE, true), MultiRowTestCaseSupplier.ulongCases(1, 1000, BigInteger.ZERO, UNSIGNED_LONG_MAX, true), MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true), + MultiRowTestCaseSupplier.aggregateMetricDoubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE), MultiRowTestCaseSupplier.dateCases(1, 1000), MultiRowTestCaseSupplier.dateNanosCases(1, 1000), MultiRowTestCaseSupplier.booleanCases(1, 1000), @@ -73,7 +75,8 @@ public static Iterable parameters() { DataType.TEXT, DataType.GEO_POINT, DataType.CARTESIAN_POINT, - DataType.UNSIGNED_LONG + DataType.UNSIGNED_LONG, + DataType.AGGREGATE_METRIC_DOUBLE )) { suppliers.add( new TestCaseSupplier( @@ -101,9 +104,20 @@ protected Expression build(Source source, List args) { private static TestCaseSupplier makeSupplier(TestCaseSupplier.TypedDataSupplier fieldSupplier) { return new TestCaseSupplier(fieldSupplier.name(), List.of(fieldSupplier.type()), () -> { var fieldTypedData = fieldSupplier.get(); - var rowCount = fieldTypedData.multiRowData().stream().filter(Objects::nonNull).count(); + long count; + if (fieldSupplier.type() == DataType.AGGREGATE_METRIC_DOUBLE) { + count = fieldTypedData.multiRowData().stream().mapToLong(data -> { + var aggMetric = (AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) data; + if (aggMetric.count() != null) { + return aggMetric.count(); + } + return 0; + }).sum(); + } else { + count = fieldTypedData.multiRowData().stream().filter(Objects::nonNull).count(); + } - return new TestCaseSupplier.TestCase(List.of(fieldTypedData), "Count", DataType.LONG, equalTo(rowCount)); + return new TestCaseSupplier.TestCase(List.of(fieldTypedData), "Count", DataType.LONG, equalTo(count)); }); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxTests.java index 8df52dc3f433f..b6845d9dbf5fc 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxTests.java @@ -13,6 +13,7 @@ import org.apache.lucene.document.InetAddressPoint; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.network.InetAddresses; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -47,6 +48,7 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.intCases(1, 1000, Integer.MIN_VALUE, Integer.MAX_VALUE, true), MultiRowTestCaseSupplier.longCases(1, 1000, Long.MIN_VALUE, Long.MAX_VALUE, true), MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true), + MultiRowTestCaseSupplier.aggregateMetricDoubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE), MultiRowTestCaseSupplier.dateCases(1, 1000), MultiRowTestCaseSupplier.booleanCases(1, 1000), MultiRowTestCaseSupplier.ipCases(1, 1000), @@ -179,6 +181,21 @@ public static Iterable parameters() { DataType.VERSION, equalTo(value) ); + }), + new TestCaseSupplier(List.of(DataType.AGGREGATE_METRIC_DOUBLE), () -> { + var value = new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + randomDouble(), + randomDouble(), + randomDouble(), + randomNonNegativeInt() + ); + return new TestCaseSupplier.TestCase( + List.of(TestCaseSupplier.TypedData.multiRow(List.of(value), DataType.AGGREGATE_METRIC_DOUBLE, "field")), + standardAggregatorName("Max", DataType.AGGREGATE_METRIC_DOUBLE), + DataType.DOUBLE, + equalTo(value.max()) + ); + }) ) ); @@ -195,16 +212,29 @@ protected Expression build(Source source, List args) { private static TestCaseSupplier makeSupplier(TestCaseSupplier.TypedDataSupplier fieldSupplier) { return new TestCaseSupplier(fieldSupplier.name(), List.of(fieldSupplier.type()), () -> { var fieldTypedData = fieldSupplier.get(); - var expected = fieldTypedData.multiRowData() - .stream() - .map(v -> (Comparable>) v) - .max(Comparator.naturalOrder()) - .orElse(null); + Comparable> expected; + + if (fieldSupplier.type() == DataType.AGGREGATE_METRIC_DOUBLE) { + expected = fieldTypedData.multiRowData() + .stream() + .map( + v -> (Comparable< + ? super Comparable>) ((Object) ((AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) v).max()) + ) + .max(Comparator.naturalOrder()) + .orElse(null); + } else { + expected = fieldTypedData.multiRowData() + .stream() + .map(v -> (Comparable>) v) + .max(Comparator.naturalOrder()) + .orElse(null); + } return new TestCaseSupplier.TestCase( List.of(fieldTypedData), standardAggregatorName("Max", fieldSupplier.type()), - fieldSupplier.type(), + fieldSupplier.type() == DataType.AGGREGATE_METRIC_DOUBLE ? DataType.DOUBLE : fieldSupplier.type(), equalTo(expected) ); }); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinTests.java index e52ab2ec325b2..b485a489637a2 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinTests.java @@ -13,6 +13,7 @@ import org.apache.lucene.document.InetAddressPoint; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.network.InetAddresses; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -47,6 +48,7 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.intCases(1, 1000, Integer.MIN_VALUE, Integer.MAX_VALUE, true), MultiRowTestCaseSupplier.longCases(1, 1000, Long.MIN_VALUE, Long.MAX_VALUE, true), MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true), + MultiRowTestCaseSupplier.aggregateMetricDoubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE), MultiRowTestCaseSupplier.dateCases(1, 1000), MultiRowTestCaseSupplier.booleanCases(1, 1000), MultiRowTestCaseSupplier.ipCases(1, 1000), @@ -179,6 +181,21 @@ public static Iterable parameters() { DataType.VERSION, equalTo(value) ); + }), + new TestCaseSupplier(List.of(DataType.AGGREGATE_METRIC_DOUBLE), () -> { + var value = new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + randomDouble(), + randomDouble(), + randomDouble(), + randomNonNegativeInt() + ); + return new TestCaseSupplier.TestCase( + List.of(TestCaseSupplier.TypedData.multiRow(List.of(value), DataType.AGGREGATE_METRIC_DOUBLE, "field")), + standardAggregatorName("Min", DataType.AGGREGATE_METRIC_DOUBLE), + DataType.DOUBLE, + equalTo(value.min()) + ); + }) ) ); @@ -195,16 +212,29 @@ protected Expression build(Source source, List args) { private static TestCaseSupplier makeSupplier(TestCaseSupplier.TypedDataSupplier fieldSupplier) { return new TestCaseSupplier(fieldSupplier.name(), List.of(fieldSupplier.type()), () -> { var fieldTypedData = fieldSupplier.get(); - var expected = fieldTypedData.multiRowData() - .stream() - .map(v -> (Comparable>) v) - .min(Comparator.naturalOrder()) - .orElse(null); + Comparable> expected; + + if (fieldSupplier.type() == DataType.AGGREGATE_METRIC_DOUBLE) { + expected = fieldTypedData.multiRowData() + .stream() + .map( + v -> (Comparable< + ? super Comparable>) ((Object) ((AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) v).min()) + ) + .min(Comparator.naturalOrder()) + .orElse(null); + } else { + expected = fieldTypedData.multiRowData() + .stream() + .map(v -> (Comparable>) v) + .min(Comparator.naturalOrder()) + .orElse(null); + } return new TestCaseSupplier.TestCase( List.of(fieldTypedData), standardAggregatorName("Min", fieldSupplier.type()), - fieldSupplier.type(), + fieldSupplier.type() == DataType.AGGREGATE_METRIC_DOUBLE ? DataType.DOUBLE : fieldSupplier.type(), equalTo(expected) ); }); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PresentTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PresentTests.java index 8e19759a1b790..f3ad294218d2a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PresentTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/PresentTests.java @@ -43,6 +43,7 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.longCases(1, 1000, Long.MIN_VALUE, Long.MAX_VALUE, true), MultiRowTestCaseSupplier.ulongCases(1, 1000, BigInteger.ZERO, UNSIGNED_LONG_MAX, true), MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true), + MultiRowTestCaseSupplier.aggregateMetricDoubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE), MultiRowTestCaseSupplier.dateCases(1, 1000), MultiRowTestCaseSupplier.dateNanosCases(1, 1000), MultiRowTestCaseSupplier.booleanCases(1, 1000), @@ -60,6 +61,7 @@ public static Iterable parameters() { // No rows for (var dataType : List.of( + DataType.AGGREGATE_METRIC_DOUBLE, DataType.BOOLEAN, DataType.CARTESIAN_POINT, DataType.CARTESIAN_SHAPE, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleErrorTests.java index a343faa50f1ad..38d3bc3dda888 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleErrorTests.java @@ -32,7 +32,7 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - if (signature.get(1).equals(DataType.NULL)) { + if (signature.get(1).equals(DataType.NULL) && signature.get(0).equals(DataType.AGGREGATE_METRIC_DOUBLE) == false) { return equalTo("second argument of [" + sourceForSignature(signature) + "] cannot be null, received []"); } return equalTo( @@ -40,7 +40,7 @@ protected Matcher expectedTypeErrorMatcher(List> validPerP true, validPerPosition, signature, - (v, p) -> p == 1 ? "integer" : "boolean, date, ip, string, version, aggregate_metric_double or numeric except counter types" + (v, p) -> p == 1 ? "integer" : "any type except counter types and aggregate metric double" ) ); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SumTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SumTests.java index 0a50a6a88d6d3..2ae30b70a4a68 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SumTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SumTests.java @@ -10,6 +10,7 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -35,13 +36,15 @@ public SumTests(@Name("TestCase") Supplier testCaseSu public static Iterable parameters() { var suppliers = new ArrayList(); - Stream.of(MultiRowTestCaseSupplier.intCases(1, 1000, Integer.MIN_VALUE, Integer.MAX_VALUE, true) - // Longs currently throw on overflow. - // Restore after https://github.com/elastic/elasticsearch/issues/110437 - // MultiRowTestCaseSupplier.longCases(1, 1000, Long.MIN_VALUE, Long.MAX_VALUE, true), - // Doubles currently return +/-Infinity on overflow. - // Restore after https://github.com/elastic/elasticsearch/issues/111026 - // MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true) + Stream.of( + MultiRowTestCaseSupplier.intCases(1, 1000, Integer.MIN_VALUE, Integer.MAX_VALUE, true), + MultiRowTestCaseSupplier.aggregateMetricDoubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE) + // Longs currently throw on overflow. + // Restore after https://github.com/elastic/elasticsearch/issues/110437 + // MultiRowTestCaseSupplier.longCases(1, 1000, Long.MIN_VALUE, Long.MAX_VALUE, true), + // Doubles currently return +/-Infinity on overflow. + // Restore after https://github.com/elastic/elasticsearch/issues/111026 + // MultiRowTestCaseSupplier.doubleCases(1, 1000, -Double.MAX_VALUE, Double.MAX_VALUE, true) ).flatMap(List::stream).map(SumTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); suppliers.addAll( @@ -73,7 +76,22 @@ public static Iterable parameters() { DataType.DOUBLE, equalTo(200.) ) - ) + ), + new TestCaseSupplier(List.of(DataType.AGGREGATE_METRIC_DOUBLE), () -> { + var value = new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + randomDouble(), + randomDouble(), + randomDouble(), + randomNonNegativeInt() + ); + return new TestCaseSupplier.TestCase( + List.of(TestCaseSupplier.TypedData.multiRow(List.of(value), DataType.AGGREGATE_METRIC_DOUBLE, "field")), + standardAggregatorName("Sum", DataType.AGGREGATE_METRIC_DOUBLE), + DataType.DOUBLE, + equalTo(value.sum()) + ); + + }) ) ); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java index 1467aa129b467..6fab022d40f15 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java @@ -32,12 +32,14 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - assert false : "All checked types must work"; - return null; + return equalTo( + typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types and aggregate metric double") + ); } @Override protected void assertNumberOfCheckedSignatures(int checked) { - assertThat(checked, equalTo(0)); + // 1 for aggregate metric double + assertThat(checked, equalTo(1)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseErrorTests.java index 28e1b846660c0..bc4837896fc4e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseErrorTests.java @@ -42,6 +42,9 @@ protected Matcher expectedTypeErrorMatcher(List> validPerP return typeErrorMessage(signature, 0, "boolean"); } DataType mainType = signature.get(1).noText(); + if (mainType == DataType.AGGREGATE_METRIC_DOUBLE) { + return typeErrorMessage(signature, 1, "any but aggregate_metric_double"); + } for (int i = 2; i < signature.size(); i++) { if (i % 2 == 0 && i != signature.size() - 1) { // condition @@ -53,6 +56,9 @@ protected Matcher expectedTypeErrorMatcher(List> validPerP if (signature.get(i).noText() != mainType) { return typeErrorMessage(signature, i, mainType.typeName()); } + if (signature.get(i) == DataType.AGGREGATE_METRIC_DOUBLE) { + return typeErrorMessage(signature, i, "any but aggregate_metric_double"); + } } } throw new IllegalStateException("can't find bad arg for " + signature); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDoubleTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDoubleTests.java index 14910572d8c9d..f41ba85de5de5 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDoubleTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDoubleTests.java @@ -84,6 +84,13 @@ public static Iterable parameters() { Double.POSITIVE_INFINITY, emptyList() ); + TestCaseSupplier.forUnaryAggregateMetricDouble( + suppliers, + evaluatorStringLeft + "AggregateMetricDouble" + evaluatorStringRight, + DataType.AGGREGATE_METRIC_DOUBLE, + agg -> agg, + emptyList() + ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java index 8d8f59b78114d..52f8d85bb479c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java @@ -153,6 +153,13 @@ public static Iterable parameters() { List.of() ); } + TestCaseSupplier.forUnaryAggregateMetricDouble( + suppliers, + "ToStringFromAggregateMetricDoubleEvaluator[field=" + read + "]", + DataType.KEYWORD, + agg -> new BytesRef(EsqlDataTypeConverter.aggregateMetricDoubleLiteralToString(agg)), + List.of() + ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendErrorTests.java index df9ab4764c879..968663d18ec2b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendErrorTests.java @@ -32,6 +32,12 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + if (signature.get(0) == DataType.AGGREGATE_METRIC_DOUBLE + || (signature.get(0) == DataType.NULL && signature.get(1) == DataType.AGGREGATE_METRIC_DOUBLE)) { + return equalTo( + typeErrorMessage(true, validPerPosition, signature, (v, p) -> "any type except counter types and aggregate metric double") + ); + } return equalTo( "second argument of [" + sourceForSignature(signature) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsErrorTests.java index c64cb8eef8d6f..73bd87d255650 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsErrorTests.java @@ -32,6 +32,12 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + if (signature.get(0) == DataType.AGGREGATE_METRIC_DOUBLE + || (signature.get(0) == DataType.NULL && signature.get(1) == DataType.AGGREGATE_METRIC_DOUBLE)) { + return equalTo( + typeErrorMessage(true, validPerPosition, signature, (v, p) -> "any type except counter types and aggregate metric double") + ); + } return equalTo( "second argument of [" + sourceForSignature(signature) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountErrorTests.java index d59a1aa2eb098..298001dbb972d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountErrorTests.java @@ -32,6 +32,11 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + if (signature.contains(DataType.AGGREGATE_METRIC_DOUBLE)) { + return equalTo( + typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types and aggregate metric double") + ); + } return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> { /* * In general MvCount should support all signatures. While building a @@ -47,7 +52,7 @@ protected void assertNumberOfCheckedSignatures(int checked) { * In general MvCount should support all signatures. While building a * new type you may we to temporarily relax this. */ - assertThat("all signatures should be supported", checked, equalTo(0)); + assertThat("all signatures except aggregate metric double should be supported", checked, equalTo(1)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeErrorTests.java index 55f34d9a72f41..6b5e59b728e4e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeErrorTests.java @@ -32,6 +32,11 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + if (signature.contains(DataType.AGGREGATE_METRIC_DOUBLE)) { + return equalTo( + typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types and aggregate metric double") + ); + } return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> { /* * In general MvDedupe should support all signatures. While building a @@ -47,7 +52,7 @@ protected void assertNumberOfCheckedSignatures(int checked) { * In general MvDedupe should support all signatures. While building a * new type you may we to temporarily relax this. */ - assertThat("all signatures should be supported", checked, equalTo(0)); + assertThat("all signatures except aggregate metric double should be supported", checked, equalTo(1)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstErrorTests.java index 7ca829a7629c5..b813a57a6e59e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstErrorTests.java @@ -32,6 +32,11 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + if (signature.contains(DataType.AGGREGATE_METRIC_DOUBLE)) { + return equalTo( + typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types and aggregate metric double") + ); + } return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> { /* * In general MvFirst should support all signatures. While building a @@ -47,7 +52,7 @@ protected void assertNumberOfCheckedSignatures(int checked) { * In general MvFirst should support all signatures. While building a * new type you may we to temporarily relax this. */ - assertThat("all signatures should be supported", checked, equalTo(0)); + assertThat("all signatures except aggregate metric double should be supported", checked, equalTo(1)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastErrorTests.java index 3db13f0368a88..fbee5a25391d9 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastErrorTests.java @@ -32,6 +32,11 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + if (signature.contains(DataType.AGGREGATE_METRIC_DOUBLE)) { + return equalTo( + typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types and aggregate metric double") + ); + } return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> { /* * In general MvLast should support all signatures. While building a @@ -47,6 +52,6 @@ protected void assertNumberOfCheckedSignatures(int checked) { * In general MvLast should support all signatures. While building a * new type you may we to temporarily relax this. */ - assertThat("all signatures should be supported", checked, equalTo(0)); + assertThat("all signatures except aggregate metric double should be supported", checked, equalTo(1)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMaxErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMaxErrorTests.java index 6eee825de85fe..dea6c20916c79 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMaxErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMaxErrorTests.java @@ -32,6 +32,13 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter and spatial types")); + return equalTo( + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter and spatial types and aggregate metric double" + ) + ); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMinErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMinErrorTests.java index b9d97d7bb4cb8..3a237cc5d6e3b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMinErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMinErrorTests.java @@ -32,6 +32,13 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter and spatial types")); + return equalTo( + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter and spatial types and aggregate metric double" + ) + ); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceErrorTests.java index 83d0e4fcf3d75..a8f973f7578d0 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceErrorTests.java @@ -32,6 +32,11 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + if (signature.get(0) == DataType.AGGREGATE_METRIC_DOUBLE) { + return equalTo( + typeErrorMessage(true, validPerPosition, signature, (v, p) -> "any type except counter types and aggregate metric double") + ); + } return equalTo(typeErrorMessage(true, validPerPosition, signature, (v, p) -> switch (p) { case 1, 2 -> "integer"; default -> throw new UnsupportedOperationException(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsErrorTests.java index cecb6a2987fd4..16eae27a35d6b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsErrorTests.java @@ -36,6 +36,6 @@ protected Matcher expectedTypeErrorMatcher(List> validPerP } private static final String TYPE_ERROR = - "boolean, cartesian_point, cartesian_shape, datetime, date_nanos, double, geo_point, geo_shape, integer, ip, keyword, long," - + " semantic_text, text, unsigned_long or version"; + "boolean, cartesian_point, cartesian_shape, date_nanos, datetime, double, geo_point, geo_shape, geohash, geohex, geotile, " + + "integer, ip, keyword, long, text, unsigned_long or version"; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsErrorTests.java index ed0a477ec613c..3bf2762340548 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsErrorTests.java @@ -36,6 +36,6 @@ protected Matcher expectedTypeErrorMatcher(List> validPerP } private static final String TYPE_ERROR = - "boolean, cartesian_point, cartesian_shape, datetime, date_nanos, double, geo_point, geo_shape, integer, ip, keyword, long, text, " - + "unsigned_long or version"; + "boolean, cartesian_point, cartesian_shape, date_nanos, datetime, double, geo_point, geo_shape, geohash, geohex, geotile, integer, " + + "ip, keyword, long, text, unsigned_long or version"; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/IgnoreNullMetricsPhysicalPlannerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/IgnoreNullMetricsPhysicalPlannerTests.java index 50f7d53eaa67c..c89325d1bbd08 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/IgnoreNullMetricsPhysicalPlannerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/IgnoreNullMetricsPhysicalPlannerTests.java @@ -31,7 +31,7 @@ public IgnoreNullMetricsPhysicalPlannerTests(String name, Configuration config) * This tests that we get the same end result plan with an explicit isNotNull and the implicit one added by the rule */ public void testSamePhysicalPlans() { - assumeTrue("requires metrics command", EsqlCapabilities.Cap.METRICS_COMMAND.isEnabled()); + assumeTrue("requires metrics command", EsqlCapabilities.Cap.TS_COMMAND_V0.isEnabled()); String testQuery = """ TS k8s | STATS max(rate(network.total_bytes_in)) BY Bucket(@timestamp, 1 hour) @@ -51,7 +51,7 @@ public void testSamePhysicalPlans() { } public void testPushdownOfSimpleCounterQuery() { - assumeTrue("requires metrics command", EsqlCapabilities.Cap.METRICS_COMMAND.isEnabled()); + assumeTrue("requires metrics command", EsqlCapabilities.Cap.TS_COMMAND_V0.isEnabled()); String query = """ TS k8s | STATS max(rate(network.total_bytes_in)) BY Bucket(@timestamp, 1 hour) @@ -65,7 +65,7 @@ public void testPushdownOfSimpleCounterQuery() { } public void testPushdownOfSimpleGagueQuery() { - assumeTrue("requires metrics command", EsqlCapabilities.Cap.METRICS_COMMAND.isEnabled()); + assumeTrue("requires metrics command", EsqlCapabilities.Cap.TS_COMMAND_V0.isEnabled()); String query = """ TS k8s | STATS max(max_over_time(network.eth0.tx)) BY Bucket(@timestamp, 1 hour) diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/160_union_types.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/160_union_types.yml index 4017adc5bc325..bfd460b541a42 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/160_union_types.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/160_union_types.yml @@ -913,7 +913,7 @@ suggested_type: - method: POST path: /_query parameters: [] - capabilities: [suggested_cast, implicit_casting_date_and_date_nanos, aggregate_metric_double_rendering] + capabilities: [suggested_cast, implicit_casting_date_and_date_nanos, aggregate_metric_double_v0] reason: "date and date_nanos should no longer produce suggested_cast column" - do: diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/40_tsdb.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/40_tsdb.yml index b9ec55a0c5223..012445ec2e574 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/40_tsdb.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/40_tsdb.yml @@ -298,7 +298,7 @@ from doc with aggregate_metric_double: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double, aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "Support for aggregate_metric_double" - do: allowed_warnings_regex: @@ -330,7 +330,7 @@ stats on aggregate_metric_double: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double, aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "Support for aggregate_metric_double" - do: allowed_warnings_regex: @@ -364,7 +364,7 @@ grouping stats on aggregate_metric_double: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double, aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "Support for aggregate_metric_double" - do: allowed_warnings_regex: @@ -407,7 +407,7 @@ sorting with aggregate_metric_double with partial submetrics: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_sorting, aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "Support for sorting when aggregate_metric_double present" - do: allowed_warnings_regex: @@ -443,7 +443,7 @@ aggregate_metric_double unsortable: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_sorting, aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "Support for sorting when aggregate_metric_double present" - do: catch: /cannot sort on aggregate_metric_double/ @@ -463,7 +463,7 @@ stats on aggregate_metric_double with partial submetrics: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_partial_submetrics, aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "Support for partial submetrics in aggregate_metric_double" - do: allowed_warnings_regex: @@ -507,7 +507,7 @@ stats on aggregate_metric_double missing min and max: - method: POST path: /_query parameters: [ ] - capabilities: [ aggregate_metric_double_partial_submetrics, aggregate_metric_double_convert_to ] + capabilities: [ aggregate_metric_double_v0 ] reason: "Support for partial submetrics in aggregate_metric_double" - do: allowed_warnings_regex: @@ -542,7 +542,7 @@ render aggregate_metric_double when missing min and max: - method: POST path: /_query parameters: [ ] - capabilities: [ aggregate_metric_double_rendering, aggregate_metric_double_convert_to ] + capabilities: [ aggregate_metric_double_v0 ] reason: "Support for rendering aggregate_metric_doubles" - do: allowed_warnings_regex: @@ -569,7 +569,7 @@ render aggregate_metric_double when missing value: - method: POST path: /_query parameters: [ ] - capabilities: [ aggregate_metric_double_rendering, aggregate_metric_double_convert_to ] + capabilities: [ aggregate_metric_double_v0 ] reason: "Support for rendering aggregate_metric_doubles" - do: allowed_warnings_regex: @@ -597,7 +597,7 @@ to_string aggregate_metric_double: - method: POST path: /_query parameters: [ ] - capabilities: [ aggregate_metric_double_rendering, aggregate_metric_double_convert_to ] + capabilities: [ aggregate_metric_double_v0 ] reason: "Support for rendering aggregate_metric_doubles" - do: allowed_warnings_regex: @@ -624,7 +624,7 @@ from index pattern unsupported counter: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_partial_submetrics, aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "Support for partial submetrics in aggregate_metric_double" - do: allowed_warnings_regex: @@ -719,7 +719,7 @@ to_aggregate_metric_double with multi_values: - method: POST path: /_query parameters: [ ] - capabilities: [ aggregate_metric_double_convert_to ] + capabilities: [ aggregate_metric_double_v0 ] reason: "Support for to_aggregate_metric_double function" - do: @@ -769,7 +769,7 @@ avg of aggregate_metric_double: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_avg, aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "support avg aggregations with aggregate metric double" - do: diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/46_downsample.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/46_downsample.yml index a311889f8d492..ac219b4071319 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/46_downsample.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/46_downsample.yml @@ -83,7 +83,7 @@ setup: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double, dense_vector_agg_metric_double_if_fns] + capabilities: [aggregate_metric_double_v0, dense_vector_agg_metric_double_if_fns] reason: "Support for aggregate_metric_double" - do: indices.downsample: @@ -128,7 +128,7 @@ setup: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_rendering] + capabilities: [aggregate_metric_double_v0] reason: "Support for rendering aggregate_metric_doubles" - do: indices.downsample: @@ -164,7 +164,7 @@ setup: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_convert_to] + capabilities: [aggregate_metric_double_v0] reason: "Support for to_aggregate_metric_double function" - do: @@ -270,7 +270,7 @@ setup: - method: POST path: /_query parameters: [] - capabilities: [metrics_capability, aggregate_metric_double_implicit_casting_in_aggs] + capabilities: [aggregate_metric_double_v0] reason: "Support for casting aggregate metric double implicitly when present in aggregations" - do: @@ -349,7 +349,7 @@ setup: query: | FROM test-* | EVAL a = TO_AGGREGATE_METRIC_DOUBLE(1) // Temporary workaround to enable aggregate_metric_double - | WHERE k8s.pod.uid == \"947e4ced-1786-4e53-9e0c-5c447e959507\" + | WHERE k8s.pod.uid == "947e4ced-1786-4e53-9e0c-5c447e959507" | STATS max(k8s.pod.network.rx), min(k8s.pod.network.rx), sum(k8s.pod.network.rx), count(k8s.pod.network.rx), avg(k8s.pod.network.rx) | LIMIT 100 @@ -374,7 +374,7 @@ setup: - do: esql.query: body: - query: "TS test-* | STATS max = max(k8s.pod.network.rx) | LIMIT 100" + query: "FROM test-* | STATS max = max(k8s.pod.network.rx) | LIMIT 100" - length: {values: 1} - length: {values.0: 1} - match: {columns.0.name: "max"} @@ -389,7 +389,7 @@ setup: - method: POST path: /_query parameters: [] - capabilities: [metrics_command, aggregate_metric_double_implicit_casting_in_aggs] + capabilities: [ts_command_v0, aggregate_metric_double_v0] reason: "Support for casting aggregate metric double implicitly when present in aggregations" - do: @@ -513,7 +513,7 @@ setup: - method: POST path: /_query parameters: [] - capabilities: [metrics_command, aggregate_metric_double_implicit_casting_in_aggs] + capabilities: [ts_command_v0, aggregate_metric_double_v0] reason: "Support for casting aggregate metric double implicitly when present in aggregations" - do: @@ -653,7 +653,7 @@ setup: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_sorting_fixed] + capabilities: [aggregate_metric_double_v0] reason: "Fix sorting for rows comprised of docs from multiple indices where agg metric is missing from some" - do: @@ -726,7 +726,7 @@ setup: - method: POST path: /_query parameters: [] - capabilities: [aggregate_metric_double_mv_expand] + capabilities: [aggregate_metric_double_v0] reason: "Have MV_EXPAND not error out when applied to aggregate_metric_doubles (is a no-op)" - do: From 988d8922bf34fd2703e28b56bb438902492bf3d4 Mon Sep 17 00:00:00 2001 From: Larisa Motova Date: Tue, 30 Sep 2025 09:41:06 -1000 Subject: [PATCH 2/5] spotless apply and other changes --- .../esql/core/expression/TypeResolutions.java | 8 ++++++-- .../esql/core/plugin/EsqlCorePlugin.java | 1 - .../xpack/esql/core/type/DataType.java | 3 +-- .../expression/function/aggregate/Sample.java | 5 +++-- .../function/scalar/multivalue/MvSort.java | 4 ++-- .../function/aggregate/ValuesErrorTests.java | 7 ++++++- .../scalar/multivalue/MvAppendErrorTests.java | 7 ++++++- .../multivalue/MvContainsErrorTests.java | 20 +++++++++++++++---- .../scalar/multivalue/MvCountErrorTests.java | 9 ++++++++- .../scalar/multivalue/MvDedupeErrorTests.java | 9 ++++++++- .../scalar/multivalue/MvFirstErrorTests.java | 9 ++++++++- .../scalar/multivalue/MvLastErrorTests.java | 9 ++++++++- .../scalar/multivalue/MvMaxErrorTests.java | 7 ++++++- 13 files changed, 78 insertions(+), 20 deletions(-) diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java index c2398dc1ff5cc..56bbf69c76e55 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java @@ -78,7 +78,11 @@ public static TypeResolution isDate(Expression e, String operationName, ParamOrd /** * @see DataType#isRepresentable(DataType) */ - public static TypeResolution isRepresentableExceptCountersDenseVectorAndAggregateMetricDouble(Expression e, String operationName, ParamOrdinal paramOrd) { + public static TypeResolution isRepresentableExceptCountersDenseVectorAndAggregateMetricDouble( + Expression e, + String operationName, + ParamOrdinal paramOrd + ) { return isType( e, dt -> isRepresentable(dt) && dt != DENSE_VECTOR && dt != AGGREGATE_METRIC_DOUBLE, @@ -95,7 +99,7 @@ public static TypeResolution isRepresentableExceptCountersSpatialDenseVectorAndA ) { return isType( e, - (t) -> isSpatialOrGrid(t) == false && DataType.isRepresentable(t) && t != DENSE_VECTOR, + (t) -> isSpatialOrGrid(t) == false && DataType.isRepresentable(t) && t != DENSE_VECTOR && t != AGGREGATE_METRIC_DOUBLE, operationName, paramOrd, "any type except counter, spatial types, dense_vector, or aggregate_metric_double" diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java index 0a2caa8c9a953..1b2a59b5c6886 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java @@ -7,7 +7,6 @@ package org.elasticsearch.xpack.esql.core.plugin; -import org.elasticsearch.common.util.FeatureFlag; import org.elasticsearch.plugins.ExtensiblePlugin; import org.elasticsearch.plugins.Plugin; diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java index 422c9ead26cd0..f78c02110b66a 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java @@ -342,8 +342,7 @@ public enum DataType implements Writeable { * * */ - public static final Map UNDER_CONSTRUCTION = Map.ofEntries( - ); + public static final Map UNDER_CONSTRUCTION = Map.ofEntries(); private final String typeName; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java index 75b76ff15103a..4f7ae2f3a2a34 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java @@ -126,8 +126,9 @@ protected TypeResolution resolveType() { if (childrenResolved() == false) { return new TypeResolution("Unresolved children"); } - var typeResolution = isRepresentableExceptCountersDenseVectorAndAggregateMetricDouble(field(), sourceText(), FIRST).and(isNotNull(limitField(), sourceText(), SECOND)) - .and(isType(limitField(), dt -> dt == DataType.INTEGER, sourceText(), SECOND, "integer")); + var typeResolution = isRepresentableExceptCountersDenseVectorAndAggregateMetricDouble(field(), sourceText(), FIRST).and( + isNotNull(limitField(), sourceText(), SECOND) + ).and(isType(limitField(), dt -> dt == DataType.INTEGER, sourceText(), SECOND, "integer")); if (typeResolution.unresolved()) { return typeResolution; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSort.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSort.java index 9731a547dc7d2..ed63a82d7c93a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSort.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSort.java @@ -52,7 +52,7 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersAndDenseVector; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isRepresentableExceptCountersDenseVectorAndAggregateMetricDouble; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isString; import static org.elasticsearch.xpack.esql.expression.Validations.isFoldable; @@ -127,7 +127,7 @@ protected TypeResolution resolveType() { return new TypeResolution("Unresolved children"); } - TypeResolution resolution = isRepresentableExceptCountersAndDenseVector(field, sourceText(), FIRST); + TypeResolution resolution = isRepresentableExceptCountersDenseVectorAndAggregateMetricDouble(field, sourceText(), FIRST); if (resolution.unresolved()) { return resolution; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java index aaef60d131832..b8a68786e9913 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java @@ -33,7 +33,12 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { return equalTo( - typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double") + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double" + ) ); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendErrorTests.java index 0b036beacc9b2..22e6a496aced8 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendErrorTests.java @@ -37,7 +37,12 @@ protected Matcher expectedTypeErrorMatcher(List> validPerP if (unsupportedTypes.contains(signature.getFirst()) || signature.getFirst() == DataType.NULL && unsupportedTypes.contains(signature.get(1))) { return containsString( - typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double") + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double" + ) ); } else { return equalTo( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsErrorTests.java index bdb70bd2818e5..c34a7638ef944 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsErrorTests.java @@ -37,11 +37,23 @@ protected Matcher expectedTypeErrorMatcher(List> validPerP if (unsupportedTypes.contains(signature.getFirst()) || signature.getFirst() == DataType.NULL && unsupportedTypes.contains(signature.get(1))) { return containsString( - typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double") + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double" + ) ); } else { - return equalTo("second argument of [" + sourceForSignature(signature) + "] must be [" + signature.get(0).noText().typeName() - + "], found value [] type [" + signature.get(1).typeName() + "]"); - } + return equalTo( + "second argument of [" + + sourceForSignature(signature) + + "] must be [" + + signature.get(0).noText().typeName() + + "], found value [] type [" + + signature.get(1).typeName() + + "]" + ); + } } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountErrorTests.java index a051f0604a0d7..60814dc70b3e8 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountErrorTests.java @@ -32,7 +32,14 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double")); + return equalTo( + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double" + ) + ); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeErrorTests.java index 8863ce83d3544..de367326fbf74 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeErrorTests.java @@ -32,7 +32,14 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double")); + return equalTo( + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double" + ) + ); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstErrorTests.java index dff3917165110..c0a707cdb41d4 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstErrorTests.java @@ -32,7 +32,14 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double")); + return equalTo( + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double" + ) + ); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastErrorTests.java index a76ebdefb41c2..6ad79c8d698f8 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastErrorTests.java @@ -32,7 +32,14 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double")); + return equalTo( + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter types, dense_vector, or aggregate_metric_double" + ) + ); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMaxErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMaxErrorTests.java index 7a52e2f79a88d..a31c00e4f7590 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMaxErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvMaxErrorTests.java @@ -33,7 +33,12 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { return equalTo( - typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except counter, spatial types, dense_vector, or aggregate_metric_double") + typeErrorMessage( + false, + validPerPosition, + signature, + (v, p) -> "any type except counter, spatial types, dense_vector, or aggregate_metric_double" + ) ); } } From aa942c9b4c5c7f1d25d25c96c1a2e85a35589ed6 Mon Sep 17 00:00:00 2001 From: Larisa Motova Date: Tue, 30 Sep 2025 09:45:41 -1000 Subject: [PATCH 3/5] attempt plugging in transport version --- .../elasticsearch/xpack/esql/core/type/DataType.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java index f78c02110b66a..9a1edce4af63e 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java @@ -34,7 +34,6 @@ import java.util.function.Function; import static java.util.stream.Collectors.toMap; -import static org.elasticsearch.TransportVersions.INFERENCE_REQUEST_ADAPTIVE_RATE_LIMITING; /** * This enum represents data types the ES|QL query processing layer is able to @@ -312,10 +311,7 @@ public enum DataType implements Writeable { AGGREGATE_METRIC_DOUBLE( builder().esType("aggregate_metric_double") .estimatedSize(Double.BYTES * 3 + Integer.BYTES) - .createdVersion( - // Version created just *after* we committed support for aggregate_metric_double - INFERENCE_REQUEST_ADAPTIVE_RATE_LIMITING - ) + .createdVersion(DataTypesTransportVersions.ESQL_AGGREGATE_METRIC_DOUBLE_CREATED_VERSION) ), /** @@ -951,5 +947,9 @@ private static class DataTypesTransportVersions { public static final TransportVersion ESQL_DENSE_VECTOR_CREATED_VERSION = TransportVersion.fromName( "esql_dense_vector_created_version" ); + + public static final TransportVersion ESQL_AGGREGATE_METRIC_DOUBLE_CREATED_VERSION = TransportVersion.fromName( + "esql_aggregate_metric_double_created_version" + ); } } From 75e42a85fa61eb07b628e5fdbb2fa78725f66c79 Mon Sep 17 00:00:00 2001 From: Larisa Motova Date: Tue, 30 Sep 2025 09:46:44 -1000 Subject: [PATCH 4/5] run generateTransportVersion --- .../referable/esql_aggregate_metric_double_created_version.csv | 1 + server/src/main/resources/transport/upper_bounds/9.2.csv | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 server/src/main/resources/transport/definitions/referable/esql_aggregate_metric_double_created_version.csv diff --git a/server/src/main/resources/transport/definitions/referable/esql_aggregate_metric_double_created_version.csv b/server/src/main/resources/transport/definitions/referable/esql_aggregate_metric_double_created_version.csv new file mode 100644 index 0000000000000..02acf4c3b415f --- /dev/null +++ b/server/src/main/resources/transport/definitions/referable/esql_aggregate_metric_double_created_version.csv @@ -0,0 +1 @@ +9184000 diff --git a/server/src/main/resources/transport/upper_bounds/9.2.csv b/server/src/main/resources/transport/upper_bounds/9.2.csv index f575dcaf4efa8..058760544f9da 100644 --- a/server/src/main/resources/transport/upper_bounds/9.2.csv +++ b/server/src/main/resources/transport/upper_bounds/9.2.csv @@ -1 +1 @@ -esql_dense_vector_created_version,9183000 +esql_aggregate_metric_double_created_version,9184000 From 0f292bec7a16c687a6cd87b7eb8ce61009deb17f Mon Sep 17 00:00:00 2001 From: Larisa Motova Date: Tue, 30 Sep 2025 11:05:52 -1000 Subject: [PATCH 5/5] fix inline stats csv test --- .../qa/testFixtures/src/main/resources/inlinestats.csv-spec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec index 47c44741bfef1..4b5f0e2a3739c 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec @@ -3950,8 +3950,7 @@ from employees inlineStatsOnAggregateMetricDouble required_capability: inline_stats -required_capability: aggregate_metric_double_literal_registered -required_capability: aggregate_metric_double_convert_to +required_capability: aggregate_metric_double_v0 FROM k8s-downsampled | EVAL a = TO_AGGREGATE_METRIC_DOUBLE(1) // Temporary workaround to enable aggregate_metric_double | INLINE STATS tx_max = MAX(network.eth0.tx) BY pod