mirror of https://github.com/apache/druid.git
Add time taken by last query in SQL view (#7421)
* Add time taken by query * Fix time to 2 dp; set state in on state change; hide time taken at first * Refactored code: defined query result interface; more concise shorthand expression * Use single quote
This commit is contained in:
parent
bbb620125d
commit
4ea37e2614
|
@ -28,11 +28,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
button{
|
button{
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.query-elapsed {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ export interface SqlControlProps extends React.Props<any> {
|
||||||
initSql: string | null;
|
initSql: string | null;
|
||||||
onRun: (query: string) => void;
|
onRun: (query: string) => void;
|
||||||
onExplain: (query: string) => void;
|
onExplain: (query: string) => void;
|
||||||
|
queryElapsed: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SqlControlState {
|
export interface SqlControlState {
|
||||||
|
@ -166,7 +167,7 @@ export class SqlControl extends React.Component<SqlControlProps, SqlControlState
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { onRun, onExplain } = this.props;
|
const { onRun, onExplain, queryElapsed } = this.props;
|
||||||
const { query, autoCompleteOn } = this.state;
|
const { query, autoCompleteOn } = this.state;
|
||||||
|
|
||||||
const isRune = query.trim().startsWith('{');
|
const isRune = query.trim().startsWith('{');
|
||||||
|
@ -217,7 +218,11 @@ export class SqlControl extends React.Component<SqlControlProps, SqlControlState
|
||||||
<Button rightIcon={IconNames.CARET_RIGHT} onClick={() => onRun(query)}>
|
<Button rightIcon={IconNames.CARET_RIGHT} onClick={() => onRun(query)}>
|
||||||
{isRune ? 'Rune' : 'Run'}
|
{isRune ? 'Rune' : 'Run'}
|
||||||
</Button>
|
</Button>
|
||||||
{!isRune ? SqlControlPopover : null}
|
{!isRune && SqlControlPopover}
|
||||||
|
{
|
||||||
|
queryElapsed &&
|
||||||
|
<span className={'query-elapsed'}> Last query took {(queryElapsed / 1000).toFixed(2)} seconds</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@ import {
|
||||||
localStorageGet, LocalStorageKeys,
|
localStorageGet, LocalStorageKeys,
|
||||||
localStorageSet, parseQueryPlan,
|
localStorageSet, parseQueryPlan,
|
||||||
queryDruidRune,
|
queryDruidRune,
|
||||||
queryDruidSql, QueryManager, SemiJoinQueryExplanation
|
queryDruidSql, QueryManager,
|
||||||
|
SemiJoinQueryExplanation
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
import './sql-view.scss';
|
import './sql-view.scss';
|
||||||
|
@ -46,11 +47,17 @@ export interface SqlViewState {
|
||||||
explainResult: BasicQueryExplanation | SemiJoinQueryExplanation | string | null;
|
explainResult: BasicQueryExplanation | SemiJoinQueryExplanation | string | null;
|
||||||
loadingExplain: boolean;
|
loadingExplain: boolean;
|
||||||
explainError: Error | null;
|
explainError: Error | null;
|
||||||
|
queryElapsed: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SqlQueryResult {
|
||||||
|
queryResult: HeaderRows;
|
||||||
|
queryElapsed: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SqlView extends React.Component<SqlViewProps, SqlViewState> {
|
export class SqlView extends React.Component<SqlViewProps, SqlViewState> {
|
||||||
|
|
||||||
private sqlQueryManager: QueryManager<string, HeaderRows>;
|
private sqlQueryManager: QueryManager<string, SqlQueryResult>;
|
||||||
private explainQueryManager: QueryManager<string, any>;
|
private explainQueryManager: QueryManager<string, any>;
|
||||||
|
|
||||||
constructor(props: SqlViewProps, context: any) {
|
constructor(props: SqlViewProps, context: any) {
|
||||||
|
@ -62,34 +69,42 @@ export class SqlView extends React.Component<SqlViewProps, SqlViewState> {
|
||||||
explainDialogOpen: false,
|
explainDialogOpen: false,
|
||||||
loadingExplain: false,
|
loadingExplain: false,
|
||||||
explainResult: null,
|
explainResult: null,
|
||||||
explainError: null
|
explainError: null,
|
||||||
|
queryElapsed: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
this.sqlQueryManager = new QueryManager({
|
this.sqlQueryManager = new QueryManager({
|
||||||
processQuery: async (query: string) => {
|
processQuery: async (query: string) => {
|
||||||
|
const startTime = new Date();
|
||||||
if (query.trim().startsWith('{')) {
|
if (query.trim().startsWith('{')) {
|
||||||
// Secret way to issue a native JSON "rune" query
|
// Secret way to issue a native JSON "rune" query
|
||||||
const runeQuery = Hjson.parse(query);
|
const runeQuery = Hjson.parse(query);
|
||||||
return decodeRune(runeQuery, await queryDruidRune(runeQuery));
|
const result = await queryDruidRune(runeQuery);
|
||||||
|
return {
|
||||||
|
queryResult: decodeRune(runeQuery, result),
|
||||||
|
queryElapsed: new Date().valueOf() - startTime.valueOf()
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
const result = await queryDruidSql({
|
const result = await queryDruidSql({
|
||||||
query,
|
query,
|
||||||
resultFormat: 'array',
|
resultFormat: 'array',
|
||||||
header: true
|
header: true
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
header: (result && result.length) ? result[0] : [],
|
queryResult: {
|
||||||
rows: (result && result.length) ? result.slice(1) : []
|
header: (result && result.length) ? result[0] : [],
|
||||||
|
rows: (result && result.length) ? result.slice(1) : []
|
||||||
|
},
|
||||||
|
queryElapsed: new Date().valueOf() - startTime.valueOf()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onStateChange: ({ result, loading, error }) => {
|
onStateChange: ({ result, loading, error }) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
result,
|
result: result ? result.queryResult : null,
|
||||||
|
queryElapsed: result ? result.queryElapsed : null,
|
||||||
loading,
|
loading,
|
||||||
error
|
error
|
||||||
});
|
});
|
||||||
|
@ -158,6 +173,7 @@ export class SqlView extends React.Component<SqlViewProps, SqlViewState> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { initSql } = this.props;
|
const { initSql } = this.props;
|
||||||
|
const { queryElapsed } = this.state;
|
||||||
|
|
||||||
return <div className="sql-view app-view">
|
return <div className="sql-view app-view">
|
||||||
<SqlControl
|
<SqlControl
|
||||||
|
@ -167,6 +183,7 @@ export class SqlView extends React.Component<SqlViewProps, SqlViewState> {
|
||||||
this.sqlQueryManager.runQuery(q);
|
this.sqlQueryManager.runQuery(q);
|
||||||
}}
|
}}
|
||||||
onExplain={(q: string) => this.getExplain(q)}
|
onExplain={(q: string) => this.getExplain(q)}
|
||||||
|
queryElapsed={queryElapsed}
|
||||||
/>
|
/>
|
||||||
{this.renderResultTable()}
|
{this.renderResultTable()}
|
||||||
{this.renderExplainDialog()}
|
{this.renderExplainDialog()}
|
||||||
|
|
Loading…
Reference in New Issue