diff --git a/pkg/tsdb/influxdb/flux/macros.go b/pkg/tsdb/influxdb/flux/macros.go index 4dce9d76822..fbec2b4d1fe 100644 --- a/pkg/tsdb/influxdb/flux/macros.go +++ b/pkg/tsdb/influxdb/flux/macros.go @@ -25,27 +25,40 @@ func interpolateInterval(flux string, interval time.Duration) string { var fluxVariableFilterExp = regexp.MustCompile(`(?m)([a-zA-Z]+)\.([a-zA-Z]+)`) func interpolateFluxSpecificVariables(query queryModel) string { + rawQuery := query.RawQuery flux := query.RawQuery - matches := fluxVariableFilterExp.FindAllStringSubmatch(flux, -1) + matches := fluxVariableFilterExp.FindAllStringSubmatchIndex(rawQuery, -1) if matches != nil { timeRange := query.TimeRange from := timeRange.From.UTC().Format(time.RFC3339Nano) to := timeRange.To.UTC().Format(time.RFC3339Nano) for _, match := range matches { - switch match[2] { + // For query "range(start: v.timeRangeStart, stop: v.timeRangeStop)" + // rawQuery[match[0]:match[1]] will be v.timeRangeStart + // rawQuery[match[2]:match[3]] will be v + // rawQuery[match[4]:match[5]] will be timeRangeStart + fullMatch := rawQuery[match[0]:match[1]] + key := rawQuery[match[4]:match[5]] + + switch key { case "timeRangeStart": - flux = strings.ReplaceAll(flux, match[0], from) + flux = strings.ReplaceAll(flux, fullMatch, from) case "timeRangeStop": - flux = strings.ReplaceAll(flux, match[0], to) + flux = strings.ReplaceAll(flux, fullMatch, to) case "windowPeriod": - flux = strings.ReplaceAll(flux, match[0], query.Interval.String()) + flux = strings.ReplaceAll(flux, fullMatch, query.Interval.String()) case "bucket": - flux = strings.ReplaceAll(flux, match[0], "\""+query.Options.Bucket+"\"") + // Check if 'bucket' is part of a join query + beforeMatch := rawQuery[:match[0]] + if strings.Contains(beforeMatch, "join.") { + continue + } + flux = strings.ReplaceAll(flux, fullMatch, "\""+query.Options.Bucket+"\"") case "defaultBucket": - flux = strings.ReplaceAll(flux, match[0], "\""+query.Options.DefaultBucket+"\"") + flux = strings.ReplaceAll(flux, fullMatch, "\""+query.Options.DefaultBucket+"\"") case "organization": - flux = strings.ReplaceAll(flux, match[0], "\""+query.Options.Organization+"\"") + flux = strings.ReplaceAll(flux, fullMatch, "\""+query.Options.Organization+"\"") } } } diff --git a/pkg/tsdb/influxdb/flux/macros_test.go b/pkg/tsdb/influxdb/flux/macros_test.go index 9bf0fa3570a..283835ab24e 100644 --- a/pkg/tsdb/influxdb/flux/macros_test.go +++ b/pkg/tsdb/influxdb/flux/macros_test.go @@ -31,6 +31,11 @@ func TestInterpolate(t *testing.T) { before: `v.timeRangeStart, something.timeRangeStop, XYZ.bucket, uuUUu.defaultBucket, aBcDefG.organization, window.windowPeriod, a91{}.bucket, $__interval, $__interval_ms`, after: `2021-09-22T10:12:51.310985041Z, 2021-09-22T11:12:51.310985042Z, "grafana2", "grafana3", "grafana1", 1m1.258s, a91{}.bucket, 1m, 61258`, }, + { + name: "don't interpolate bucket variable in join query", + before: `range(start: v.timeRangeStart, stop: v.timeRangeStop) join.left(left: left |> group(), right: right,on:((l,r) => l.bucket == r.id), as: ((l, r) => ({l with name: r.name})))`, + after: `range(start: 2021-09-22T10:12:51.310985041Z, stop: 2021-09-22T11:12:51.310985042Z) join.left(left: left |> group(), right: right,on:((l,r) => l.bucket == r.id), as: ((l, r) => ({l with name: r.name})))`, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {