diff --git a/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx b/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx
index e77b1c895..dcba856a9 100644
--- a/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx
+++ b/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx
@@ -19,12 +19,20 @@
import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';
-
import { Alert, ProgressBar } from 'react-bootstrap';
+
import FilterableTable from 'src/components/FilterableTable/FilterableTable';
import ExploreResultsButton from 'src/SqlLab/components/ExploreResultsButton';
import ResultSet from 'src/SqlLab/components/ResultSet';
-import { queries, stoppedQuery, runningQuery, cachedQuery } from './fixtures';
+import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace';
+import {
+ cachedQuery,
+ failedQueryWithErrorMessage,
+ failedQueryWithErrors,
+ queries,
+ runningQuery,
+ stoppedQuery,
+} from './fixtures';
describe('ResultSet', () => {
const clearQuerySpy = sinon.spy();
@@ -42,6 +50,14 @@ describe('ResultSet', () => {
const stoppedQueryProps = { ...mockedProps, query: stoppedQuery };
const runningQueryProps = { ...mockedProps, query: runningQuery };
const cachedQueryProps = { ...mockedProps, query: cachedQuery };
+ const failedQueryWithErrorMessageProps = {
+ ...mockedProps,
+ query: failedQueryWithErrorMessage,
+ };
+ const failedQueryWithErrorsProps = {
+ ...mockedProps,
+ query: failedQueryWithErrors,
+ };
const newProps = {
query: {
cached: false,
@@ -117,5 +133,15 @@ describe('ResultSet', () => {
const wrapper = shallow();
expect(wrapper.find(ProgressBar)).toHaveLength(1);
});
+ it('should render a failed query with an error message', () => {
+ const wrapper = shallow(
+ ,
+ );
+ expect(wrapper.find(ErrorMessageWithStackTrace)).toHaveLength(1);
+ });
+ it('should render a failed query with an errors object', () => {
+ const wrapper = shallow();
+ expect(wrapper.find(ErrorMessageWithStackTrace)).toHaveLength(1);
+ });
});
});
diff --git a/superset-frontend/spec/javascripts/sqllab/fixtures.js b/superset-frontend/spec/javascripts/sqllab/fixtures.js
index 45bbb2ee9..e7503ee11 100644
--- a/superset-frontend/spec/javascripts/sqllab/fixtures.js
+++ b/superset-frontend/spec/javascripts/sqllab/fixtures.js
@@ -389,6 +389,50 @@ export const stoppedQuery = {
tab: 'Untitled Query 2',
tempTable: '',
};
+
+export const failedQueryWithErrorMessage = {
+ dbId: 1,
+ cached: false,
+ ctas: false,
+ errorMessage: 'Something went wrong',
+ id: 'ryhMUZCGb',
+ progress: 0,
+ results: [],
+ runAsync: false,
+ schema: 'main',
+ sql: 'SELECT ...',
+ sqlEditorId: 'rJaf5u9WZ',
+ startDttm: 1497400851936,
+ state: 'failed',
+ tab: 'Untitled Query 2',
+ tempTable: '',
+};
+
+export const failedQueryWithErrors = {
+ dbId: 1,
+ cached: false,
+ ctas: false,
+ errors: [
+ {
+ message: 'Something went wrong',
+ error_type: 'TEST_ERROR',
+ level: 'error',
+ extra: null,
+ },
+ ],
+ id: 'ryhMUZCGb',
+ progress: 0,
+ results: [],
+ runAsync: false,
+ schema: 'main',
+ sql: 'SELECT ...',
+ sqlEditorId: 'rJaf5u9WZ',
+ startDttm: 1497400851936,
+ state: 'failed',
+ tab: 'Untitled Query 2',
+ tempTable: '',
+};
+
export const runningQuery = {
dbId: 1,
cached: false,
diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js
index e38a4fe56..8fb7428aa 100644
--- a/superset-frontend/src/SqlLab/actions/sqlLab.js
+++ b/superset-frontend/src/SqlLab/actions/sqlLab.js
@@ -271,7 +271,7 @@ export function querySuccess(query, results) {
};
}
-export function queryFailed(query, msg, link) {
+export function queryFailed(query, msg, link, errors) {
return function (dispatch) {
const sync =
!query.isDataPreview &&
@@ -283,7 +283,7 @@ export function queryFailed(query, msg, link) {
: Promise.resolve();
return sync
- .then(() => dispatch({ type: QUERY_FAILED, query, msg, link }))
+ .then(() => dispatch({ type: QUERY_FAILED, query, msg, link, errors }))
.catch(() =>
dispatch(
addDangerToast(
@@ -332,7 +332,9 @@ export function fetchQueryResults(query, displayLimit) {
error.statusText ||
t('Failed at retrieving results');
- return dispatch(queryFailed(query, message, error.link));
+ return dispatch(
+ queryFailed(query, message, error.link, error.errors),
+ );
}),
);
};
@@ -376,7 +378,7 @@ export function runQuery(query) {
if (message.includes('CSRF token')) {
message = t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT);
}
- dispatch(queryFailed(query, message, error.link));
+ dispatch(queryFailed(query, message, error.link, error.errors));
}),
);
};
diff --git a/superset-frontend/src/SqlLab/components/ResultSet.tsx b/superset-frontend/src/SqlLab/components/ResultSet.tsx
index 75273b3e1..b074872cc 100644
--- a/superset-frontend/src/SqlLab/components/ResultSet.tsx
+++ b/superset-frontend/src/SqlLab/components/ResultSet.tsx
@@ -21,6 +21,7 @@ import { Alert, Button, ButtonGroup, ProgressBar } from 'react-bootstrap';
import shortid from 'shortid';
import { t } from '@superset-ui/translation';
+import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace';
import Loading from '../../components/Loading';
import ExploreCtasResultsButton from './ExploreCtasResultsButton';
import ExploreResultsButton from './ExploreResultsButton';
@@ -215,15 +216,11 @@ export default class ResultSet extends React.PureComponent<
return Query was stopped;
} else if (query.state === 'failed') {
return (
-
- {query.errorMessage}
- {query.link && (
-
- {' '}
- {t('(Request Access)')}{' '}
-
- )}
-
+
);
} else if (query.state === 'success' && query.ctas) {
const { tempSchema, tempTable } = query;
diff --git a/superset-frontend/src/SqlLab/reducers/sqlLab.js b/superset-frontend/src/SqlLab/reducers/sqlLab.js
index 6257ce8c9..d47a45aa2 100644
--- a/superset-frontend/src/SqlLab/reducers/sqlLab.js
+++ b/superset-frontend/src/SqlLab/reducers/sqlLab.js
@@ -343,6 +343,7 @@ export default function sqlLabReducer(state = {}, action) {
}
const alts = {
state: 'failed',
+ errors: action.errors,
errorMessage: action.msg,
endDttm: now(),
link: action.link,
diff --git a/superset-frontend/src/SqlLab/types.ts b/superset-frontend/src/SqlLab/types.ts
index 3b1c4e125..0fe83a7f5 100644
--- a/superset-frontend/src/SqlLab/types.ts
+++ b/superset-frontend/src/SqlLab/types.ts
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { CtasEnum } from './actions/sqlLab';
+import { SupersetError } from 'src/components/ErrorMessage/types';
+import { CtasEnum } from 'src/SqlLab/actions/sqlLab';
export type Column = {
name: string;
@@ -27,6 +28,7 @@ export type Query = {
ctas: boolean;
ctas_method?: keyof typeof CtasEnum;
dbId: number;
+ errors?: SupersetError[];
errorMessage: string | null;
extra: {
progress: string | null;
diff --git a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx
index fff4e060c..5f3f6794e 100644
--- a/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx
+++ b/superset-frontend/src/components/ErrorMessage/ErrorMessageWithStackTrace.tsx
@@ -19,13 +19,15 @@
import React, { useState } from 'react';
// @ts-ignore
import { Alert, Collapse } from 'react-bootstrap';
+import { t } from '@superset-ui/translation';
+
import getErrorMessageComponentRegistry from './getErrorMessageComponentRegistry';
import { SupersetError } from './types';
type Props = {
error?: SupersetError;
link?: string;
- message: string;
+ message?: string;
stackTrace?: string;
};
@@ -54,7 +56,7 @@ export default function ErrorMessageWithStackTrace({
bsStyle="warning"
onClick={() => setShowStackTrace(!showStackTrace)}
>
- {message}
+ {message || t('An error occurred.')}
{link && (
(Request Access)