You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by yo...@apache.org on 2022/09/21 01:41:41 UTC
[superset] branch master updated: feat: generate consistent QueryObject whether GenericAxis is enabled or disabled (#21519)
This is an automated email from the ASF dual-hosted git repository.
yongjiezhao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 4d12e3709e feat: generate consistent QueryObject whether GenericAxis is enabled or disabled (#21519)
4d12e3709e is described below
commit 4d12e3709eb7ab1cc4f687c15ed54a4738266482
Author: Yongjie Zhao <yo...@apache.org>
AuthorDate: Wed Sep 21 09:41:21 2022 +0800
feat: generate consistent QueryObject whether GenericAxis is enabled or disabled (#21519)
---
.../src/operators/pivotOperator.ts | 4 +-
.../src/operators/prophetOperator.ts | 5 +-
.../src/operators/renameOperator.ts | 6 +-
.../src/operators/timeComparePivotOperator.ts | 5 +-
.../src/operators/utils/index.ts | 1 -
.../test/operators/pivotOperator.test.ts | 2 +-
.../test/operators/prophetOperator.test.ts | 2 +-
.../test/operators/renameOperator.test.ts | 2 +-
.../operators/timeComparePivotOperator.test.ts | 2 +-
.../src/query/buildQueryContext.ts | 4 +-
.../src/query/getXAxis.ts} | 14 +-
.../packages/superset-ui-core/src/query/index.ts | 1 +
.../src/query/normalizeTimeColumn.ts | 4 +-
.../test/query/buildQueryContext.test.ts | 3 +-
.../superset-ui-core/test/query/getAxis.test.ts | 71 ++++++++
.../test/query/normalizeTimeColumn.test.ts | 50 +++++-
.../src/MixedTimeseries/buildQuery.ts | 16 +-
.../src/MixedTimeseries/transformProps.ts | 7 +-
.../src/Timeseries/buildQuery.ts | 24 ++-
.../src/Timeseries/transformProps.ts | 8 +-
.../test/MixedTimeseries/buildQuery.test.ts | 129 ++++++++++++++-
.../test/Timeseries/buildQuery.test.ts | 179 +++++++++++++++++++++
22 files changed, 474 insertions(+), 65 deletions(-)
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts
index efd4f50a8b..bd929dd774 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts
@@ -21,16 +21,16 @@ import {
getColumnLabel,
getMetricLabel,
PostProcessingPivot,
+ getXAxis,
} from '@superset-ui/core';
import { PostProcessingFactory } from './types';
-import { getAxis } from './utils';
export const pivotOperator: PostProcessingFactory<PostProcessingPivot> = (
formData,
queryObject,
) => {
const metricLabels = ensureIsArray(queryObject.metrics).map(getMetricLabel);
- const xAxis = getAxis(formData);
+ const xAxis = getXAxis(formData);
if (xAxis && metricLabels.length) {
return {
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/prophetOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/prophetOperator.ts
index 5d8d7feea9..da651ba12c 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/prophetOperator.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/prophetOperator.ts
@@ -16,16 +16,15 @@
* specific language governing permissions and limitationsxw
* under the License.
*/
-import { PostProcessingProphet } from '@superset-ui/core';
+import { PostProcessingProphet, getXAxis } from '@superset-ui/core';
import { PostProcessingFactory } from './types';
-import { getAxis } from './utils';
/* eslint-disable @typescript-eslint/no-unused-vars */
export const prophetOperator: PostProcessingFactory<PostProcessingProphet> = (
formData,
queryObject,
) => {
- const xAxis = getAxis(formData);
+ const xAxis = getXAxis(formData);
if (formData.forecastEnabled && xAxis) {
return {
operation: 'prophet',
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts
index 84cbbce8c5..c51e588cf3 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts
@@ -22,6 +22,7 @@ import {
ensureIsArray,
getMetricLabel,
ComparisionType,
+ getXAxis,
} from '@superset-ui/core';
import { PostProcessingFactory } from './types';
import { getMetricOffsetsMap, isTimeComparison } from './utils';
@@ -32,7 +33,8 @@ export const renameOperator: PostProcessingFactory<PostProcessingRename> = (
) => {
const metrics = ensureIsArray(queryObject.metrics);
const columns = ensureIsArray(queryObject.columns);
- const { x_axis: xAxis, truncate_metric } = formData;
+ const { truncate_metric } = formData;
+ const xAxis = getXAxis(formData);
// remove or rename top level of column name(metric name) in the MultiIndex when
// 1) only 1 metric
// 2) exist dimentsion
@@ -42,7 +44,7 @@ export const renameOperator: PostProcessingFactory<PostProcessingRename> = (
if (
metrics.length === 1 &&
columns.length > 0 &&
- (xAxis || queryObject.is_timeseries) &&
+ xAxis &&
!(
// todo: we should provide an approach to handle derived metrics
(
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts
index e1310a4e3a..d4ecbf9b62 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts
@@ -22,14 +22,15 @@ import {
getColumnLabel,
NumpyFunction,
PostProcessingPivot,
+ getXAxis,
} from '@superset-ui/core';
-import { getMetricOffsetsMap, isTimeComparison, getAxis } from './utils';
+import { getMetricOffsetsMap, isTimeComparison } from './utils';
import { PostProcessingFactory } from './types';
export const timeComparePivotOperator: PostProcessingFactory<PostProcessingPivot> =
(formData, queryObject) => {
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
- const xAxis = getAxis(formData);
+ const xAxis = getXAxis(formData);
if (isTimeComparison(formData, queryObject) && xAxis) {
const aggregates = Object.fromEntries(
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/index.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/index.ts
index 809ebe06ed..8d65ca1e59 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/index.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/index.ts
@@ -21,4 +21,3 @@ export { getMetricOffsetsMap } from './getMetricOffsetsMap';
export { isTimeComparison } from './isTimeComparison';
export { isDerivedSeries } from './isDerivedSeries';
export { TIME_COMPARISON_SEPARATOR } from './constants';
-export { getAxis } from './getAxis';
diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/operators/pivotOperator.test.ts b/superset-frontend/packages/superset-ui-chart-controls/test/operators/pivotOperator.test.ts
index c6c7f905d2..f29c4c568c 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/test/operators/pivotOperator.test.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/test/operators/pivotOperator.test.ts
@@ -141,7 +141,7 @@ test('pivot by adhoc x_axis', () => {
x_axis: {
label: 'my_case_expr',
expressionType: 'SQL',
- expression: 'case when a = 1 then 1 else 0 end',
+ sqlExpression: 'case when a = 1 then 1 else 0 end',
},
},
{
diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/operators/prophetOperator.test.ts b/superset-frontend/packages/superset-ui-chart-controls/test/operators/prophetOperator.test.ts
index 2f3c63ddf8..9613584f8e 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/test/operators/prophetOperator.test.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/test/operators/prophetOperator.test.ts
@@ -108,7 +108,7 @@ test('should do prophetOperator over adhoc column', () => {
x_axis: {
label: 'my_case_expr',
expressionType: 'SQL',
- expression: 'case when a = 1 then 1 else 0 end',
+ sqlExpression: 'case when a = 1 then 1 else 0 end',
},
forecastEnabled: true,
forecastPeriods: '3',
diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/operators/renameOperator.test.ts b/superset-frontend/packages/superset-ui-chart-controls/test/operators/renameOperator.test.ts
index 26bbe9e369..3aed86401e 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/test/operators/renameOperator.test.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/test/operators/renameOperator.test.ts
@@ -110,7 +110,7 @@ test('should add renameOperator if does not exist x_axis', () => {
renameOperator(
{
...formData,
- ...{ x_axis: null },
+ ...{ x_axis: null, granularity_sqla: 'time column' },
},
queryObject,
),
diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/operators/timeComparePivotOperator.test.ts b/superset-frontend/packages/superset-ui-chart-controls/test/operators/timeComparePivotOperator.test.ts
index bf46940d71..f95050cbbe 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/test/operators/timeComparePivotOperator.test.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/test/operators/timeComparePivotOperator.test.ts
@@ -146,7 +146,7 @@ test('should pivot on adhoc x-axis', () => {
x_axis: {
label: 'my_case_expr',
expressionType: 'SQL',
- expression: 'case when a = 1 then 1 else 0 end',
+ sqlExpression: 'case when a = 1 then 1 else 0 end',
},
},
queryObject,
diff --git a/superset-frontend/packages/superset-ui-core/src/query/buildQueryContext.ts b/superset-frontend/packages/superset-ui-core/src/query/buildQueryContext.ts
index 4ab69ab40e..c5b2b3780b 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/buildQueryContext.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/buildQueryContext.ts
@@ -23,8 +23,8 @@ import { QueryFieldAliases, QueryFormData } from './types/QueryFormData';
import { QueryContext, QueryObject } from './types/Query';
import { SetDataMaskHook } from '../chart';
import { JsonObject } from '../connection';
-import { isFeatureEnabled, FeatureFlag } from '../utils';
import { normalizeTimeColumn } from './normalizeTimeColumn';
+import { isXAxisSet } from './getXAxis';
const WRAP_IN_ARRAY = (baseQueryObject: QueryObject) => [baseQueryObject];
@@ -54,7 +54,7 @@ export default function buildQueryContext(
query.post_processing = query.post_processing.filter(Boolean);
}
});
- if (isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES)) {
+ if (isXAxisSet(formData)) {
queries = queries.map(query => normalizeTimeColumn(formData, query));
}
return {
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/getAxis.ts b/superset-frontend/packages/superset-ui-core/src/query/getXAxis.ts
similarity index 79%
rename from superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/getAxis.ts
rename to superset-frontend/packages/superset-ui-core/src/query/getXAxis.ts
index d47089504e..2413ef5166 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/utils/getAxis.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/getXAxis.ts
@@ -19,17 +19,21 @@
import {
DTTM_ALIAS,
getColumnLabel,
- isDefined,
+ isQueryFormColumn,
QueryFormData,
} from '@superset-ui/core';
-export const getAxis = (formData: QueryFormData): string | undefined => {
+export const isXAxisSet = (formData: QueryFormData) =>
+ isQueryFormColumn(formData.x_axis);
+
+export const getXAxis = (formData: QueryFormData): string | undefined => {
// The formData should be "raw form_data" -- the snake_case version of formData rather than camelCase.
if (!(formData.granularity_sqla || formData.x_axis)) {
return undefined;
}
- return isDefined(formData.x_axis)
- ? getColumnLabel(formData.x_axis)
- : DTTM_ALIAS;
+ if (isXAxisSet(formData)) {
+ return getColumnLabel(formData.x_axis);
+ }
+ return DTTM_ALIAS;
};
diff --git a/superset-frontend/packages/superset-ui-core/src/query/index.ts b/superset-frontend/packages/superset-ui-core/src/query/index.ts
index a539267f9d..c3d9bc1bd8 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/index.ts
@@ -29,6 +29,7 @@ export { default as getMetricLabel } from './getMetricLabel';
export { default as DatasourceKey } from './DatasourceKey';
export { default as normalizeOrderBy } from './normalizeOrderBy';
export { normalizeTimeColumn } from './normalizeTimeColumn';
+export { getXAxis, isXAxisSet } from './getXAxis';
export * from './types/AnnotationLayer';
export * from './types/QueryFormData';
diff --git a/superset-frontend/packages/superset-ui-core/src/query/normalizeTimeColumn.ts b/superset-frontend/packages/superset-ui-core/src/query/normalizeTimeColumn.ts
index 9879e9fe0a..f7ea0d0e60 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/normalizeTimeColumn.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/normalizeTimeColumn.ts
@@ -26,14 +26,14 @@ import {
QueryFormData,
QueryObject,
} from './types';
-import { FeatureFlag, isFeatureEnabled } from '../utils';
+import { isXAxisSet } from './getXAxis';
export function normalizeTimeColumn(
formData: QueryFormData,
queryObject: QueryObject,
): QueryObject {
// The formData should be "raw form_data" -- the snake_case version of formData rather than camelCase.
- if (!(isFeatureEnabled(FeatureFlag.GENERIC_CHART_AXES) && formData.x_axis)) {
+ if (!isXAxisSet(formData)) {
return queryObject;
}
diff --git a/superset-frontend/packages/superset-ui-core/test/query/buildQueryContext.test.ts b/superset-frontend/packages/superset-ui-core/test/query/buildQueryContext.test.ts
index 3cfbb4e3bb..4a9e71a6dd 100644
--- a/superset-frontend/packages/superset-ui-core/test/query/buildQueryContext.test.ts
+++ b/superset-frontend/packages/superset-ui-core/test/query/buildQueryContext.test.ts
@@ -123,7 +123,7 @@ describe('buildQueryContext', () => {
},
]);
});
- it('should call normalizeTimeColumn if GENERIC_CHART_AXES is enabled', () => {
+ it('should call normalizeTimeColumn if GENERIC_CHART_AXES is enabled and has x_axis', () => {
// @ts-ignore
const spy = jest.spyOn(window, 'window', 'get').mockImplementation(() => ({
featureFlags: {
@@ -139,6 +139,7 @@ describe('buildQueryContext', () => {
{
datasource: '5__table',
viz_type: 'table',
+ x_axis: 'axis',
},
() => [{}],
);
diff --git a/superset-frontend/packages/superset-ui-core/test/query/getAxis.test.ts b/superset-frontend/packages/superset-ui-core/test/query/getAxis.test.ts
new file mode 100644
index 0000000000..6db1c150ea
--- /dev/null
+++ b/superset-frontend/packages/superset-ui-core/test/query/getAxis.test.ts
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { isXAxisSet } from '@superset-ui/core';
+
+describe('GENERIC_CHART_AXES is enabled', () => {
+ let windowSpy: any;
+
+ beforeAll(() => {
+ // @ts-ignore
+ windowSpy = jest.spyOn(window, 'window', 'get').mockImplementation(() => ({
+ featureFlags: {
+ GENERIC_CHART_AXES: true,
+ },
+ }));
+ });
+
+ afterAll(() => {
+ windowSpy.mockRestore();
+ });
+
+ it('isEnabledAxies when FF is disabled', () => {
+ expect(
+ isXAxisSet({ datasource: '123', viz_type: 'table' }),
+ ).not.toBeTruthy();
+ expect(
+ isXAxisSet({ datasource: '123', viz_type: 'table', x_axis: 'axis' }),
+ ).toBeTruthy();
+ });
+});
+
+describe('GENERIC_CHART_AXES is disabled', () => {
+ let windowSpy: any;
+
+ beforeAll(() => {
+ // @ts-ignore
+ windowSpy = jest.spyOn(window, 'window', 'get').mockImplementation(() => ({
+ featureFlags: {
+ GENERIC_CHART_AXES: false,
+ },
+ }));
+ });
+
+ afterAll(() => {
+ windowSpy.mockRestore();
+ });
+
+ it('isEnabledAxies when FF is disabled', () => {
+ expect(
+ isXAxisSet({ datasource: '123', viz_type: 'table' }),
+ ).not.toBeTruthy();
+ expect(
+ isXAxisSet({ datasource: '123', viz_type: 'table', x_axis: 'axis' }),
+ ).toBeTruthy();
+ });
+});
diff --git a/superset-frontend/packages/superset-ui-core/test/query/normalizeTimeColumn.test.ts b/superset-frontend/packages/superset-ui-core/test/query/normalizeTimeColumn.test.ts
index 1466d10619..22189b9055 100644
--- a/superset-frontend/packages/superset-ui-core/test/query/normalizeTimeColumn.test.ts
+++ b/superset-frontend/packages/superset-ui-core/test/query/normalizeTimeColumn.test.ts
@@ -22,7 +22,7 @@ import {
SqlaFormData,
} from '@superset-ui/core';
-describe('disabled GENERIC_CHART_AXES', () => {
+describe('GENERIC_CHART_AXES is disabled', () => {
let windowSpy: any;
beforeAll(() => {
@@ -47,7 +47,6 @@ describe('disabled GENERIC_CHART_AXES', () => {
time_range: '1 year ago : 2013',
columns: ['col1'],
metrics: ['count(*)'],
- x_axis: 'time_column',
};
const query: QueryObject = {
datasource: '5__table',
@@ -64,9 +63,54 @@ describe('disabled GENERIC_CHART_AXES', () => {
};
expect(normalizeTimeColumn(formData, query)).toEqual(query);
});
+
+ it('should return converted QueryObject even though disabled GENERIC_CHART_AXES (x_axis in formData)', () => {
+ const formData: SqlaFormData = {
+ datasource: '5__table',
+ viz_type: 'table',
+ granularity: 'time_column',
+ time_grain_sqla: 'P1Y',
+ time_range: '1 year ago : 2013',
+ columns: ['col1'],
+ metrics: ['count(*)'],
+ x_axis: 'time_column',
+ };
+ const query: QueryObject = {
+ datasource: '5__table',
+ viz_type: 'table',
+ granularity: 'time_column',
+ extras: {
+ time_grain_sqla: 'P1Y',
+ },
+ time_range: '1 year ago : 2013',
+ orderby: [['count(*)', true]],
+ columns: ['time_column', 'col1'],
+ metrics: ['count(*)'],
+ is_timeseries: true,
+ };
+ expect(normalizeTimeColumn(formData, query)).toEqual({
+ datasource: '5__table',
+ viz_type: 'table',
+ granularity: 'time_column',
+ extras: {},
+ time_range: '1 year ago : 2013',
+ orderby: [['count(*)', true]],
+ columns: [
+ {
+ timeGrain: 'P1Y',
+ columnType: 'BASE_AXIS',
+ sqlExpression: 'time_column',
+ label: 'time_column',
+ expressionType: 'SQL',
+ },
+ 'col1',
+ ],
+ metrics: ['count(*)'],
+ });
+ });
});
-describe('enabled GENERIC_CHART_AXES', () => {
+describe('GENERIC_CHART_AXES is enabled', () => {
let windowSpy: any;
beforeAll(() => {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/buildQuery.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/buildQuery.ts
index 4bd4df0bcc..d22772c070 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/buildQuery.ts
@@ -18,12 +18,13 @@
*/
import {
buildQueryContext,
- DTTM_ALIAS,
ensureIsArray,
normalizeOrderBy,
PostProcessingPivot,
QueryFormData,
QueryObject,
+ getXAxis,
+ isXAxisSet,
} from '@superset-ui/core';
import {
pivotOperator,
@@ -41,11 +42,8 @@ import {
} from '../utils/formDataSuffix';
export default function buildQuery(formData: QueryFormData) {
- const { x_axis: index } = formData;
- const is_timeseries = index === DTTM_ALIAS || !index;
const baseFormData = {
...formData,
- is_timeseries,
};
const formData1 = removeFormDataSuffix(baseFormData, '_b');
@@ -55,9 +53,12 @@ export default function buildQuery(formData: QueryFormData) {
buildQueryContext(fd, baseQueryObject => {
const queryObject = {
...baseQueryObject,
- columns: [...ensureIsArray(index), ...ensureIsArray(fd.groupby)],
+ columns: [
+ ...(isXAxisSet(formData) ? ensureIsArray(getXAxis(formData)) : []),
+ ...ensureIsArray(fd.groupby),
+ ],
series_columns: fd.groupby,
- is_timeseries,
+ ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
};
const pivotOperatorInRuntime: PostProcessingPivot = isTimeComparison(
@@ -68,8 +69,6 @@ export default function buildQuery(formData: QueryFormData) {
: pivotOperator(fd, {
...queryObject,
columns: fd.groupby,
- index,
- is_timeseries,
});
const tmpQueryObject = {
@@ -83,7 +82,6 @@ export default function buildQuery(formData: QueryFormData) {
renameOperator(fd, {
...queryObject,
columns: fd.groupby,
- is_timeseries,
}),
flattenOperator(fd, queryObject),
],
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
index 1300f66201..e6e12b498d 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
@@ -20,16 +20,16 @@
import {
AnnotationLayer,
CategoricalColorNamespace,
- DTTM_ALIAS,
GenericDataType,
- getColumnLabel,
getNumberFormatter,
isEventAnnotationLayer,
isFormulaAnnotationLayer,
isIntervalAnnotationLayer,
isTimeseriesAnnotationLayer,
+ QueryFormData,
TimeseriesChartDataResponseResult,
TimeseriesDataRecord,
+ getXAxis,
} from '@superset-ui/core';
import { EChartsCoreOption, SeriesOption } from 'echarts';
import {
@@ -152,8 +152,7 @@ export default function transformProps(
const colorScale = CategoricalColorNamespace.getScale(colorScheme as string);
- const xAxisCol =
- verboseMap[xAxisOrig] || getColumnLabel(xAxisOrig || DTTM_ALIAS);
+ const xAxisCol = getXAxis(chartProps.rawFormData as QueryFormData) as string;
const rebasedDataA = rebaseForecastDatum(data1, verboseMap);
const rawSeriesA = extractSeries(rebasedDataA, {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/buildQuery.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/buildQuery.ts
index 085635209a..3e563d8833 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/buildQuery.ts
@@ -18,11 +18,12 @@
*/
import {
buildQueryContext,
- DTTM_ALIAS,
ensureIsArray,
normalizeOrderBy,
PostProcessingPivot,
QueryFormData,
+ getXAxis,
+ isXAxisSet,
} from '@superset-ui/core';
import {
rollingWindowOperator,
@@ -38,8 +39,7 @@ import {
} from '@superset-ui/chart-controls';
export default function buildQuery(formData: QueryFormData) {
- const { x_axis, groupby } = formData;
- const is_timeseries = x_axis === DTTM_ALIAS || !x_axis;
+ const { groupby } = formData;
return buildQueryContext(formData, baseQueryObject => {
/* the `pivotOperatorInRuntime` determines how to pivot the dataframe returned from the raw query.
1. If it's a time compared query, there will return a pivoted dataframe that append time compared metrics. for instance:
@@ -66,18 +66,17 @@ export default function buildQuery(formData: QueryFormData) {
baseQueryObject,
)
? timeComparePivotOperator(formData, baseQueryObject)
- : pivotOperator(formData, {
- ...baseQueryObject,
- index: x_axis,
- is_timeseries,
- });
+ : pivotOperator(formData, baseQueryObject);
return [
{
...baseQueryObject,
- columns: [...ensureIsArray(x_axis), ...ensureIsArray(groupby)],
+ columns: [
+ ...(isXAxisSet(formData) ? ensureIsArray(getXAxis(formData)) : []),
+ ...ensureIsArray(groupby),
+ ],
series_columns: groupby,
- is_timeseries,
+ ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
// todo: move `normalizeOrderBy to extractQueryFields`
orderby: normalizeOrderBy(baseQueryObject).orderby,
time_offsets: isTimeComparison(formData, baseQueryObject)
@@ -92,10 +91,7 @@ export default function buildQuery(formData: QueryFormData) {
rollingWindowOperator(formData, baseQueryObject),
timeCompareOperator(formData, baseQueryObject),
resampleOperator(formData, baseQueryObject),
- renameOperator(formData, {
- ...baseQueryObject,
- is_timeseries,
- }),
+ renameOperator(formData, baseQueryObject),
contributionOperator(formData, baseQueryObject),
flattenOperator(formData, baseQueryObject),
// todo: move prophet before flatten
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
index 5d49b657e8..177b14a35e 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
@@ -28,9 +28,9 @@ import {
isTimeseriesAnnotationLayer,
TimeseriesChartDataResponseResult,
t,
- DTTM_ALIAS,
+ getXAxis,
} from '@superset-ui/core';
-import { getAxis, isDerivedSeries } from '@superset-ui/chart-controls';
+import { isDerivedSeries } from '@superset-ui/chart-controls';
import { EChartsCoreOption, SeriesOption } from 'echarts';
import { ZRLineType } from 'echarts/types/src/util/types';
import {
@@ -148,9 +148,7 @@ export default function transformProps(
const colorScale = CategoricalColorNamespace.getScale(colorScheme as string);
const rebasedData = rebaseForecastDatum(data, verboseMap);
- // todo: if the both granularity_sqla and x_axis are `null`, should throw an error
- const xAxisCol =
- verboseMap[xAxisOrig] || getAxis(chartProps.rawFormData) || DTTM_ALIAS;
+ const xAxisCol = getXAxis(chartProps.rawFormData) as string;
const isHorizontal = orientation === OrientationType.horizontal;
const { totalStackedValues, thresholdValues } = extractDataTotalValues(
rebasedData,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/MixedTimeseries/buildQuery.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/MixedTimeseries/buildQuery.test.ts
index d8eec19ea6..2593676763 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/MixedTimeseries/buildQuery.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/MixedTimeseries/buildQuery.test.ts
@@ -267,7 +267,22 @@ test('should compile AA in query B', () => {
});
});
-test('should compile query objects with x-axis', () => {
+test('should convert a queryObject with x-axis although FF is disabled', () => {
+ let windowSpy: any;
+
+ beforeAll(() => {
+ // @ts-ignore
+ windowSpy = jest.spyOn(window, 'window', 'get').mockImplementation(() => ({
+ featureFlags: {
+ GENERIC_CHART_AXES: false,
+ },
+ }));
+ });
+
+ afterAll(() => {
+ windowSpy.mockRestore();
+ });
+
const { queries } = buildQuery({
...formDataMixedChart,
x_axis: 'my_index',
@@ -280,11 +295,19 @@ test('should compile query objects with x-axis', () => {
filters: [],
extras: {
having: '',
- time_grain_sqla: 'P1W',
where: "(foo in ('a', 'b'))",
},
applied_time_extras: {},
- columns: ['my_index', 'foo'],
+ columns: [
+ {
+ columnType: 'BASE_AXIS',
+ expressionType: 'SQL',
+ label: 'my_index',
+ sqlExpression: 'my_index',
+ timeGrain: 'P1W',
+ },
+ 'foo',
+ ],
metrics: ['sum(sales)'],
annotation_layers: [],
row_limit: 10,
@@ -296,7 +319,6 @@ test('should compile query objects with x-axis', () => {
url_params: {},
custom_params: {},
custom_form_data: {},
- is_timeseries: false,
time_offsets: [],
post_processing: [
{
@@ -332,8 +354,16 @@ test('should compile query objects with x-axis', () => {
// check the main props on the second query
expect(queries[1]).toEqual(
expect.objectContaining({
- is_timeseries: false,
- columns: ['my_index'],
+ columns: [
+ {
+ columnType: 'BASE_AXIS',
+ expressionType: 'SQL',
+ label: 'my_index',
+ sqlExpression: 'my_index',
+ timeGrain: 'P1W',
+ },
+ ],
+ granularity: 'ds',
series_columns: [],
metrics: ['count'],
post_processing: [
@@ -357,3 +387,90 @@ test('should compile query objects with x-axis', () => {
}),
);
});
+
+test("shouldn't convert a queryObject with axis although FF is enabled", () => {
+ let windowSpy: any;
+
+ beforeAll(() => {
+ // @ts-ignore
+ windowSpy = jest.spyOn(window, 'window', 'get').mockImplementation(() => ({
+ featureFlags: {
+ GENERIC_CHART_AXES: true,
+ },
+ }));
+ });
+
+ afterAll(() => {
+ windowSpy.mockRestore();
+ });
+
+ const { queries } = buildQuery(formDataMixedChart);
+ expect(queries[0]).toEqual(
+ expect.objectContaining({
+ granularity: 'ds',
+ columns: ['foo'],
+ series_columns: ['foo'],
+ metrics: ['sum(sales)'],
+ is_timeseries: true,
+ extras: {
+ time_grain_sqla: 'P1W',
+ having: '',
+ where: "(foo in ('a', 'b'))",
+ },
+ post_processing: [
+ {
+ operation: 'pivot',
+ options: {
+ aggregates: {
+ 'sum(sales)': {
+ operator: 'mean',
+ },
+ },
+ columns: ['foo'],
+ drop_missing_columns: false,
+ index: ['__timestamp'],
+ },
+ },
+ {
+ operation: 'rename',
+ options: { columns: { 'sum(sales)': null }, inplace: true, level: 0 },
+ },
+ {
+ operation: 'flatten',
+ },
+ ],
+ }),
+ );
+ expect(queries[1]).toEqual(
+ expect.objectContaining({
+ granularity: 'ds',
+ columns: [],
+ series_columns: [],
+ metrics: ['count'],
+ is_timeseries: true,
+ extras: {
+ time_grain_sqla: 'P1W',
+ having: '',
+ where: "(name in ('c', 'd'))",
+ },
+ post_processing: [
+ {
+ operation: 'pivot',
+ options: {
+ aggregates: {
+ count: {
+ operator: 'mean',
+ },
+ },
+ columns: [],
+ drop_missing_columns: false,
+ index: ['__timestamp'],
+ },
+ },
+ {
+ operation: 'flatten',
+ },
+ ],
+ }),
+ );
+});
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/buildQuery.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/buildQuery.test.ts
index 7c0787dc02..50432a136a 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/buildQuery.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/buildQuery.test.ts
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+import { SqlaFormData } from '@superset-ui/core';
import buildQuery from '../../src/Timeseries/buildQuery';
describe('Timeseries buildQuery', () => {
@@ -59,3 +60,181 @@ describe('Timeseries buildQuery', () => {
expect(query.orderby).toEqual([['foo', true]]);
});
});
+
+describe('GENERIC_CHART_AXES is enabled', () => {
+ let windowSpy: any;
+
+ beforeAll(() => {
+ // @ts-ignore
+ windowSpy = jest.spyOn(window, 'window', 'get').mockImplementation(() => ({
+ featureFlags: {
+ GENERIC_CHART_AXES: true,
+ },
+ }));
+ });
+
+ afterAll(() => {
+ windowSpy.mockRestore();
+ });
+
+ const formData: SqlaFormData = {
+ datasource: '5__table',
+ viz_type: 'table',
+ granularity_sqla: 'time_column',
+ time_grain_sqla: 'P1Y',
+ time_range: '1 year ago : 2013',
+ groupby: ['col1'],
+ metrics: ['count(*)'],
+ };
+
+ it("shouldn't convert queryObject", () => {
+ const { queries } = buildQuery(formData);
+ expect(queries[0]).toEqual(
+ expect.objectContaining({
+ granularity: 'time_column',
+ time_range: '1 year ago : 2013',
+ extras: { time_grain_sqla: 'P1Y', having: '', where: '' },
+ columns: ['col1'],
+ series_columns: ['col1'],
+ metrics: ['count(*)'],
+ is_timeseries: true,
+ post_processing: [
+ {
+ operation: 'pivot',
+ options: {
+ aggregates: { 'count(*)': { operator: 'mean' } },
+ columns: ['col1'],
+ drop_missing_columns: true,
+ index: ['__timestamp'],
+ },
+ },
+ { operation: 'flatten' },
+ ],
+ }),
+ );
+ });
+
+ it('should convert queryObject', () => {
+ const { queries } = buildQuery({ ...formData, x_axis: 'time_column' });
+ expect(queries[0]).toEqual(
+ expect.objectContaining({
+ granularity: 'time_column',
+ time_range: '1 year ago : 2013',
+ extras: { having: '', where: '' },
+ columns: [
+ {
+ columnType: 'BASE_AXIS',
+ expressionType: 'SQL',
+ label: 'time_column',
+ sqlExpression: 'time_column',
+ timeGrain: 'P1Y',
+ },
+ 'col1',
+ ],
+ series_columns: ['col1'],
+ metrics: ['count(*)'],
+ post_processing: [
+ {
+ operation: 'pivot',
+ options: {
+ aggregates: { 'count(*)': { operator: 'mean' } },
+ columns: ['col1'],
+ drop_missing_columns: true,
+ index: ['time_column'],
+ },
+ },
+ { operation: 'flatten' },
+ ],
+ }),
+ );
+ });
+});
+
+describe('GENERIC_CHART_AXES is disabled', () => {
+ let windowSpy: any;
+
+ beforeAll(() => {
+ // @ts-ignore
+ windowSpy = jest.spyOn(window, 'window', 'get').mockImplementation(() => ({
+ featureFlags: {
+ GENERIC_CHART_AXES: false,
+ },
+ }));
+ });
+
+ afterAll(() => {
+ windowSpy.mockRestore();
+ });
+
+ const formData: SqlaFormData = {
+ datasource: '5__table',
+ viz_type: 'table',
+ granularity_sqla: 'time_column',
+ time_grain_sqla: 'P1Y',
+ time_range: '1 year ago : 2013',
+ groupby: ['col1'],
+ metrics: ['count(*)'],
+ };
+
+ it("shouldn't convert queryObject", () => {
+ const { queries } = buildQuery(formData);
+ expect(queries[0]).toEqual(
+ expect.objectContaining({
+ granularity: 'time_column',
+ time_range: '1 year ago : 2013',
+ extras: { time_grain_sqla: 'P1Y', having: '', where: '' },
+ columns: ['col1'],
+ series_columns: ['col1'],
+ metrics: ['count(*)'],
+ is_timeseries: true,
+ post_processing: [
+ {
+ operation: 'pivot',
+ options: {
+ aggregates: { 'count(*)': { operator: 'mean' } },
+ columns: ['col1'],
+ drop_missing_columns: true,
+ index: ['__timestamp'],
+ },
+ },
+ { operation: 'flatten' },
+ ],
+ }),
+ );
+ });
+
+ it('should convert queryObject', () => {
+ const { queries } = buildQuery({ ...formData, x_axis: 'time_column' });
+ expect(queries[0]).toEqual(
+ expect.objectContaining({
+ granularity: 'time_column',
+ time_range: '1 year ago : 2013',
+ extras: { having: '', where: '' },
+ columns: [
+ {
+ columnType: 'BASE_AXIS',
+ expressionType: 'SQL',
+ label: 'time_column',
+ sqlExpression: 'time_column',
+ timeGrain: 'P1Y',
+ },
+ 'col1',
+ ],
+ series_columns: ['col1'],
+ metrics: ['count(*)'],
+ post_processing: [
+ {
+ operation: 'pivot',
+ options: {
+ aggregates: { 'count(*)': { operator: 'mean' } },
+ columns: ['col1'],
+ drop_missing_columns: true,
+ index: ['time_column'],
+ },
+ },
+ { operation: 'flatten' },
+ ],
+ }),
+ );
+ });
+});