metricsql: improve timestamp function compatibility with Prometheus when used with sub-expressions (#9603)

### Describe Your Changes

Fixes
[#9527](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9527)
Related PR: https://github.com/VictoriaMetrics/metricsql/pull/55

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
This commit is contained in:
Max Kotliar
2025-08-21 17:38:12 +03:00
committed by GitHub
parent 795c3deaee
commit 7d552dbd9a
5 changed files with 21 additions and 8 deletions

View File

@@ -65,10 +65,10 @@ func VisitAll(e Expr, f func(expr Expr)) {
//
// These expressions are implicitly converted into another expressions, which returns unexpected results most of the time:
//
// rate(default_rollup(sum(foo))[1i:1i])
// rate(default_rollup(abs(foo))[1i:1i])
// rate(default_rollup(foo + bar)[1i:1i])
// rate(default_rollup(foo > 10)[1i:1i])
// rate(sum(default_rollup(foo[1i:1i])))
// rate(abs(default_rollup(foo[1i:1i])))
// rate(default_rollup(foo[1i:1i]) + default_rollup(bar[1i:1i]))
// rate(default_rollup(foo[1i:1i]) > 10)
//
// See https://docs.victoriametrics.com/victoriametrics/metricsql/#implicit-query-conversions
//
@@ -83,6 +83,17 @@ func IsLikelyInvalid(e Expr) bool {
if !ok {
return
}
if fe.Name == `timestamp` {
// In Prometheus, timestamp is defined as a transform function on instant vectors,
// but its behavior is closer to a rollup since it returns raw sample timestamps.
// VictoriaMetrics explicitly defines timestamp as a rollup function.
// To remain consistent with Prometheus, IsLikelyInvalid does not treat timestamp
// as an implicit conversion even when applied to non-metric expressions, like timestamp(sum(foo)).
//
// See more in https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9527#issuecomment-3191439447
return
}
idx := GetRollupArgIdx(fe)
if idx < 0 || idx >= len(fe.Args) {
return