mirror of https://github.com/apache/druid.git
Fix web console query view crashing on simple query (#9897)
* only parse full queries * upgraded sql parser
This commit is contained in:
parent
b91d50044e
commit
63baa29ad1
|
@ -4707,7 +4707,7 @@ license_category: binary
|
|||
module: web-console
|
||||
license_name: Apache License version 2.0
|
||||
copyright: Imply Data
|
||||
version: 0.5.1
|
||||
version: 0.6.1
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -4243,9 +4243,9 @@
|
|||
}
|
||||
},
|
||||
"druid-query-toolkit": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.5.1.tgz",
|
||||
"integrity": "sha512-oI1YddnzIbkcelI93qaRtonu3PLGw65fDqLLK6e35gD4Ef/Yf8bOZvFK9wDYNAXcA6SDy7UDarfWsgD2dDWsjg==",
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.6.1.tgz",
|
||||
"integrity": "sha512-ykrWD9AbDQEvE55x8ST1kyiiGHSN8zhp/Lqe7z43/l7XG9QD7AQwfBzOn+HATXFynrOQN/3z3Cis70EzdDjc1g==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
"d3-axis": "^1.0.12",
|
||||
"d3-scale": "^3.2.0",
|
||||
"d3-selection": "^1.4.0",
|
||||
"druid-query-toolkit": "^0.5.1",
|
||||
"druid-query-toolkit": "^0.6.1",
|
||||
"file-saver": "^2.0.2",
|
||||
"has-own-prop": "^2.0.0",
|
||||
"hjson": "^3.2.1",
|
||||
|
|
|
@ -81,3 +81,85 @@ exports[`sql view matches snapshot 1`] = `
|
|||
</t>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`sql view matches snapshot with query 1`] = `
|
||||
<div
|
||||
className="query-view app-view"
|
||||
>
|
||||
<ColumnTree
|
||||
columnMetadataLoading={true}
|
||||
defaultSchema="druid"
|
||||
getParsedQuery={[Function]}
|
||||
onQueryStringChange={[Function]}
|
||||
/>
|
||||
<t
|
||||
customClassName=""
|
||||
onDragEnd={null}
|
||||
onDragStart={null}
|
||||
onSecondaryPaneSizeChange={[Function]}
|
||||
percentage={true}
|
||||
primaryIndex={0}
|
||||
primaryMinSize={30}
|
||||
secondaryInitialSize={60}
|
||||
secondaryMinSize={30}
|
||||
vertical={true}
|
||||
>
|
||||
<div
|
||||
className="control-pane"
|
||||
>
|
||||
<QueryInput
|
||||
currentSchema="druid"
|
||||
onQueryStringChange={[Function]}
|
||||
queryString="SELECT +3"
|
||||
runeMode={false}
|
||||
/>
|
||||
<div
|
||||
className="control-bar"
|
||||
>
|
||||
<HotkeysTarget(RunButton)
|
||||
loading={false}
|
||||
onEditContext={[Function]}
|
||||
onExplain={[Function]}
|
||||
onHistory={[Function]}
|
||||
onPrettier={[Function]}
|
||||
onQueryContextChange={[Function]}
|
||||
onRun={[Function]}
|
||||
queryContext={Object {}}
|
||||
runeMode={false}
|
||||
/>
|
||||
<Blueprint3.Tooltip
|
||||
content="Automatically run queries when modified via helper action menus."
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={800}
|
||||
transitionDuration={100}
|
||||
>
|
||||
<Blueprint3.Switch
|
||||
checked={true}
|
||||
className="auto-run"
|
||||
label="Auto run"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
</Blueprint3.Tooltip>
|
||||
<Blueprint3.Tooltip
|
||||
content="Automatically wrap the query with a limit to protect against queries with very large result sets."
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={800}
|
||||
transitionDuration={100}
|
||||
>
|
||||
<Blueprint3.Switch
|
||||
checked={true}
|
||||
className="smart-query-limit"
|
||||
label="Smart query limit"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
</Blueprint3.Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<Memo(QueryOutput)
|
||||
loading={false}
|
||||
onQueryChange={[Function]}
|
||||
runeMode={false}
|
||||
/>
|
||||
</t>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -17,21 +17,19 @@
|
|||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { sqlParserFactory } from 'druid-query-toolkit';
|
||||
import { parseSqlQuery } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { NumberMenuItems } from './number-menu-items';
|
||||
|
||||
describe('number menu', () => {
|
||||
const parser = sqlParserFactory(['COUNT']);
|
||||
|
||||
it('matches snapshot when menu is opened for column not inside group by', () => {
|
||||
const numberMenu = (
|
||||
<NumberMenuItems
|
||||
schema="schema"
|
||||
table="table"
|
||||
columnName={'added'}
|
||||
parsedQuery={parser(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
parsedQuery={parseSqlQuery(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
onQueryChange={() => {}}
|
||||
/>
|
||||
);
|
||||
|
@ -46,7 +44,7 @@ describe('number menu', () => {
|
|||
schema="schema"
|
||||
table="table"
|
||||
columnName={'added'}
|
||||
parsedQuery={parser(`SELECT added, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
parsedQuery={parseSqlQuery(`SELECT added, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
onQueryChange={() => {}}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -17,21 +17,19 @@
|
|||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { sqlParserFactory } from 'druid-query-toolkit';
|
||||
import { parseSqlQuery } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { StringMenuItems } from './string-menu-items';
|
||||
|
||||
describe('string menu', () => {
|
||||
const parser = sqlParserFactory(['COUNT']);
|
||||
|
||||
it('matches snapshot when menu is opened for column not inside group by', () => {
|
||||
const stringMenu = (
|
||||
<StringMenuItems
|
||||
table={'table'}
|
||||
schema={'schema'}
|
||||
columnName={'cityName'}
|
||||
parsedQuery={parser(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
parsedQuery={parseSqlQuery(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
onQueryChange={() => {}}
|
||||
/>
|
||||
);
|
||||
|
@ -46,7 +44,7 @@ describe('string menu', () => {
|
|||
table={'table'}
|
||||
schema={'schema'}
|
||||
columnName={'channel'}
|
||||
parsedQuery={parser(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
parsedQuery={parseSqlQuery(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
onQueryChange={() => {}}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -17,21 +17,19 @@
|
|||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { sqlParserFactory } from 'druid-query-toolkit';
|
||||
import { parseSqlQuery } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { TimeMenuItems } from './time-menu-items';
|
||||
|
||||
describe('time menu', () => {
|
||||
const parser = sqlParserFactory(['COUNT']);
|
||||
|
||||
it('matches snapshot when menu is opened for column not inside group by', () => {
|
||||
const timeMenu = (
|
||||
<TimeMenuItems
|
||||
table={'table'}
|
||||
schema={'schema'}
|
||||
columnName={'__time'}
|
||||
parsedQuery={parser(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
parsedQuery={parseSqlQuery(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
onQueryChange={() => {}}
|
||||
/>
|
||||
);
|
||||
|
@ -46,7 +44,7 @@ describe('time menu', () => {
|
|||
table={'table'}
|
||||
schema={'schema'}
|
||||
columnName={'__time'}
|
||||
parsedQuery={parser(`SELECT __time, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
parsedQuery={parseSqlQuery(`SELECT __time, count(*) as cnt FROM wikipedia GROUP BY 1`)}
|
||||
onQueryChange={() => {}}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { sqlParserFactory } from 'druid-query-toolkit';
|
||||
import { parseSqlQuery } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { ColumnMetadata } from '../../../utils/column-metadata';
|
||||
|
@ -25,13 +25,11 @@ import { ColumnMetadata } from '../../../utils/column-metadata';
|
|||
import { ColumnTree } from './column-tree';
|
||||
|
||||
describe('column tree', () => {
|
||||
const parser = sqlParserFactory(['COUNT']);
|
||||
|
||||
it('matches snapshot', () => {
|
||||
const columnTree = (
|
||||
<ColumnTree
|
||||
getParsedQuery={() => {
|
||||
return parser(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`);
|
||||
return parseSqlQuery(`SELECT channel, count(*) as cnt FROM wikipedia GROUP BY 1`);
|
||||
}}
|
||||
defaultSchema="druid"
|
||||
defaultTable="wikipedia"
|
||||
|
|
|
@ -17,18 +17,14 @@
|
|||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { sqlParserFactory } from 'druid-query-toolkit';
|
||||
import { parseSqlQuery } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { SQL_FUNCTIONS } from '../../../../lib/sql-docs';
|
||||
|
||||
import { QueryOutput } from './query-output';
|
||||
|
||||
describe('query output', () => {
|
||||
it('matches snapshot', () => {
|
||||
const parser = sqlParserFactory(SQL_FUNCTIONS.map(sqlFunction => sqlFunction.name));
|
||||
|
||||
const parsedQuery = parser(`SELECT
|
||||
const parsedQuery = parseSqlQuery(`SELECT
|
||||
"language",
|
||||
COUNT(*) AS "Count", COUNT(DISTINCT "language") AS "dist_language", COUNT(*) FILTER (WHERE "language"= 'xxx') AS "language_filtered_count"
|
||||
FROM "github"
|
||||
|
|
|
@ -27,6 +27,11 @@ describe('sql view', () => {
|
|||
expect(sqlView).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('matches snapshot with query', () => {
|
||||
const sqlView = shallow(<QueryView initQuery={'SELECT +3'} />);
|
||||
expect(sqlView).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('trimSemicolon', () => {
|
||||
expect(QueryView.trimSemicolon('SELECT * FROM tbl;')).toEqual('SELECT * FROM tbl');
|
||||
expect(QueryView.trimSemicolon('SELECT * FROM tbl; ')).toEqual('SELECT * FROM tbl ');
|
||||
|
|
|
@ -23,8 +23,8 @@ import {
|
|||
HeaderRows,
|
||||
isFirstRowHeader,
|
||||
normalizeQueryResult,
|
||||
parseSqlQuery,
|
||||
shouldIncludeTimestamp,
|
||||
sqlParserFactory,
|
||||
SqlQuery,
|
||||
} from 'druid-query-toolkit';
|
||||
import Hjson from 'hjson';
|
||||
|
@ -32,7 +32,6 @@ import memoizeOne from 'memoize-one';
|
|||
import React from 'react';
|
||||
import SplitterLayout from 'react-splitter-layout';
|
||||
|
||||
import { SQL_FUNCTIONS } from '../../../lib/sql-docs';
|
||||
import { QueryPlanDialog } from '../../dialogs';
|
||||
import { EditContextDialog } from '../../dialogs/edit-context-dialog/edit-context-dialog';
|
||||
import { QueryHistoryDialog } from '../../dialogs/query-history-dialog/query-history-dialog';
|
||||
|
@ -63,11 +62,9 @@ import { RunButton } from './run-button/run-button';
|
|||
|
||||
import './query-view.scss';
|
||||
|
||||
const parserRaw = sqlParserFactory(SQL_FUNCTIONS.map(sqlFunction => sqlFunction.name));
|
||||
|
||||
const parser = memoizeOne((sql: string) => {
|
||||
const parser = memoizeOne((sql: string): SqlQuery | undefined => {
|
||||
try {
|
||||
return parserRaw(sql);
|
||||
return parseSqlQuery(sql);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
@ -87,7 +84,7 @@ export interface QueryViewProps {
|
|||
|
||||
export interface QueryViewState {
|
||||
queryString: string;
|
||||
parsedQuery: SqlQuery;
|
||||
parsedQuery?: SqlQuery;
|
||||
queryContext: QueryContext;
|
||||
wrapQueryLimit: number | undefined;
|
||||
autoRun: boolean;
|
||||
|
@ -479,18 +476,22 @@ export class QueryView extends React.PureComponent<QueryViewProps, QueryViewStat
|
|||
const { queryString, queryContext, loading, result, error, columnMetadata } = this.state;
|
||||
const emptyQuery = QueryView.isEmptyQuery(queryString);
|
||||
|
||||
let currentSchema;
|
||||
let currentTable;
|
||||
let currentSchema: string | undefined;
|
||||
let currentTable: string | undefined;
|
||||
|
||||
if (result && result.parsedQuery instanceof SqlQuery) {
|
||||
if (result && result.parsedQuery) {
|
||||
currentSchema = result.parsedQuery.getSchema();
|
||||
currentTable = result.parsedQuery.getTableName();
|
||||
} else if (localStorageGet(LocalStorageKeys.QUERY_KEY)) {
|
||||
const defaultQueryString = localStorageGet(LocalStorageKeys.QUERY_KEY);
|
||||
const tempAst = defaultQueryString ? parser(defaultQueryString) : undefined;
|
||||
if (tempAst) {
|
||||
currentSchema = tempAst.getSchema();
|
||||
currentTable = tempAst.getTableName();
|
||||
|
||||
const defaultQueryAst: SqlQuery | undefined = defaultQueryString
|
||||
? parser(defaultQueryString)
|
||||
: undefined;
|
||||
|
||||
if (defaultQueryAst) {
|
||||
currentSchema = defaultQueryAst.getSchema();
|
||||
currentTable = defaultQueryAst.getTableName();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue