From bdfbc2453fa638af2c28c7e55f19928af9d42936 Mon Sep 17 00:00:00 2001 From: "Jonathan A. Sternberg" Date: Thu, 31 Aug 2017 02:33:03 -0500 Subject: [PATCH] Use parenthesis to surround the selected tags for influxdb queries (#9131) The generated queries when selecting multiple tags are incorrect. In InfluxQL, `AND` has a higher precedence than `OR` so the condition: WHERE "hostname" = 'server1' OR "hostname" = 'server2' AND time > now() - 5m This is parsed as if it were: WHERE "hostname" = 'server1' OR ("hostname" = 'server2' AND time > now() - 5m) But the intention is to write a query like this: WHERE ("hostname" = 'server1' OR "hostname" = 'server2') AND time > now() - 5m This change modifies the generated query so it surrounds a query with multiple conditions in parenthesis so it doesn't conflict with the time expression in an unexpected way. This is currently not an issue because InfluxDB doesn't actually evaluate the condition for the time expression correctly. It just looks through the AST for anything that looks like a time expression and then assumes the proper format of `AND` was used rather than validating that it was used correctly. --- pkg/tsdb/influxdb/query.go | 6 +++++- pkg/tsdb/influxdb/query_test.go | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/tsdb/influxdb/query.go b/pkg/tsdb/influxdb/query.go index f271c5d245f..0bcdf1d5291 100644 --- a/pkg/tsdb/influxdb/query.go +++ b/pkg/tsdb/influxdb/query.go @@ -151,8 +151,12 @@ func (query *Query) renderMeasurement() string { func (query *Query) renderWhereClause() string { res := " WHERE " conditions := query.renderTags() - res += strings.Join(conditions, " ") if len(conditions) > 0 { + if len(conditions) > 1 { + res += "(" + strings.Join(conditions, " ") + ")" + } else { + res += conditions[0] + } res += " AND " } diff --git a/pkg/tsdb/influxdb/query_test.go b/pkg/tsdb/influxdb/query_test.go index 533df27f91f..0977ef8c1ce 100644 --- a/pkg/tsdb/influxdb/query_test.go +++ b/pkg/tsdb/influxdb/query_test.go @@ -57,7 +57,7 @@ func TestInfluxdbQueryBuilder(t *testing.T) { rawQuery, err := query.Build(queryContext) So(err, ShouldBeNil) - So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "cpu" WHERE "hostname" = 'server1' OR "hostname" = 'server2' AND time > now() - 5m GROUP BY time(5s), "datacenter" fill(null)`) + So(rawQuery, ShouldEqual, `SELECT mean("value") FROM "cpu" WHERE ("hostname" = 'server1' OR "hostname" = 'server2') AND time > now() - 5m GROUP BY time(5s), "datacenter" fill(null)`) }) Convey("can build query with math part", func() {