mirror of
https://github.com/apache/superset.git
synced 2024-09-12 08:39:45 -04:00
fix(explore): Dashboard filters on adhoc cols not working in Explore (#23239)
This commit is contained in:
parent
5a099e0762
commit
6076457b90
@ -70,6 +70,7 @@ import Control from './Control';
|
|||||||
import { ExploreAlert } from './ExploreAlert';
|
import { ExploreAlert } from './ExploreAlert';
|
||||||
import { RunQueryButton } from './RunQueryButton';
|
import { RunQueryButton } from './RunQueryButton';
|
||||||
import { Operators } from '../constants';
|
import { Operators } from '../constants';
|
||||||
|
import { CLAUSES } from './controls/FilterControl/types';
|
||||||
|
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
|
|
||||||
@ -317,7 +318,7 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
|
|||||||
setControlValue('adhoc_filters', [
|
setControlValue('adhoc_filters', [
|
||||||
...(adhoc_filters || []),
|
...(adhoc_filters || []),
|
||||||
{
|
{
|
||||||
clause: 'WHERE',
|
clause: CLAUSES.WHERE,
|
||||||
subject: x_axis,
|
subject: x_axis,
|
||||||
operator: Operators.TEMPORAL_RANGE,
|
operator: Operators.TEMPORAL_RANGE,
|
||||||
comparator: defaultTimeFilter || NO_TIME_RANGE,
|
comparator: defaultTimeFilter || NO_TIME_RANGE,
|
||||||
|
@ -32,14 +32,13 @@ import { TimeseriesDefaultFormData } from '@superset-ui/plugin-chart-echarts';
|
|||||||
|
|
||||||
import { render, screen } from 'spec/helpers/testing-library';
|
import { render, screen } from 'spec/helpers/testing-library';
|
||||||
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import {
|
import {
|
||||||
DndFilterSelect,
|
DndFilterSelect,
|
||||||
DndFilterSelectProps,
|
DndFilterSelectProps,
|
||||||
} from 'src/explore/components/controls/DndColumnSelectControl/DndFilterSelect';
|
} from 'src/explore/components/controls/DndColumnSelectControl/DndFilterSelect';
|
||||||
import { PLACEHOLDER_DATASOURCE } from 'src/dashboard/constants';
|
import { PLACEHOLDER_DATASOURCE } from 'src/dashboard/constants';
|
||||||
|
import { EXPRESSION_TYPES } from '../FilterControl/types';
|
||||||
|
|
||||||
const defaultProps: DndFilterSelectProps = {
|
const defaultProps: DndFilterSelectProps = {
|
||||||
type: 'DndFilterSelect',
|
type: 'DndFilterSelect',
|
||||||
|
@ -43,10 +43,7 @@ import { Datasource, OptionSortType } from 'src/explore/types';
|
|||||||
import { OptionValueType } from 'src/explore/components/controls/DndColumnSelectControl/types';
|
import { OptionValueType } from 'src/explore/components/controls/DndColumnSelectControl/types';
|
||||||
import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
|
import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
|
||||||
import DndSelectLabel from 'src/explore/components/controls/DndColumnSelectControl/DndSelectLabel';
|
import DndSelectLabel from 'src/explore/components/controls/DndColumnSelectControl/DndSelectLabel';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
CLAUSES,
|
|
||||||
EXPRESSION_TYPES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
||||||
import {
|
import {
|
||||||
DatasourcePanelDndItem,
|
DatasourcePanelDndItem,
|
||||||
@ -58,6 +55,7 @@ import { ControlComponentProps } from 'src/explore/components/Control';
|
|||||||
import AdhocFilterControl from '../FilterControl/AdhocFilterControl';
|
import AdhocFilterControl from '../FilterControl/AdhocFilterControl';
|
||||||
import DndAdhocFilterOption from './DndAdhocFilterOption';
|
import DndAdhocFilterOption from './DndAdhocFilterOption';
|
||||||
import { useDefaultTimeFilter } from '../DateFilterControl/utils';
|
import { useDefaultTimeFilter } from '../DateFilterControl/utils';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../FilterControl/types';
|
||||||
|
|
||||||
const { warning } = Modal;
|
const { warning } = Modal;
|
||||||
|
|
||||||
|
@ -16,11 +16,9 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import { Operators } from 'src/explore/constants';
|
import { Operators } from 'src/explore/constants';
|
||||||
|
import { EXPRESSION_TYPES, CLAUSES } from '../types';
|
||||||
|
|
||||||
describe('AdhocFilter', () => {
|
describe('AdhocFilter', () => {
|
||||||
it('sets filterOptionName in constructor', () => {
|
it('sets filterOptionName in constructor', () => {
|
||||||
|
@ -21,60 +21,13 @@ import {
|
|||||||
Operators,
|
Operators,
|
||||||
OPERATOR_ENUM_TO_OPERATOR_TYPE,
|
OPERATOR_ENUM_TO_OPERATOR_TYPE,
|
||||||
} from 'src/explore/constants';
|
} from 'src/explore/constants';
|
||||||
import { getSimpleSQLExpression } from 'src/explore/exploreUtils';
|
import { translateToSql } from '../utils/translateToSQL';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
export const EXPRESSION_TYPES = {
|
|
||||||
SIMPLE: 'SIMPLE',
|
|
||||||
SQL: 'SQL',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CLAUSES = {
|
|
||||||
HAVING: 'HAVING',
|
|
||||||
WHERE: 'WHERE',
|
|
||||||
};
|
|
||||||
|
|
||||||
const OPERATORS_TO_SQL = {
|
|
||||||
'==': '=',
|
|
||||||
'!=': '<>',
|
|
||||||
'>': '>',
|
|
||||||
'<': '<',
|
|
||||||
'>=': '>=',
|
|
||||||
'<=': '<=',
|
|
||||||
IN: 'IN',
|
|
||||||
'NOT IN': 'NOT IN',
|
|
||||||
LIKE: 'LIKE',
|
|
||||||
ILIKE: 'ILIKE',
|
|
||||||
REGEX: 'REGEX',
|
|
||||||
'IS NOT NULL': 'IS NOT NULL',
|
|
||||||
'IS NULL': 'IS NULL',
|
|
||||||
'IS TRUE': 'IS TRUE',
|
|
||||||
'IS FALSE': 'IS FALSE',
|
|
||||||
'LATEST PARTITION': ({ datasource }) =>
|
|
||||||
`= '{{ presto.latest_partition('${datasource.schema}.${datasource.datasource_name}') }}'`,
|
|
||||||
};
|
|
||||||
|
|
||||||
const CUSTOM_OPERATIONS = [...CUSTOM_OPERATORS].map(
|
const CUSTOM_OPERATIONS = [...CUSTOM_OPERATORS].map(
|
||||||
op => OPERATOR_ENUM_TO_OPERATOR_TYPE[op].operation,
|
op => OPERATOR_ENUM_TO_OPERATOR_TYPE[op].operation,
|
||||||
);
|
);
|
||||||
|
|
||||||
function translateToSql(adhocMetric, { useSimple } = {}) {
|
|
||||||
if (adhocMetric.expressionType === EXPRESSION_TYPES.SIMPLE || useSimple) {
|
|
||||||
const { subject, comparator } = adhocMetric;
|
|
||||||
const operator =
|
|
||||||
adhocMetric.operator &&
|
|
||||||
// 'LATEST PARTITION' supported callback only
|
|
||||||
adhocMetric.operator ===
|
|
||||||
OPERATOR_ENUM_TO_OPERATOR_TYPE[Operators.LATEST_PARTITION].operation
|
|
||||||
? OPERATORS_TO_SQL[adhocMetric.operator](adhocMetric)
|
|
||||||
: OPERATORS_TO_SQL[adhocMetric.operator];
|
|
||||||
return getSimpleSQLExpression(subject, operator, comparator);
|
|
||||||
}
|
|
||||||
if (adhocMetric.expressionType === EXPRESSION_TYPES.SQL) {
|
|
||||||
return adhocMetric.sqlExpression;
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class AdhocFilter {
|
export default class AdhocFilter {
|
||||||
constructor(adhocFilter) {
|
constructor(adhocFilter) {
|
||||||
this.expressionType = adhocFilter.expressionType || EXPRESSION_TYPES.SIMPLE;
|
this.expressionType = adhocFilter.expressionType || EXPRESSION_TYPES.SIMPLE;
|
||||||
|
@ -22,10 +22,7 @@ import sinon from 'sinon';
|
|||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { supersetTheme } from '@superset-ui/core';
|
import { supersetTheme } from '@superset-ui/core';
|
||||||
|
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import { LabelsContainer } from 'src/explore/components/controls/OptionControls';
|
import { LabelsContainer } from 'src/explore/components/controls/OptionControls';
|
||||||
import {
|
import {
|
||||||
AGGREGATES,
|
AGGREGATES,
|
||||||
@ -34,6 +31,7 @@ import {
|
|||||||
} from 'src/explore/constants';
|
} from 'src/explore/constants';
|
||||||
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
||||||
import AdhocFilterControl from '.';
|
import AdhocFilterControl from '.';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const simpleAdhocFilter = new AdhocFilter({
|
const simpleAdhocFilter = new AdhocFilter({
|
||||||
expressionType: EXPRESSION_TYPES.SIMPLE,
|
expressionType: EXPRESSION_TYPES.SIMPLE,
|
||||||
|
@ -45,12 +45,10 @@ import Icons from 'src/components/Icons';
|
|||||||
import Modal from 'src/components/Modal';
|
import Modal from 'src/components/Modal';
|
||||||
import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
|
import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
|
||||||
import AdhocFilterOption from 'src/explore/components/controls/FilterControl/AdhocFilterOption';
|
import AdhocFilterOption from 'src/explore/components/controls/FilterControl/AdhocFilterOption';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
CLAUSES,
|
|
||||||
EXPRESSION_TYPES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import adhocFilterType from 'src/explore/components/controls/FilterControl/adhocFilterType';
|
import adhocFilterType from 'src/explore/components/controls/FilterControl/adhocFilterType';
|
||||||
import columnType from 'src/explore/components/controls/FilterControl/columnType';
|
import columnType from 'src/explore/components/controls/FilterControl/columnType';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const { warning } = Modal;
|
const { warning } = Modal;
|
||||||
|
|
||||||
|
@ -24,15 +24,13 @@ import Button from 'src/components/Button';
|
|||||||
|
|
||||||
import ErrorBoundary from 'src/components/ErrorBoundary';
|
import ErrorBoundary from 'src/components/ErrorBoundary';
|
||||||
import Tabs from 'src/components/Tabs';
|
import Tabs from 'src/components/Tabs';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import { AGGREGATES } from 'src/explore/constants';
|
import { AGGREGATES } from 'src/explore/constants';
|
||||||
import AdhocFilterEditPopoverSimpleTabContent from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent';
|
import AdhocFilterEditPopoverSimpleTabContent from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent';
|
||||||
import AdhocFilterEditPopoverSqlTabContent from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent';
|
import AdhocFilterEditPopoverSqlTabContent from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent';
|
||||||
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
|
||||||
import AdhocFilterEditPopover from '.';
|
import AdhocFilterEditPopover from '.';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const simpleAdhocFilter = new AdhocFilter({
|
const simpleAdhocFilter = new AdhocFilter({
|
||||||
expressionType: EXPRESSION_TYPES.SIMPLE,
|
expressionType: EXPRESSION_TYPES.SIMPLE,
|
||||||
|
@ -24,9 +24,7 @@ import { styled, t } from '@superset-ui/core';
|
|||||||
import ErrorBoundary from 'src/components/ErrorBoundary';
|
import ErrorBoundary from 'src/components/ErrorBoundary';
|
||||||
import Tabs from 'src/components/Tabs';
|
import Tabs from 'src/components/Tabs';
|
||||||
import adhocMetricType from 'src/explore/components/controls/MetricControl/adhocMetricType';
|
import adhocMetricType from 'src/explore/components/controls/MetricControl/adhocMetricType';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import AdhocFilterEditPopoverSimpleTabContent from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent';
|
import AdhocFilterEditPopoverSimpleTabContent from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent';
|
||||||
import AdhocFilterEditPopoverSqlTabContent from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent';
|
import AdhocFilterEditPopoverSqlTabContent from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent';
|
||||||
import columnType from 'src/explore/components/controls/FilterControl/columnType';
|
import columnType from 'src/explore/components/controls/FilterControl/columnType';
|
||||||
@ -34,6 +32,7 @@ import {
|
|||||||
POPOVER_INITIAL_HEIGHT,
|
POPOVER_INITIAL_HEIGHT,
|
||||||
POPOVER_INITIAL_WIDTH,
|
POPOVER_INITIAL_WIDTH,
|
||||||
} from 'src/explore/constants';
|
} from 'src/explore/constants';
|
||||||
|
import { EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
|
adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
|
||||||
|
@ -25,10 +25,7 @@ import thunk from 'redux-thunk';
|
|||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import configureStore from 'redux-mock-store';
|
import configureStore from 'redux-mock-store';
|
||||||
|
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import {
|
import {
|
||||||
AGGREGATES,
|
AGGREGATES,
|
||||||
Operators,
|
Operators,
|
||||||
@ -46,6 +43,7 @@ import AdhocFilterEditPopoverSimpleTabContent, {
|
|||||||
useSimpleTabFilterProps,
|
useSimpleTabFilterProps,
|
||||||
Props,
|
Props,
|
||||||
} from '.';
|
} from '.';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const simpleAdhocFilter = new AdhocFilter({
|
const simpleAdhocFilter = new AdhocFilter({
|
||||||
expressionType: EXPRESSION_TYPES.SIMPLE,
|
expressionType: EXPRESSION_TYPES.SIMPLE,
|
||||||
|
@ -38,10 +38,7 @@ import {
|
|||||||
OPERATOR_ENUM_TO_OPERATOR_TYPE,
|
OPERATOR_ENUM_TO_OPERATOR_TYPE,
|
||||||
} from 'src/explore/constants';
|
} from 'src/explore/constants';
|
||||||
import FilterDefinitionOption from 'src/explore/components/controls/MetricControl/FilterDefinitionOption';
|
import FilterDefinitionOption from 'src/explore/components/controls/MetricControl/FilterDefinitionOption';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import { Tooltip } from 'src/components/Tooltip';
|
import { Tooltip } from 'src/components/Tooltip';
|
||||||
import { Input } from 'src/components/Input';
|
import { Input } from 'src/components/Input';
|
||||||
import { optionLabel } from 'src/utils/common';
|
import { optionLabel } from 'src/utils/common';
|
||||||
@ -54,6 +51,7 @@ import {
|
|||||||
import useAdvancedDataTypes from './useAdvancedDataTypes';
|
import useAdvancedDataTypes from './useAdvancedDataTypes';
|
||||||
import { useDatePickerInAdhocFilter } from '../utils';
|
import { useDatePickerInAdhocFilter } from '../utils';
|
||||||
import { useDefaultTimeFilter } from '../../DateFilterControl/utils';
|
import { useDefaultTimeFilter } from '../../DateFilterControl/utils';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const StyledInput = styled(Input)`
|
const StyledInput = styled(Input)`
|
||||||
margin-bottom: ${({ theme }) => theme.gridUnit * 4}px;
|
margin-bottom: ${({ theme }) => theme.gridUnit * 4}px;
|
||||||
|
@ -21,11 +21,9 @@ import React from 'react';
|
|||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import AdhocFilterEditPopoverSqlTabContent from '.';
|
import AdhocFilterEditPopoverSqlTabContent from '.';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const sqlAdhocFilter = new AdhocFilter({
|
const sqlAdhocFilter = new AdhocFilter({
|
||||||
expressionType: EXPRESSION_TYPES.SQL,
|
expressionType: EXPRESSION_TYPES.SQL,
|
||||||
|
@ -25,10 +25,8 @@ import sqlKeywords from 'src/SqlLab/utils/sqlKeywords';
|
|||||||
|
|
||||||
import adhocMetricType from 'src/explore/components/controls/MetricControl/adhocMetricType';
|
import adhocMetricType from 'src/explore/components/controls/MetricControl/adhocMetricType';
|
||||||
import columnType from 'src/explore/components/controls/FilterControl/columnType';
|
import columnType from 'src/explore/components/controls/FilterControl/columnType';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
|
adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
|
||||||
|
@ -19,11 +19,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen, waitFor } from 'spec/helpers/testing-library';
|
import { render, screen, waitFor } from 'spec/helpers/testing-library';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import AdhocFilterOption, { AdhocFilterOptionProps } from '.';
|
import AdhocFilterOption, { AdhocFilterOptionProps } from '.';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const simpleAdhocFilter = new AdhocFilter({
|
const simpleAdhocFilter = new AdhocFilter({
|
||||||
expressionType: EXPRESSION_TYPES.SIMPLE,
|
expressionType: EXPRESSION_TYPES.SIMPLE,
|
||||||
|
@ -19,11 +19,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen } from 'spec/helpers/testing-library';
|
import { render, screen } from 'spec/helpers/testing-library';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import AdhocFilter, {
|
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
||||||
EXPRESSION_TYPES,
|
|
||||||
CLAUSES,
|
|
||||||
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
|
|
||||||
import AdhocFilterPopoverTrigger from '.';
|
import AdhocFilterPopoverTrigger from '.';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
const simpleAdhocFilter = new AdhocFilter({
|
const simpleAdhocFilter = new AdhocFilter({
|
||||||
expressionType: EXPRESSION_TYPES.SIMPLE,
|
expressionType: EXPRESSION_TYPES.SIMPLE,
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { EXPRESSION_TYPES, CLAUSES } from './AdhocFilter';
|
import { CLAUSES, EXPRESSION_TYPES } from './types';
|
||||||
|
|
||||||
export default PropTypes.oneOfType([
|
export default PropTypes.oneOfType([
|
||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export enum EXPRESSION_TYPES {
|
||||||
|
SIMPLE = 'SIMPLE',
|
||||||
|
SQL = 'SQL',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CLAUSES {
|
||||||
|
HAVING = 'HAVING',
|
||||||
|
WHERE = 'WHERE',
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
AdhocFilter,
|
||||||
|
isFreeFormAdhocFilter,
|
||||||
|
isSimpleAdhocFilter,
|
||||||
|
SimpleAdhocFilter,
|
||||||
|
} from '@superset-ui/core';
|
||||||
|
import {
|
||||||
|
OPERATOR_ENUM_TO_OPERATOR_TYPE,
|
||||||
|
Operators,
|
||||||
|
} from 'src/explore/constants';
|
||||||
|
import { getSimpleSQLExpression } from 'src/explore/exploreUtils';
|
||||||
|
|
||||||
|
export const OPERATORS_TO_SQL = {
|
||||||
|
'==': '=',
|
||||||
|
'!=': '<>',
|
||||||
|
'>': '>',
|
||||||
|
'<': '<',
|
||||||
|
'>=': '>=',
|
||||||
|
'<=': '<=',
|
||||||
|
IN: 'IN',
|
||||||
|
'NOT IN': 'NOT IN',
|
||||||
|
LIKE: 'LIKE',
|
||||||
|
ILIKE: 'ILIKE',
|
||||||
|
REGEX: 'REGEX',
|
||||||
|
'IS NOT NULL': 'IS NOT NULL',
|
||||||
|
'IS NULL': 'IS NULL',
|
||||||
|
'IS TRUE': 'IS TRUE',
|
||||||
|
'IS FALSE': 'IS FALSE',
|
||||||
|
'LATEST PARTITION': ({
|
||||||
|
datasource,
|
||||||
|
}: {
|
||||||
|
datasource: { schema: string; datasource_name: string };
|
||||||
|
}) =>
|
||||||
|
`= '{{ presto.latest_partition('${datasource.schema}.${datasource.datasource_name}') }}'`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const translateToSql = (
|
||||||
|
adhocFilter: AdhocFilter,
|
||||||
|
{ useSimple }: { useSimple: boolean } = { useSimple: false },
|
||||||
|
) => {
|
||||||
|
if (isSimpleAdhocFilter(adhocFilter) || useSimple) {
|
||||||
|
const { subject, operator } = adhocFilter as SimpleAdhocFilter;
|
||||||
|
const comparator =
|
||||||
|
'comparator' in adhocFilter ? adhocFilter.comparator : undefined;
|
||||||
|
const op =
|
||||||
|
operator &&
|
||||||
|
// 'LATEST PARTITION' supported callback only
|
||||||
|
operator ===
|
||||||
|
OPERATOR_ENUM_TO_OPERATOR_TYPE[Operators.LATEST_PARTITION].operation
|
||||||
|
? OPERATORS_TO_SQL[operator](adhocFilter)
|
||||||
|
: OPERATORS_TO_SQL[operator];
|
||||||
|
return getSimpleSQLExpression(subject, op, comparator);
|
||||||
|
}
|
||||||
|
if (isFreeFormAdhocFilter(adhocFilter)) {
|
||||||
|
return adhocFilter.sqlExpression;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
@ -21,7 +21,8 @@ import { NO_TIME_RANGE } from '@superset-ui/core';
|
|||||||
import { Operators } from 'src/explore/constants';
|
import { Operators } from 'src/explore/constants';
|
||||||
import * as FetchTimeRangeModule from 'src/explore/components/controls/DateFilterControl';
|
import * as FetchTimeRangeModule from 'src/explore/components/controls/DateFilterControl';
|
||||||
import { useGetTimeRangeLabel } from './useGetTimeRangeLabel';
|
import { useGetTimeRangeLabel } from './useGetTimeRangeLabel';
|
||||||
import AdhocFilter, { CLAUSES, EXPRESSION_TYPES } from '../AdhocFilter';
|
import AdhocFilter from '../AdhocFilter';
|
||||||
|
import { CLAUSES, EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
test('should return empty object if operator is not TEMPORAL_RANGE', () => {
|
test('should return empty object if operator is not TEMPORAL_RANGE', () => {
|
||||||
const adhocFilter = new AdhocFilter({
|
const adhocFilter = new AdhocFilter({
|
||||||
|
@ -20,7 +20,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import { NO_TIME_RANGE } from '@superset-ui/core';
|
import { NO_TIME_RANGE } from '@superset-ui/core';
|
||||||
import { fetchTimeRange } from 'src/explore/components/controls/DateFilterControl';
|
import { fetchTimeRange } from 'src/explore/components/controls/DateFilterControl';
|
||||||
import { Operators } from 'src/explore/constants';
|
import { Operators } from 'src/explore/constants';
|
||||||
import AdhocFilter, { EXPRESSION_TYPES } from '../AdhocFilter';
|
import AdhocFilter from '../AdhocFilter';
|
||||||
|
import { EXPRESSION_TYPES } from '../types';
|
||||||
|
|
||||||
interface Results {
|
interface Results {
|
||||||
actualTimeRange?: string;
|
actualTimeRange?: string;
|
||||||
|
@ -129,6 +129,15 @@ const getDashboardFormData = (overrides: JsonObject = {}) => ({
|
|||||||
op: '<=',
|
op: '<=',
|
||||||
val: 10000,
|
val: 10000,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
col: {
|
||||||
|
sqlExpression: 'totally viable sql expression',
|
||||||
|
expressionType: 'SQL',
|
||||||
|
label: 'My column',
|
||||||
|
},
|
||||||
|
op: 'IN',
|
||||||
|
val: ['Value1', 'Value2'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
granularity_sqla: 'ds',
|
granularity_sqla: 'ds',
|
||||||
time_range: 'Last month',
|
time_range: 'Last month',
|
||||||
@ -179,6 +188,7 @@ const getExpectedResultFormData = (overrides: JsonObject = {}) => ({
|
|||||||
clause: 'WHERE',
|
clause: 'WHERE',
|
||||||
expressionType: 'SIMPLE',
|
expressionType: 'SIMPLE',
|
||||||
operator: 'IN',
|
operator: 'IN',
|
||||||
|
operatorId: 'IN',
|
||||||
subject: 'name',
|
subject: 'name',
|
||||||
comparator: ['Aaron'],
|
comparator: ['Aaron'],
|
||||||
isExtra: true,
|
isExtra: true,
|
||||||
@ -188,11 +198,19 @@ const getExpectedResultFormData = (overrides: JsonObject = {}) => ({
|
|||||||
clause: 'WHERE',
|
clause: 'WHERE',
|
||||||
expressionType: 'SIMPLE',
|
expressionType: 'SIMPLE',
|
||||||
operator: '<=',
|
operator: '<=',
|
||||||
|
operatorId: 'LESS_THAN_OR_EQUAL',
|
||||||
subject: 'num_boys',
|
subject: 'num_boys',
|
||||||
comparator: 10000,
|
comparator: 10000,
|
||||||
isExtra: true,
|
isExtra: true,
|
||||||
filterOptionName: expect.any(String),
|
filterOptionName: expect.any(String),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
clause: 'WHERE',
|
||||||
|
expressionType: 'SQL',
|
||||||
|
sqlExpression: `(totally viable sql expression) IN ('Value1', 'Value2')`,
|
||||||
|
filterOptionName: expect.any(String),
|
||||||
|
isExtra: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
adhoc_filters_b: [
|
adhoc_filters_b: [
|
||||||
{
|
{
|
||||||
@ -208,6 +226,7 @@ const getExpectedResultFormData = (overrides: JsonObject = {}) => ({
|
|||||||
clause: 'WHERE',
|
clause: 'WHERE',
|
||||||
expressionType: 'SIMPLE',
|
expressionType: 'SIMPLE',
|
||||||
operator: 'IN',
|
operator: 'IN',
|
||||||
|
operatorId: 'IN',
|
||||||
subject: 'name',
|
subject: 'name',
|
||||||
comparator: ['Aaron'],
|
comparator: ['Aaron'],
|
||||||
isExtra: true,
|
isExtra: true,
|
||||||
@ -217,11 +236,19 @@ const getExpectedResultFormData = (overrides: JsonObject = {}) => ({
|
|||||||
clause: 'WHERE',
|
clause: 'WHERE',
|
||||||
expressionType: 'SIMPLE',
|
expressionType: 'SIMPLE',
|
||||||
operator: '<=',
|
operator: '<=',
|
||||||
|
operatorId: 'LESS_THAN_OR_EQUAL',
|
||||||
subject: 'num_boys',
|
subject: 'num_boys',
|
||||||
comparator: 10000,
|
comparator: 10000,
|
||||||
isExtra: true,
|
isExtra: true,
|
||||||
filterOptionName: expect.any(String),
|
filterOptionName: expect.any(String),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
clause: 'WHERE',
|
||||||
|
expressionType: 'SQL',
|
||||||
|
sqlExpression: `(totally viable sql expression) IN ('Value1', 'Value2')`,
|
||||||
|
filterOptionName: expect.any(String),
|
||||||
|
isExtra: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
applied_time_extras: {
|
applied_time_extras: {
|
||||||
__time_grain: 'P1D',
|
__time_grain: 'P1D',
|
||||||
@ -282,6 +309,15 @@ const getExpectedResultFormData = (overrides: JsonObject = {}) => ({
|
|||||||
op: '<=',
|
op: '<=',
|
||||||
val: 10000,
|
val: 10000,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
col: {
|
||||||
|
expressionType: 'SQL',
|
||||||
|
label: 'My column',
|
||||||
|
sqlExpression: 'totally viable sql expression',
|
||||||
|
},
|
||||||
|
op: 'IN',
|
||||||
|
val: ['Value1', 'Value2'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
granularity_sqla: 'ds',
|
granularity_sqla: 'ds',
|
||||||
time_range: 'Last month',
|
time_range: 'Last month',
|
||||||
|
@ -18,31 +18,55 @@
|
|||||||
*/
|
*/
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
import {
|
import {
|
||||||
EXTRA_FORM_DATA_OVERRIDE_REGULAR_MAPPINGS,
|
|
||||||
EXTRA_FORM_DATA_OVERRIDE_EXTRA_KEYS,
|
|
||||||
isDefined,
|
|
||||||
JsonObject,
|
|
||||||
ensureIsArray,
|
|
||||||
QueryObjectFilterClause,
|
|
||||||
SimpleAdhocFilter,
|
|
||||||
QueryFormData,
|
|
||||||
AdhocFilter,
|
AdhocFilter,
|
||||||
|
ensureIsArray,
|
||||||
|
EXTRA_FORM_DATA_OVERRIDE_EXTRA_KEYS,
|
||||||
|
EXTRA_FORM_DATA_OVERRIDE_REGULAR_MAPPINGS,
|
||||||
|
isAdhocColumn,
|
||||||
|
isDefined,
|
||||||
isFreeFormAdhocFilter,
|
isFreeFormAdhocFilter,
|
||||||
isSimpleAdhocFilter,
|
isSimpleAdhocFilter,
|
||||||
|
JsonObject,
|
||||||
NO_TIME_RANGE,
|
NO_TIME_RANGE,
|
||||||
|
QueryFormData,
|
||||||
|
QueryObjectFilterClause,
|
||||||
|
SimpleAdhocFilter,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
|
import { OPERATOR_ENUM_TO_OPERATOR_TYPE } from '../constants';
|
||||||
|
import { translateToSql } from '../components/controls/FilterControl/utils/translateToSQL';
|
||||||
|
import {
|
||||||
|
CLAUSES,
|
||||||
|
EXPRESSION_TYPES,
|
||||||
|
} from '../components/controls/FilterControl/types';
|
||||||
|
|
||||||
const simpleFilterToAdhoc = (
|
const simpleFilterToAdhoc = (
|
||||||
filterClause: QueryObjectFilterClause,
|
filterClause: QueryObjectFilterClause,
|
||||||
clause = 'where',
|
clause: CLAUSES = CLAUSES.WHERE,
|
||||||
) => {
|
) => {
|
||||||
const result = {
|
let result: AdhocFilter;
|
||||||
clause: clause.toUpperCase(),
|
if (isAdhocColumn(filterClause.col)) {
|
||||||
expressionType: 'SIMPLE',
|
result = {
|
||||||
operator: filterClause.op,
|
expressionType: 'SQL',
|
||||||
subject: filterClause.col,
|
clause,
|
||||||
comparator: 'val' in filterClause ? filterClause.val : undefined,
|
sqlExpression: translateToSql({
|
||||||
} as SimpleAdhocFilter;
|
expressionType: EXPRESSION_TYPES.SIMPLE,
|
||||||
|
subject: `(${filterClause.col.sqlExpression})`,
|
||||||
|
operator: filterClause.op,
|
||||||
|
comparator: 'val' in filterClause ? filterClause.val : undefined,
|
||||||
|
} as SimpleAdhocFilter),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
result = {
|
||||||
|
expressionType: 'SIMPLE',
|
||||||
|
clause,
|
||||||
|
operator: filterClause.op,
|
||||||
|
operatorId: Object.entries(OPERATOR_ENUM_TO_OPERATOR_TYPE).find(
|
||||||
|
operatorEntry => operatorEntry[1].operation === filterClause.op,
|
||||||
|
)?.[0],
|
||||||
|
subject: filterClause.col,
|
||||||
|
comparator: 'val' in filterClause ? filterClause.val : undefined,
|
||||||
|
} as SimpleAdhocFilter;
|
||||||
|
}
|
||||||
if (filterClause.isExtra) {
|
if (filterClause.isExtra) {
|
||||||
Object.assign(result, {
|
Object.assign(result, {
|
||||||
isExtra: true,
|
isExtra: true,
|
||||||
|
@ -25,6 +25,10 @@ import {
|
|||||||
ExtraFormData,
|
ExtraFormData,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
import { FALSE_STRING, NULL_STRING, TRUE_STRING } from 'src/utils/common';
|
import { FALSE_STRING, NULL_STRING, TRUE_STRING } from 'src/utils/common';
|
||||||
|
import {
|
||||||
|
CLAUSES,
|
||||||
|
EXPRESSION_TYPES,
|
||||||
|
} from '../explore/components/controls/FilterControl/types';
|
||||||
|
|
||||||
export const getSelectExtraFormData = (
|
export const getSelectExtraFormData = (
|
||||||
col: string,
|
col: string,
|
||||||
@ -36,8 +40,8 @@ export const getSelectExtraFormData = (
|
|||||||
if (emptyFilter) {
|
if (emptyFilter) {
|
||||||
extra.adhoc_filters = [
|
extra.adhoc_filters = [
|
||||||
{
|
{
|
||||||
expressionType: 'SQL',
|
expressionType: EXPRESSION_TYPES.SQL,
|
||||||
clause: 'WHERE',
|
clause: CLAUSES.WHERE,
|
||||||
sqlExpression: '1 = 0',
|
sqlExpression: '1 = 0',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user