Skip to content

Commit

Permalink
feat: add support for filters in sqlLab (apache#14765)
Browse files Browse the repository at this point in the history
  • Loading branch information
cccs-jc authored and cccs-RyanS committed Dec 17, 2021
1 parent d9c805b commit 78ddd05
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
31 changes: 31 additions & 0 deletions docs/installation.rst
Expand Up @@ -1256,6 +1256,37 @@ in this dictionary are made available for users to use in their SQL.
'my_crazy_macro': lambda x: x*2,
}
Default values for jinja templates can be specified via ``Parameters`` menu in the SQL Lab user interface.
In the UI you can assign a set of parameters as JSON

.. code-block:: JSON
{
"my_table": "foo"
}
The parameters become available in your SQL (example:SELECT * FROM {{ my_table }} ) by using Jinja templating syntax.
SQL Lab template parameters are stored with the dataset as TEMPLATE PARAMETERS.

There is a special ``_filters`` parameter which can be used to test filters used in the jinja template.

.. code-block:: JSON
{
"_filters": {
"col": "action_type",
"op": "IN",
"val": ["sell", "buy"]
}
.. code-block:: python
SELECT action, count(*) as times
FROM logs
WHERE
action in ({{ "'" + "','".join(filter_values('action_type')) + "'" }})
GROUP BY action
Note ``_filters`` is not stored with the dataset. It's only used within the SQL Lab UI.


Besides default Jinja templating, SQL lab also supports self-defined template
processor by setting the ``CUSTOM_TEMPLATE_PROCESSORS`` in your superset configuration.
The values in this dictionary overwrite the default Jinja template processors of the
Expand Down
15 changes: 14 additions & 1 deletion superset-frontend/src/SqlLab/components/ResultSet.tsx
Expand Up @@ -271,9 +271,22 @@ export default class ResultSet extends React.PureComponent<
return;
}

const { schema, sql, dbId, templateParams } = this.props.query;
const { schema, sql, dbId } = this.props.query;
let { templateParams } = this.props.query;
const selectedColumns = this.props.query?.results?.selected_columns || [];

// The filters param is only used to test jinja templates.
// Remove the special filters entry from the templateParams
// before saving the dataset.
if (templateParams) {
const p = JSON.parse(templateParams);
if (p.filters) {
/* eslint-disable-next-line no-underscore-dangle */
delete p._filters;
templateParams = JSON.stringify(p);
}
}

this.props.actions
.createDatasource({
schema,
Expand Down
25 changes: 24 additions & 1 deletion superset/views/utils.py
Expand Up @@ -127,13 +127,16 @@ def loads_request_json(request_json_data: str) -> Dict[Any, Any]:
def get_form_data( # pylint: disable=too-many-locals
slice_id: Optional[int] = None, use_slice_data: bool = False
) -> Tuple[Dict[str, Any], Optional[Slice]]:
form_data = {}
form_data: Dict[str, Any] = {}
# chart data API requests are JSON
request_json_data = (
request.json["queries"][0]
if request.is_json and "queries" in request.json
else None
)

add_sqllab_custom_filters(form_data)

request_form_data = request.form.get("form_data")
request_args_data = request.args.get("form_data")
if request_json_data:
Expand Down Expand Up @@ -196,6 +199,26 @@ def get_form_data( # pylint: disable=too-many-locals
return form_data, slc


def add_sqllab_custom_filters(form_data: Dict[Any, Any]) -> Any:
"""
SQLLab can include a "filters" attribute in the templateParams.
The filters attribute is a list of filters to include in the
request. Useful for testing templates in SQLLab.
"""
try:
data = json.loads(request.data)
if isinstance(data, dict):
params_str = data.get("templateParams")
if isinstance(params_str, str):
params = json.loads(params_str)
if isinstance(params, dict):
filters = params.get("filters")
if filters:
form_data.update({"filters": filters})
except (TypeError, json.JSONDecodeError):
data = {}


def get_datasource_info(
datasource_id: Optional[int], datasource_type: Optional[str], form_data: FormData
) -> Tuple[int, Optional[str]]:
Expand Down

0 comments on commit 78ddd05

Please sign in to comment.