From bb0d7830c97055beae70a9105326328ec9265482 Mon Sep 17 00:00:00 2001 From: Gabriel Dutra Date: Thu, 20 Feb 2020 18:49:29 -0300 Subject: [PATCH] Fixes + temp remove validation for Query param --- .../components/QueryBasedParameterInput.jsx | 3 +- .../parameters/QueryBasedDropdownParameter.js | 32 +++++---- redash/models/parameterized_query.py | 65 +++++++------------ 3 files changed, 43 insertions(+), 57 deletions(-) diff --git a/client/app/components/QueryBasedParameterInput.jsx b/client/app/components/QueryBasedParameterInput.jsx index 134548a5f8..61a607319b 100644 --- a/client/app/components/QueryBasedParameterInput.jsx +++ b/client/app/components/QueryBasedParameterInput.jsx @@ -39,9 +39,10 @@ export default class QueryBasedParameterInput extends React.Component { } componentDidUpdate(prevProps) { - if (this.props.queryId !== prevProps.queryId) { + if (this.props.queryId !== prevProps.queryId || this.props.parameter !== prevProps.parameter) { this._loadOptions(this.props.queryId); } + if (this.props.value !== prevProps.value) { this.setValue(this.props.value); } diff --git a/client/app/services/parameters/QueryBasedDropdownParameter.js b/client/app/services/parameters/QueryBasedDropdownParameter.js index 17af6e9e92..823bdcc4f3 100644 --- a/client/app/services/parameters/QueryBasedDropdownParameter.js +++ b/client/app/services/parameters/QueryBasedDropdownParameter.js @@ -1,4 +1,4 @@ -import { isNull, isUndefined, isArray, isEmpty, isString, get, map, join, has, toString } from "lodash"; +import { isNull, isUndefined, isArray, isEmpty, get, map, join, has, toString } from "lodash"; import { Query } from "@/services/query"; import QueryResult from "@/services/query-result"; import Parameter from "./Parameter"; @@ -47,11 +47,7 @@ class QueryBasedDropdownParameter extends Parameter { const parameterValues = map(this.value, v => `${prefix}${v}${suffix}`); return join(parameterValues, separator); } - const executionParamValues = { ...this.staticParams }; - if (isString(this.searchColumn)) { - executionParamValues[this.searchColumn] = this.searchTerm; - } - return !isEmpty(executionParamValues) ? { value: this.value, executionParamValues } : this.value; + return this.value; } toUrlParams() { @@ -99,9 +95,10 @@ class QueryBasedDropdownParameter extends Parameter { loadDropdownValues() { return Query.get({ id: this.queryId }).then(query => { - if (query.hasParameters()) { + const queryHasParameters = query.hasParameters(); + if (queryHasParameters && this.searchColumn) { this.searchFunction = searchTerm => - QueryResult.getByQueryId(query.id, { ...this.staticParams, search: searchTerm }, -1) + QueryResult.getByQueryId(query.id, { ...this.staticParams, [this.searchColumn]: searchTerm }, -1) .toPromise() .then(result => { this.searchTerm = searchTerm; @@ -110,13 +107,20 @@ class QueryBasedDropdownParameter extends Parameter { .then(mapOptionValuesToString); return this.searchTerm ? this.searchFunction(this.searchTerm) : Promise.resolve([]); } else { - if (this.parentQueryId) { - return Query.associatedDropdown({ queryId: this.parentQueryId, dropdownQueryId: this.queryId }).then( - mapOptionValuesToString - ); - } - return Query.asDropdown({ id: this.queryId }).then(mapOptionValuesToString); + this.searchFunction = null; + } + + if (queryHasParameters) { + return QueryResult.getByQueryId(query.id, { ...this.staticParams }, -1) + .toPromise() + .then(result => get(result, "query_result.data.rows")) + .then(mapOptionValuesToString); + } else if (this.parentQueryId) { + return Query.associatedDropdown({ queryId: this.parentQueryId, dropdownQueryId: this.queryId }).then( + mapOptionValuesToString + ); } + return Query.asDropdown({ id: this.queryId }).then(mapOptionValuesToString); }); } } diff --git a/redash/models/parameterized_query.py b/redash/models/parameterized_query.py index c3de9455f1..3dbb266c4e 100644 --- a/redash/models/parameterized_query.py +++ b/redash/models/parameterized_query.py @@ -15,50 +15,43 @@ def _pluck_name_and_value(default_column, row): return {"name": row[name_column], "value": str(row[value_column])} -def _load_result(query_id, org, parameters = None): +def _load_result(query_id, org): from redash import models query = models.Query.get_by_id_and_org(query_id, org) if query.data_source: - if parameters: - param_query = query.parameterized - param_query.apply(parameters) - query_result = models.QueryResult.get_latest(query.data_source, param_query.text, -1) - else: - query_result = models.QueryResult.get_by_id_and_org( - query.latest_query_data_id, org - ) + query_result = models.QueryResult.get_by_id_and_org( + query.latest_query_data_id, org + ) return query_result.data else: raise QueryDetachedFromDataSourceError(query_id) -def dropdown_values(query_id, org, parameters=None): - data = _load_result(query_id, org, parameters) +def dropdown_values(query_id, org): + data = _load_result(query_id, org) first_column = data["columns"][0]["name"] pluck = partial(_pluck_name_and_value, first_column) return list(map(pluck, data["rows"])) -def join_parameter_list_value(value, key, schema): - definition = next( - (definition for definition in schema if definition["name"] == key), {} - ) - multi_values_options = definition.get("multiValuesOptions", {}) - separator = str(multi_values_options.get("separator", ",")) - prefix = str(multi_values_options.get("prefix", "")) - suffix = str(multi_values_options.get("suffix", "")) - return separator.join( - [prefix + v + suffix for v in value] - ) - -def resolve_parameter_values(parameters, schema): +def join_parameter_list_values(parameters, schema): updated_parameters = {} for (key, value) in parameters.items(): - if isinstance(value, dict) and "value" in value: - value = value["value"] - updated_parameters[key] = join_parameter_list_value(value, key, schema) if isinstance(value, list) else value + if isinstance(value, list): + definition = next( + (definition for definition in schema if definition["name"] == key), {} + ) + multi_values_options = definition.get("multiValuesOptions", {}) + separator = str(multi_values_options.get("separator", ",")) + prefix = str(multi_values_options.get("prefix", "")) + suffix = str(multi_values_options.get("suffix", "")) + updated_parameters[key] = separator.join( + [prefix + v + suffix for v in value] + ) + else: + updated_parameters[key] = value return updated_parameters @@ -83,7 +76,7 @@ def _collect_query_parameters(query): def _parameter_names(parameter_values): names = [] for key, value in parameter_values.items(): - if isinstance(value, dict) and ("start" in value or "end" in value): + if isinstance(value, dict): for inner_key in value.keys(): names.append("{}.{}".format(key, inner_key)) else: @@ -141,7 +134,7 @@ def apply(self, parameters): else: self.parameters.update(parameters) self.query = mustache_render( - self.template, resolve_parameter_values(parameters, self.schema) + self.template, join_parameter_list_values(parameters, self.schema) ) return self @@ -165,25 +158,13 @@ def _valid(self, name, value): if isinstance(enum_options, str): enum_options = enum_options.split("\n") - if definition.get("type") == "query": - if isinstance(value, dict) and "executionParamValues" in value: - query_based_with_parameter = True - dpd_values = [v["value"] for v in dropdown_values(query_id, self.org, value["executionParamValues"])] - else: - query_based_with_parameter = False - dpd_values = [v["value"] for v in dropdown_values(query_id, self.org)] - validators = { "text": lambda value: isinstance(value, str), "number": _is_number, "enum": lambda value: _is_value_within_options( value, enum_options, allow_multiple_values ), - "query": lambda value: _is_value_within_options( - value["value"] if query_based_with_parameter else value, - dpd_values, - allow_multiple_values, - ), + "query": lambda value: True, "date": _is_date, "datetime-local": _is_date, "datetime-with-seconds": _is_date,