From efdfd65042b38477ad9dacca3d522bd3568c6de7 Mon Sep 17 00:00:00 2001 From: David Cui <53581635+davidcui-amzn@users.noreply.github.com> Date: Wed, 2 Dec 2020 14:16:43 -0800 Subject: [PATCH] Add Error Message for Explain and Run (#872) Added error messages for `Explain` aside from empty box. More detail in error messages for invalid queries on `Run` --- workbench/public/components/Main/main.tsx | 21 +++++++++++++--- .../public/components/PPLPage/PPLPage.tsx | 19 ++++++++++++++- .../public/components/SQLPage/SQLPage.tsx | 24 +++++++++++++++++-- workbench/server/services/QueryService.ts | 5 ++++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/workbench/public/components/Main/main.tsx b/workbench/public/components/Main/main.tsx index 40a7beef03..e0d438f460 100644 --- a/workbench/public/components/Main/main.tsx +++ b/workbench/public/components/Main/main.tsx @@ -34,6 +34,7 @@ import { CoreStart } from 'kibana/public'; interface ResponseData { ok: boolean; resp: any; + body: any; } export interface ResponseDetail { @@ -94,6 +95,12 @@ interface MainState { const SUCCESS_MESSAGE = 'Success'; +const errorQueryResponse = (queryResultResponseDetail: any) => { + let errorMessage = queryResultResponseDetail.errorMessage + ', this query is not runnable. \n \n' + + queryResultResponseDetail.data; + return errorMessage; +} + // It gets column names and row values to display in a Table from the json API response export function getQueryResultsForTable( queryResults: ResponseDetail[] @@ -103,7 +110,7 @@ export function getQueryResultsForTable( if (!queryResultResponseDetail.fulfilled) { return { fulfilled: queryResultResponseDetail.fulfilled, - errorMessage: queryResultResponseDetail.errorMessage, + errorMessage: errorQueryResponse(queryResultResponseDetail), }; } else { let databaseRecords: { [key: string]: any }[] = []; @@ -242,6 +249,15 @@ export class Main extends React.Component { }; } + formatQueryErrorBody(data: any) { + let prettyErrorMessage = ""; + prettyErrorMessage += 'reason: ' + data.errorReason + '\n'; + prettyErrorMessage += 'details: ' + data.errorDetails + '\n'; + prettyErrorMessage += 'type: ' + data.errorType + '\n'; + prettyErrorMessage += 'status: ' + data.status; + return prettyErrorMessage; + } + processQueryResponse(response: IHttpResponse): ResponseDetail { if (!response) { return { @@ -254,7 +270,7 @@ export class Main extends React.Component { return { fulfilled: false, errorMessage: response.data.resp, - data: '', + data: this.formatQueryErrorBody(response.data), }; } @@ -332,7 +348,6 @@ export class Main extends React.Component { this.processQueryResponse(response as IHttpResponse) ); const resultTable: ResponseDetail[] = getQueryResultsForTable(results); - this.setState( { queries: queries, diff --git a/workbench/public/components/PPLPage/PPLPage.tsx b/workbench/public/components/PPLPage/PPLPage.tsx index b34fb77fa2..7a59a6d2e8 100644 --- a/workbench/public/components/PPLPage/PPLPage.tsx +++ b/workbench/public/components/PPLPage/PPLPage.tsx @@ -69,6 +69,23 @@ export class PPLPage extends React.Component { const closeModal = () => this.setIsModalVisible(false); const showModal = () => this.setIsModalVisible(true); + const pplTranslationsNotEmpty = () => { + if (this.props.pplTranslations.length > 0) { + return this.props.pplTranslations[0].fulfilled; + } + return false; + } + + const showExplainErrorMessage = () => { + return this.props.pplTranslations.map((queryTranslation: any) => JSON.stringify( + queryTranslation.errorMessage + ": This query is not explainable.", null, 2 + )); + } + + const explainContent = pplTranslationsNotEmpty() + ? this.props.pplTranslations.map((queryTranslation: any) => JSON.stringify(queryTranslation.data, null, 2)).join("\n") + : showExplainErrorMessage(); + let modal; if (this.state.isModalVisible) { @@ -85,7 +102,7 @@ export class PPLPage extends React.Component { fontSize="m" isCopyable > - {this.props.pplTranslations.map((queryTranslation: any) => JSON.stringify(queryTranslation.data, null, 2)).join("\n")} + {explainContent} diff --git a/workbench/public/components/SQLPage/SQLPage.tsx b/workbench/public/components/SQLPage/SQLPage.tsx index d6c658ba14..e2c3e1d92f 100644 --- a/workbench/public/components/SQLPage/SQLPage.tsx +++ b/workbench/public/components/SQLPage/SQLPage.tsx @@ -72,6 +72,23 @@ export class SQLPage extends React.Component { const closeModal = () => this.setIsModalVisible(false); const showModal = () => this.setIsModalVisible(true); + const sqlTranslationsNotEmpty = () => { + if (this.props.sqlTranslations.length > 0) { + return this.props.sqlTranslations[0].fulfilled; + } + return false; + } + + const showExplainErrorMessage = () => { + return this.props.sqlTranslations.map((queryTranslation: any) => JSON.stringify( + queryTranslation.errorMessage + ": This query is not explainable.", null, 2 + )); + } + + const explainContent = sqlTranslationsNotEmpty() + ? this.props.sqlTranslations.map((queryTranslation: any) => JSON.stringify(queryTranslation.data, null, 2)).join("\n") + : showExplainErrorMessage(); + let modal; if (this.state.isModalVisible) { @@ -88,7 +105,7 @@ export class SQLPage extends React.Component { fontSize="m" isCopyable > - {this.props.sqlTranslations.map((queryTranslation: any) => JSON.stringify(queryTranslation.data, null, 2)).join("\n")} + {explainContent} @@ -148,7 +165,10 @@ export class SQLPage extends React.Component { this.props.onTranslate(this.props.sqlQuery) } > - + Explain {modal} diff --git a/workbench/server/services/QueryService.ts b/workbench/server/services/QueryService.ts index d916d31f04..ede6c9dfde 100644 --- a/workbench/server/services/QueryService.ts +++ b/workbench/server/services/QueryService.ts @@ -41,10 +41,15 @@ export default class QueryService { }; } catch (err) { console.log(err); + const errorObj = JSON.parse(err.body); return { data: { ok: false, resp: err.message, + errorReason: errorObj.error.reason, + errorDetails: errorObj.error.details, + errorType: errorObj.error.type, + status: errorObj.status }, }; }