diff --git a/docs/src/pages/docs/Miscellaneous/issue_codes.mdx b/docs/src/pages/docs/Miscellaneous/issue_codes.mdx index cf06ba93f6c58..b34209786b777 100644 --- a/docs/src/pages/docs/Miscellaneous/issue_codes.mdx +++ b/docs/src/pages/docs/Miscellaneous/issue_codes.mdx @@ -43,3 +43,33 @@ This may be due to a syntax error, a bug in your query, or some other internal failure within the database. This is usually not an issue within Superset, but instead a problem with the underlying database that serves your query. + +## Issue 1003 + +``` +There is a syntax error in the SQL query. Perhaps there was a misspelling or a typo. +``` + +Your query failed because of a syntax error within the underlying query. Please +validate that all columns or tables referenced within the query exist and are spelled +correctly. + +## Issue 1004 + +``` +The column was deleted or renamed in the database. +``` + +Your query failed because it is referencing a column that no longer exists in +the underlying datasource. You should modify the query to reference the +replacement column, or remove this column from your query. + +## Issue 1005 + +``` +The table was deleted or renamed in the database. +``` + +Your query failed because it is referencing a table that no longer exists in +the underlying database. You should modify your query to reference the correct +table. diff --git a/superset-frontend/src/components/ErrorMessage/types.ts b/superset-frontend/src/components/ErrorMessage/types.ts index e5b1b682190eb..dc0c3948528c3 100644 --- a/superset-frontend/src/components/ErrorMessage/types.ts +++ b/superset-frontend/src/components/ErrorMessage/types.ts @@ -26,6 +26,8 @@ export const ErrorTypeEnum = { // DB Engine errors GENERIC_DB_ENGINE_ERROR: 'GENERIC_DB_ENGINE_ERROR', + COLUMN_DOES_NOT_EXIST_ERROR: 'COLUMN_DOES_NOT_EXIST_ERROR', + TABLE_DOES_NOT_EXIST_ERROR: 'TABLE_DOES_NOT_EXIST_ERROR', // Viz errors VIZ_GET_DF_ERROR: 'VIZ_GET_DF_ERROR', diff --git a/superset-frontend/src/setup/setupErrorMessages.ts b/superset-frontend/src/setup/setupErrorMessages.ts index 29f3940a15ec2..1df6ab05def25 100644 --- a/superset-frontend/src/setup/setupErrorMessages.ts +++ b/superset-frontend/src/setup/setupErrorMessages.ts @@ -38,5 +38,13 @@ export default function setupErrorMessages() { ErrorTypeEnum.GENERIC_DB_ENGINE_ERROR, DatabaseErrorMessage, ); + errorMessageComponentRegistry.registerValue( + ErrorTypeEnum.COLUMN_DOES_NOT_EXIST_ERROR, + DatabaseErrorMessage, + ); + errorMessageComponentRegistry.registerValue( + ErrorTypeEnum.TABLE_DOES_NOT_EXIST_ERROR, + DatabaseErrorMessage, + ); setupErrorMessagesExtra(); } diff --git a/superset/db_engine_specs/presto.py b/superset/db_engine_specs/presto.py index ef5a8a3d1dd08..04c9896cf45d4 100644 --- a/superset/db_engine_specs/presto.py +++ b/superset/db_engine_specs/presto.py @@ -14,6 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +import dataclasses import logging import re import textwrap @@ -27,7 +28,7 @@ import pandas as pd import simplejson as json -from flask_babel import lazy_gettext as _ +from flask_babel import gettext as __, lazy_gettext as _ from sqlalchemy import Column, literal_column, types from sqlalchemy.engine.base import Engine from sqlalchemy.engine.reflection import Inspector @@ -38,6 +39,7 @@ from superset import app, cache, is_feature_enabled, security_manager from superset.db_engine_specs.base import BaseEngineSpec +from superset.errors import ErrorLevel, SupersetError, SupersetErrorType from superset.exceptions import SupersetTemplateException from superset.models.sql_lab import Query from superset.models.sql_types.presto_sql_types import ( @@ -55,6 +57,9 @@ # prevent circular imports from superset.models.core import Database +COLUMN_NOT_RESOLVED_ERROR_REGEX = "line (.+?): .*Column '(.+?)' cannot be resolved" +TABLE_DOES_NOT_EXIST_ERROR_REGEX = ".*Table (.+?) does not exist" + QueryStatus = utils.QueryStatus config = app.config logger = logging.getLogger(__name__) @@ -1035,3 +1040,53 @@ def get_function_names(cls, database: "Database") -> List[str]: :return: A list of function names useable in the database """ return database.get_df("SHOW FUNCTIONS")["Function"].tolist() + + @classmethod + def extract_errors(cls, ex: Exception) -> List[Dict[str, Any]]: + raw_message = cls._extract_error_message(ex) + + column_match = re.search(COLUMN_NOT_RESOLVED_ERROR_REGEX, raw_message) + if column_match: + return [ + dataclasses.asdict( + SupersetError( + error_type=SupersetErrorType.COLUMN_DOES_NOT_EXIST_ERROR, + message=__( + 'We can\'t seem to resolve the column "%(column_name)s" at ' + "line %(location)s.", + column_name=column_match.group(2), + location=column_match.group(1), + ), + level=ErrorLevel.ERROR, + extra={"engine_name": cls.engine_name}, + ) + ) + ] + + table_match = re.search(TABLE_DOES_NOT_EXIST_ERROR_REGEX, raw_message) + if table_match: + return [ + dataclasses.asdict( + SupersetError( + error_type=SupersetErrorType.TABLE_DOES_NOT_EXIST_ERROR, + message=__( + 'The table "%(table_name)s" does not exist. ' + "A valid table must be used to run this query.", + table_name=table_match.group(1), + ), + level=ErrorLevel.ERROR, + extra={"engine_name": cls.engine_name}, + ) + ) + ] + + return [ + dataclasses.asdict( + SupersetError( + error_type=SupersetErrorType.GENERIC_DB_ENGINE_ERROR, + message=cls._extract_error_message(ex), + level=ErrorLevel.ERROR, + extra={"engine_name": cls.engine_name}, + ) + ) + ] diff --git a/superset/errors.py b/superset/errors.py index 3542d7d3bfea4..14d389fa3c607 100644 --- a/superset/errors.py +++ b/superset/errors.py @@ -36,6 +36,8 @@ class SupersetErrorType(str, Enum): # DB Engine errors GENERIC_DB_ENGINE_ERROR = "GENERIC_DB_ENGINE_ERROR" + COLUMN_DOES_NOT_EXIST_ERROR = "COLUMN_DOES_NOT_EXIST_ERROR" + TABLE_DOES_NOT_EXIST_ERROR = "TABLE_DOES_NOT_EXIST_ERROR" # Viz errors VIZ_GET_DF_ERROR = "VIZ_GET_DF_ERROR" @@ -68,6 +70,36 @@ class SupersetErrorType(str, Enum): "message": _("Issue 1002 - The database returned an unexpected error."), } ], + SupersetErrorType.COLUMN_DOES_NOT_EXIST_ERROR: [ + { + "code": 1003, + "message": _( + "Issue 1003 - There is a syntax error in the SQL query. " + "Perhaps there was a misspelling or a typo." + ), + }, + { + "code": 1004, + "message": _( + "Issue 1004 - The column was deleted or renamed in the database." + ), + }, + ], + SupersetErrorType.TABLE_DOES_NOT_EXIST_ERROR: [ + { + "code": 1003, + "message": _( + "Issue 1003 - There is a syntax error in the SQL query. " + "Perhaps there was a misspelling or a typo." + ), + }, + { + "code": 1005, + "message": _( + "Issue 1005 - The table was deleted or renamed in the database." + ), + }, + ], }