grafana/public/app/features/query/state/updateQueries.ts
Andreas Christou bf91fb76fa
QueryBuilder: Preserve queries when switching from Mixed (#71224)
* When switching from mixed to another datasource preserve relevant queries

- Update query refs
- Update tests

* Ensure templateVars are handled correctly

- Add test

* Comment

* Unused var

* For ds template variable only preserve if going from&to template

- Add test
2023-07-18 15:15:43 +01:00

80 lines
3.0 KiB
TypeScript

import { CoreApp, DataSourceApi, hasQueryExportSupport, hasQueryImportSupport } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { isExpressionReference } from '@grafana/runtime/src/utils/DataSourceWithBackend';
import { DataQuery } from '@grafana/schema';
import { getNextRefIdChar } from 'app/core/utils/query';
export async function updateQueries(
nextDS: DataSourceApi,
nextDSUidOrVariableExpression: string,
queries: DataQuery[],
currentDS?: DataSourceApi
): Promise<DataQuery[]> {
let nextQueries = queries;
const datasource = { type: nextDS.type, uid: nextDSUidOrVariableExpression };
const DEFAULT_QUERY = { ...nextDS?.getDefaultQuery?.(CoreApp.PanelEditor), datasource, refId: 'A' };
// we are changing data source type
if (currentDS?.meta.id !== nextDS.meta.id) {
// If changing to mixed do nothing
if (nextDS.meta.mixed) {
return queries;
}
// when both data sources support abstract queries
else if (hasQueryExportSupport(currentDS) && hasQueryImportSupport(nextDS)) {
const abstractQueries = await currentDS.exportToAbstractQueries(queries);
nextQueries = await nextDS.importFromAbstractQueries(abstractQueries);
}
// when datasource supports query import
else if (currentDS && nextDS.importQueries) {
nextQueries = await nextDS.importQueries(queries, currentDS);
}
// Otherwise clear queries that do not match the next datasource UID
else {
if (currentDS) {
const templateSrv = getTemplateSrv();
const reducedQueries: DataQuery[] = [];
let nextUid = nextDS.uid;
const nextIsTemplate = templateSrv.containsTemplate(nextDSUidOrVariableExpression);
if (nextIsTemplate) {
nextUid = templateSrv.replace(nextDS.uid);
}
// Queries will only be preserved if the datasource UID of the query matches the UID
// of the next chosen datasource
const nextDsQueries = queries.reduce((reduced, currentQuery) => {
if (currentQuery.datasource) {
let currUid = currentQuery.datasource.uid;
const currIsTemplate = templateSrv.containsTemplate(currUid);
if (currIsTemplate) {
currUid = templateSrv.replace(currentQuery.datasource.uid);
}
if (currUid === nextUid && currIsTemplate === nextIsTemplate) {
currentQuery.refId = getNextRefIdChar(reduced);
return reduced.concat([currentQuery]);
}
}
return reduced;
}, reducedQueries);
if (nextDsQueries.length > 0) {
return nextDsQueries;
}
}
return [DEFAULT_QUERY];
}
}
if (nextQueries.length === 0) {
return [DEFAULT_QUERY];
}
// Set data source on all queries except expression queries
return nextQueries.map((query) => {
if (!isExpressionReference(query.datasource) && !nextDS.meta.mixed) {
query.datasource = datasource;
}
return query;
});
}