diff --git a/superset/assets/javascripts/SqlLab/actions.js b/superset/assets/javascripts/SqlLab/actions.js index 93c4afe75c..0edbe2f7ee 100644 --- a/superset/assets/javascripts/SqlLab/actions.js +++ b/superset/assets/javascripts/SqlLab/actions.js @@ -85,8 +85,12 @@ export function fetchQueryResults(query) { success(results) { dispatch(querySuccess(query, results)); }, - error() { - dispatch(queryFailed(query, 'Failed at retrieving results from the results backend')); + error(err) { + let msg = 'Failed at retrieving results from the results backend'; + if (err.responseJSON && err.responseJSON.error) { + msg = err.responseJSON.error; + } + dispatch(queryFailed(query, msg)); }, }); }; diff --git a/superset/assets/javascripts/SqlLab/components/HighlightedSql.jsx b/superset/assets/javascripts/SqlLab/components/HighlightedSql.jsx index a3ae2f2cee..e649125fac 100644 --- a/superset/assets/javascripts/SqlLab/components/HighlightedSql.jsx +++ b/superset/assets/javascripts/SqlLab/components/HighlightedSql.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import { Well } from 'react-bootstrap'; import SyntaxHighlighter from 'react-syntax-highlighter'; import { github } from 'react-syntax-highlighter/dist/styles'; import ModalTrigger from '../../components/ModalTrigger'; @@ -45,11 +44,9 @@ class HighlightedSql extends React.Component { const props = this.props; let shownSql = props.shrink ? this.shrinkSql(props.sql) : props.sql; return ( - - - {shownSql} - - ); + + {shownSql} + ); } generateModal() { const props = this.props; diff --git a/superset/assets/javascripts/SqlLab/components/QueryTable.jsx b/superset/assets/javascripts/SqlLab/components/QueryTable.jsx index 04c6b79ac3..9637c5d05c 100644 --- a/superset/assets/javascripts/SqlLab/components/QueryTable.jsx +++ b/superset/assets/javascripts/SqlLab/components/QueryTable.jsx @@ -2,7 +2,7 @@ import React from 'react'; import moment from 'moment'; import { Table } from 'reactable'; -import { Label, ProgressBar } from 'react-bootstrap'; +import { Label, ProgressBar, Well } from 'react-bootstrap'; import Link from './Link'; import VisualizeModal from './VisualizeModal'; import ResultSet from './ResultSet'; @@ -107,7 +107,9 @@ class QueryTable extends React.PureComponent { ); q.sql = ( - + + + ); if (q.resultsKey) { q.output = ( diff --git a/superset/assets/javascripts/SqlLab/components/ResultSet.jsx b/superset/assets/javascripts/SqlLab/components/ResultSet.jsx index 847d33a07d..003d0745da 100644 --- a/superset/assets/javascripts/SqlLab/components/ResultSet.jsx +++ b/superset/assets/javascripts/SqlLab/components/ResultSet.jsx @@ -220,7 +220,7 @@ class ResultSet extends React.PureComponent { ); } - return (The query returned no data); + return The query returned no data; } } ResultSet.propTypes = propTypes; diff --git a/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx b/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx index 042f40786a..6fb91051f0 100644 --- a/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx @@ -24,9 +24,9 @@ describe('HighlightedSql', () => { it('renders two SyntaxHighlighter in modal', () => { const wrapper = mount( ); - const well = wrapper.find('.well'); - expect(well).to.have.length(1); - well.simulate('click'); + const pre = wrapper.find('pre'); + expect(pre).to.have.length(1); + pre.simulate('click'); const modalBody = mount(wrapper.state().modalBody); expect(modalBody.find(SyntaxHighlighter)).to.have.length(2); }); diff --git a/superset/sql_lab.py b/superset/sql_lab.py index 1bb1d0b734..6eb251e3b3 100644 --- a/superset/sql_lab.py +++ b/superset/sql_lab.py @@ -87,6 +87,9 @@ def get_sql_results(self, query_id, return_results=True, store_results=False): session.commit() raise Exception(query.error_message) + if store_results and not results_backend: + handle_error("Results backend isn't configured.") + # Limit enforced only for retrieving the data, not for the CTA queries. superset_query = sql_parse.SupersetQuery(executed_sql) if not superset_query.is_select() and not database.allow_dml: @@ -169,7 +172,7 @@ def get_sql_results(self, query_id, return_results=True, store_results=False): payload['query'] = query.to_dict() payload = json.dumps(payload, default=utils.json_iso_dttm_ser) - if store_results and results_backend: + if store_results: key = '{}'.format(uuid.uuid4()) logging.info("Storing results in results backend, key: {}".format(key)) results_backend.set(key, zlib.compress(payload)) diff --git a/superset/views.py b/superset/views.py index 604faf8a14..88bdb6ed99 100755 --- a/superset/views.py +++ b/superset/views.py @@ -2061,7 +2061,7 @@ class Superset(BaseSupersetView): models.SqlaTable.table_name == table_name) ).first() if not table: - json_error_response(__( + return json_error_response(__( "Table %(t)s wasn't found in the database %(d)s", t=table_name, s=db_name), status=404) slices = session.query(models.Slice).filter_by( @@ -2378,6 +2378,9 @@ class Superset(BaseSupersetView): @log_this def results(self, key): """Serves a key off of the results backend""" + if not results_backend: + return json_error_response("Results backend isn't configured") + blob = results_backend.get(key) if blob: json_payload = zlib.decompress(blob) @@ -2387,7 +2390,7 @@ class Superset(BaseSupersetView): mydb = session.query(models.Database).filter_by(id=db_id).one() if not self.database_access(mydb): - json_error_response( + return json_error_response( get_database_access_error_msg(mydb.database_name)) return Response(