Skip to content

Commit

Permalink
feat: add more SIP-40 errors to SQL Lab (#15436)
Browse files Browse the repository at this point in the history
  • Loading branch information
betodealmeida committed Jun 30, 2021
1 parent 743d9cc commit 149c5fd
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 16 deletions.
26 changes: 24 additions & 2 deletions docs/src/pages/docs/Miscellaneous/issue_codes.mdx
Expand Up @@ -271,8 +271,6 @@ One or more parameters specified in the query are malformatted.
```

The query contains one or more malformed template parameters. Please check your query and confirm that all template parameters are surround by double braces, for example, "{{ ds }}". Then, try running your query again.
The object does not exist in this database.
```

## Issue 1029

Expand All @@ -289,3 +287,27 @@ The query potentially has a syntax error.
```

The query might have a syntax error. Please check and run again.

## Issue 1031

```
The results backend no longer has the data from the query.
```

The results from the query might have been deleted from the results backend after some period. Please re-run your query.

## Issue 1032

```
The query associated with the results was deleted.
```

The query associated with the stored results no longer exists. Please re-run your query.

## Issue 1033

```
The results stored in the backend were stored in a different format, and no longer can be deserialized.
```

The query results were stored in a format that is no longer supported. Please re-run your query.
2 changes: 2 additions & 0 deletions superset-frontend/src/components/ErrorMessage/types.ts
Expand Up @@ -52,6 +52,7 @@ export const ErrorTypeEnum = {
TABLE_SECURITY_ACCESS_ERROR: 'TABLE_SECURITY_ACCESS_ERROR',
DATASOURCE_SECURITY_ACCESS_ERROR: 'DATASOURCE_SECURITY_ACCESS_ERROR',
DATABASE_SECURITY_ACCESS_ERROR: 'DATABASE_SECURITY_ACCESS_ERROR',
QUERY_SECURITY_ACCESS_ERROR: 'QUERY_SECURITY_ACCESS_ERROR',
MISSING_OWNERSHIP_ERROR: 'MISSING_OWNERSHIP_ERROR',

// Other errors
Expand All @@ -65,6 +66,7 @@ export const ErrorTypeEnum = {
INVALID_CTAS_QUERY_ERROR: 'INVALID_CTAS_QUERY_ERROR',
INVALID_CVAS_QUERY_ERROR: 'INVALID_CVAS_QUERY_ERROR',
SQLLAB_TIMEOUT_ERROR: 'SQLLAB_TIMEOUT_ERROR',
RESULTS_BACKEND_ERROR: 'RESULTS_BACKEND_ERROR',

// Generic errors
GENERIC_COMMAND_ERROR: 'GENERIC_COMMAND_ERROR',
Expand Down
8 changes: 8 additions & 0 deletions superset-frontend/src/setup/setupErrorMessages.ts
Expand Up @@ -71,10 +71,18 @@ export default function setupErrorMessages() {
ErrorTypeEnum.INVALID_CVAS_QUERY_ERROR,
DatabaseErrorMessage,
);
errorMessageComponentRegistry.registerValue(
ErrorTypeEnum.QUERY_SECURITY_ACCESS_ERROR,
DatabaseErrorMessage,
);
errorMessageComponentRegistry.registerValue(
ErrorTypeEnum.CONNECTION_INVALID_HOSTNAME_ERROR,
DatabaseErrorMessage,
);
errorMessageComponentRegistry.registerValue(
ErrorTypeEnum.RESULTS_BACKEND_ERROR,
DatabaseErrorMessage,
);
errorMessageComponentRegistry.registerValue(
ErrorTypeEnum.SQLLAB_TIMEOUT_ERROR,
DatabaseErrorMessage,
Expand Down
26 changes: 25 additions & 1 deletion superset/errors.py
Expand Up @@ -61,6 +61,7 @@ class SupersetErrorType(str, Enum):
TABLE_SECURITY_ACCESS_ERROR = "TABLE_SECURITY_ACCESS_ERROR"
DATASOURCE_SECURITY_ACCESS_ERROR = "DATASOURCE_SECURITY_ACCESS_ERROR"
DATABASE_SECURITY_ACCESS_ERROR = "DATABASE_SECURITY_ACCESS_ERROR"
QUERY_SECURITY_ACCESS_ERROR = "QUERY_SECURITY_ACCESS_ERROR"
MISSING_OWNERSHIP_ERROR = "MISSING_OWNERSHIP_ERROR"

# Other errors
Expand All @@ -74,6 +75,7 @@ class SupersetErrorType(str, Enum):
INVALID_CTAS_QUERY_ERROR = "INVALID_CTAS_QUERY_ERROR"
INVALID_CVAS_QUERY_ERROR = "INVALID_CVAS_QUERY_ERROR"
SQLLAB_TIMEOUT_ERROR = "SQLLAB_TIMEOUT_ERROR"
RESULTS_BACKEND_ERROR = "RESULTS_BACKEND_ERROR"

# Generic errors
GENERIC_COMMAND_ERROR = "GENERIC_COMMAND_ERROR"
Expand Down Expand Up @@ -331,7 +333,29 @@ class SupersetErrorType(str, Enum):
},
],
SupersetErrorType.SYNTAX_ERROR: [
{"code": 1030, "message": _("Issue 1029 - The query has a syntax error."),},
{"code": 1030, "message": _("Issue 1030 - The query has a syntax error.")},
],
SupersetErrorType.RESULTS_BACKEND_ERROR: [
{
"code": 1031,
"message": _(
"Issue 1031 - The results backend no longer has the data from the "
"query."
),
},
{
"code": 1032,
"message": _(
"Issue 1032 - The query associated with the results was deleted."
),
},
{
"code": 1033,
"message": _(
"Issue 1033 - The results stored in the backend were stored in a "
"different format, and no longer can be deserialized."
),
},
],
}

Expand Down
10 changes: 8 additions & 2 deletions superset/exceptions.py
Expand Up @@ -43,9 +43,11 @@ def exception(self) -> Optional[Exception]:
class SupersetErrorException(SupersetException):
"""Exceptions with a single SupersetErrorType associated with them"""

def __init__(self, error: SupersetError) -> None:
def __init__(self, error: SupersetError, status: Optional[int] = None) -> None:
super().__init__(error.message)
self.error = error
if status is not None:
self.status = status


class SupersetGenericErrorException(SupersetErrorException):
Expand Down Expand Up @@ -81,9 +83,13 @@ def __init__(
class SupersetErrorsException(SupersetException):
"""Exceptions with multiple SupersetErrorType associated with them"""

def __init__(self, errors: List[SupersetError]) -> None:
def __init__(
self, errors: List[SupersetError], status: Optional[int] = None
) -> None:
super().__init__(str(errors))
self.errors = errors
if status is not None:
self.status = status


class SupersetTimeoutException(SupersetErrorFromParamsException):
Expand Down
64 changes: 53 additions & 11 deletions superset/views/core.py
Expand Up @@ -2196,39 +2196,81 @@ def results_exec( # pylint: disable=too-many-return-statements
now_as_float() - read_from_results_backend_start,
)
if not blob:
return json_error_response(
"Data could not be retrieved. " "You may want to re-run the query.",
raise SupersetErrorException(
SupersetError(
message=__(
"Data could not be retrieved from the results backend. You "
"need to re-run the original query."
),
error_type=SupersetErrorType.RESULTS_BACKEND_ERROR,
level=ErrorLevel.ERROR,
),
status=410,
)

query = db.session.query(Query).filter_by(results_key=key).one_or_none()
if query is None:
return json_error_response(
"Data could not be retrieved. You may want to re-run the query.",
raise SupersetErrorException(
SupersetError(
message=__(
"The query associated with these results could not be find. "
"You need to re-run the original query."
),
error_type=SupersetErrorType.RESULTS_BACKEND_ERROR,
level=ErrorLevel.ERROR,
),
status=404,
)

try:
query.raise_for_access()
except SupersetSecurityException as ex:
return json_errors_response([ex.error], status=403)
raise SupersetErrorException(
SupersetError(
message=__(
"You are not authorized to see this query. If you think this "
"is an error, please reach out to your administrator."
),
error_type=SupersetErrorType.QUERY_SECURITY_ACCESS_ERROR,
level=ErrorLevel.ERROR,
),
status=403,
) from ex

payload = utils.zlib_decompress(blob, decode=not results_backend_use_msgpack)
try:
obj = _deserialize_results_payload(
payload, query, cast(bool, results_backend_use_msgpack)
)
except SerializationError:
return json_error_response(
__("Data could not be deserialized. You may want to re-run the query."),
except SerializationError as ex:
raise SupersetErrorException(
SupersetError(
message=__(
"Data could not be deserialized from the results backend. The "
"storage format might have changed, rendering the old data "
"stake. You need to re-run the original query."
),
error_type=SupersetErrorType.RESULTS_BACKEND_ERROR,
level=ErrorLevel.ERROR,
),
status=404,
)
) from ex

if "rows" in request.args:
try:
rows = int(request.args["rows"])
except ValueError:
return json_error_response("Invalid `rows` argument", status=400)
except ValueError as ex:
raise SupersetErrorException(
SupersetError(
message=__(
"The provided `rows` argument is not a valid integer."
),
error_type=SupersetErrorType.INVALID_PAYLOAD_SCHEMA_ERROR,
level=ErrorLevel.ERROR,
),
status=400,
) from ex

obj = apply_display_max_row_limit(obj, rows)

return json_success(
Expand Down

0 comments on commit 149c5fd

Please sign in to comment.