From b82da5c016e55ff08cc75a252641a7e19f66d280 Mon Sep 17 00:00:00 2001 From: Elizabeth Thompson Date: Fri, 17 Dec 2021 10:52:00 -0800 Subject: [PATCH] accept null params for validation (#17788) --- superset/views/core.py | 2 +- tests/integration_tests/base_tests.py | 8 ++++- .../integration_tests/sql_validator_tests.py | 31 +++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/superset/views/core.py b/superset/views/core.py index 9557c30e83d98..0ad97199fbdd3 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -2412,7 +2412,7 @@ def validate_sql_json( schema = request.form.get("schema") or None template_params = json.loads(request.form.get("templateParams") or "{}") - if len(template_params) > 0: + if template_params is not None and len(template_params) > 0: # TODO: factor the Database object out of template rendering # or provide it as mydb so we can render template params # without having to also persist a Query ORM object. diff --git a/tests/integration_tests/base_tests.py b/tests/integration_tests/base_tests.py index 92fbf52dd3336..d77f216c736a9 100644 --- a/tests/integration_tests/base_tests.py +++ b/tests/integration_tests/base_tests.py @@ -458,6 +458,7 @@ def validate_sql( user_name=None, raise_on_error=False, database_name="examples", + template_params=None, ): if user_name: self.logout() @@ -466,7 +467,12 @@ def validate_sql( resp = self.get_json_resp( "/superset/validate_sql_json/", raise_on_error=False, - data=dict(database_id=dbid, sql=sql, client_id=client_id), + data=dict( + database_id=dbid, + sql=sql, + client_id=client_id, + templateParams=template_params, + ), ) if raise_on_error and "error" in resp: raise Exception("validate_sql failed") diff --git a/tests/integration_tests/sql_validator_tests.py b/tests/integration_tests/sql_validator_tests.py index 6c7658336b816..92d5cf4061ee0 100644 --- a/tests/integration_tests/sql_validator_tests.py +++ b/tests/integration_tests/sql_validator_tests.py @@ -94,6 +94,37 @@ def test_validate_sql_endpoint_mocked(self, get_validator_by_name): self.assertEqual(1, len(resp)) self.assertIn("expected,", resp[0]["message"]) + @patch("superset.views.core.get_validator_by_name") + @patch.dict( + "superset.config.SQL_VALIDATORS_BY_ENGINE", + PRESTO_SQL_VALIDATORS_BY_ENGINE, + clear=True, + ) + def test_validate_sql_endpoint_mocked_params(self, get_validator_by_name): + """Assert that, with a mocked validator, annotations make it back out + from the validate_sql_json endpoint as a list of json dictionaries""" + if get_example_database().backend == "hive": + pytest.skip("Hive validator is not implemented") + self.login("admin") + + validator = MagicMock() + get_validator_by_name.return_value = validator + validator.validate.return_value = [ + SQLValidationAnnotation( + message="This worked", line_number=4, start_column=12, end_column=42, + ) + ] + + resp = self.validate_sql( + "SELECT * FROM somewhere_over_the_rainbow", + client_id="1", + raise_on_error=False, + template_params="null", + ) + + self.assertEqual(1, len(resp)) + self.assertNotIn("error,", resp[0]["message"]) + @patch("superset.views.core.get_validator_by_name") @patch.dict( "superset.config.SQL_VALIDATORS_BY_ENGINE",