From c5d2d5565452d9a3bbecb0126a14beddf45d72c7 Mon Sep 17 00:00:00 2001 From: Giordano Ricci Date: Mon, 17 Jul 2023 12:25:49 +0100 Subject: [PATCH] Explore: Remove exploreMixedDatasource feature toggle (#71534) --- docs/sources/explore/_index.md | 8 - docs/sources/explore/query-management.md | 2 + .../feature-toggles/index.md | 1 - .../src/types/featureToggles.gen.ts | 1 - pkg/services/featuremgmt/registry.go | 8 - pkg/services/featuremgmt/toggles_gen.csv | 1 - pkg/services/featuremgmt/toggles_gen.go | 4 - public/app/core/utils/explore.ts | 16 -- public/app/core/utils/richHistory.ts | 3 +- .../app/features/explore/ExploreToolbar.tsx | 4 +- .../explore/hooks/useStateSync/index.test.tsx | 57 ++--- .../explore/hooks/useStateSync/index.ts | 27 +-- .../explore/hooks/useTimeSrvFix.test.tsx | 6 - .../features/explore/spec/helper/setup.tsx | 19 +- .../app/features/explore/state/query.test.ts | 227 +++++++----------- public/app/features/explore/state/query.ts | 2 +- 16 files changed, 122 insertions(+), 264 deletions(-) diff --git a/docs/sources/explore/_index.md b/docs/sources/explore/_index.md index f723b0f028d..0bae5337996 100644 --- a/docs/sources/explore/_index.md +++ b/docs/sources/explore/_index.md @@ -66,11 +66,3 @@ Available in Grafana 7.3 and later versions. {{% /admonition %}} The Share shortened link capability allows you to create smaller and simpler URLs of the format /goto/:uid instead of using longer URLs with query parameters. To create a shortened link to the executed query, click the **Share** option in the Explore toolbar. A shortened link that is never used will automatically get deleted after seven (7) days. - -## Available feature toggles - -### exploreMixedDatasource - -Enabled by default, allows users in Explore to have different data sources for different queries. If compatible, results will be combined. - -Learn more about how to use [Mixed data source]({{< relref "../datasources/#special-data-sources" >}}). diff --git a/docs/sources/explore/query-management.md b/docs/sources/explore/query-management.md index 3d5120e5ec5..731e694b0f5 100644 --- a/docs/sources/explore/query-management.md +++ b/docs/sources/explore/query-management.md @@ -53,6 +53,8 @@ Filter query history in Query history and Starred tab by data source name: 1. Click the **Filter queries for specific data source(s)** field. 1. Select the data source for which you would like to filter your history. You can select multiple data sources. +> **Note:** Queries ran using the Mixed data source will appear only when filtering for Mixed and not when filtering by their individual data sources. + In **Query history** tab it is also possible to filter queries by date using the slider: - Use vertical slider to filter queries by date. diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index f2269c09bf2..34b525fa186 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -23,7 +23,6 @@ Some features are enabled by default. You can disable these feature by setting t | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | | `disableEnvelopeEncryption` | Disable envelope encryption (emergency only) | | | `featureHighlights` | Highlight Grafana Enterprise features | | -| `exploreMixedDatasource` | Enable mixed datasource in Explore | Yes | | `dataConnectionsConsole` | Enables a new top-level page called Connections. This page is an experiment that provides a better experience when you install and configure data sources and other plugins. | Yes | | `topnav` | Enables new top navigation and page layouts | Yes | | `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes | diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index eaa5a4f25bb..8ffb6da0ee9 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -29,7 +29,6 @@ export interface FeatureToggles { featureHighlights?: boolean; migrationLocking?: boolean; storage?: boolean; - exploreMixedDatasource?: boolean; newTraceViewHeader?: boolean; correlations?: boolean; datasourceQueryMultiStatus?: boolean; diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 84d9d260f51..03b662ae2a8 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -79,14 +79,6 @@ var ( Stage: FeatureStageExperimental, Owner: grafanaAppPlatformSquad, }, - { - Name: "exploreMixedDatasource", - Description: "Enable mixed datasource in Explore", - Stage: FeatureStageGeneralAvailability, - FrontendOnly: true, - Expression: "true", // turned on by default - Owner: grafanaExploreSquad, - }, { Name: "newTraceViewHeader", Description: "Shows the new trace view header", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index 157c262b242..c8336b9678b 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -10,7 +10,6 @@ lokiExperimentalStreaming,experimental,@grafana/observability-logs,false,false,f featureHighlights,GA,@grafana/grafana-as-code,false,false,false,false migrationLocking,preview,@grafana/backend-platform,false,false,false,false storage,experimental,@grafana/grafana-app-platform-squad,false,false,false,false -exploreMixedDatasource,GA,@grafana/explore-squad,false,false,false,true newTraceViewHeader,experimental,@grafana/observability-traces-and-profiling,false,false,false,true correlations,preview,@grafana/explore-squad,false,false,false,false datasourceQueryMultiStatus,experimental,@grafana/plugins-platform-backend,false,false,false,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index b71d8c5335e..432a13fdf7e 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -51,10 +51,6 @@ const ( // Configurable storage for dashboards, datasources, and resources FlagStorage = "storage" - // FlagExploreMixedDatasource - // Enable mixed datasource in Explore - FlagExploreMixedDatasource = "exploreMixedDatasource" - // FlagNewTraceViewHeader // Shows the new trace view header FlagNewTraceViewHeader = "newTraceViewHeader" diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 9758216cd17..df89672f9ca 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -74,22 +74,6 @@ export async function getExploreUrl(args: GetExploreUrlArguments): Promise omit(t, 'legendFormat')) .filter((t) => t.datasource?.uid !== ExpressionDatasourceUID); let url: string | undefined; - // if the mixed datasource is not enabled for explore, choose only one datasource - if ( - config.featureToggles.exploreMixedDatasource === false && - exploreDatasource.meta?.id === 'mixed' && - exploreTargets - ) { - // Find first explore datasource among targets - for (const t of exploreTargets) { - const datasource = await datasourceSrv.get(t.datasource || undefined); - if (datasource) { - exploreDatasource = datasource; - exploreTargets = panel.targets.filter((t) => t.datasource === datasource.name); - break; - } - } - } if (exploreDatasource) { const range = timeSrv.timeRangeForUrl(); diff --git a/public/app/core/utils/richHistory.ts b/public/app/core/utils/richHistory.ts index 5679f1ffee1..9a4b64b1454 100644 --- a/public/app/core/utils/richHistory.ts +++ b/public/app/core/utils/richHistory.ts @@ -8,7 +8,6 @@ import { createErrorNotification, createWarningNotification } from 'app/core/cop import { dispatch } from 'app/store/store'; import { RichHistoryQuery } from 'app/types/explore'; -import { config } from '../config'; import { RichHistoryResults, RichHistoryServiceError, @@ -218,7 +217,7 @@ export function mapQueriesToHeadings(query: RichHistoryQuery[], sortOrder: SortO */ export function createDatasourcesList() { return getDataSourceSrv() - .getList({ mixed: config.featureToggles.exploreMixedDatasource === true }) + .getList({ mixed: true }) .map((dsSettings) => { return { name: dsSettings.name, diff --git a/public/app/features/explore/ExploreToolbar.tsx b/public/app/features/explore/ExploreToolbar.tsx index 39eb12347fd..6496f8d15bf 100644 --- a/public/app/features/explore/ExploreToolbar.tsx +++ b/public/app/features/explore/ExploreToolbar.tsx @@ -4,7 +4,7 @@ import React, { RefObject, useMemo } from 'react'; import { shallowEqual } from 'react-redux'; import { DataSourceInstanceSettings, RawTimeRange } from '@grafana/data'; -import { config, reportInteraction } from '@grafana/runtime'; +import { reportInteraction } from '@grafana/runtime'; import { defaultIntervals, PageToolbar, RefreshPicker, SetInterval, ToolbarButton, ButtonGroup } from '@grafana/ui'; import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate'; import { createAndCopyShortLink } from 'app/core/utils/shortLinks'; @@ -135,7 +135,7 @@ export function ExploreToolbar({ exploreId, topOfViewRef, onChangeTime }: Props) leftItems={[ >) => DataSourceSrv['get']; } -function setup({ queryParams = {}, exploreMixedDatasource = false, datasourceGetter = defaultDsGetter }: SetupParams) { +function setup({ queryParams = {}, datasourceGetter = defaultDsGetter }: SetupParams) { const history = createMemoryHistory({ initialEntries: [{ pathname: '/explore', search: stringify(queryParams) }], }); @@ -67,12 +66,9 @@ function setup({ queryParams = {}, exploreMixedDatasource = false, datasourceGet const datasources = [ makeDatasourceSetup({ name: 'loki', uid: 'loki-uid' }), makeDatasourceSetup({ name: 'elastic', uid: 'elastic-uid' }), + makeDatasourceSetup({ name: MIXED_DATASOURCE_NAME, uid: MIXED_DATASOURCE_NAME, id: 999 }), ]; - if (exploreMixedDatasource) { - datasources.push(makeDatasourceSetup({ name: MIXED_DATASOURCE_NAME, uid: MIXED_DATASOURCE_NAME, id: 999 })); - } - setDataSourceSrv({ get: datasourceGetter(datasources), getInstanceSettings: jest.fn(), @@ -104,12 +100,6 @@ function setup({ queryParams = {}, exploreMixedDatasource = false, datasourceGet grafanaContext={{ ...context, location, - config: { - ...context.config, - featureToggles: { - exploreMixedDatasource, - }, - }, }} store={store} > @@ -408,7 +398,6 @@ describe('useStateSync', () => { it('uses the first query datasource if no root datasource is specified in the URL', async () => { const { waitForNextUpdate, store } = setup({ - exploreMixedDatasource: true, queryParams: { panes: JSON.stringify({ one: { @@ -429,7 +418,6 @@ describe('useStateSync', () => { it('updates the URL opening and closing a pane datasource changes', async () => { const { waitForNextUpdate, store, location } = setup({ - exploreMixedDatasource: true, queryParams: { panes: JSON.stringify({ one: { @@ -467,28 +455,25 @@ describe('useStateSync', () => { }); }); - describe('with exploreMixedDatasource enabled', () => { - it('filters out queries from the URL that do not have a datasource', async () => { - const { waitForNextUpdate, store } = setup({ - exploreMixedDatasource: true, - queryParams: { - panes: JSON.stringify({ - one: { - datasource: MIXED_DATASOURCE_NAME, - queries: [ - { expr: 'a', refId: 'A' }, - { expr: 'b', datasource: { uid: 'loki-uid', type: 'logs' }, refId: 'B' }, - ], - }, - }), - schemaVersion: 1, - }, - }); - - await waitForNextUpdate(); - - expect(store.getState().explore.panes['one']?.queries.length).toBe(1); - expect(store.getState().explore.panes['one']?.queries[0]).toMatchObject({ expr: 'b', refId: 'B' }); + it('filters out queries from the URL that do not have a datasource', async () => { + const { waitForNextUpdate, store } = setup({ + queryParams: { + panes: JSON.stringify({ + one: { + datasource: MIXED_DATASOURCE_NAME, + queries: [ + { expr: 'a', refId: 'A' }, + { expr: 'b', datasource: { uid: 'loki-uid', type: 'logs' }, refId: 'B' }, + ], + }, + }), + schemaVersion: 1, + }, }); + + await waitForNextUpdate(); + + expect(store.getState().explore.panes['one']?.queries.length).toBe(1); + expect(store.getState().explore.panes['one']?.queries[0]).toMatchObject({ expr: 'b', refId: 'B' }); }); }); diff --git a/public/app/features/explore/hooks/useStateSync/index.ts b/public/app/features/explore/hooks/useStateSync/index.ts index 7940cb0d1d9..f6515b87d90 100644 --- a/public/app/features/explore/hooks/useStateSync/index.ts +++ b/public/app/features/explore/hooks/useStateSync/index.ts @@ -25,12 +25,7 @@ import { parseURL } from './parseURL'; * Bi-directionally syncs URL changes with Explore's state. */ export function useStateSync(params: ExploreQueryParams) { - const { - location, - config: { - featureToggles: { exploreMixedDatasource }, - }, - } = useGrafana(); + const { location } = useGrafana(); const dispatch = useDispatch(); const panesState = useSelector(selectPanes); const orgId = useSelector((state) => state.user.orgId); @@ -170,7 +165,7 @@ export function useStateSync(params: ExploreQueryParams) { Promise.all( Object.entries(urlState.panes).map(([exploreId, { datasource, queries, range, panelsState }]) => { - return getPaneDatasource(datasource, queries, orgId, !!exploreMixedDatasource).then((paneDatasource) => { + return getPaneDatasource(datasource, queries, orgId).then((paneDatasource) => { return Promise.resolve( // Given the Grafana datasource will always be present, this should always be defined. paneDatasource @@ -254,7 +249,7 @@ export function useStateSync(params: ExploreQueryParams) { prevParams.current = params; isURLOutOfSync && initState.current === 'done' && sync(); - }, [dispatch, panesState, exploreMixedDatasource, orgId, location, params]); + }, [dispatch, panesState, orgId, location, params]); } function getDefaultQuery(ds: DataSourceApi) { @@ -303,7 +298,7 @@ async function removeQueriesWithInvalidDatasource(queries: DataQuery[]) { /** * Returns the datasource that an explore pane should be using. - * If the URL specifies a datasource and that datasource exists, it will be used unless said datasource is mixed and `allowMixed` is false. + * If the URL specifies a datasource and that datasource exists, it will be used unless said datasource is mixed. * Otherwise the datasource will be extracetd from the the first query specifying a valid datasource. * * If there's no datasource in the queries, the last used datasource will be used. @@ -312,28 +307,22 @@ async function removeQueriesWithInvalidDatasource(queries: DataQuery[]) { * @param rootDatasource the top-level datasource specified in the URL * @param queries the queries in the pane * @param orgId the orgId of the user - * @param allowMixed whether mixed datasources are allowed * * @returns the datasource UID that the pane should use, undefined if no suitable datasource is found */ async function getPaneDatasource( rootDatasource: DataSourceRef | string | null | undefined, queries: DataQuery[], - orgId: number, - allowMixed: boolean + orgId: number ) { - // If there's a root datasource, use it unless it's mixed and we don't allow mixed. + // If there's a root datasource, use it unless it's unavailable if (rootDatasource) { try { - const ds = await getDatasourceSrv().get(rootDatasource); - - if (!isMixedDatasource(ds) || allowMixed) { - return ds; - } + return await getDatasourceSrv().get(rootDatasource); } catch (_) {} } - // TODO: if queries have multiple datasources and allowMixed is true, we should return mixed datasource + // TODO: if queries have multiple datasources we should return mixed datasource // Else we try to find a datasource in the queries, returning the first one that exists const queriesWithDS = queries.filter((q) => q.datasource); for (const query of queriesWithDS) { diff --git a/public/app/features/explore/hooks/useTimeSrvFix.test.tsx b/public/app/features/explore/hooks/useTimeSrvFix.test.tsx index 332613a7938..1b3ddbf9d89 100644 --- a/public/app/features/explore/hooks/useTimeSrvFix.test.tsx +++ b/public/app/features/explore/hooks/useTimeSrvFix.test.tsx @@ -25,12 +25,6 @@ describe('useTimeSrvFix', () => { grafanaContext={{ ...context, location, - config: { - ...context.config, - featureToggles: { - exploreMixedDatasource: true, - }, - }, }} > {children} diff --git a/public/app/features/explore/spec/helper/setup.tsx b/public/app/features/explore/spec/helper/setup.tsx index 4bce74e55b8..aa2958badc7 100644 --- a/public/app/features/explore/spec/helper/setup.tsx +++ b/public/app/features/explore/spec/helper/setup.tsx @@ -18,7 +18,6 @@ import { import { setDataSourceSrv, setEchoSrv, - config, setLocationService, HistoryWrapper, LocationService, @@ -45,7 +44,6 @@ type SetupOptions = { datasources?: DatasourceSetup[]; urlParams?: ExploreQueryParams; prevUsedDatasource?: { orgId: number; datasource: string }; - mixedEnabled?: boolean; }; export function setupExplore(options?: SetupOptions): { @@ -71,12 +69,9 @@ export function setupExplore(options?: SetupOptions): { const defaultDatasources: DatasourceSetup[] = [ makeDatasourceSetup(), makeDatasourceSetup({ name: 'elastic', id: 2 }), + makeDatasourceSetup({ name: MIXED_DATASOURCE_NAME, uid: MIXED_DATASOURCE_NAME, id: 999 }), ]; - if (config.featureToggles.exploreMixedDatasource) { - defaultDatasources.push(makeDatasourceSetup({ name: MIXED_DATASOURCE_NAME, uid: MIXED_DATASOURCE_NAME, id: 999 })); - } - const dsSettings = options?.datasources || defaultDatasources; setDataSourceSrv({ @@ -138,17 +133,7 @@ export function setupExplore(options?: SetupOptions): { const { unmount, container } = render( - + ({ }, }; }, - config: { - featureToggles: { exploreMixedDatasource: false }, - }, })); function setupQueryResponse(state: StoreState) { @@ -447,155 +443,102 @@ describe('importing queries', () => { }); describe('adding new query rows', () => { - describe('with mixed datasources disabled', () => { - it('should add query row when there is not yet a row and meta.mixed === true (impossible in UI)', async () => { - const queries: DataQuery[] = []; - const datasourceInstance = { - query: jest.fn(), - getRef: () => { - return { type: 'loki', uid: 'uid-loki' }; - }, - meta: { - id: 'mixed', - mixed: true, - } as unknown as DataSourcePluginMeta<{}>, - }; + it('should add another query row if there are two rows already', async () => { + const queries = [ + { + datasource: { type: 'loki', uid: 'ds3' }, + refId: 'C', + }, + { + datasource: { type: 'loki', uid: 'ds4' }, + refId: 'D', + }, + ]; + const datasourceInstance = { + query: jest.fn(), + getRef: jest.fn(), + meta: { + id: 'loki', + mixed: false, + } as unknown as DataSourcePluginMeta<{}>, + }; + const getState = await setupStore(queries, datasourceInstance); - const getState = await setupStore(queries, datasourceInstance); - - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('mixed'); - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(true); - expect(getState().explore.panes[exploreId]!.queries).toHaveLength(1); - expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['uid-loki-0']); - }); - it('should add query row when there is not yet a row and meta.mixed === false', async () => { - const queries: DataQuery[] = []; - const datasourceInstance = { - query: jest.fn(), - getRef: () => { - return { type: 'loki', uid: 'uid-loki' }; - }, - meta: { - id: 'loki', - mixed: false, - } as unknown as DataSourcePluginMeta<{}>, - }; - - const getState = await setupStore(queries, datasourceInstance); - - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('loki'); - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(false); - expect(getState().explore.panes[exploreId]!.queries).toHaveLength(1); - expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['uid-loki-0']); - }); - - it('should add another query row if there are two rows already', async () => { - const queries = [ - { - datasource: { type: 'loki', uid: 'ds3' }, - refId: 'C', - }, - { - datasource: { type: 'loki', uid: 'ds4' }, - refId: 'D', - }, - ]; - const datasourceInstance = { - query: jest.fn(), - getRef: jest.fn(), - meta: { - id: 'loki', - mixed: false, - } as unknown as DataSourcePluginMeta<{}>, - }; - const getState = await setupStore(queries, datasourceInstance); - - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('loki'); - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(false); - expect(getState().explore.panes[exploreId]!.queries).toHaveLength(3); - expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['ds3-0', 'ds4-1', 'ds4-2']); - }); + expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('loki'); + expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(false); + expect(getState().explore.panes[exploreId]!.queries).toHaveLength(3); + expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['ds3-0', 'ds4-1', 'ds4-2']); }); - describe('with mixed datasources enabled', () => { - beforeEach(() => { - config.featureToggles.exploreMixedDatasource = true; - }); - afterEach(() => { - config.featureToggles.exploreMixedDatasource = false; - }); + it('should add query row whith root ds (without overriding the default ds) when there is not yet a row', async () => { + const queries: DataQuery[] = []; + const datasourceInstance = { + query: jest.fn(), + getRef: jest.fn(), + meta: { + id: 'mixed', + mixed: true, + } as unknown as DataSourcePluginMeta<{}>, + }; - it('should add query row whith root ds (without overriding the default ds) when there is not yet a row', async () => { - const queries: DataQuery[] = []; - const datasourceInstance = { - query: jest.fn(), - getRef: jest.fn(), - meta: { - id: 'mixed', - mixed: true, - } as unknown as DataSourcePluginMeta<{}>, - }; + const getState = await setupStore(queries, datasourceInstance); - const getState = await setupStore(queries, datasourceInstance); + expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('mixed'); + expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(true); + expect(getState().explore.panes[exploreId]!.queries).toHaveLength(1); + expect(getState().explore.panes[exploreId]!.queries[0]?.datasource?.type).toBe('postgres'); + expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['ds1-0']); + }); - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('mixed'); - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(true); - expect(getState().explore.panes[exploreId]!.queries).toHaveLength(1); - expect(getState().explore.panes[exploreId]!.queries[0]?.datasource?.type).toBe('postgres'); - expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['ds1-0']); - }); + it('should add query row whith root ds (with overriding the default ds) when there is not yet a row', async () => { + const queries: DataQuery[] = []; + const datasourceInstance = { + query: jest.fn(), + getRef: () => { + return { type: 'loki', uid: 'uid-loki' }; + }, + meta: { + id: 'loki', + mixed: false, + } as unknown as DataSourcePluginMeta<{}>, + }; - it('should add query row whith root ds (with overriding the default ds) when there is not yet a row', async () => { - const queries: DataQuery[] = []; - const datasourceInstance = { - query: jest.fn(), - getRef: () => { - return { type: 'loki', uid: 'uid-loki' }; - }, - meta: { - id: 'loki', - mixed: false, - } as unknown as DataSourcePluginMeta<{}>, - }; + const getState = await setupStore(queries, datasourceInstance); - const getState = await setupStore(queries, datasourceInstance); + expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('loki'); + expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(false); + expect(getState().explore.panes[exploreId]!.queries).toHaveLength(1); + expect(getState().explore.panes[exploreId]!.queries[0]?.datasource?.type).toBe('loki'); + expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['uid-loki-0']); + }); - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('loki'); - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(false); - expect(getState().explore.panes[exploreId]!.queries).toHaveLength(1); - expect(getState().explore.panes[exploreId]!.queries[0]?.datasource?.type).toBe('loki'); - expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['uid-loki-0']); - }); + it('should add another query row if there are two rows already', async () => { + const queries = [ + { + datasource: { type: 'postgres', uid: 'ds3' }, + refId: 'C', + }, + { + datasource: { type: 'loki', uid: 'ds4' }, + refId: 'D', + }, + ]; + const datasourceInstance = { + query: jest.fn(), + getRef: jest.fn(), + meta: { + id: 'mixed', + mixed: true, + } as unknown as DataSourcePluginMeta<{}>, + }; - it('should add another query row if there are two rows already (impossible in UI)', async () => { - const queries = [ - { - datasource: { type: 'postgres', uid: 'ds3' }, - refId: 'C', - }, - { - datasource: { type: 'loki', uid: 'ds4' }, - refId: 'D', - }, - ]; - const datasourceInstance = { - query: jest.fn(), - getRef: jest.fn(), - meta: { - // datasourceInstance.meta.id is set to postgres because it's the default datasource - id: 'postgres', - mixed: false, - } as unknown as DataSourcePluginMeta<{}>, - }; + const getState = await setupStore(queries, datasourceInstance); - const getState = await setupStore(queries, datasourceInstance); - - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('postgres'); - expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(false); - expect(getState().explore.panes[exploreId]!.queries).toHaveLength(3); - expect(getState().explore.panes[exploreId]!.queries[2]?.datasource?.type).toBe('loki'); - expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['ds3-0', 'ds4-1', 'ds4-2']); - }); + expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.id).toBe('mixed'); + expect(getState().explore.panes[exploreId]!.datasourceInstance?.meta?.mixed).toBe(true); + expect(getState().explore.panes[exploreId]!.queries).toHaveLength(3); + expect(getState().explore.panes[exploreId]!.queries[2]?.datasource?.type).toBe('loki'); + expect(getState().explore.panes[exploreId]!.queryKeys).toEqual(['ds3-0', 'ds4-1', 'ds4-2']); }); }); diff --git a/public/app/features/explore/state/query.ts b/public/app/features/explore/state/query.ts index 79ede4ef485..9081c363ace 100644 --- a/public/app/features/explore/state/query.ts +++ b/public/app/features/explore/state/query.ts @@ -258,7 +258,7 @@ export function addQueryRow(exploreId: string, index: number): ThunkResult // if it's not mixed, send it as an override. generateEmptyQuery doesn't have access to state if (queries.length === 0) { const rootDatasource = getState().explore.panes[exploreId]!.datasourceInstance; - if (!config.featureToggles.exploreMixedDatasource || !rootDatasource?.meta.mixed) { + if (!rootDatasource?.meta.mixed) { datasourceOverride = rootDatasource; } }