mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Templating: Makes so __searchFilter can be used as part of regular expression (#20103)
* Fix: Fixes searchfilter wildcard char in regular expressions Fixes: #20006 * Refactor: Uses TemplateSrv and ScopedVars instead * Docs: Updates docs with new format * Tests: Corrects test description
This commit is contained in:
parent
fc5cc4cbf9
commit
7aeed4d987
@ -114,19 +114,25 @@ variable with all possible values that exist in the wildcard position.
|
|||||||
You can also create nested variables that use other variables in their definition. For example
|
You can also create nested variables that use other variables in their definition. For example
|
||||||
`apps.$app.servers.*` uses the variable `$app` in its query definition.
|
`apps.$app.servers.*` uses the variable `$app` in its query definition.
|
||||||
|
|
||||||
#### Using `$__searchFilter` to filter results in Query Variable
|
#### Using `__searchFilter` to filter results in Query Variable
|
||||||
> Available from Grafana 6.5 and above
|
> Available from Grafana 6.5 and above
|
||||||
|
|
||||||
Using `$__searchFilter` in the query field will filter the query result based on what the user types in the dropdown select box.
|
Using `__searchFilter` in the query field will filter the query result based on what the user types in the dropdown select box.
|
||||||
When nothing has been entered by the user the default value for `$__searchFilter` is `*`.
|
When nothing has been entered by the user the default value for `__searchFilter` is `*` and `` when used as part of a regular expression.
|
||||||
|
|
||||||
The example below shows how to use `$__searchFilter` as part of the query field to enable searching for `server` while the user types in the dropdown select box.
|
The example below shows how to use `__searchFilter` as part of the query field to enable searching for `server` while the user types in the dropdown select box.
|
||||||
|
|
||||||
Query
|
Query
|
||||||
```bash
|
```bash
|
||||||
apps.$app.servers.$__searchFilter
|
apps.$app.servers.$__searchFilter
|
||||||
```
|
```
|
||||||
|
|
||||||
|
TagValues
|
||||||
|
```bash
|
||||||
|
tag_values(server, server=~${__searchFilter:regex})
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Variable Usage
|
### Variable Usage
|
||||||
|
|
||||||
You can use a variable in a metric node path or as a parameter to a function.
|
You can use a variable in a metric node path or as a parameter to a function.
|
||||||
|
@ -276,17 +276,19 @@ the hosts variable only show hosts from the current selected region with a query
|
|||||||
SELECT hostname FROM my_host WHERE region IN($region)
|
SELECT hostname FROM my_host WHERE region IN($region)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Using `$__searchFilter` to filter results in Query Variable
|
#### Using `__searchFilter` to filter results in Query Variable
|
||||||
> Available from Grafana 6.5 and above
|
> Available from Grafana 6.5 and above
|
||||||
|
|
||||||
Using `$__searchFilter` in the query field will filter the query result based on what the user types in the dropdown select box.
|
Using `__searchFilter` in the query field will filter the query result based on what the user types in the dropdown select box.
|
||||||
When nothing has been entered by the user the default value for `$__searchFilter` is `%`.
|
When nothing has been entered by the user the default value for `__searchFilter` is `%`.
|
||||||
|
|
||||||
The example below shows how to use `$__searchFilter` as part of the query field to enable searching for `hostname` while the user types in the dropdown select box.
|
> Important that you surround the `__searchFilter` expression with quotes as Grafana does not do this for you.
|
||||||
|
|
||||||
|
The example below shows how to use `__searchFilter` as part of the query field to enable searching for `hostname` while the user types in the dropdown select box.
|
||||||
|
|
||||||
Query
|
Query
|
||||||
```sql
|
```sql
|
||||||
SELECT hostname FROM my_host WHERE hostname LIKE $__searchFilter
|
SELECT hostname FROM my_host WHERE hostname LIKE '$__searchFilter'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using Variables in Queries
|
### Using Variables in Queries
|
||||||
|
@ -282,17 +282,19 @@ the hosts variable only show hosts from the current selected region with a query
|
|||||||
SELECT hostname FROM host WHERE region IN($region)
|
SELECT hostname FROM host WHERE region IN($region)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Using `$__searchFilter` to filter results in Query Variable
|
#### Using `__searchFilter` to filter results in Query Variable
|
||||||
> Available from Grafana 6.5 and above
|
> Available from Grafana 6.5 and above
|
||||||
|
|
||||||
Using `$__searchFilter` in the query field will filter the query result based on what the user types in the dropdown select box.
|
Using `__searchFilter` in the query field will filter the query result based on what the user types in the dropdown select box.
|
||||||
When nothing has been entered by the user the default value for `$__searchFilter` is `%`.
|
When nothing has been entered by the user the default value for `__searchFilter` is `%`.
|
||||||
|
|
||||||
The example below shows how to use `$__searchFilter` as part of the query field to enable searching for `hostname` while the user types in the dropdown select box.
|
> Important that you surround the `__searchFilter` expression with quotes as Grafana does not do this for you.
|
||||||
|
|
||||||
|
The example below shows how to use `__searchFilter` as part of the query field to enable searching for `hostname` while the user types in the dropdown select box.
|
||||||
|
|
||||||
Query
|
Query
|
||||||
```sql
|
```sql
|
||||||
SELECT hostname FROM my_host WHERE hostname LIKE $__searchFilter
|
SELECT hostname FROM my_host WHERE hostname LIKE '$__searchFilter'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using Variables in Queries
|
### Using Variables in Queries
|
||||||
|
@ -2,9 +2,10 @@ import {
|
|||||||
assignModelProperties,
|
assignModelProperties,
|
||||||
containsSearchFilter,
|
containsSearchFilter,
|
||||||
containsVariable,
|
containsVariable,
|
||||||
interpolateSearchFilter,
|
getSearchFilterScopedVar,
|
||||||
SEARCH_FILTER_VARIABLE,
|
SEARCH_FILTER_VARIABLE,
|
||||||
} from '../variable';
|
} from '../variable';
|
||||||
|
import { ScopedVars } from '@grafana/data';
|
||||||
|
|
||||||
describe('containsVariable', () => {
|
describe('containsVariable', () => {
|
||||||
describe('when checking if a string contains a variable', () => {
|
describe('when checking if a string contains a variable', () => {
|
||||||
@ -92,84 +93,164 @@ describe('containsSearchFilter', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe(`when called with a query with ${SEARCH_FILTER_VARIABLE}`, () => {
|
describe(`when called with a query with $${SEARCH_FILTER_VARIABLE}`, () => {
|
||||||
it('then it should return false', () => {
|
it('then it should return true', () => {
|
||||||
const result = containsSearchFilter(`$app.${SEARCH_FILTER_VARIABLE}`);
|
const result = containsSearchFilter(`$app.$${SEARCH_FILTER_VARIABLE}`);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe(`when called with a query with [[${SEARCH_FILTER_VARIABLE}]]`, () => {
|
||||||
|
it('then it should return true', () => {
|
||||||
|
const result = containsSearchFilter(`$app.[[${SEARCH_FILTER_VARIABLE}]]`);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe(`when called with a query with \$\{${SEARCH_FILTER_VARIABLE}:regex\}`, () => {
|
||||||
|
it('then it should return true', () => {
|
||||||
|
const result = containsSearchFilter(`$app.\$\{${SEARCH_FILTER_VARIABLE}:regex\}`);
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('interpolateSearchFilter', () => {
|
interface GetSearchFilterScopedVarScenario {
|
||||||
describe('when called with a query without ${SEARCH_FILTER_VARIABLE}', () => {
|
query: string;
|
||||||
it('then it should return query', () => {
|
wildcardChar: string;
|
||||||
const query = '$app.*';
|
options: { searchFilter?: string };
|
||||||
const options = { searchFilter: 'filter' };
|
expected: ScopedVars;
|
||||||
const wildcardChar = '*';
|
}
|
||||||
const quoteLiteral = false;
|
|
||||||
|
|
||||||
const result = interpolateSearchFilter({
|
const scenarios: GetSearchFilterScopedVarScenario[] = [
|
||||||
query,
|
// testing the $__searchFilter notation
|
||||||
options,
|
{
|
||||||
wildcardChar,
|
query: 'abc.$__searchFilter',
|
||||||
quoteLiteral,
|
wildcardChar: '',
|
||||||
});
|
options: { searchFilter: '' },
|
||||||
|
expected: { __searchFilter: { value: '', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.$__searchFilter',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: { searchFilter: '' },
|
||||||
|
expected: { __searchFilter: { value: '*', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.$__searchFilter',
|
||||||
|
wildcardChar: '',
|
||||||
|
options: { searchFilter: 'a' },
|
||||||
|
expected: { __searchFilter: { value: 'a', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.$__searchFilter',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: { searchFilter: 'a' },
|
||||||
|
expected: { __searchFilter: { value: 'a*', text: '' } },
|
||||||
|
},
|
||||||
|
// testing the [[__searchFilter]] notation
|
||||||
|
{
|
||||||
|
query: 'abc.[[__searchFilter]]',
|
||||||
|
wildcardChar: '',
|
||||||
|
options: { searchFilter: '' },
|
||||||
|
expected: { __searchFilter: { value: '', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.[[__searchFilter]]',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: { searchFilter: '' },
|
||||||
|
expected: { __searchFilter: { value: '*', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.[[__searchFilter]]',
|
||||||
|
wildcardChar: '',
|
||||||
|
options: { searchFilter: 'a' },
|
||||||
|
expected: { __searchFilter: { value: 'a', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.[[__searchFilter]]',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: { searchFilter: 'a' },
|
||||||
|
expected: { __searchFilter: { value: 'a*', text: '' } },
|
||||||
|
},
|
||||||
|
// testing the ${__searchFilter:fmt} notation
|
||||||
|
{
|
||||||
|
query: 'abc.${__searchFilter:regex}',
|
||||||
|
wildcardChar: '',
|
||||||
|
options: { searchFilter: '' },
|
||||||
|
expected: { __searchFilter: { value: '', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.${__searchFilter:regex}',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: { searchFilter: '' },
|
||||||
|
expected: { __searchFilter: { value: '*', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.${__searchFilter:regex}',
|
||||||
|
wildcardChar: '',
|
||||||
|
options: { searchFilter: 'a' },
|
||||||
|
expected: { __searchFilter: { value: 'a', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.${__searchFilter:regex}',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: { searchFilter: 'a' },
|
||||||
|
expected: { __searchFilter: { value: 'a*', text: '' } },
|
||||||
|
},
|
||||||
|
// testing the no options
|
||||||
|
{
|
||||||
|
query: 'abc.$__searchFilter',
|
||||||
|
wildcardChar: '',
|
||||||
|
options: null,
|
||||||
|
expected: { __searchFilter: { value: '', text: '' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.$__searchFilter',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: null,
|
||||||
|
expected: { __searchFilter: { value: '*', text: '' } },
|
||||||
|
},
|
||||||
|
// testing the no search filter at all
|
||||||
|
{
|
||||||
|
query: 'abc.$def',
|
||||||
|
wildcardChar: '',
|
||||||
|
options: { searchFilter: '' },
|
||||||
|
expected: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.$def',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: { searchFilter: '' },
|
||||||
|
expected: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.$def',
|
||||||
|
wildcardChar: '',
|
||||||
|
options: { searchFilter: 'a' },
|
||||||
|
expected: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query: 'abc.$def',
|
||||||
|
wildcardChar: '*',
|
||||||
|
options: { searchFilter: 'a' },
|
||||||
|
expected: {},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
expect(result).toEqual(query);
|
scenarios.map(scenario => {
|
||||||
});
|
describe('getSearchFilterScopedVar', () => {
|
||||||
});
|
describe(`when called with query:'${scenario.query}'`, () => {
|
||||||
|
describe(`and wildcardChar:'${scenario.wildcardChar}'`, () => {
|
||||||
|
describe(`and options:'${JSON.stringify(scenario.options, null, 0)}'`, () => {
|
||||||
|
it(`then the result should be ${JSON.stringify(scenario.expected, null, 0)}`, () => {
|
||||||
|
const { expected, ...args } = scenario;
|
||||||
|
|
||||||
describe(`when called with a query with ${SEARCH_FILTER_VARIABLE}`, () => {
|
expect(getSearchFilterScopedVar(args)).toEqual(expected);
|
||||||
const query = `$app.${SEARCH_FILTER_VARIABLE}`;
|
|
||||||
|
|
||||||
describe('and no searchFilter is given', () => {
|
|
||||||
it(`then ${SEARCH_FILTER_VARIABLE} should be replaced by wildchar character`, () => {
|
|
||||||
const options = {};
|
|
||||||
const wildcardChar = '*';
|
|
||||||
const quoteLiteral = false;
|
|
||||||
|
|
||||||
const result = interpolateSearchFilter({
|
|
||||||
query,
|
|
||||||
options,
|
|
||||||
wildcardChar,
|
|
||||||
quoteLiteral,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toEqual(`$app.*`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('and searchFilter is given', () => {
|
|
||||||
const options = { searchFilter: 'filter' };
|
|
||||||
|
|
||||||
it(`then ${SEARCH_FILTER_VARIABLE} should be replaced with searchfilter and wildchar character`, () => {
|
|
||||||
const wildcardChar = '*';
|
|
||||||
const quoteLiteral = false;
|
|
||||||
|
|
||||||
const result = interpolateSearchFilter({
|
|
||||||
query,
|
|
||||||
options,
|
|
||||||
wildcardChar,
|
|
||||||
quoteLiteral,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toEqual(`$app.filter*`);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe(`and quoteLiteral is used`, () => {
|
|
||||||
it(`then the literal should be quoted`, () => {
|
|
||||||
const wildcardChar = '*';
|
|
||||||
const quoteLiteral = true;
|
|
||||||
|
|
||||||
const result = interpolateSearchFilter({
|
|
||||||
query,
|
|
||||||
options,
|
|
||||||
wildcardChar,
|
|
||||||
quoteLiteral,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toEqual(`$app.'filter*'`);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import kbn from 'app/core/utils/kbn';
|
import kbn from 'app/core/utils/kbn';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { variableRegex } from 'app/features/templating/variable';
|
import { variableRegex } from 'app/features/templating/variable';
|
||||||
import { TimeRange, ScopedVars } from '@grafana/data';
|
import { ScopedVars, TimeRange } from '@grafana/data';
|
||||||
|
|
||||||
function luceneEscape(value: string) {
|
function luceneEscape(value: string) {
|
||||||
return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, '\\$1');
|
return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, '\\$1');
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { assignModelProperties } from 'app/core/utils/model_utils';
|
import { assignModelProperties } from 'app/core/utils/model_utils';
|
||||||
|
import { ScopedVars } from '@grafana/data';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This regex matches 3 types of variable reference with an optional format specifier
|
* This regex matches 3 types of variable reference with an optional format specifier
|
||||||
@ -15,31 +16,32 @@ export const variableRegexExec = (variableString: string) => {
|
|||||||
return variableRegex.exec(variableString);
|
return variableRegex.exec(variableString);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SEARCH_FILTER_VARIABLE = '$__searchFilter';
|
export const SEARCH_FILTER_VARIABLE = '__searchFilter';
|
||||||
|
|
||||||
export const containsSearchFilter = (query: string): boolean =>
|
export const containsSearchFilter = (query: string): boolean =>
|
||||||
query ? query.indexOf(SEARCH_FILTER_VARIABLE) !== -1 : false;
|
query ? query.indexOf(SEARCH_FILTER_VARIABLE) !== -1 : false;
|
||||||
|
|
||||||
export interface InterpolateSearchFilterOptions {
|
export const getSearchFilterScopedVar = (args: {
|
||||||
query: string;
|
query: string;
|
||||||
options: any;
|
|
||||||
wildcardChar: string;
|
wildcardChar: string;
|
||||||
quoteLiteral: boolean;
|
options: { searchFilter?: string };
|
||||||
}
|
}): ScopedVars => {
|
||||||
|
const { query, wildcardChar } = args;
|
||||||
export const interpolateSearchFilter = (args: InterpolateSearchFilterOptions): string => {
|
|
||||||
const { query, wildcardChar, quoteLiteral } = args;
|
|
||||||
let { options } = args;
|
|
||||||
|
|
||||||
if (!containsSearchFilter(query)) {
|
if (!containsSearchFilter(query)) {
|
||||||
return query;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
options = options || {};
|
let { options } = args;
|
||||||
|
|
||||||
const filter = options.searchFilter ? `${options.searchFilter}${wildcardChar}` : `${wildcardChar}`;
|
options = options || { searchFilter: '' };
|
||||||
const replaceValue = quoteLiteral ? `'${filter}'` : filter;
|
const value = options.searchFilter ? `${options.searchFilter}${wildcardChar}` : `${wildcardChar}`;
|
||||||
|
|
||||||
return query.replace(SEARCH_FILTER_VARIABLE, replaceValue);
|
return {
|
||||||
|
__searchFilter: {
|
||||||
|
value,
|
||||||
|
text: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum VariableRefresh {
|
export enum VariableRefresh {
|
||||||
|
@ -7,7 +7,7 @@ import { BackendSrv } from 'app/core/services/backend_srv';
|
|||||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||||
//Types
|
//Types
|
||||||
import { GraphiteQuery } from './types';
|
import { GraphiteQuery } from './types';
|
||||||
import { interpolateSearchFilter } from '../../../features/templating/variable';
|
import { getSearchFilterScopedVar } from '../../../features/templating/variable';
|
||||||
|
|
||||||
export class GraphiteDatasource {
|
export class GraphiteDatasource {
|
||||||
basicAuth: string;
|
basicAuth: string;
|
||||||
@ -251,12 +251,10 @@ export class GraphiteDatasource {
|
|||||||
|
|
||||||
metricFindQuery(query: string, optionalOptions: any) {
|
metricFindQuery(query: string, optionalOptions: any) {
|
||||||
const options: any = optionalOptions || {};
|
const options: any = optionalOptions || {};
|
||||||
const interpolatedQuery = interpolateSearchFilter({
|
let interpolatedQuery = this.templateSrv.replace(
|
||||||
query: this.templateSrv.replace(query),
|
query,
|
||||||
options: optionalOptions,
|
getSearchFilterScopedVar({ query, wildcardChar: '', options: optionalOptions })
|
||||||
wildcardChar: '*',
|
);
|
||||||
quoteLiteral: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// special handling for tag_values(<tag>[,<expression>]*), this is used for template variables
|
// special handling for tag_values(<tag>[,<expression>]*), this is used for template variables
|
||||||
let matches = interpolatedQuery.match(/^tag_values\(([^,]+)((, *[^,]+)*)\)$/);
|
let matches = interpolatedQuery.match(/^tag_values\(([^,]+)((, *[^,]+)*)\)$/);
|
||||||
@ -289,6 +287,11 @@ export class GraphiteDatasource {
|
|||||||
return this.getTagsAutoComplete(expressions, undefined, options);
|
return this.getTagsAutoComplete(expressions, undefined, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interpolatedQuery = this.templateSrv.replace(
|
||||||
|
query,
|
||||||
|
getSearchFilterScopedVar({ query, wildcardChar: '*', options: optionalOptions })
|
||||||
|
);
|
||||||
|
|
||||||
const httpOptions: any = {
|
const httpOptions: any = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/metrics/find',
|
url: '/metrics/find',
|
||||||
|
@ -7,7 +7,7 @@ import { TemplateSrv } from 'app/features/templating/template_srv';
|
|||||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
//Types
|
//Types
|
||||||
import { MysqlQueryForInterpolation } from './types';
|
import { MysqlQueryForInterpolation } from './types';
|
||||||
import { interpolateSearchFilter } from '../../../features/templating/variable';
|
import { getSearchFilterScopedVar } from '../../../features/templating/variable';
|
||||||
|
|
||||||
export class MysqlDatasource {
|
export class MysqlDatasource {
|
||||||
id: any;
|
id: any;
|
||||||
@ -131,12 +131,11 @@ export class MysqlDatasource {
|
|||||||
refId = optionalOptions.variable.name;
|
refId = optionalOptions.variable.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawSql = interpolateSearchFilter({
|
const rawSql = this.templateSrv.replace(
|
||||||
query: this.templateSrv.replace(query, {}, this.interpolateVariable),
|
query,
|
||||||
options: optionalOptions,
|
getSearchFilterScopedVar({ query, wildcardChar: '%', options: optionalOptions }),
|
||||||
wildcardChar: '%',
|
this.interpolateVariable
|
||||||
quoteLiteral: true,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
const interpolatedQuery = {
|
const interpolatedQuery = {
|
||||||
refId: refId,
|
refId: refId,
|
||||||
|
@ -124,7 +124,7 @@ describe('MySQLDatasource', () => {
|
|||||||
describe('When performing metricFindQuery with $__searchFilter and a searchFilter is given', () => {
|
describe('When performing metricFindQuery with $__searchFilter and a searchFilter is given', () => {
|
||||||
let results: any;
|
let results: any;
|
||||||
let calledWith: any = {};
|
let calledWith: any = {};
|
||||||
const query = 'select title from atable where title LIKE $__searchFilter';
|
const query = "select title from atable where title LIKE '$__searchFilter'";
|
||||||
const response = {
|
const response = {
|
||||||
results: {
|
results: {
|
||||||
tempvar: {
|
tempvar: {
|
||||||
@ -162,7 +162,7 @@ describe('MySQLDatasource', () => {
|
|||||||
describe('When performing metricFindQuery with $__searchFilter but no searchFilter is given', () => {
|
describe('When performing metricFindQuery with $__searchFilter but no searchFilter is given', () => {
|
||||||
let results: any;
|
let results: any;
|
||||||
let calledWith: any = {};
|
let calledWith: any = {};
|
||||||
const query = 'select title from atable where title LIKE $__searchFilter';
|
const query = "select title from atable where title LIKE '$__searchFilter'";
|
||||||
const response = {
|
const response = {
|
||||||
results: {
|
results: {
|
||||||
tempvar: {
|
tempvar: {
|
||||||
|
@ -7,7 +7,7 @@ import { TemplateSrv } from 'app/features/templating/template_srv';
|
|||||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
//Types
|
//Types
|
||||||
import { PostgresQueryForInterpolation } from './types';
|
import { PostgresQueryForInterpolation } from './types';
|
||||||
import { interpolateSearchFilter } from '../../../features/templating/variable';
|
import { getSearchFilterScopedVar } from '../../../features/templating/variable';
|
||||||
|
|
||||||
export class PostgresDatasource {
|
export class PostgresDatasource {
|
||||||
id: any;
|
id: any;
|
||||||
@ -127,18 +127,17 @@ export class PostgresDatasource {
|
|||||||
.then((data: any) => this.responseParser.transformAnnotationResponse(options, data));
|
.then((data: any) => this.responseParser.transformAnnotationResponse(options, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
metricFindQuery(query: string, optionalOptions: { variable?: any }) {
|
metricFindQuery(query: string, optionalOptions: { variable?: any; searchFilter?: string }) {
|
||||||
let refId = 'tempvar';
|
let refId = 'tempvar';
|
||||||
if (optionalOptions && optionalOptions.variable && optionalOptions.variable.name) {
|
if (optionalOptions && optionalOptions.variable && optionalOptions.variable.name) {
|
||||||
refId = optionalOptions.variable.name;
|
refId = optionalOptions.variable.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawSql = interpolateSearchFilter({
|
const rawSql = this.templateSrv.replace(
|
||||||
query: this.templateSrv.replace(query, {}, this.interpolateVariable),
|
query,
|
||||||
options: optionalOptions,
|
getSearchFilterScopedVar({ query, wildcardChar: '%', options: optionalOptions }),
|
||||||
wildcardChar: '%',
|
this.interpolateVariable
|
||||||
quoteLiteral: true,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
const interpolatedQuery = {
|
const interpolatedQuery = {
|
||||||
refId: refId,
|
refId: refId,
|
||||||
|
@ -131,7 +131,7 @@ describe('PostgreSQLDatasource', () => {
|
|||||||
describe('When performing metricFindQuery with $__searchFilter and a searchFilter is given', () => {
|
describe('When performing metricFindQuery with $__searchFilter and a searchFilter is given', () => {
|
||||||
let results: any;
|
let results: any;
|
||||||
let calledWith: any = {};
|
let calledWith: any = {};
|
||||||
const query = 'select title from atable where title LIKE $__searchFilter';
|
const query = "select title from atable where title LIKE '$__searchFilter'";
|
||||||
const response = {
|
const response = {
|
||||||
results: {
|
results: {
|
||||||
tempvar: {
|
tempvar: {
|
||||||
@ -169,7 +169,7 @@ describe('PostgreSQLDatasource', () => {
|
|||||||
describe('When performing metricFindQuery with $__searchFilter but no searchFilter is given', () => {
|
describe('When performing metricFindQuery with $__searchFilter but no searchFilter is given', () => {
|
||||||
let results: any;
|
let results: any;
|
||||||
let calledWith: any = {};
|
let calledWith: any = {};
|
||||||
const query = 'select title from atable where title LIKE $__searchFilter';
|
const query = "select title from atable where title LIKE '$__searchFilter'";
|
||||||
const response = {
|
const response = {
|
||||||
results: {
|
results: {
|
||||||
tempvar: {
|
tempvar: {
|
||||||
|
@ -13,7 +13,7 @@ import { queryMetricTree } from './metricTree';
|
|||||||
import { from, merge, Observable } from 'rxjs';
|
import { from, merge, Observable } from 'rxjs';
|
||||||
import { runStream } from './runStreams';
|
import { runStream } from './runStreams';
|
||||||
import templateSrv from 'app/features/templating/template_srv';
|
import templateSrv from 'app/features/templating/template_srv';
|
||||||
import { interpolateSearchFilter } from '../../../features/templating/variable';
|
import { getSearchFilterScopedVar } from '../../../features/templating/variable';
|
||||||
|
|
||||||
type TestData = TimeSeries | TableData;
|
type TestData = TimeSeries | TableData;
|
||||||
|
|
||||||
@ -126,12 +126,10 @@ export class TestDataDataSource extends DataSourceApi<TestDataQuery> {
|
|||||||
metricFindQuery(query: string, options: any) {
|
metricFindQuery(query: string, options: any) {
|
||||||
return new Promise<MetricFindValue[]>((resolve, reject) => {
|
return new Promise<MetricFindValue[]>((resolve, reject) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const interpolatedQuery = interpolateSearchFilter({
|
const interpolatedQuery = templateSrv.replace(
|
||||||
query: templateSrv.replace(query),
|
query,
|
||||||
options,
|
getSearchFilterScopedVar({ query, wildcardChar: '*', options })
|
||||||
wildcardChar: '*',
|
);
|
||||||
quoteLiteral: false,
|
|
||||||
});
|
|
||||||
const children = queryMetricTree(interpolatedQuery);
|
const children = queryMetricTree(interpolatedQuery);
|
||||||
const items = children.map(item => ({ value: item.name, text: item.name }));
|
const items = children.map(item => ({ value: item.name, text: item.name }));
|
||||||
resolve(items);
|
resolve(items);
|
||||||
|
Loading…
Reference in New Issue
Block a user