You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2026/04/16 11:27:59 UTC
(superset) branch master updated: fix(sqllab): format_sql to apply db dialect by database_id (#39393)
This is an automated email from the ASF dual-hosted git repository.
michaelsmolina pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 0b51e9cd5e3 fix(sqllab): format_sql to apply db dialect by database_id (#39393)
0b51e9cd5e3 is described below
commit 0b51e9cd5e3bc3fe054b16001f9ab236c1aa6f28
Author: JUST.in DO IT <ju...@airbnb.com>
AuthorDate: Thu Apr 16 04:27:51 2026 -0700
fix(sqllab): format_sql to apply db dialect by database_id (#39393)
---
superset/sqllab/api.py | 43 ++++++++++++++++------------
tests/integration_tests/sql_lab/api_tests.py | 33 +++++++++++++++++++--
2 files changed, 55 insertions(+), 21 deletions(-)
diff --git a/superset/sqllab/api.py b/superset/sqllab/api.py
index a2c669f0aa5..c94b26bed17 100644
--- a/superset/sqllab/api.py
+++ b/superset/sqllab/api.py
@@ -238,31 +238,36 @@ class SqlLabRestApi(BaseSupersetApi):
sql = model["sql"]
template_params = model.get("template_params")
database_id = model.get("database_id")
+ database_engine = None
- # Process Jinja templates if template_params and database_id are provided
- if template_params and database_id is not None:
+ # Process Jinja templates if template_params are provided
+ if database_id is not None:
database = DatabaseDAO.find_by_id(database_id)
+
if database:
- try:
- template_params = (
- json.loads(template_params)
- if isinstance(template_params, str)
- else template_params
- )
- if template_params:
- template_processor = get_template_processor(
- database=database
+ database_engine = database.db_engine_spec.engine
+
+ if template_params:
+ try:
+ template_params = (
+ json.loads(template_params)
+ if isinstance(template_params, str)
+ else template_params
)
- sql = template_processor.process_template(
- sql, **template_params
+ if template_params:
+ template_processor = get_template_processor(
+ database=database
+ )
+ sql = template_processor.process_template(
+ sql, **template_params
+ )
+ except json.JSONDecodeError:
+ logger.warning(
+ "Invalid template parameter %s. Skipping processing",
+ str(template_params),
)
- except json.JSONDecodeError:
- logger.warning(
- "Invalid template parameter %s. Skipping processing",
- str(template_params),
- )
- result = SQLScript(sql, model.get("engine")).format()
+ result = SQLScript(sql, model.get("engine", database_engine)).format()
return self.response(200, result=result)
except ValidationError as error:
return self.response_400(message=error.messages)
diff --git a/tests/integration_tests/sql_lab/api_tests.py b/tests/integration_tests/sql_lab/api_tests.py
index 9454e7c9b10..4e9f50f1310 100644
--- a/tests/integration_tests/sql_lab/api_tests.py
+++ b/tests/integration_tests/sql_lab/api_tests.py
@@ -39,6 +39,7 @@ from superset.utils.database import (
from superset.utils import core as utils, json
from superset.models.sql_lab import Query
+from superset.sql.parse import SQLScript
from tests.integration_tests.base_tests import SupersetTestCase
from tests.integration_tests.constants import (
ADMIN_USERNAME,
@@ -288,10 +289,38 @@ class TestSqlLabApi(SupersetTestCase):
self.assertDictEqual(resp_data, success_resp) # noqa: PT009
assert rv.status_code == 200
+ def test_format_sql_request_with_db_id(self):
+ self.login(ADMIN_USERNAME)
+ example_db = get_example_database()
+
+ # IIF is normalized differently per dialect:
+ # SQLite preserves IIF(), Postgres/base converts to CASE WHEN.
+ # Compute the expected result from the actual engine so the test is
+ # environment-independent.
+ sql = "select IIF(score > 0, 'positive', 'negative') from my_table"
+ engine = example_db.db_engine_spec.engine
+ expected = SQLScript(sql, engine).format()
+
+ data = {"sql": sql, "database_id": example_db.id}
+ rv = self.client.post(
+ "/api/v1/sqllab/format_sql/",
+ json=data,
+ )
+ resp_data = json.loads(rv.data.decode("utf-8"))
+ assert rv.status_code == 200
+ assert resp_data["result"] == expected
+
def test_format_sql_request_with_jinja(self):
self.login(ADMIN_USERNAME)
example_db = get_example_database()
+ # Quoted identifier formatting varies by dialect (e.g., MySQL uses backticks).
+ # Compute the expected result from the actual engine so the test is
+ # environment-independent.
+ rendered_sql = 'select * from "Vehicle Sales"'
+ engine = example_db.db_engine_spec.engine
+ expected = SQLScript(rendered_sql, engine).format()
+
data = {
"sql": "select * from {{tbl}}",
"database_id": example_db.id,
@@ -302,10 +331,10 @@ class TestSqlLabApi(SupersetTestCase):
json=data,
)
resp_data = json.loads(rv.data.decode("utf-8"))
+ assert rv.status_code == 200
# Verify that Jinja template was processed before formatting
assert "{{tbl}}" not in resp_data["result"]
- assert '"Vehicle Sales"' in resp_data["result"]
- assert rv.status_code == 200
+ assert resp_data["result"] == expected
@mock.patch("superset.commands.sql_lab.results.results_backend_use_msgpack", False)
def test_execute_required_params(self):