mirror of
https://github.com/getredash/redash.git
synced 2026-03-23 04:00:09 -04:00
* stop testing `collect_query_parameters`, it's an implementation detail * add tests for `missing_query_params` * rename SQLQuery -> ParameterizedSqlQuery * rename sql_query.py to parameterized_query.py * split to parameterized queries and parameterized SQL queries, where parameterized queries only do templating and parameterized SQL queries add tree validation on top of it * move missing parameter detection to ParameterizedQuery * get rid of some old code * fix tests * set syntax to `custom` * revert the max-age-related refactoring * 👋 tree validations 😢 * BaseQueryRunner is no longer a factory for ParameterizedQuery, for now * add an endpoint for running a query by its id and (optional) parameters without having to provide the query text * adds parameter schema to ParameterizedQuery * adds parameter schema validation (currently for strings) * validate number parameters * validate date parameters * validate parameters on POST /api/queries/<id>/results * validate enum parameters * validate date range parameters * validate query-based dropdowns by preprocessing them at the handler level and converting them to a populated enum * change _is_date_range to be a tad more succinct * a single assignment with a `map` is sufficiently explanatory * Update redash/utils/parameterized_query.py Co-Authored-By: rauchy <omer@rauchy.net> * Update redash/utils/parameterized_query.py Co-Authored-By: rauchy <omer@rauchy.net> * Update redash/utils/parameterized_query.py Co-Authored-By: rauchy <omer@rauchy.net> * Update redash/utils/parameterized_query.py Co-Authored-By: rauchy <omer@rauchy.net> * Update redash/handlers/query_results.py Co-Authored-By: rauchy <omer@rauchy.net> * Update redash/utils/parameterized_query.py Co-Authored-By: rauchy <omer@rauchy.net> * build error message inside the error * support all types of numbers as number parameters * check for permissions when populating query-based dropdowns * check for access to query before running it * check for empty rows when populating query-based enums * don't bother loading query results if user doesn't have access * 💥 on unexpected parameter types * parameter schema default is a list, not a dictionary * remove redundant null guards
134 lines
4.8 KiB
Python
134 lines
4.8 KiB
Python
from unittest import TestCase
|
|
import pytest
|
|
|
|
from redash.utils.parameterized_query import ParameterizedQuery, InvalidParameterError
|
|
|
|
|
|
class TestParameterizedQuery(TestCase):
|
|
def test_returns_empty_list_for_regular_query(self):
|
|
query = ParameterizedQuery(u"SELECT 1")
|
|
self.assertEqual(set([]), query.missing_params)
|
|
|
|
def test_finds_all_params_when_missing(self):
|
|
query = ParameterizedQuery(u"SELECT {{param}} FROM {{table}}")
|
|
self.assertEqual(set(['param', 'table']), query.missing_params)
|
|
|
|
def test_finds_all_params(self):
|
|
query = ParameterizedQuery(u"SELECT {{param}} FROM {{table}}").apply({
|
|
'param': 'value',
|
|
'table': 'value'
|
|
})
|
|
self.assertEqual(set([]), query.missing_params)
|
|
|
|
def test_deduplicates_params(self):
|
|
query = ParameterizedQuery(u"SELECT {{param}}, {{param}} FROM {{table}}").apply({
|
|
'param': 'value',
|
|
'table': 'value'
|
|
})
|
|
self.assertEqual(set([]), query.missing_params)
|
|
|
|
def test_handles_nested_params(self):
|
|
query = ParameterizedQuery(u"SELECT {{param}}, {{param}} FROM {{table}} -- {{#test}} {{nested_param}} {{/test}}").apply({
|
|
'param': 'value',
|
|
'table': 'value'
|
|
})
|
|
self.assertEqual(set(['test', 'nested_param']), query.missing_params)
|
|
|
|
def test_handles_objects(self):
|
|
query = ParameterizedQuery(u"SELECT * FROM USERS WHERE created_at between '{{ created_at.start }}' and '{{ created_at.end }}'").apply({
|
|
'created_at': {
|
|
'start': 1,
|
|
'end': 2
|
|
}
|
|
})
|
|
self.assertEqual(set([]), query.missing_params)
|
|
|
|
def test_raises_on_invalid_text_parameters(self):
|
|
schema = [{"name": "bar", "type": "text"}]
|
|
query = ParameterizedQuery("foo", schema)
|
|
|
|
with pytest.raises(InvalidParameterError):
|
|
query.apply({"bar": 7})
|
|
|
|
def test_validates_text_parameters(self):
|
|
schema = [{"name": "bar", "type": "text"}]
|
|
query = ParameterizedQuery("foo {{bar}}", schema)
|
|
|
|
query.apply({"bar": u"baz"})
|
|
|
|
self.assertEquals("foo baz", query.text)
|
|
|
|
def test_raises_on_invalid_number_parameters(self):
|
|
schema = [{"name": "bar", "type": "number"}]
|
|
query = ParameterizedQuery("foo", schema)
|
|
|
|
with pytest.raises(InvalidParameterError):
|
|
query.apply({"bar": "baz"})
|
|
|
|
def test_validates_number_parameters(self):
|
|
schema = [{"name": "bar", "type": "number"}]
|
|
query = ParameterizedQuery("foo {{bar}}", schema)
|
|
|
|
query.apply({"bar": 7})
|
|
|
|
self.assertEquals("foo 7", query.text)
|
|
|
|
def test_raises_on_invalid_date_parameters(self):
|
|
schema = [{"name": "bar", "type": "date"}]
|
|
query = ParameterizedQuery("foo", schema)
|
|
|
|
with pytest.raises(InvalidParameterError):
|
|
query.apply({"bar": "baz"})
|
|
|
|
def test_validates_date_parameters(self):
|
|
schema = [{"name": "bar", "type": "date"}]
|
|
query = ParameterizedQuery("foo {{bar}}", schema)
|
|
|
|
query.apply({"bar": "2000-01-01 12:00:00"})
|
|
|
|
self.assertEquals("foo 2000-01-01 12:00:00", query.text)
|
|
|
|
def test_raises_on_invalid_enum_parameters(self):
|
|
schema = [{"name": "bar", "type": "enum", "enumOptions": ["baz", "qux"]}]
|
|
query = ParameterizedQuery("foo", schema)
|
|
|
|
with pytest.raises(InvalidParameterError):
|
|
query.apply({"bar": 7})
|
|
|
|
def test_raises_on_unlisted_enum_value_parameters(self):
|
|
schema = [{"name": "bar", "type": "enum", "enumOptions": ["baz", "qux"]}]
|
|
query = ParameterizedQuery("foo", schema)
|
|
|
|
with pytest.raises(InvalidParameterError):
|
|
query.apply({"bar": "shlomo"})
|
|
|
|
def test_validates_enum_parameters(self):
|
|
schema = [{"name": "bar", "type": "enum", "enumOptions": ["baz", "qux"]}]
|
|
query = ParameterizedQuery("foo {{bar}}", schema)
|
|
|
|
query.apply({"bar": "baz"})
|
|
|
|
self.assertEquals("foo baz", query.text)
|
|
|
|
def test_raises_on_invalid_date_range_parameters(self):
|
|
schema = [{"name": "bar", "type": "date-range"}]
|
|
query = ParameterizedQuery("foo", schema)
|
|
|
|
with pytest.raises(InvalidParameterError):
|
|
query.apply({"bar": "baz"})
|
|
|
|
def test_validates_date_range_parameters(self):
|
|
schema = [{"name": "bar", "type": "date-range"}]
|
|
query = ParameterizedQuery("foo {{bar.start}} {{bar.end}}", schema)
|
|
|
|
query.apply({"bar": {"start": "2000-01-01 12:00:00", "end": "2000-12-31 12:00:00"}})
|
|
|
|
self.assertEquals("foo 2000-01-01 12:00:00 2000-12-31 12:00:00", query.text)
|
|
|
|
def test_raises_on_unexpected_param_types(self):
|
|
schema = [{"name": "bar", "type": "burrito"}]
|
|
query = ParameterizedQuery("foo", schema)
|
|
|
|
with pytest.raises(InvalidParameterError):
|
|
query.apply({"bar": "baz"})
|