Skip to content

Commit

Permalink
fix: Avoid 500 if end users write bad SQL (#26638)
Browse files Browse the repository at this point in the history
  • Loading branch information
Khrol authored and michael-s-molina committed Jan 18, 2024
1 parent d9905c6 commit e683c23
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ test('should render the menu items in Embedded mode', async () => {
setup(guestUserProps);
expect(screen.getAllByRole('menuitem')).toHaveLength(3);
expect(screen.getByText('Refresh dashboard')).toBeInTheDocument();
expect(screen.getByText('Download')).toBeInTheDocument();
expect(screen.getByText('Download as image')).toBeInTheDocument();
expect(screen.getByText('Set auto-refresh interval')).toBeInTheDocument();
});

Expand Down
2 changes: 1 addition & 1 deletion superset/db_engine_specs/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ class SupersetDBAPIOperationalError(SupersetDBAPIError):


class SupersetDBAPIProgrammingError(SupersetDBAPIError):
pass
status = 400
26 changes: 24 additions & 2 deletions superset/db_engine_specs/trino.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@
from superset.constants import QUERY_CANCEL_KEY, QUERY_EARLY_CANCEL_KEY, USER_AGENT
from superset.databases.utils import make_url_safe
from superset.db_engine_specs.base import BaseEngineSpec
from superset.db_engine_specs.exceptions import SupersetDBAPIConnectionError
from superset.db_engine_specs.exceptions import (
SupersetDBAPIConnectionError,
SupersetDBAPIDatabaseError,
SupersetDBAPIOperationalError,
SupersetDBAPIProgrammingError,
)
from superset.db_engine_specs.presto import PrestoBaseEngineSpec
from superset.models.sql_lab import Query
from superset.utils import core as utils
Expand Down Expand Up @@ -332,11 +337,28 @@ def update_params_from_encrypted_extra(
def get_dbapi_exception_mapping(cls) -> dict[type[Exception], type[Exception]]:
# pylint: disable=import-outside-toplevel
from requests import exceptions as requests_exceptions
from trino import exceptions as trino_exceptions

return {
static_mapping: dict[type[Exception], type[Exception]] = {
requests_exceptions.ConnectionError: SupersetDBAPIConnectionError,
}

class _CustomMapping(dict[type[Exception], type[Exception]]):
def get( # type: ignore[override]
self, item: type[Exception], default: type[Exception] | None = None
) -> type[Exception] | None:
if static := static_mapping.get(item):
return static
if issubclass(item, trino_exceptions.InternalError):
return SupersetDBAPIDatabaseError
if issubclass(item, trino_exceptions.OperationalError):
return SupersetDBAPIOperationalError
if issubclass(item, trino_exceptions.ProgrammingError):
return SupersetDBAPIProgrammingError
return default

return _CustomMapping()

@classmethod
def get_indexes(
cls,
Expand Down
19 changes: 19 additions & 0 deletions tests/unit_tests/db_engine_specs/test_trino.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,18 @@
import pandas as pd
import pytest
from pytest_mock import MockerFixture
from requests.exceptions import ConnectionError as RequestsConnectionError
from sqlalchemy import types
from trino.exceptions import TrinoExternalError, TrinoInternalError, TrinoUserError

import superset.config
from superset.constants import QUERY_CANCEL_KEY, QUERY_EARLY_CANCEL_KEY, USER_AGENT
from superset.db_engine_specs.exceptions import (
SupersetDBAPIConnectionError,
SupersetDBAPIDatabaseError,
SupersetDBAPIOperationalError,
SupersetDBAPIProgrammingError,
)
from superset.utils.core import GenericDataType
from tests.unit_tests.db_engine_specs.utils import (
assert_column_spec,
Expand Down Expand Up @@ -411,3 +419,14 @@ def test_get_indexes_no_table():
db_mock, inspector_mock, "test_table", "test_schema"
)
assert result == []


def test_get_dbapi_exception_mapping():
from superset.db_engine_specs.trino import TrinoEngineSpec

mapping = TrinoEngineSpec.get_dbapi_exception_mapping()
assert mapping.get(TrinoUserError) == SupersetDBAPIProgrammingError
assert mapping.get(TrinoInternalError) == SupersetDBAPIDatabaseError
assert mapping.get(TrinoExternalError) == SupersetDBAPIOperationalError
assert mapping.get(RequestsConnectionError) == SupersetDBAPIConnectionError
assert mapping.get(Exception) is None

0 comments on commit e683c23

Please sign in to comment.