You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by er...@apache.org on 2020/09/30 04:51:38 UTC

[incubator-superset] branch master updated: feat: more specific presto error messages (#11099)

This is an automated email from the ASF dual-hosted git repository.

erikrit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new fa5dab8  feat: more specific presto error messages (#11099)
fa5dab8 is described below

commit fa5dab85c44fad34a665c44ed11255c28561cfda
Author: Erik Ritter <er...@airbnb.com>
AuthorDate: Tue Sep 29 21:50:58 2020 -0700

    feat: more specific presto error messages (#11099)
---
 docs/src/pages/docs/Miscellaneous/issue_codes.mdx  | 30 ++++++++++++
 .../src/components/ErrorMessage/types.ts           |  2 +
 superset-frontend/src/setup/setupErrorMessages.ts  |  8 +++
 superset/db_engine_specs/presto.py                 | 57 +++++++++++++++++++++-
 superset/errors.py                                 | 32 ++++++++++++
 5 files changed, 128 insertions(+), 1 deletion(-)

diff --git a/docs/src/pages/docs/Miscellaneous/issue_codes.mdx b/docs/src/pages/docs/Miscellaneous/issue_codes.mdx
index cf06ba9..b342097 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 e5b1b68..dc0c394 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 29f3940..1df6ab0 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 ef5a8a3..04c9896 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 @@ from urllib import parse
 
 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 sqlalchemy.sql.expression import ColumnClause, Select
 
 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 @@ if TYPE_CHECKING:
     # 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 @@ class PrestoEngineSpec(BaseEngineSpec):
         :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 3542d7d..14d389f 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 @@ ERROR_TYPES_TO_ISSUE_CODES_MAPPING = {
             "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."
+            ),
+        },
+    ],
 }