12
12
import org .elasticsearch .xpack .esql .action .EsqlCapabilities ;
13
13
import org .elasticsearch .xpack .esql .analysis .Analyzer ;
14
14
import org .elasticsearch .xpack .esql .analysis .AnalyzerContext ;
15
+ import org .elasticsearch .xpack .esql .core .expression .Alias ;
16
+ import org .elasticsearch .xpack .esql .core .expression .Attribute ;
17
+ import org .elasticsearch .xpack .esql .core .tree .NodeUtils ;
15
18
import org .elasticsearch .xpack .esql .core .type .EsField ;
16
19
import org .elasticsearch .xpack .esql .expression .function .EsqlFunctionRegistry ;
20
+ import org .elasticsearch .xpack .esql .expression .function .aggregate .Max ;
21
+ import org .elasticsearch .xpack .esql .expression .function .aggregate .Rate ;
17
22
import org .elasticsearch .xpack .esql .index .EsIndex ;
18
23
import org .elasticsearch .xpack .esql .index .IndexResolution ;
19
24
import org .elasticsearch .xpack .esql .optimizer .AbstractLogicalPlanOptimizerTests ;
@@ -86,10 +91,10 @@ public void testMaxOverTime() {
86
91
| LIMIT 10
87
92
""" );
88
93
Limit limit = as (plan , Limit .class );
89
- Aggregate innerStats = as (limit .child (), Aggregate .class );
90
- TimeSeriesAggregate outerStats = as (innerStats .child (), TimeSeriesAggregate .class );
94
+ Aggregate outerStats = as (limit .child (), Aggregate .class );
95
+ TimeSeriesAggregate innerStats = as (outerStats .child (), TimeSeriesAggregate .class );
91
96
// TODO: Add asserts about the specific aggregation details here
92
- Eval eval = as (outerStats .child (), Eval .class );
97
+ Eval eval = as (innerStats .child (), Eval .class );
93
98
EsRelation relation = as (eval .child (), EsRelation .class );
94
99
}
95
100
@@ -101,10 +106,29 @@ public void testMaxOfRate() {
101
106
| LIMIT 10
102
107
""" );
103
108
Limit limit = as (plan , Limit .class );
104
- Aggregate innerStats = as (limit .child (), Aggregate .class );
105
- TimeSeriesAggregate outerStats = as (innerStats .child (), TimeSeriesAggregate .class );
106
- // TODO: Add asserts about the specific aggregation details here
107
- Eval eval = as (outerStats .child (), Eval .class );
109
+
110
+ Aggregate outerStats = as (limit .child (), Aggregate .class );
111
+ assertEquals (1 , outerStats .groupings ().size ());
112
+ Attribute timeBucketGroup = as (outerStats .groupings ().get (0 ), Attribute .class );
113
+ assertEquals ("time_bucket" , timeBucketGroup .name ());
114
+ assertEquals (2 , outerStats .aggregates ().size ());
115
+ assertEquals (timeBucketGroup , outerStats .aggregates ().get (1 ));
116
+ Alias outerAggFunction = as (outerStats .aggregates ().get (0 ), Alias .class );
117
+ Max outerMax = as (outerAggFunction .child (), Max .class );
118
+
119
+ TimeSeriesAggregate innerStats = as (outerStats .child (), TimeSeriesAggregate .class );
120
+ assertEquals (2 , innerStats .groupings ().size ());
121
+ assertEquals (timeBucketGroup , innerStats .groupings ().get (1 ));
122
+ Attribute tsidGroup = as (innerStats .groupings ().get (0 ), Attribute .class );
123
+ assertEquals ("_tsid" , tsidGroup .name ());
124
+
125
+ assertEquals (2 , innerStats .aggregates ().size ());
126
+ Alias innerAggFunction = as (innerStats .aggregates ().get (0 ), Alias .class );
127
+ Rate rateAgg = as (innerAggFunction .child (), Rate .class );
128
+ Alias timeBucketAlias = as (innerStats .aggregates ().get (1 ), Alias .class );
129
+ assertEquals (timeBucketGroup , timeBucketAlias .child ());
130
+
131
+ Eval eval = as (innerStats .child (), Eval .class );
108
132
EsRelation relation = as (eval .child (), EsRelation .class );
109
133
}
110
134
@@ -148,6 +172,44 @@ public void testRateWithRename() {
148
172
LogicalPlan plan = planK8s ("""
149
173
TS k8s
150
174
| RENAME `@timestamp` AS newTs
175
+ | STATS maxRate = max(rate(network.total_cost)) BY time_bucket = bucket(newTs, 1hour)
176
+ """ );
177
+ Limit limit = as (plan , Limit .class );
178
+
179
+ Aggregate outerStats = as (limit .child (), Aggregate .class );
180
+ assertEquals (1 , outerStats .groupings ().size ());
181
+ Attribute timeBucketGroup = as (outerStats .groupings ().get (0 ), Attribute .class );
182
+ assertEquals ("time_bucket" , timeBucketGroup .name ());
183
+ assertEquals (2 , outerStats .aggregates ().size ());
184
+ assertEquals (timeBucketGroup , outerStats .aggregates ().get (1 ));
185
+ Alias outerAggFunction = as (outerStats .aggregates ().get (0 ), Alias .class );
186
+ Max outerMax = as (outerAggFunction .child (), Max .class );
187
+
188
+ TimeSeriesAggregate innerStats = as (outerStats .child (), TimeSeriesAggregate .class );
189
+ assertEquals (2 , innerStats .groupings ().size ());
190
+ assertEquals (timeBucketGroup , innerStats .groupings ().get (1 ));
191
+ Attribute tsidGroup = as (innerStats .groupings ().get (0 ), Attribute .class );
192
+ assertEquals ("_tsid" , tsidGroup .name ());
193
+
194
+ assertEquals (2 , innerStats .aggregates ().size ());
195
+ Alias innerAggFunction = as (innerStats .aggregates ().get (0 ), Alias .class );
196
+ Rate rateAgg = as (innerAggFunction .child (), Rate .class );
197
+ Alias timeBucketAlias = as (innerStats .aggregates ().get (1 ), Alias .class );
198
+ assertEquals (timeBucketGroup , timeBucketAlias .child ());
199
+
200
+ Eval eval = as (innerStats .child (), Eval .class );
201
+ EsRelation relation = as (eval .child (), EsRelation .class );
202
+ }
203
+
204
+ public void testRateWithManyRenames () {
205
+ assumeTrue ("requires metrics command" , EsqlCapabilities .Cap .TS_COMMAND_V0 .isEnabled ());
206
+ LogicalPlan plan = planK8s ("""
207
+ TS k8s
208
+ | RENAME `@timestamp` AS ts1
209
+ | RENAME ts1 AS ts2
210
+ | RENAME ts2 AS ts3
211
+ | RENAME ts3 AS ts4
212
+ | RENAME ts4 as newTs
151
213
| STATS maxRate = max(rate(network.total_cost)) BY tbucket = bucket(newTs, 1hour)
152
214
""" );
153
215
}
@@ -169,4 +231,16 @@ public void testTbucketWithRename() {
169
231
| STATS maxRate = max(max_over_time(network.eth0.tx)) BY tbucket = tbucket(1hour)
170
232
""" );
171
233
}
234
+
235
+ public void testTbucketWithManyRenames () {
236
+ assumeTrue ("requires metrics command" , EsqlCapabilities .Cap .TS_COMMAND_V0 .isEnabled ());
237
+ LogicalPlan plan = planK8s ("""
238
+ TS k8s
239
+ | RENAME `@timestamp` AS ts1
240
+ | RENAME ts1 AS ts2
241
+ | RENAME ts2 AS ts3
242
+ | RENAME ts3 AS ts4
243
+ | STATS maxRate = max(max_over_time(network.eth0.tx)) BY tbucket = tbucket(1hour)
244
+ """ );
245
+ }
172
246
}
0 commit comments