From d0f001288b45d6eaf85e58d6be7bf763825859f3 Mon Sep 17 00:00:00 2001 From: Shenoy Pratik <sgguruda@amazon.com> Date: Mon, 9 Dec 2024 13:41:24 -0800 Subject: [PATCH] [Bug] Fix SQL/PPL crash with incorrect query (#2284) * fix SQL/PPL crash with incorrect query Signed-off-by: Shenoy Pratik <sgguruda@amazon.com> * add constants Signed-off-by: Shenoy Pratik <sgguruda@amazon.com> --------- Signed-off-by: Shenoy Pratik <sgguruda@amazon.com> --- .../notebooks_test/notebooks.spec.js | 64 +++++++++++++++---- .cypress/support/constants.js | 1 - .cypress/utils/constants.js | 11 +++- server/services/queryService.ts | 2 +- 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/.cypress/integration/notebooks_test/notebooks.spec.js b/.cypress/integration/notebooks_test/notebooks.spec.js index e9e75a4b9..1c1afac31 100644 --- a/.cypress/integration/notebooks_test/notebooks.spec.js +++ b/.cypress/integration/notebooks_test/notebooks.spec.js @@ -13,6 +13,8 @@ import { PPL_QUERY_TEXT, NOTEBOOK_TEXT, OPENSEARCH_URL, + PPL_INCORRECT_QUERY_TEXT, + SQL_INCORRECT_QUERY_TEXT, } from '../../utils/constants'; import { v4 as uuid4 } from 'uuid'; @@ -74,7 +76,9 @@ describe('Testing notebooks table', () => { cy.get('h3[data-test-subj="notebookTableTitle"]').contains('Notebooks (0)').should('exist'); cy.get('div[data-test-subj="notebookEmptyTableText"]').contains('No notebooks'); cy.get('a[data-test-subj="notebookEmptyTableCreateBtn"]').contains('Create notebook'); - cy.get('button[data-test-subj="notebookEmptyTableAddSamplesBtn"]').contains('Add sample notebooks'); + cy.get('button[data-test-subj="notebookEmptyTableAddSamplesBtn"]').contains( + 'Add sample notebooks' + ); }); it('Displays error toast for invalid notebook name', () => { @@ -96,13 +100,9 @@ describe('Testing notebooks table', () => { cy.get('input.euiFieldSearch').focus().type('this notebook should not exist'); cy.get('.euiTableCellContent__text').contains('No items found').should('exist'); cy.get('.euiFormControlLayoutClearButton').click(); - cy.get('input.euiFieldSearch') - .focus() - .type(TEST_NOTEBOOK); + cy.get('input.euiFieldSearch').focus().type(TEST_NOTEBOOK); - cy.get('a.euiLink') - .contains(TEST_NOTEBOOK) - .should('exist'); + cy.get('a.euiLink').contains(TEST_NOTEBOOK).should('exist'); }); it('Notebooks table columns headers and pagination', () => { @@ -295,6 +295,24 @@ describe('Testing paragraphs', () => { }); }); + it('Adds an incorrect SQL query paragraph', () => { + cy.get('button[data-test-subj="AddParagraphButton"]').click(); + cy.get('button[data-test-subj="AddCodeBlockBtn"]').click(); + + cy.get('textarea[data-test-subj="editorArea-6"]').clear(); + cy.get('textarea[data-test-subj="editorArea-6"]').focus(); + cy.get('textarea[data-test-subj="editorArea-6"]').type(SQL_INCORRECT_QUERY_TEXT); + cy.get('button[data-test-subj="runRefreshBtn-6"]').click(); + + cy.get('textarea[data-test-subj="editorArea-6"]').should('exist'); + cy.get('div[id$="-error-0"]') + .should('exist') + .and('have.class', 'euiFormErrorText') + .and('contain.text', 'Invalid SQL query'); + + cy.get('.euiDataGrid__overflow').should('exist'); + }); + it('Adds an observability visualization paragraph', () => { cy.get('h3[data-test-subj="notebookTitle"]').contains(TEST_NOTEBOOK).should('exist'); cy.get('button[data-test-subj="notebook-paragraph-actions-button"]').click(); @@ -309,7 +327,9 @@ describe('Testing paragraphs', () => { cy.get('input[data-test-subj="comboBoxSearchInput"]') .focus() .type('[Logs] Count total requests by t'); - cy.get('.euiComboBoxOption__content').contains('[Logs] Count total requests by tags').click({ force: true }); + cy.get('.euiComboBoxOption__content') + .contains('[Logs] Count total requests by tags') + .click({ force: true }); cy.get('button[data-test-subj="runRefreshBtn-0"]').click(); cy.get('h5').contains('[Logs] Count total requests by tags').should('exist'); }); @@ -318,12 +338,12 @@ describe('Testing paragraphs', () => { cy.get('button[data-test-subj="AddParagraphButton"]').click(); cy.get('button[data-test-subj="AddCodeBlockBtn"]').click(); - cy.get('textarea[data-test-subj="editorArea-7"]').clear(); - cy.get('textarea[data-test-subj="editorArea-7"]').focus(); - cy.get('textarea[data-test-subj="editorArea-7"]').type(PPL_QUERY_TEXT); - cy.get('button[data-test-subj="runRefreshBtn-7"]').click(); + cy.get('textarea[data-test-subj="editorArea-8"]').clear(); + cy.get('textarea[data-test-subj="editorArea-8"]').focus(); + cy.get('textarea[data-test-subj="editorArea-8"]').type(PPL_QUERY_TEXT); + cy.get('button[data-test-subj="runRefreshBtn-8"]').click(); - cy.get('textarea[data-test-subj="editorArea-7"]').should('not.exist'); + cy.get('textarea[data-test-subj="editorArea-8"]').should('not.exist'); cy.get('div[data-test-subj="queryOutputText"]') .contains('source=opensearch_dashboards_sample_data_flights') .should('exist'); @@ -331,6 +351,24 @@ describe('Testing paragraphs', () => { cy.get('.euiDataGrid__overflow').should('exist'); }); + it('Adds an incorrect PPL query paragraph', () => { + cy.get('button[data-test-subj="AddParagraphButton"]').click(); + cy.get('button[data-test-subj="AddCodeBlockBtn"]').click(); + + cy.get('textarea[data-test-subj="editorArea-9"]').clear(); + cy.get('textarea[data-test-subj="editorArea-9"]').focus(); + cy.get('textarea[data-test-subj="editorArea-9"]').type(PPL_INCORRECT_QUERY_TEXT); + cy.get('button[data-test-subj="runRefreshBtn-9"]').click(); + + cy.get('textarea[data-test-subj="editorArea-9"]').should('exist'); + cy.get('div[id$="-error-0"]') + .should('exist') + .and('have.class', 'euiFormErrorText') + .and('contain.text', 'Error occurred in OpenSearch engine: no such index'); + + cy.get('.euiDataGrid__overflow').should('exist'); + }); + it('Clears outputs', () => { cy.get('h3[data-test-subj="notebookTitle"]').contains(TEST_NOTEBOOK).should('exist'); cy.get('.euiButton__text').contains('Clear all outputs').click(); diff --git a/.cypress/support/constants.js b/.cypress/support/constants.js index d7978c222..1001fd49d 100644 --- a/.cypress/support/constants.js +++ b/.cypress/support/constants.js @@ -7,4 +7,3 @@ export const ADMIN_AUTH = { username: 'admin', password: 'admin', }; - diff --git a/.cypress/utils/constants.js b/.cypress/utils/constants.js index e6f5f48a8..c1e211d44 100644 --- a/.cypress/utils/constants.js +++ b/.cypress/utils/constants.js @@ -74,7 +74,9 @@ export const setTimeFilter = (setEndTime = false, refresh = true) => { .focus() .type('{selectall}' + startTime, { force: true }); if (setEndTime) { - cy.get('button.euiDatePopoverButton--end[data-test-subj="superDatePickerendDatePopoverButton"]').click(); + cy.get( + 'button.euiDatePopoverButton--end[data-test-subj="superDatePickerendDatePopoverButton"]' + ).click(); cy.get('.euiTab__content').contains('Absolute').click(); cy.get('input[data-test-subj="superDatePickerAbsoluteDateInput"]') .focus() @@ -128,10 +130,17 @@ export const SQL_QUERY_TEXT = `%sql select * from opensearch_dashboards_sample_data_flights limit 20 {enter} `; +export const SQL_INCORRECT_QUERY_TEXT = `%sql +selectaaaaa * from opensearch_dashboards_sample_data_flights limit 20 {enter} +`; + export const PPL_QUERY_TEXT = `%ppl source=opensearch_dashboards_sample_data_flights {enter} `; +export const PPL_INCORRECT_QUERY_TEXT = `%ppl +source=opensearch_dashboards_sample_data_flights__ {enter} +`; export const suppressResizeObserverIssue = () => { // exception is thrown on loading EuiDataGrid in cypress only, ignore for now diff --git a/server/services/queryService.ts b/server/services/queryService.ts index 2c8a5d004..55e330252 100644 --- a/server/services/queryService.ts +++ b/server/services/queryService.ts @@ -51,7 +51,7 @@ export class QueryService { return { data: { ok: false, - resp: err.message, + resp: err.response, body: err.body, }, };