SQL: Remove double quotes for multi-value variables (#71130)

* RemoveFirstLastQuotes

* MoveTemplateHandleToFront

* PreserveTemplateInQuery

* Revert "RemoveFirstLastQuotes"

This reverts commit e1ef5764b8.

* CheckForTemplateVarType

* CheckTemplateVars

* ReRunChecks

* ExtractMultiTestToFunction + AddTests

* RemoveAsyncFromTests

* Move condition definition out of .some()
This commit is contained in:
Sol 2023-08-04 09:43:13 +01:00 committed by GitHub
parent 290fc3aadf
commit 1aed2ede7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 1 deletions

View File

@ -2904,6 +2904,9 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"] [0, 0, 0, "Unexpected any. Specify a different type.", "2"]
], ],
"public/app/features/plugins/sql/components/visual-query-builder/SQLWhereRow.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/plugins/tests/datasource_srv.test.ts:5381": [ "public/app/features/plugins/tests/datasource_srv.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"],

View File

@ -2,10 +2,14 @@ import { render, waitFor } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
import { customBuilder } from 'app/features/variables/shared/testing/builders';
import { SQLExpression } from '../types';
import { DatasetSelector } from './DatasetSelector'; import { DatasetSelector } from './DatasetSelector';
import { buildMockDatasetSelectorProps, buildMockTableSelectorProps } from './SqlComponents.testHelpers'; import { buildMockDatasetSelectorProps, buildMockTableSelectorProps } from './SqlComponents.testHelpers';
import { TableSelector } from './TableSelector'; import { TableSelector } from './TableSelector';
import { removeQuotesForMultiVariables } from './visual-query-builder/SQLWhereRow';
beforeEach(() => { beforeEach(() => {
config.featureToggles.sqlDatasourceDatabaseSelection = true; config.featureToggles.sqlDatasourceDatabaseSelection = true;
@ -63,3 +67,41 @@ describe('TableSelector', () => {
}); });
}); });
}); });
describe('SQLWhereRow', () => {
it('should remove quotes in a where clause including multi-value variable', () => {
const exp: SQLExpression = {
whereString: "hostname IN ('${multiHost}')",
};
const multiVar = customBuilder().withId('multiVar').withName('multiHost').build();
const nonMultiVar = customBuilder().withId('nonMultiVar').withName('host').build();
multiVar.multi = true;
nonMultiVar.multi = false;
const variables = [multiVar, nonMultiVar];
removeQuotesForMultiVariables(exp, variables);
expect(exp.whereString).toBe('hostname IN (${multiHost})');
});
it('should not remove quotes in a where clause not including a multi-value variable', () => {
const exp: SQLExpression = {
whereString: "hostname IN ('${nonMultiHost}')",
};
const multiVar = customBuilder().withId('multiVar').withName('multiHost').build();
const nonMultiVar = customBuilder().withId('nonMultiVar').withName('host').build();
multiVar.multi = true;
nonMultiVar.multi = false;
const variables = [multiVar, nonMultiVar];
removeQuotesForMultiVariables(exp, variables);
expect(exp.whereString).toBe("hostname IN ('${nonMultiHost}')");
});
});

View File

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import useAsync from 'react-use/lib/useAsync'; import useAsync from 'react-use/lib/useAsync';
import { SelectableValue } from '@grafana/data'; import { SelectableValue, VariableWithMultiSupport } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { QueryWithDefaults } from '../../defaults'; import { QueryWithDefaults } from '../../defaults';
import { DB, SQLExpression, SQLQuery, SQLSelectableValue } from '../../types'; import { DB, SQLExpression, SQLQuery, SQLSelectableValue } from '../../types';
@ -31,6 +32,9 @@ export function SQLWhereRow({ query, fields, onQueryChange, db }: WhereRowProps)
config={{ fields: state.value || {} }} config={{ fields: state.value || {} }}
sql={query.sql!} sql={query.sql!}
onSqlChange={(val: SQLExpression) => { onSqlChange={(val: SQLExpression) => {
const templateVars = getTemplateSrv().getVariables() as VariableWithMultiSupport[];
removeQuotesForMultiVariables(val, templateVars);
onSqlChange(val); onSqlChange(val);
}} }}
/> />
@ -49,3 +53,13 @@ function mapFieldsToTypes(columns: SQLSelectableValue[]) {
} }
return fields; return fields;
} }
export function removeQuotesForMultiVariables(val: SQLExpression, templateVars: VariableWithMultiSupport[]) {
const multiVariableInWhereString = (tv: VariableWithMultiSupport) =>
tv.multi && (val.whereString?.includes(`\${${tv.name}}`) || val.whereString?.includes(`$${tv.name}`));
if (templateVars.some((tv) => multiVariableInWhereString(tv))) {
val.whereString = val.whereString?.replaceAll("')", ')');
val.whereString = val.whereString?.replaceAll("('", '(');
}
}