5151 * becomes
5252 *
5353 * TS k8s
54- * | STATS rate(request) BY _tsid
55- * | STATS max(`rate(request)` )
54+ * | STATS rate_$1 = rate(request) BY _tsid
55+ * | STATS max(rate_$1 )
5656 *
5757 * TS k8s | STATS max(rate(request)) BY host
5858 *
5959 * becomes
6060 *
6161 * TS k8s
62- * | STATS rate(request), VALUES(host) BY _tsid
63- * | STATS max(`rate(request)` ) BY host=`VALUES(host)`
62+ * | STATS rate_$1= rate(request), VALUES(host) BY _tsid
63+ * | STATS max(rate_$1 ) BY host=`VALUES(host)`
6464 *
6565 * TS k8s | STATS avg(rate(request)) BY host
6666 *
6767 * becomes
6868 *
6969 * TS k8s
70- * | STATS rate(request), VALUES(host) BY _tsid
71- * | STATS sum=sum(`rate(request)`) , count(`rate(request)` ) BY host=`VALUES(host)`
72- * | EVAL `avg(rate(request))` = `sum(rate(request)) ` / `count(rate(request) )`
70+ * | STATS rate_$1= rate(request), VALUES(host) BY _tsid
71+ * | STATS sum(rate_$1) , count(rate_$1 ) BY host=`VALUES(host)`
72+ * | EVAL `avg(rate(request))` = `sum(rate_$1) ` / `count(rate_$1 )`
7373 * | KEEP `avg(rate(request))`, host
7474 *
7575 * TS k8s | STATS avg(rate(request)) BY host, bucket(@timestamp, 1minute)
7878 *
7979 * TS k8s
8080 * | EVAL `bucket(@timestamp, 1minute)`=datetrunc(@timestamp, 1minute)
81- * | STATS rate(request), VALUES(host) BY _tsid,`bucket(@timestamp, 1minute)`
82- * | STATS sum=sum(`rate(request)`) , count(`rate(request)` ) BY host=`VALUES(host)`, `bucket(@timestamp, 1minute)`
83- * | EVAL `avg(rate(request))` = `sum(rate(request)) ` / `count(rate(request) )`
81+ * | STATS rate_$1= rate(request), VALUES(host) BY _tsid,`bucket(@timestamp, 1minute)`
82+ * | STATS sum=sum(rate_$1) , count(rate_$1 ) BY host=`VALUES(host)`, `bucket(@timestamp, 1minute)`
83+ * | EVAL `avg(rate(request))` = `sum(rate_$1) ` / `count(rate_$1 )`
8484 * | KEEP `avg(rate(request))`, host, `bucket(@timestamp, 1minute)`
8585 * </pre>
8686 *
9393 * TS k8s | STATS max(rate(request)), max(memory_used) becomes:
9494 *
9595 * TS k8s
96- * | STATS rate(request), $p1=to_partial(max(memory_used)) BY _tsid
97- * | STATS max(`rate(request)` ), `max(memory_used)` = from_partial($p1, max($_))
96+ * | STATS rate_$1= rate(request), $p1=to_partial(max(memory_used)) BY _tsid
97+ * | STATS max(rate_$1 ), `max(memory_used)` = from_partial($p1, max($_))
9898 *
9999 * TS k8s | STATS max(rate(request)) avg(memory_used) BY host
100100 *
101101 * becomes
102102 *
103103 * TS k8s
104- * | STATS rate(request), $p1=to_partial(sum(memory_used)), $p2=to_partial(count(memory_used)), VALUES(host) BY _tsid
105- * | STATS max(`rate(request)` ), $sum=from_partial($p1, sum($_)), $count=from_partial($p2, count($_)) BY host=`VALUES(host)`
104+ * | STATS rate_$1= rate(request), $p1=to_partial(sum(memory_used)), $p2=to_partial(count(memory_used)), VALUES(host) BY _tsid
105+ * | STATS max(rate_$1 ), $sum=from_partial($p1, sum($_)), $count=from_partial($p2, count($_)) BY host=`VALUES(host)`
106106 * | EVAL `avg(memory_used)` = $sum / $count
107107 * | KEEP `max(rate(request))`, `avg(memory_used)`, host
108108 *
112112 *
113113 * TS k8s
114114 * | EVAL `bucket(@timestamp, 5m)` = datetrunc(@timestamp, '5m')
115- * | STATS rate(request), $p1=to_partial(min(memory_used)), VALUES(pod) BY _tsid, `bucket(@timestamp, 5m)`
116- * | STATS sum(`rate(request)` ), `min(memory_used)` = from_partial($p1, min($)) BY pod=`VALUES(pod)`, `bucket(@timestamp, 5m)`
117- * | KEEP `min(memory_used)`, `sum(rate(request) )`, pod, `bucket(@timestamp, 5m)`
115+ * | STATS rate_$1= rate(request), $p1=to_partial(min(memory_used)), VALUES(pod) BY _tsid, `bucket(@timestamp, 5m)`
116+ * | STATS sum(rate_$1 ), `min(memory_used)` = from_partial($p1, min($)) BY pod=`VALUES(pod)`, `bucket(@timestamp, 5m)`
117+ * | KEEP `min(memory_used)`, `sum(rate_$1 )`, pod, `bucket(@timestamp, 5m)`
118118 *
119119 * {agg}_over_time time-series aggregation will be rewritten in the similar way
120120 *
123123 * becomes
124124 *
125125 * FROM k8s
126- * | STATS max_memory_usage = max(memory_usage), host_values=VALUES(host) BY _tsid, time_bucket=bucket(@timestamp, 1minute)
127- * | STATS sum(max_memory_usage ) BY host_values, time_bucket
126+ * | STATS max_over_time_$1 = max(memory_usage), host_values=VALUES(host) BY _tsid, time_bucket=bucket(@timestamp, 1minute)
127+ * | STATS sum(max_over_time_$1 ) BY host_values, time_bucket
128128 *
129129 *
130130 * TS k8s | STATS sum(avg_over_time(memory_usage)) BY host, bucket(@timestamp, 1minute)
131131 *
132132 * becomes
133133 *
134134 * FROM k8s
135- * | STATS avg_memory_usage = avg(memory_usage), host_values=VALUES(host) BY _tsid, time_bucket=bucket(@timestamp, 1minute)
136- * | STATS sum(avg_memory_usage ) BY host_values, time_bucket
135+ * | STATS avg_over_time_$1 = avg(memory_usage), host_values=VALUES(host) BY _tsid, time_bucket=bucket(@timestamp, 1minute)
136+ * | STATS sum(avg_over_time_$1 ) BY host_values, time_bucket
137137 *
138+ * TS k8s | STATS max(rate(post_requests) + rate(get_requests)) BY host, bucket(@timestamp, 1minute)
139+ *
140+ * becomes
141+ *
142+ * FROM k8s
143+ * | STATS rate_$1=rate(post_requests), rate_$2=rate(post_requests) BY _tsid, time_bucket=bucket(@timestamp, 1minute)
144+ * | STATS max(rate_$1 + rate_$2) BY host_values, time_bucket
138145 * </pre>
139146 */
140147public final class TranslateTimeSeriesAggregate extends OptimizerRules .OptimizerRule <Aggregate > {
@@ -157,6 +164,7 @@ LogicalPlan translate(TimeSeriesAggregate aggregate) {
157164 List <NamedExpression > firstPassAggs = new ArrayList <>();
158165 List <NamedExpression > secondPassAggs = new ArrayList <>();
159166 Holder <Boolean > hasRateAggregates = new Holder <>(Boolean .FALSE );
167+ var internalNames = new InternalNames ();
160168 for (NamedExpression agg : aggregate .aggregates ()) {
161169 if (agg instanceof Alias alias && alias .child () instanceof AggregateFunction af ) {
162170 Holder <Boolean > changed = new Holder <>(Boolean .FALSE );
@@ -167,7 +175,7 @@ LogicalPlan translate(TimeSeriesAggregate aggregate) {
167175 }
168176 AggregateFunction firstStageFn = tsAgg .perTimeSeriesAggregation ();
169177 Alias newAgg = timeSeriesAggs .computeIfAbsent (firstStageFn , k -> {
170- Alias firstStageAlias = new Alias (tsAgg .source (), agg . name ( ), firstStageFn );
178+ Alias firstStageAlias = new Alias (tsAgg .source (), internalNames . next ( tsAgg . functionName () ), firstStageFn );
171179 firstPassAggs .add (firstStageAlias );
172180 return firstStageAlias ;
173181 });
@@ -269,4 +277,13 @@ private static List<? extends NamedExpression> mergeExpressions(
269277 groupings .forEach (g -> merged .add (Expressions .attribute (g )));
270278 return merged ;
271279 }
280+
281+ private static class InternalNames {
282+ final Map <String , Integer > next = new HashMap <>();
283+
284+ String next (String prefix ) {
285+ int id = next .merge (prefix , 1 , Integer ::sum );
286+ return prefix + "_$" + id ;
287+ }
288+ }
272289}
0 commit comments