diff --git a/public/app/plugins/datasource/influxdb/influx_query_model.test.ts b/public/app/plugins/datasource/influxdb/influx_query_model.test.ts index 6f52956da38..92a92f41aac 100644 --- a/public/app/plugins/datasource/influxdb/influx_query_model.test.ts +++ b/public/app/plugins/datasource/influxdb/influx_query_model.test.ts @@ -604,4 +604,53 @@ describe('InfluxQuery', () => { }); }); }); + + describe('test query generated with templateVariable and non-regex operator', () => { + const testCases = [ + ['=', 'SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" = \'$tempVar\') AND $timeFilter'], + ['!=', 'SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" != \'$tempVar\') AND $timeFilter'], + ['Is', 'SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" = \'$tempVar\') AND $timeFilter'], + ['Is Not', 'SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" != \'$tempVar\') AND $timeFilter'], + ['>', 'SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" > $tempVar) AND $timeFilter'], + ['<', 'SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" < $tempVar) AND $timeFilter'], + ]; + + it.each(testCases)('should not wrap with InfluxDB regex wrapper for "%s" operator', (operator, expectedQuery) => { + const query = new InfluxQueryModel( + { + refId: 'A', + measurement: 'cpu', + policy: 'autogen', + groupBy: [], + tags: [{ key: 'value', value: '/^$tempVar$/', operator }], + }, + templateSrv, + {} + ); + const queryText = query.render(); + expect(queryText).toBe(expectedQuery); + }); + }); + describe('test query generated with templateVariable and regex operator', () => { + const testCases = [ + ['=~', 'SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" =~ /^$tempVar$/) AND $timeFilter'], + ['!~', 'SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" !~ /^$tempVar$/) AND $timeFilter'], + ]; + + it.each(testCases)('should wrap with InfluxDB regex wrapper for "%s" operator', (operator, expectedQuery) => { + const query = new InfluxQueryModel( + { + refId: 'A', + measurement: 'cpu', + policy: 'autogen', + groupBy: [], + tags: [{ key: 'value', value: '/^$tempVar$/', operator }], + }, + templateSrv, + {} + ); + const queryText = query.render(); + expect(queryText).toBe(expectedQuery); + }); + }); }); diff --git a/public/app/plugins/datasource/influxdb/influx_query_model.ts b/public/app/plugins/datasource/influxdb/influx_query_model.ts index 1be91772f0e..620a0535acf 100644 --- a/public/app/plugins/datasource/influxdb/influx_query_model.ts +++ b/public/app/plugins/datasource/influxdb/influx_query_model.ts @@ -141,6 +141,17 @@ export default class InfluxQueryModel { this.updatePersistedParts(); } + private removeRegexWrapper(str: string) { + const regex = /\/\^(.*?)\$\//; // match any string that starts with "/^" and ends with "$/", capturing the characters in between + const match = str.match(regex); + + if (match && match.length > 1) { + return match[1]; + } else { + return str; + } + } + private isOperatorTypeHandler(operator: string, value: string, fieldName: string) { let textValue; if (operator === 'Is Not') { @@ -151,7 +162,7 @@ export default class InfluxQueryModel { // Tags should always quote if (fieldName.endsWith('::tag')) { - textValue = "'" + value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'") + "'"; + textValue = "'" + this.removeRegexWrapper(value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'")) + "'"; return { operator: operator, value: textValue, @@ -169,7 +180,7 @@ export default class InfluxQueryModel { textValue = lowerValue; } else { // String or unrecognised: quote - textValue = "'" + value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'") + "'"; + textValue = "'" + this.removeRegexWrapper(value.replace(/\\/g, '\\\\').replace(/\'/g, "\\'")) + "'"; } return { operator: operator, @@ -199,7 +210,7 @@ export default class InfluxQueryModel { if (interpolate) { value = this.templateSrv.replace(value, this.scopedVars); } - + value = this.removeRegexWrapper(value); if (operator.startsWith('Is')) { let r = this.isOperatorTypeHandler(operator, value, tag.key); operator = r.operator;