[release-11.5.3] InfluxDB: Improve handling of template variables contained in regular expressions (InfluxQL) (#100977)
InfluxDB: Improve handling of template variables contained in regular expressions (InfluxQL) (#100762)
* Improve handling of template vars in regex
* Review
* Minor update
(cherry picked from commit 8b3047ba1e)
Co-authored-by: Andreas Christou <andreas.christou@grafana.com>
This commit is contained in:
co-authored by
Andreas Christou
parent
68e70b4c5a
commit
9e4537fe03
@@ -363,6 +363,18 @@ describe('interpolateQueryExpr', () => {
|
|||||||
expect(result).toBe(expectation);
|
expect(result).toBe(expectation);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should **not** return the escaped value if the value **is not** wrapped in regex and the query is more complex (e.g. text is contained between two / but not a regex', () => {
|
||||||
|
const value = 'testmatch';
|
||||||
|
const variableMock = queryBuilder().withId('tempVar').withName('tempVar').withMulti(false).build();
|
||||||
|
const result = ds.interpolateQueryExpr(
|
||||||
|
value,
|
||||||
|
variableMock,
|
||||||
|
`select value where ("tag"::tag =~ /value/) AND where other = $tempVar $timeFilter GROUP BY time($__interval) tz('Europe/London')`
|
||||||
|
);
|
||||||
|
const expectation = `testmatch`;
|
||||||
|
expect(result).toBe(expectation);
|
||||||
|
});
|
||||||
|
|
||||||
it('should return floating point number as it is', () => {
|
it('should return floating point number as it is', () => {
|
||||||
const variableMock = queryBuilder()
|
const variableMock = queryBuilder()
|
||||||
.withId('tempVar')
|
.withId('tempVar')
|
||||||
|
|||||||
@@ -351,17 +351,30 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
|||||||
// If the variable is not a multi-value variable
|
// If the variable is not a multi-value variable
|
||||||
// we want to see how it's been used. If it is used in a regex expression
|
// we want to see how it's been used. If it is used in a regex expression
|
||||||
// we escape it. Otherwise, we return it directly.
|
// we escape it. Otherwise, we return it directly.
|
||||||
// regex below checks if the variable inside /^...$/ (^ and $ is optional)
|
// The regex below searches for regexes within the query string
|
||||||
|
const regexMatcher = new RegExp(
|
||||||
|
/\/((?![*+?])(?:[^\r\n\[/\\]|\\.|\[(?:[^\r\n\]\\]|\\.)*\])+)\/((?:g(?:im?|mi?)?|i(?:gm?|mg?)?|m(?:gi?|ig?)?)?)/,
|
||||||
|
'gm'
|
||||||
|
);
|
||||||
|
// If matches are found this regex is evaluated to check if the variable is contained in the regex /^...$/ (^ and $ is optional)
|
||||||
// i.e. /^$myVar$/ or /$myVar/ or /^($myVar)$/
|
// i.e. /^$myVar$/ or /$myVar/ or /^($myVar)$/
|
||||||
const regex = new RegExp(`\\/(?:\\^)?(.*)(\\$${variable.name})(.*)(?:\\$)?\\/`, 'gm');
|
const regex = new RegExp(`\\/(?:\\^)?(.*)(\\$${variable.name})(.*)(?:\\$)?\\/`, 'gm');
|
||||||
if (query && regex.test(query)) {
|
if (!query) {
|
||||||
if (typeof value === 'string') {
|
return value;
|
||||||
return escapeRegex(value);
|
}
|
||||||
|
|
||||||
|
const queryMatches = query.match(regexMatcher);
|
||||||
|
if (!queryMatches) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
for (const match of queryMatches) {
|
||||||
|
if (!match.match(regex)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the value is a string array first escape them then join them with pipe
|
// If the value is a string array first escape them then join them with pipe
|
||||||
// then put inside parenthesis.
|
// then put inside parenthesis.
|
||||||
return `(${value.map((v) => escapeRegex(v)).join('|')})`;
|
return typeof value === 'string' ? escapeRegex(value) : `(${value.map((v) => escapeRegex(v)).join('|')})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
Reference in New Issue
Block a user