prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Issues with Query Based Dropdown when the value is numeric
  When the values the query returns for the dropdown are numeric, we have two issues:
  
  1. We don’t load the correct value because the value from the URL passed as string, while the actual value is a number.
  2. We don’t load results at all, because they fail parameter schema validation (the string doesn't match the values the dropdown has, which are numbers).
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `redash/utils/parameterized_query.py`
  Content:
  ```
  1 import pystache
  2 from functools import partial
  3 from flask_login import current_user
  4 from numbers import Number
  5 from redash.utils import mustache_render, json_loads
  6 from redash.permissions import require_access, view_only
  7 from funcy import distinct
  8 from dateutil.parser import parse
  9 
  10 
  11 def _pluck_name_and_value(default_column, row):
  12     row = {k.lower(): v for k, v in row.items()}
  13     name_column = "name" if "name" in row.keys() else default_column.lower()
  14     value_column = "value" if "value" in row.keys() else default_column.lower()
  15 
  16     return {"name": row[name_column], "value": row[value_column]}
  17 
  18 
  19 def _load_result(query_id):
  20     from redash.authentication.org_resolving import current_org
  21     from redash import models
  22 
  23     query = models.Query.get_by_id_and_org(query_id, current_org)
  24     require_access(query.data_source.groups, current_user, view_only)
  25     query_result = models.QueryResult.get_by_id_and_org(query.latest_query_data_id, current_org)
  26 
  27     return json_loads(query_result.data)
  28 
  29 
  30 def dropdown_values(query_id):
  31     data = _load_result(query_id)
  32     first_column = data["columns"][0]["name"]
  33     pluck = partial(_pluck_name_and_value, first_column)
  34     return map(pluck, data["rows"])
  35 
  36 
  37 def _collect_key_names(nodes):
  38     keys = []
  39     for node in nodes._parse_tree:
  40         if isinstance(node, pystache.parser._EscapeNode):
  41             keys.append(node.key)
  42         elif isinstance(node, pystache.parser._SectionNode):
  43             keys.append(node.key)
  44             keys.extend(_collect_key_names(node.parsed))
  45 
  46     return distinct(keys)
  47 
  48 
  49 def _collect_query_parameters(query):
  50     nodes = pystache.parse(query)
  51     keys = _collect_key_names(nodes)
  52     return keys
  53 
  54 
  55 def _parameter_names(parameter_values):
  56     names = []
  57     for key, value in parameter_values.iteritems():
  58         if isinstance(value, dict):
  59             for inner_key in value.keys():
  60                 names.append(u'{}.{}'.format(key, inner_key))
  61         else:
  62             names.append(key)
  63 
  64     return names
  65 
  66 
  67 def _is_date(string):
  68     try:
  69         parse(string)
  70         return True
  71     except ValueError:
  72         return False
  73 
  74 
  75 def _is_date_range(obj):
  76     try:
  77         return _is_date(obj["start"]) and _is_date(obj["end"])
  78     except (KeyError, TypeError):
  79         return False
  80 
  81 
  82 class ParameterizedQuery(object):
  83     def __init__(self, template, schema=None):
  84         self.schema = schema or []
  85         self.template = template
  86         self.query = template
  87         self.parameters = {}
  88 
  89     def apply(self, parameters):
  90         invalid_parameter_names = [key for (key, value) in parameters.iteritems() if not self._valid(key, value)]
  91         if invalid_parameter_names:
  92             raise InvalidParameterError(invalid_parameter_names)
  93         else:
  94             self.parameters.update(parameters)
  95             self.query = mustache_render(self.template, self.parameters)
  96 
  97         return self
  98 
  99     def _valid(self, name, value):
  100         if not self.schema:
  101             return True
  102 
  103         definition = next((definition for definition in self.schema if definition["name"] == name), None)
  104 
  105         if not definition:
  106             return False
  107 
  108         validators = {
  109             "text": lambda value: isinstance(value, basestring),
  110             "number": lambda value: isinstance(value, Number),
  111             "enum": lambda value: value in definition["enumOptions"],
  112             "query": lambda value: value in [v["value"] for v in dropdown_values(definition["queryId"])],
  113             "date": _is_date,
  114             "datetime-local": _is_date,
  115             "datetime-with-seconds": _is_date,
  116             "date-range": _is_date_range,
  117             "datetime-range": _is_date_range,
  118             "datetime-range-with-seconds": _is_date_range,
  119         }
  120 
  121         validate = validators.get(definition["type"], lambda x: False)
  122 
  123         return validate(value)
  124 
  125     @property
  126     def is_safe(self):
  127         text_parameters = filter(lambda p: p["type"] == "text", self.schema)
  128         return not any(text_parameters)
  129 
  130     @property
  131     def missing_params(self):
  132         query_parameters = set(_collect_query_parameters(self.template))
  133         return set(query_parameters) - set(_parameter_names(self.parameters))
  134 
  135     @property
  136     def text(self):
  137         return self.query
  138 
  139 
  140 class InvalidParameterError(Exception):
  141     def __init__(self, parameters):
  142         message = u"The following parameter values are incompatible with their definitions: {}".format(", ".join(parameters))
  143         super(InvalidParameterError, self).__init__(message)
  144
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/redash/utils/parameterized_query.py b/redash/utils/parameterized_query.py
  --- a/redash/utils/parameterized_query.py
  +++ b/redash/utils/parameterized_query.py
  @@ -13,7 +13,7 @@
       name_column = "name" if "name" in row.keys() else default_column.lower()
       value_column = "value" if "value" in row.keys() else default_column.lower()
   
  -    return {"name": row[name_column], "value": row[value_column]}
  +    return {"name": row[name_column], "value": unicode(row[value_column])}
   
   
   def _load_result(query_id):
  
verification_info: {"golden_diff": "diff --git a/redash/utils/parameterized_query.py b/redash/utils/parameterized_query.py\n--- a/redash/utils/parameterized_query.py\n+++ b/redash/utils/parameterized_query.py\n@@ -13,7 +13,7 @@\n     name_column = \"name\" if \"name\" in row.keys() else default_column.lower()\n     value_column = \"value\" if \"value\" in row.keys() else default_column.lower()\n \n-    return {\"name\": row[name_column], \"value\": row[value_column]}\n+    return {\"name\": row[name_column], \"value\": unicode(row[value_column])}\n \n \n def _load_result(query_id):\n", "issue": "Issues with Query Based Dropdown when the value is numeric\nWhen the values the query returns for the dropdown are numeric, we have two issues:\r\n\r\n1. We don\u2019t load the correct value because the value from the URL passed as string, while the actual value is a number.\r\n2. We don\u2019t load results at all, because they fail parameter schema validation (the string doesn't match the values the dropdown has, which are numbers).\n", "before_files": [{"content": "import pystache\nfrom functools import partial\nfrom flask_login import current_user\nfrom numbers import Number\nfrom redash.utils import mustache_render, json_loads\nfrom redash.permissions import require_access, view_only\nfrom funcy import distinct\nfrom dateutil.parser import parse\n\n\ndef _pluck_name_and_value(default_column, row):\n    row = {k.lower(): v for k, v in row.items()}\n    name_column = \"name\" if \"name\" in row.keys() else default_column.lower()\n    value_column = \"value\" if \"value\" in row.keys() else default_column.lower()\n\n    return {\"name\": row[name_column], \"value\": row[value_column]}\n\n\ndef _load_result(query_id):\n    from redash.authentication.org_resolving import current_org\n    from redash import models\n\n    query = models.Query.get_by_id_and_org(query_id, current_org)\n    require_access(query.data_source.groups, current_user, view_only)\n    query_result = models.QueryResult.get_by_id_and_org(query.latest_query_data_id, current_org)\n\n    return json_loads(query_result.data)\n\n\ndef dropdown_values(query_id):\n    data = _load_result(query_id)\n    first_column = data[\"columns\"][0][\"name\"]\n    pluck = partial(_pluck_name_and_value, first_column)\n    return map(pluck, data[\"rows\"])\n\n\ndef _collect_key_names(nodes):\n    keys = []\n    for node in nodes._parse_tree:\n        if isinstance(node, pystache.parser._EscapeNode):\n            keys.append(node.key)\n        elif isinstance(node, pystache.parser._SectionNode):\n            keys.append(node.key)\n            keys.extend(_collect_key_names(node.parsed))\n\n    return distinct(keys)\n\n\ndef _collect_query_parameters(query):\n    nodes = pystache.parse(query)\n    keys = _collect_key_names(nodes)\n    return keys\n\n\ndef _parameter_names(parameter_values):\n    names = []\n    for key, value in parameter_values.iteritems():\n        if isinstance(value, dict):\n            for inner_key in value.keys():\n                names.append(u'{}.{}'.format(key, inner_key))\n        else:\n            names.append(key)\n\n    return names\n\n\ndef _is_date(string):\n    try:\n        parse(string)\n        return True\n    except ValueError:\n        return False\n\n\ndef _is_date_range(obj):\n    try:\n        return _is_date(obj[\"start\"]) and _is_date(obj[\"end\"])\n    except (KeyError, TypeError):\n        return False\n\n\nclass ParameterizedQuery(object):\n    def __init__(self, template, schema=None):\n        self.schema = schema or []\n        self.template = template\n        self.query = template\n        self.parameters = {}\n\n    def apply(self, parameters):\n        invalid_parameter_names = [key for (key, value) in parameters.iteritems() if not self._valid(key, value)]\n        if invalid_parameter_names:\n            raise InvalidParameterError(invalid_parameter_names)\n        else:\n            self.parameters.update(parameters)\n            self.query = mustache_render(self.template, self.parameters)\n\n        return self\n\n    def _valid(self, name, value):\n        if not self.schema:\n            return True\n\n        definition = next((definition for definition in self.schema if definition[\"name\"] == name), None)\n\n        if not definition:\n            return False\n\n        validators = {\n            \"text\": lambda value: isinstance(value, basestring),\n            \"number\": lambda value: isinstance(value, Number),\n            \"enum\": lambda value: value in definition[\"enumOptions\"],\n            \"query\": lambda value: value in [v[\"value\"] for v in dropdown_values(definition[\"queryId\"])],\n            \"date\": _is_date,\n            \"datetime-local\": _is_date,\n            \"datetime-with-seconds\": _is_date,\n            \"date-range\": _is_date_range,\n            \"datetime-range\": _is_date_range,\n            \"datetime-range-with-seconds\": _is_date_range,\n        }\n\n        validate = validators.get(definition[\"type\"], lambda x: False)\n\n        return validate(value)\n\n    @property\n    def is_safe(self):\n        text_parameters = filter(lambda p: p[\"type\"] == \"text\", self.schema)\n        return not any(text_parameters)\n\n    @property\n    def missing_params(self):\n        query_parameters = set(_collect_query_parameters(self.template))\n        return set(query_parameters) - set(_parameter_names(self.parameters))\n\n    @property\n    def text(self):\n        return self.query\n\n\nclass InvalidParameterError(Exception):\n    def __init__(self, parameters):\n        message = u\"The following parameter values are incompatible with their definitions: {}\".format(\", \".join(parameters))\n        super(InvalidParameterError, self).__init__(message)\n", "path": "redash/utils/parameterized_query.py"}], "after_files": [{"content": "import pystache\nfrom functools import partial\nfrom flask_login import current_user\nfrom numbers import Number\nfrom redash.utils import mustache_render, json_loads\nfrom redash.permissions import require_access, view_only\nfrom funcy import distinct\nfrom dateutil.parser import parse\n\n\ndef _pluck_name_and_value(default_column, row):\n    row = {k.lower(): v for k, v in row.items()}\n    name_column = \"name\" if \"name\" in row.keys() else default_column.lower()\n    value_column = \"value\" if \"value\" in row.keys() else default_column.lower()\n\n    return {\"name\": row[name_column], \"value\": unicode(row[value_column])}\n\n\ndef _load_result(query_id):\n    from redash.authentication.org_resolving import current_org\n    from redash import models\n\n    query = models.Query.get_by_id_and_org(query_id, current_org)\n    require_access(query.data_source.groups, current_user, view_only)\n    query_result = models.QueryResult.get_by_id_and_org(query.latest_query_data_id, current_org)\n\n    return json_loads(query_result.data)\n\n\ndef dropdown_values(query_id):\n    data = _load_result(query_id)\n    first_column = data[\"columns\"][0][\"name\"]\n    pluck = partial(_pluck_name_and_value, first_column)\n    return map(pluck, data[\"rows\"])\n\n\ndef _collect_key_names(nodes):\n    keys = []\n    for node in nodes._parse_tree:\n        if isinstance(node, pystache.parser._EscapeNode):\n            keys.append(node.key)\n        elif isinstance(node, pystache.parser._SectionNode):\n            keys.append(node.key)\n            keys.extend(_collect_key_names(node.parsed))\n\n    return distinct(keys)\n\n\ndef _collect_query_parameters(query):\n    nodes = pystache.parse(query)\n    keys = _collect_key_names(nodes)\n    return keys\n\n\ndef _parameter_names(parameter_values):\n    names = []\n    for key, value in parameter_values.iteritems():\n        if isinstance(value, dict):\n            for inner_key in value.keys():\n                names.append(u'{}.{}'.format(key, inner_key))\n        else:\n            names.append(key)\n\n    return names\n\n\ndef _is_date(string):\n    try:\n        parse(string)\n        return True\n    except ValueError:\n        return False\n\n\ndef _is_date_range(obj):\n    try:\n        return _is_date(obj[\"start\"]) and _is_date(obj[\"end\"])\n    except (KeyError, TypeError):\n        return False\n\n\nclass ParameterizedQuery(object):\n    def __init__(self, template, schema=None):\n        self.schema = schema or []\n        self.template = template\n        self.query = template\n        self.parameters = {}\n\n    def apply(self, parameters):\n        invalid_parameter_names = [key for (key, value) in parameters.iteritems() if not self._valid(key, value)]\n        if invalid_parameter_names:\n            raise InvalidParameterError(invalid_parameter_names)\n        else:\n            self.parameters.update(parameters)\n            self.query = mustache_render(self.template, self.parameters)\n\n        return self\n\n    def _valid(self, name, value):\n        if not self.schema:\n            return True\n\n        definition = next((definition for definition in self.schema if definition[\"name\"] == name), None)\n\n        if not definition:\n            return False\n\n        validators = {\n            \"text\": lambda value: isinstance(value, basestring),\n            \"number\": lambda value: isinstance(value, Number),\n            \"enum\": lambda value: value in definition[\"enumOptions\"],\n            \"query\": lambda value: value in [v[\"value\"] for v in dropdown_values(definition[\"queryId\"])],\n            \"date\": _is_date,\n            \"datetime-local\": _is_date,\n            \"datetime-with-seconds\": _is_date,\n            \"date-range\": _is_date_range,\n            \"datetime-range\": _is_date_range,\n            \"datetime-range-with-seconds\": _is_date_range,\n        }\n\n        validate = validators.get(definition[\"type\"], lambda x: False)\n\n        return validate(value)\n\n    @property\n    def is_safe(self):\n        text_parameters = filter(lambda p: p[\"type\"] == \"text\", self.schema)\n        return not any(text_parameters)\n\n    @property\n    def missing_params(self):\n        query_parameters = set(_collect_query_parameters(self.template))\n        return set(query_parameters) - set(_parameter_names(self.parameters))\n\n    @property\n    def text(self):\n        return self.query\n\n\nclass InvalidParameterError(Exception):\n    def __init__(self, parameters):\n        message = u\"The following parameter values are incompatible with their definitions: {}\".format(\", \".join(parameters))\n        super(InvalidParameterError, self).__init__(message)\n", "path": "redash/utils/parameterized_query.py"}]}