From b1c14ddf8245007dab7f2d9a19dc85de9261662c Mon Sep 17 00:00:00 2001 From: Gabe Lyons Date: Wed, 23 May 2018 11:46:00 -0700 Subject: [PATCH] integrating dashboard filters with adhoc filters (#5056) --- .../src/dashboard/components/Dashboard.jsx | 3 +- superset/utils.py | 41 ++++++++++++ superset/views/core.py | 1 + superset/viz.py | 64 ++++--------------- 4 files changed, 56 insertions(+), 53 deletions(-) diff --git a/superset/assets/src/dashboard/components/Dashboard.jsx b/superset/assets/src/dashboard/components/Dashboard.jsx index 2a6a22799716c..2cb08c3aa6b24 100644 --- a/superset/assets/src/dashboard/components/Dashboard.jsx +++ b/superset/assets/src/dashboard/components/Dashboard.jsx @@ -144,8 +144,7 @@ class Dashboard extends React.PureComponent { getFormDataExtra(slice) { const formDataExtra = Object.assign({}, slice.formData); - const extraFilters = this.effectiveExtraFilters(slice.slice_id); - formDataExtra.extra_filters = formDataExtra.filters.concat(extraFilters); + formDataExtra.extra_filters = this.effectiveExtraFilters(slice.slice_id); return formDataExtra; } diff --git a/superset/utils.py b/superset/utils.py index 25d4ef38daeaa..08ce0d2f385af 100644 --- a/superset/utils.py +++ b/superset/utils.py @@ -841,3 +841,44 @@ def ensure_path_exists(path): except OSError as exc: if not (os.path.isdir(path) and exc.errno == errno.EEXIST): raise + + +def split_adhoc_filters_into_base_filters(fd): + """ + Mutates form data to restructure the adhoc filters in the form of the four base + filters, `where`, `having`, `filters`, and `having_filters` which represent + free form where sql, free form having sql, structured where clauses and structured + having clauses. + """ + adhoc_filters = fd.get('adhoc_filters', None) + if isinstance(adhoc_filters, list): + simple_where_filters = [] + simple_having_filters = [] + sql_where_filters = [] + sql_having_filters = [] + for adhoc_filter in adhoc_filters: + expression_type = adhoc_filter.get('expressionType') + clause = adhoc_filter.get('clause') + if expression_type == 'SIMPLE': + if clause == 'WHERE': + simple_where_filters.append({ + 'col': adhoc_filter.get('subject'), + 'op': adhoc_filter.get('operator'), + 'val': adhoc_filter.get('comparator'), + }) + elif clause == 'HAVING': + simple_having_filters.append({ + 'col': adhoc_filter.get('subject'), + 'op': adhoc_filter.get('operator'), + 'val': adhoc_filter.get('comparator'), + }) + elif expression_type == 'SQL': + if clause == 'WHERE': + sql_where_filters.append(adhoc_filter.get('sqlExpression')) + elif clause == 'HAVING': + sql_having_filters.append(adhoc_filter.get('sqlExpression')) + fd['where'] = ' AND '.join(['({})'.format(sql) for sql in sql_where_filters]) + fd['having'] = ' AND '.join(['({})'.format(sql) for sql in sql_having_filters]) + fd['having_filters'] = simple_having_filters + fd['filters'] = simple_where_filters + del fd['adhoc_filters'] diff --git a/superset/views/core.py b/superset/views/core.py index e8fc43fcb6b8a..40d24b268abb4 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -1279,6 +1279,7 @@ def explore(self, datasource_type=None, datasource_id=None): form_data['datasource'] = str(datasource_id) + '__' + datasource_type # On explore, merge extra filters into the form data + utils.split_adhoc_filters_into_base_filters(form_data) merge_extra_filters(form_data) # merge request url params diff --git a/superset/viz.py b/superset/viz.py index 5565993ee6fa7..f3db31c247047 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -235,7 +235,11 @@ def query_obj(self): groupby.remove(DTTM_ALIAS) is_timeseries = True - # Add extra filters into the query form data + # extras are used to query elements specific to a datasource type + # for instance the extra where clause that applies only to Tables + + utils.split_adhoc_filters_into_base_filters(form_data) + merge_extra_filters(form_data) granularity = ( @@ -272,57 +276,15 @@ def query_obj(self): self.from_dttm = from_dttm self.to_dttm = to_dttm - # extras are used to query elements specific to a datasource type - # for instance the extra where clause that applies only to Tables + filters = form_data.get('filters', []) - extras = {} - filters = [] - adhoc_filters = form_data.get('adhoc_filters', None) - if adhoc_filters is None: - extras = { - 'where': form_data.get('where', ''), - 'having': form_data.get('having', ''), - 'having_druid': form_data.get('having_filters', []), - 'time_grain_sqla': form_data.get('time_grain_sqla', ''), - 'druid_time_origin': form_data.get('druid_time_origin', ''), - } - filters = form_data.get('filters', []) - elif isinstance(adhoc_filters, list): - simple_where_filters = [] - simple_having_filters = [] - sql_where_filters = [] - sql_having_filters = [] - for adhoc_filter in adhoc_filters: - expression_type = adhoc_filter.get('expressionType') - clause = adhoc_filter.get('clause') - if expression_type == 'SIMPLE': - if clause == 'WHERE': - simple_where_filters.append({ - 'col': adhoc_filter.get('subject'), - 'op': adhoc_filter.get('operator'), - 'val': adhoc_filter.get('comparator'), - }) - elif clause == 'HAVING': - simple_having_filters.append({ - 'col': adhoc_filter.get('subject'), - 'op': adhoc_filter.get('operator'), - 'val': adhoc_filter.get('comparator'), - }) - elif expression_type == 'SQL': - if clause == 'WHERE': - sql_where_filters.append(adhoc_filter.get('sqlExpression')) - elif clause == 'HAVING': - sql_having_filters.append(adhoc_filter.get('sqlExpression')) - extras = { - 'where': ' AND '.join(['({})'.format(sql) for sql in sql_where_filters]), - 'having': ' AND '.join( - ['({})'.format(sql) for sql in sql_having_filters], - ), - 'having_druid': simple_having_filters, - 'time_grain_sqla': form_data.get('time_grain_sqla', ''), - 'druid_time_origin': form_data.get('druid_time_origin', ''), - } - filters = simple_where_filters + extras = { + 'where': form_data.get('where', ''), + 'having': form_data.get('having', ''), + 'having_druid': form_data.get('having_filters', []), + 'time_grain_sqla': form_data.get('time_grain_sqla', ''), + 'druid_time_origin': form_data.get('druid_time_origin', ''), + } d = { 'granularity': granularity,