diff --git a/web-console/src/views/query-view/__snapshots__/query-view.spec.tsx.snap b/web-console/src/views/query-view/__snapshots__/query-view.spec.tsx.snap index d5139b40d73..22338e01b92 100644 --- a/web-console/src/views/query-view/__snapshots__/query-view.spec.tsx.snap +++ b/web-console/src/views/query-view/__snapshots__/query-view.spec.tsx.snap @@ -49,6 +49,8 @@ exports[`sql view matches snapshot 1`] = ` queryContext={Object {}} runeMode={false} setAutoRun={[Function]} + setWrapQuery={[Function]} + wrapQuery={true} /> diff --git a/web-console/src/views/query-view/column-tree/column-tree.tsx b/web-console/src/views/query-view/column-tree/column-tree.tsx index 0a491b0f1b5..08e2f7c4b98 100644 --- a/web-console/src/views/query-view/column-tree/column-tree.tsx +++ b/web-console/src/views/query-view/column-tree/column-tree.tsx @@ -45,7 +45,7 @@ import './column-tree.scss'; function handleTableClick( tableSchema: string, nodeData: ITreeNode, - onQueryStringChange: (queryString: string) => void, + onQueryStringChange: (queryString: string, run: boolean) => void, ): void { let columns: string[]; if (nodeData.childNodes) { @@ -54,12 +54,18 @@ function handleTableClick( columns = ['*']; } if (tableSchema === 'druid') { - onQueryStringChange(`SELECT ${columns.join(', ')} + onQueryStringChange( + `SELECT ${columns.join(', ')} FROM ${escapeSqlIdentifier(String(nodeData.label))} -WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY`); +WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY`, + true, + ); } else { - onQueryStringChange(`SELECT ${columns.join(', ')} -FROM ${tableSchema}.${nodeData.label}`); + onQueryStringChange( + `SELECT ${columns.join(', ')} +FROM ${tableSchema}.${nodeData.label}`, + true, + ); } } @@ -67,40 +73,49 @@ function handleColumnClick( columnSchema: string, columnTable: string, nodeData: ITreeNode, - onQueryStringChange: (queryString: string) => void, + onQueryStringChange: (queryString: string, run: boolean) => void, ): void { if (columnSchema === 'druid') { if (nodeData.icon === IconNames.TIME) { - onQueryStringChange(`SELECT + onQueryStringChange( + `SELECT TIME_FLOOR(${escapeSqlIdentifier(String(nodeData.label))}, 'PT1H') AS "Time", COUNT(*) AS "Count" FROM ${escapeSqlIdentifier(columnTable)} WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY GROUP BY 1 -ORDER BY "Time" ASC`); +ORDER BY "Time" ASC`, + true, + ); } else { - onQueryStringChange(`SELECT + onQueryStringChange( + `SELECT "${nodeData.label}", COUNT(*) AS "Count" FROM ${escapeSqlIdentifier(columnTable)} WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY GROUP BY 1 -ORDER BY "Count" DESC`); +ORDER BY "Count" DESC`, + true, + ); } } else { - onQueryStringChange(`SELECT + onQueryStringChange( + `SELECT ${escapeSqlIdentifier(String(nodeData.label))}, COUNT(*) AS "Count" FROM ${columnSchema}.${columnTable} GROUP BY 1 -ORDER BY "Count" DESC`); +ORDER BY "Count" DESC`, + true, + ); } } export interface ColumnTreeProps { columnMetadataLoading: boolean; columnMetadata?: ColumnMetadata[]; - onQueryStringChange: (queryString: string) => void; + onQueryStringChange: (queryString: string, run: boolean) => void; defaultSchema?: string; defaultTable?: string; addFunctionToGroupBy: ( diff --git a/web-console/src/views/query-view/query-input/query-input.tsx b/web-console/src/views/query-view/query-input/query-input.tsx index 0970888cac8..4e761b1d37c 100644 --- a/web-console/src/views/query-view/query-input/query-input.tsx +++ b/web-console/src/views/query-view/query-input/query-input.tsx @@ -173,8 +173,14 @@ export class QueryInput extends React.PureComponent { + // This gets the event as a second arg + const { onQueryStringChange } = this.props; + onQueryStringChange(value); + }; + render(): JSX.Element { - const { queryString, runeMode, onQueryStringChange } = this.props; + const { queryString, runeMode } = this.props; const { editorHeight } = this.state; // Set the key in the AceEditor to force a rebind and prevent an error that happens otherwise @@ -186,7 +192,7 @@ export class QueryInput extends React.PureComponent { interface QueryWithContext { queryString: string; queryContext: QueryContext; - wrapQuery?: boolean; + wrapQuery: boolean; } export interface QueryViewProps { @@ -103,6 +103,8 @@ export interface QueryViewState { queryString: string; queryAst: SqlQuery; queryContext: QueryContext; + wrapQuery: boolean; + autoRun: boolean; columnMetadataLoading: boolean; columnMetadata?: ColumnMetadata[]; @@ -123,8 +125,6 @@ export interface QueryViewState { editContextDialogOpen: boolean; historyDialogOpen: boolean; queryHistory: QueryRecord[]; - - autoRun: boolean; } interface QueryResult { @@ -139,6 +139,22 @@ export class QueryView extends React.PureComponent { return await queryDruidSql({ @@ -244,8 +281,8 @@ export class QueryView extends React.PureComponent { - const { queryString, queryContext } = queryWithContext; + const { queryString, queryContext, wrapQuery } = queryWithContext; + + const actualQuery = wrapQuery + ? QueryView.wrapInLimitIfNeeded(queryString) + : QueryView.trimSemicolon(queryString); + const explainPayload: Record = { - query: `EXPLAIN PLAN FOR (${QueryView.trimSemicolon(queryString)}\n)`, + query: QueryView.wrapInExplainIfNeeded(actualQuery), resultFormat: 'object', }; @@ -337,28 +379,6 @@ export class QueryView extends React.PureComponent this.setAutoRun(autoRun)} + setAutoRun={this.setAutoRun} + wrapQuery={wrapQuery} + setWrapQuery={this.setWrapQuery} onEditContext={() => this.setState({ editContextDialogOpen: true })} runeMode={runeMode} queryContext={queryContext} @@ -515,31 +539,17 @@ export class QueryView extends React.PureComponent { - const { autoRun, queryAst } = this.state; + const { queryAst } = this.state; if (!queryAst) return; - const groupedAst = queryAst.addFunctionToGroupBy(functionName, spacing, argumentsArray, alias); - const queryString = groupedAst.toString(); - this.setState({ - queryString, - queryAst: parser(queryString), - }); - if (autoRun && preferablyRun) { - this.handleRun(true, queryString); - } + const modifiedAst = queryAst.addFunctionToGroupBy(functionName, spacing, argumentsArray, alias); + this.handleQueryStringChange(modifiedAst.toString(), preferablyRun); }; private addToGroupBy = (columnName: string, preferablyRun: boolean): void => { - const { autoRun, queryAst } = this.state; + const { queryAst } = this.state; if (!queryAst) return; - const groupedAst = queryAst.addToGroupBy(columnName); - const queryString = groupedAst.toString(); - this.setState({ - queryString, - queryAst: parser(queryString), - }); - if (autoRun && preferablyRun) { - this.handleRun(true, queryString); - } + const modifiedAst = queryAst.addToGroupBy(columnName); + this.handleQueryStringChange(modifiedAst.toString(), preferablyRun); }; private addAggregateColumn = ( @@ -550,7 +560,7 @@ export class QueryView extends React.PureComponent { - const { autoRun, queryAst } = this.state; + const { queryAst } = this.state; if (!queryAst) return; const modifiedAst = queryAst.addAggregateColumn( columnName, @@ -559,14 +569,7 @@ export class QueryView extends React.PureComponent { - const { autoRun, queryAst } = this.state; + const { queryAst } = this.state; if (!queryAst) return; const modifiedAst = queryAst.orderBy(header, direction); - const queryString = modifiedAst.toString(); - this.setState({ - queryString, - queryAst: parser(queryString), - }); - if (autoRun && preferablyRun) { - this.handleRun(true, queryString); - } + this.handleQueryStringChange(modifiedAst.toString(), preferablyRun); }; private sqlExcludeColumn = (header: string, preferablyRun: boolean): void => { - const { autoRun, queryAst } = this.state; + const { queryAst } = this.state; if (!queryAst) return; const modifiedAst = queryAst.excludeColumn(header); - const queryString = modifiedAst.toString(); - this.setState({ - queryString, - queryAst: parser(queryString), - }); - if (autoRun && preferablyRun) { - this.handleRun(true, queryString); - } + this.handleQueryStringChange(modifiedAst.toString(), preferablyRun); }; private sqlFilterRow = (filters: RowFilter[], preferablyRun: boolean): void => { - const { autoRun, queryAst } = this.state; + const { queryAst } = this.state; if (!queryAst) return; let modifiedAst: SqlQuery = queryAst; @@ -611,14 +600,7 @@ export class QueryView extends React.PureComponent { @@ -630,8 +612,11 @@ export class QueryView extends React.PureComponent { - this.setState({ queryString, queryAst: parser(queryString) }); + private handleQueryStringChange = (queryString: string, preferablyRun?: boolean): void => { + this.setState({ queryString, queryAst: parser(queryString) }, () => { + const { autoRun } = this.state; + if (preferablyRun && autoRun) this.handleRun(); + }); }; private handleQueryContextChange = (queryContext: QueryContext) => { @@ -643,18 +628,19 @@ export class QueryView extends React.PureComponent { - const { queryString, queryContext, queryHistory } = this.state; - if (!customQueryString) { - customQueryString = queryString; - } + private setWrapQuery = (wrapQuery: boolean) => { + this.setState({ wrapQuery }); + }; + + private handleRun = () => { + const { queryString, queryContext, wrapQuery, queryHistory } = this.state; while (queryHistory.length > 9) { queryHistory.pop(); } queryHistory.unshift({ version: `${new Date().toISOString()}`, - queryString: customQueryString, + queryString, }); let queryHistoryString; try { @@ -664,16 +650,17 @@ export class QueryView extends React.PureComponent { - const { queryString, queryContext } = this.state; + const { queryString, queryContext, wrapQuery } = this.state; + this.setState({ explainDialogOpen: true }); - this.explainQueryManager.runQuery({ queryString, queryContext }); + this.explainQueryManager.runQuery({ queryString, queryContext, wrapQuery }); }; private handleSecondaryPaneSizeChange = (secondaryPaneSize: number) => { @@ -702,24 +689,13 @@ export class QueryView extends React.PureComponent { - const { autoRun } = this.state; - - this.handleQueryStringChange(queryString); - if (autoRun) { - this.handleRun(true, queryString); - } - }; - render(): JSX.Element { const { columnMetadata, columnMetadataLoading, columnMetadataError, queryAst } = this.state; let defaultSchema; - if (queryAst && queryAst instanceof SqlQuery) { - defaultSchema = queryAst.getSchema(); - } let defaultTable; - if (queryAst && queryAst instanceof SqlQuery) { + if (queryAst instanceof SqlQuery) { + defaultSchema = queryAst.getSchema(); defaultTable = queryAst.getTableName(); } @@ -738,7 +714,7 @@ export class QueryView extends React.PureComponent diff --git a/web-console/src/views/query-view/run-button/run-button.spec.tsx b/web-console/src/views/query-view/run-button/run-button.spec.tsx index d61e5f77587..46cf63a0553 100644 --- a/web-console/src/views/query-view/run-button/run-button.spec.tsx +++ b/web-console/src/views/query-view/run-button/run-button.spec.tsx @@ -26,7 +26,9 @@ describe('run button', () => { const runButton = ( null} + setAutoRun={() => {}} + wrapQuery + setWrapQuery={() => {}} onHistory={() => null} onEditContext={() => null} runeMode={false} diff --git a/web-console/src/views/query-view/run-button/run-button.tsx b/web-console/src/views/query-view/run-button/run-button.tsx index 276288ba3fb..4064ef50ab4 100644 --- a/web-console/src/views/query-view/run-button/run-button.tsx +++ b/web-console/src/views/query-view/run-button/run-button.tsx @@ -46,21 +46,19 @@ import { DRUID_DOCS_RUNE, DRUID_DOCS_SQL } from '../../../variables'; export interface RunButtonProps { runeMode: boolean; autoRun: boolean; + setAutoRun: (autoRun: boolean) => void; + wrapQuery: boolean; + setWrapQuery: (wrapQuery: boolean) => void; queryContext: QueryContext; onQueryContextChange: (newQueryContext: QueryContext) => void; - onRun: (wrapQuery: boolean) => void; + onRun: () => void; onExplain: () => void; onEditContext: () => void; onHistory: () => void; - setAutoRun: (autoRun: boolean) => void; -} - -interface RunButtonState { - wrapQuery: boolean; } @HotkeysTarget -export class RunButton extends React.PureComponent { +export class RunButton extends React.PureComponent { constructor(props: RunButtonProps, context: any) { super(props, context); this.state = { @@ -85,7 +83,7 @@ export class RunButton extends React.PureComponent { const { onRun } = this.props; if (!onRun) return; - onRun(this.state.wrapQuery); + onRun(); }; renderExtraMenu() { @@ -96,10 +94,11 @@ export class RunButton extends React.PureComponent this.setState({ wrapQuery: !wrapQuery })} + onChange={() => setWrapQuery(!wrapQuery)} />