mirror of
https://github.com/apache/druid.git
synced 2025-02-17 07:25:02 +00:00
Web-console: gate auto complete on current table and schema (#8322)
* gate auto complete on current table and schema * reset defaults * add static functions * move completions to state
This commit is contained in:
parent
31af4eb9ad
commit
cae1361c32
@ -32,6 +32,7 @@ exports[`sql view matches snapshot 1`] = `
|
|||||||
className="control-pane"
|
className="control-pane"
|
||||||
>
|
>
|
||||||
<QueryInput
|
<QueryInput
|
||||||
|
currentSchema="druid"
|
||||||
onQueryStringChange={[Function]}
|
onQueryStringChange={[Function]}
|
||||||
queryString="test"
|
queryString="test"
|
||||||
runeMode={false}
|
runeMode={false}
|
||||||
|
@ -25,7 +25,6 @@ import AceEditor from 'react-ace';
|
|||||||
import { SQL_DATE_TYPES, SQL_FUNCTIONS, SyntaxDescription } from '../../../../lib/sql-function-doc';
|
import { SQL_DATE_TYPES, SQL_FUNCTIONS, SyntaxDescription } from '../../../../lib/sql-function-doc';
|
||||||
import { uniq } from '../../../utils';
|
import { uniq } from '../../../utils';
|
||||||
import { ColumnMetadata } from '../../../utils/column-metadata';
|
import { ColumnMetadata } from '../../../utils/column-metadata';
|
||||||
import { ColumnTreeProps, ColumnTreeState } from '../column-tree/column-tree';
|
|
||||||
|
|
||||||
import { SQL_CONSTANTS, SQL_DYNAMICS, SQL_EXPRESSION_PARTS, SQL_KEYWORDS } from './keywords';
|
import { SQL_CONSTANTS, SQL_DYNAMICS, SQL_EXPRESSION_PARTS, SQL_KEYWORDS } from './keywords';
|
||||||
|
|
||||||
@ -38,59 +37,22 @@ export interface QueryInputProps {
|
|||||||
onQueryStringChange: (newQueryString: string) => void;
|
onQueryStringChange: (newQueryString: string) => void;
|
||||||
runeMode: boolean;
|
runeMode: boolean;
|
||||||
columnMetadata?: ColumnMetadata[];
|
columnMetadata?: ColumnMetadata[];
|
||||||
|
currentSchema?: string;
|
||||||
|
currentTable?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueryInputState {
|
export interface QueryInputState {
|
||||||
// For reasons (https://github.com/securingsincity/react-ace/issues/415) react ace editor needs an explicit height
|
// For reasons (https://github.com/securingsincity/react-ace/issues/415) react ace editor needs an explicit height
|
||||||
// Since this component will grown and shrink dynamically we will measure its height and then set it.
|
// Since this component will grown and shrink dynamically we will measure its height and then set it.
|
||||||
editorHeight: number;
|
editorHeight: number;
|
||||||
|
completions: any[];
|
||||||
prevColumnMetadata?: ColumnMetadata[];
|
prevColumnMetadata?: ColumnMetadata[];
|
||||||
|
prevCurrentTable?: string;
|
||||||
|
prevCurrentSchema?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class QueryInput extends React.PureComponent<QueryInputProps, QueryInputState> {
|
export class QueryInput extends React.PureComponent<QueryInputProps, QueryInputState> {
|
||||||
static getDerivedStateFromProps(props: ColumnTreeProps, state: ColumnTreeState) {
|
static replaceDefaultAutoCompleter(): void {
|
||||||
const { columnMetadata } = props;
|
|
||||||
|
|
||||||
if (columnMetadata && columnMetadata !== state.prevColumnMetadata) {
|
|
||||||
const completions = ([] as any[]).concat(
|
|
||||||
uniq(columnMetadata.map(d => d.TABLE_SCHEMA)).map(v => ({
|
|
||||||
value: v,
|
|
||||||
score: 10,
|
|
||||||
meta: 'schema',
|
|
||||||
})),
|
|
||||||
uniq(columnMetadata.map(d => d.TABLE_NAME)).map(v => ({
|
|
||||||
value: v,
|
|
||||||
score: 49,
|
|
||||||
meta: 'datasource',
|
|
||||||
})),
|
|
||||||
uniq(columnMetadata.map(d => d.COLUMN_NAME)).map(v => ({
|
|
||||||
value: v,
|
|
||||||
score: 50,
|
|
||||||
meta: 'column',
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
langTools.addCompleter({
|
|
||||||
getCompletions: (_editor: any, _session: any, _pos: any, _prefix: any, callback: any) => {
|
|
||||||
callback(null, completions);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
prevColumnMetadata: columnMetadata,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props: QueryInputProps, context: any) {
|
|
||||||
super(props, context);
|
|
||||||
this.state = {
|
|
||||||
editorHeight: 200,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private replaceDefaultAutoCompleter = () => {
|
|
||||||
if (!langTools) return;
|
if (!langTools) return;
|
||||||
|
|
||||||
const keywordList = ([] as any[]).concat(
|
const keywordList = ([] as any[]).concat(
|
||||||
@ -112,9 +74,9 @@ export class QueryInput extends React.PureComponent<QueryInputProps, QueryInputS
|
|||||||
langTools.textCompleter,
|
langTools.textCompleter,
|
||||||
keywordCompleter,
|
keywordCompleter,
|
||||||
]);
|
]);
|
||||||
};
|
}
|
||||||
|
|
||||||
private addFunctionAutoCompleter = (): void => {
|
static addFunctionAutoCompleter(): void {
|
||||||
if (!langTools) return;
|
if (!langTools) return;
|
||||||
|
|
||||||
const functionList: any[] = SQL_FUNCTIONS.map((entry: SyntaxDescription) => {
|
const functionList: any[] = SQL_FUNCTIONS.map((entry: SyntaxDescription) => {
|
||||||
@ -161,11 +123,75 @@ export class QueryInput extends React.PureComponent<QueryInputProps, QueryInputS
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromProps(props: QueryInputProps, state: QueryInputState) {
|
||||||
|
const { columnMetadata, currentSchema, currentTable } = props;
|
||||||
|
|
||||||
|
if (
|
||||||
|
columnMetadata &&
|
||||||
|
(columnMetadata !== state.prevColumnMetadata ||
|
||||||
|
currentSchema !== state.prevCurrentSchema ||
|
||||||
|
currentTable !== state.prevCurrentTable)
|
||||||
|
) {
|
||||||
|
const completions = ([] as any[]).concat(
|
||||||
|
uniq(columnMetadata.map(d => d.TABLE_SCHEMA)).map(v => ({
|
||||||
|
value: v,
|
||||||
|
score: 10,
|
||||||
|
meta: 'schema',
|
||||||
|
})),
|
||||||
|
uniq(
|
||||||
|
columnMetadata
|
||||||
|
.filter(d => (currentSchema ? d.TABLE_SCHEMA === currentSchema : true))
|
||||||
|
.map(d => d.TABLE_NAME),
|
||||||
|
).map(v => ({
|
||||||
|
value: v,
|
||||||
|
score: 49,
|
||||||
|
meta: 'datasource',
|
||||||
|
})),
|
||||||
|
uniq(
|
||||||
|
columnMetadata
|
||||||
|
.filter(d =>
|
||||||
|
currentTable && currentSchema
|
||||||
|
? d.TABLE_NAME === currentTable && d.TABLE_SCHEMA === currentSchema
|
||||||
|
: true,
|
||||||
|
)
|
||||||
|
.map(d => d.COLUMN_NAME),
|
||||||
|
).map(v => ({
|
||||||
|
value: v,
|
||||||
|
score: 50,
|
||||||
|
meta: 'column',
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
completions,
|
||||||
|
prevColumnMetadata: columnMetadata,
|
||||||
|
prevCurrentSchema: currentSchema,
|
||||||
|
prevCurrentTable: currentTable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props: QueryInputProps, context: any) {
|
||||||
|
super(props, context);
|
||||||
|
this.state = {
|
||||||
|
editorHeight: 200,
|
||||||
|
completions: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
this.replaceDefaultAutoCompleter();
|
QueryInput.replaceDefaultAutoCompleter();
|
||||||
this.addFunctionAutoCompleter();
|
QueryInput.addFunctionAutoCompleter();
|
||||||
|
if (langTools) {
|
||||||
|
langTools.addCompleter({
|
||||||
|
getCompletions: (_editor: any, _session: any, _pos: any, _prefix: any, callback: any) => {
|
||||||
|
callback(null, this.state.completions);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleAceContainerResize = (entries: IResizeEntry[]) => {
|
private handleAceContainerResize = (entries: IResizeEntry[]) => {
|
||||||
|
@ -477,6 +477,21 @@ export class QueryView extends React.PureComponent<QueryViewProps, QueryViewStat
|
|||||||
wrapQuery,
|
wrapQuery,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
|
let currentSchema;
|
||||||
|
let currentTable;
|
||||||
|
|
||||||
|
if (result && result.parsedQuery instanceof SqlQuery) {
|
||||||
|
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 runeMode = QueryView.isJsonLike(queryString);
|
const runeMode = QueryView.isJsonLike(queryString);
|
||||||
return (
|
return (
|
||||||
<SplitterLayout
|
<SplitterLayout
|
||||||
@ -491,6 +506,8 @@ export class QueryView extends React.PureComponent<QueryViewProps, QueryViewStat
|
|||||||
>
|
>
|
||||||
<div className="control-pane">
|
<div className="control-pane">
|
||||||
<QueryInput
|
<QueryInput
|
||||||
|
currentSchema={currentSchema ? currentSchema : 'druid'}
|
||||||
|
currentTable={currentTable}
|
||||||
queryString={queryString}
|
queryString={queryString}
|
||||||
onQueryStringChange={this.handleQueryStringChange}
|
onQueryStringChange={this.handleQueryStringChange}
|
||||||
runeMode={runeMode}
|
runeMode={runeMode}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user