diff --git a/superset/models/sql_lab.py b/superset/models/sql_lab.py index cb34a921d49a..9552d856760c 100644 --- a/superset/models/sql_lab.py +++ b/superset/models/sql_lab.py @@ -48,7 +48,7 @@ from sqlalchemy.sql.elements import ColumnElement, literal_column from superset import security_manager -from superset.exceptions import SupersetSecurityException +from superset.exceptions import SupersetParseError, SupersetSecurityException from superset.jinja_context import BaseTemplateProcessor, get_template_processor from superset.models.helpers import ( AuditMixinNullable, @@ -85,7 +85,7 @@ def sql_tables(self) -> list[Table]: self.database, # type: ignore ) ) - except (SupersetSecurityException, TemplateError): + except (SupersetSecurityException, SupersetParseError, TemplateError): return [] diff --git a/tests/unit_tests/models/sql_lab_test.py b/tests/unit_tests/models/sql_lab_test.py index a2ce2a6afade..e9fa77337011 100644 --- a/tests/unit_tests/models/sql_lab_test.py +++ b/tests/unit_tests/models/sql_lab_test.py @@ -22,7 +22,7 @@ from pytest_mock import MockerFixture from superset.errors import ErrorLevel, SupersetError, SupersetErrorType -from superset.exceptions import SupersetSecurityException +from superset.exceptions import SupersetParseError, SupersetSecurityException from superset.models.sql_lab import Query, SavedQuery @@ -43,6 +43,10 @@ level=ErrorLevel.ERROR, ) ), + SupersetParseError( + sql="INVALID SQL", + message="Invalid SQL syntax", + ), TemplateError, ], ) @@ -57,3 +61,42 @@ def test_sql_tables_mixin_sql_tables_exception( ) assert klass(sql="SELECT 1", database=MagicMock()).sql_tables == [] + + +@pytest.mark.parametrize( + "klass", + [ + Query, + SavedQuery, + ], +) +@pytest.mark.parametrize( + "invalid_sql", + [ + "SELECT * FROM table WHERE invalid syntax", + "INVALID SQL STATEMENT", + "SELECT * FROM; DROP TABLE users;", + "", + None, + ], +) +def test_sql_tables_mixin_invalid_sql_returns_empty_list( + klass: type[Model], + invalid_sql: str, + mocker: MockerFixture, +) -> None: + """Test that SqlTablesMixin returns empty list when SQL parsing fails.""" + mocker.patch( + "superset.models.sql_lab.extract_tables_from_jinja_sql", + side_effect=SupersetParseError( + sql=invalid_sql or "INVALID SQL", + message=f"Failed to parse SQL: {invalid_sql}", + ), + ) + + instance = ( + klass(sql=invalid_sql, database=MagicMock()) + if invalid_sql is not None + else klass(database=MagicMock()) + ) + assert instance.sql_tables == []