mirror of https://github.com/apache/druid.git
make completions smarter (#13830)
This commit is contained in:
parent
70f9052f1d
commit
e4e6c7ed01
|
@ -72,9 +72,10 @@ export interface FlexibleQueryInputProps {
|
||||||
|
|
||||||
export interface FlexibleQueryInputState {
|
export interface FlexibleQueryInputState {
|
||||||
// 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 grow and shrink dynamically we will measure its height and then set it.
|
||||||
editorHeight: number;
|
editorHeight: number;
|
||||||
completions: any[];
|
quotedCompletions: Ace.Completion[];
|
||||||
|
unquotedCompletions: Ace.Completion[];
|
||||||
prevColumnMetadata?: readonly ColumnMetadata[];
|
prevColumnMetadata?: readonly ColumnMetadata[];
|
||||||
prevCurrentTable?: string;
|
prevCurrentTable?: string;
|
||||||
prevCurrentSchema?: string;
|
prevCurrentSchema?: string;
|
||||||
|
@ -89,7 +90,7 @@ export class FlexibleQueryInput extends React.PureComponent<
|
||||||
static replaceDefaultAutoCompleter(): void {
|
static replaceDefaultAutoCompleter(): void {
|
||||||
if (!langTools) return;
|
if (!langTools) return;
|
||||||
|
|
||||||
const keywordList = ([] as any[]).concat(
|
const keywordList = ([] as Ace.Completion[]).concat(
|
||||||
SQL_KEYWORDS.map(v => ({ name: v, value: v, score: 0, meta: 'keyword' })),
|
SQL_KEYWORDS.map(v => ({ name: v, value: v, score: 0, meta: 'keyword' })),
|
||||||
SQL_EXPRESSION_PARTS.map(v => ({ name: v, value: v, score: 0, meta: 'keyword' })),
|
SQL_EXPRESSION_PARTS.map(v => ({ name: v, value: v, score: 0, meta: 'keyword' })),
|
||||||
SQL_CONSTANTS.map(v => ({ name: v, value: v, score: 0, meta: 'constant' })),
|
SQL_CONSTANTS.map(v => ({ name: v, value: v, score: 0, meta: 'constant' })),
|
||||||
|
@ -108,7 +109,13 @@ export class FlexibleQueryInput extends React.PureComponent<
|
||||||
langTools.snippetCompleter,
|
langTools.snippetCompleter,
|
||||||
langTools.textCompleter,
|
langTools.textCompleter,
|
||||||
{
|
{
|
||||||
getCompletions: (_editor: any, _session: any, _pos: any, _prefix: any, callback: any) => {
|
getCompletions: (
|
||||||
|
_state: string,
|
||||||
|
_session: Ace.EditSession,
|
||||||
|
_pos: Ace.Point,
|
||||||
|
_prefix: string,
|
||||||
|
callback: any,
|
||||||
|
) => {
|
||||||
return callback(null, keywordList);
|
return callback(null, keywordList);
|
||||||
},
|
},
|
||||||
getDocTooltip: (item: any) => {
|
getDocTooltip: (item: any) => {
|
||||||
|
@ -123,17 +130,19 @@ export class FlexibleQueryInput extends React.PureComponent<
|
||||||
static addFunctionAutoCompleter(): void {
|
static addFunctionAutoCompleter(): void {
|
||||||
if (!langTools) return;
|
if (!langTools) return;
|
||||||
|
|
||||||
const functionList: any[] = Object.entries(SQL_FUNCTIONS).flatMap(([name, versions]) => {
|
const functionList: Ace.Completion[] = Object.entries(SQL_FUNCTIONS).flatMap(
|
||||||
return versions.map(([args, description]) => ({
|
([name, versions]) => {
|
||||||
name: name,
|
return versions.map(([args, description]) => ({
|
||||||
value: versions.length > 1 ? `${name}(${args})` : name,
|
name: name,
|
||||||
score: 1100, // Use a high score to appear over the 'local' suggestions that have a score of 1000
|
value: versions.length > 1 ? `${name}(${args})` : name,
|
||||||
meta: 'function',
|
score: 1100, // Use a high score to appear over the 'local' suggestions that have a score of 1000
|
||||||
syntax: `${name}(${args})`,
|
meta: 'function',
|
||||||
description,
|
syntax: `${name}(${args})`,
|
||||||
completer: COMPLETER,
|
description,
|
||||||
}));
|
completer: COMPLETER,
|
||||||
});
|
}));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
langTools.addCompleter({
|
langTools.addCompleter({
|
||||||
getCompletions: (_editor: any, _session: any, _pos: any, _prefix: any, callback: any) => {
|
getCompletions: (_editor: any, _session: any, _pos: any, _prefix: any, callback: any) => {
|
||||||
|
@ -154,6 +163,43 @@ export class FlexibleQueryInput extends React.PureComponent<
|
||||||
<div class="doc-description">${item.description}</div>`;
|
<div class="doc-description">${item.description}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getCompletions(
|
||||||
|
columnMetadata: readonly ColumnMetadata[],
|
||||||
|
currentSchema: string | undefined,
|
||||||
|
currentTable: string | undefined,
|
||||||
|
quote: boolean,
|
||||||
|
): Ace.Completion[] {
|
||||||
|
return ([] as Ace.Completion[]).concat(
|
||||||
|
uniq(columnMetadata.map(d => d.TABLE_SCHEMA)).map(v => ({
|
||||||
|
value: quote ? String(T(v)) : v,
|
||||||
|
score: 10,
|
||||||
|
meta: 'schema',
|
||||||
|
})),
|
||||||
|
uniq(
|
||||||
|
columnMetadata
|
||||||
|
.filter(d => (currentSchema ? d.TABLE_SCHEMA === currentSchema : true))
|
||||||
|
.map(d => d.TABLE_NAME),
|
||||||
|
).map(v => ({
|
||||||
|
value: quote ? String(T(v)) : 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: quote ? String(C(v)) : v,
|
||||||
|
score: 50,
|
||||||
|
meta: 'column',
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static getDerivedStateFromProps(props: FlexibleQueryInputProps, state: FlexibleQueryInputState) {
|
static getDerivedStateFromProps(props: FlexibleQueryInputProps, state: FlexibleQueryInputState) {
|
||||||
const { columnMetadata, currentSchema, currentTable } = props;
|
const { columnMetadata, currentSchema, currentTable } = props;
|
||||||
|
|
||||||
|
@ -163,38 +209,19 @@ export class FlexibleQueryInput extends React.PureComponent<
|
||||||
currentSchema !== state.prevCurrentSchema ||
|
currentSchema !== state.prevCurrentSchema ||
|
||||||
currentTable !== state.prevCurrentTable)
|
currentTable !== state.prevCurrentTable)
|
||||||
) {
|
) {
|
||||||
const completions = ([] as any[]).concat(
|
|
||||||
uniq(columnMetadata.map(d => d.TABLE_SCHEMA)).map(v => ({
|
|
||||||
value: String(T(v)),
|
|
||||||
score: 10,
|
|
||||||
meta: 'schema',
|
|
||||||
})),
|
|
||||||
uniq(
|
|
||||||
columnMetadata
|
|
||||||
.filter(d => (currentSchema ? d.TABLE_SCHEMA === currentSchema : true))
|
|
||||||
.map(d => d.TABLE_NAME),
|
|
||||||
).map(v => ({
|
|
||||||
value: String(T(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: String(C(v)),
|
|
||||||
score: 50,
|
|
||||||
meta: 'column',
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
completions,
|
quotedCompletions: FlexibleQueryInput.getCompletions(
|
||||||
|
columnMetadata,
|
||||||
|
currentSchema,
|
||||||
|
currentTable,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
unquotedCompletions: FlexibleQueryInput.getCompletions(
|
||||||
|
columnMetadata,
|
||||||
|
currentSchema,
|
||||||
|
currentTable,
|
||||||
|
false,
|
||||||
|
),
|
||||||
prevColumnMetadata: columnMetadata,
|
prevColumnMetadata: columnMetadata,
|
||||||
prevCurrentSchema: currentSchema,
|
prevCurrentSchema: currentSchema,
|
||||||
prevCurrentTable: currentTable,
|
prevCurrentTable: currentTable,
|
||||||
|
@ -207,7 +234,8 @@ export class FlexibleQueryInput extends React.PureComponent<
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.state = {
|
this.state = {
|
||||||
editorHeight: 200,
|
editorHeight: 200,
|
||||||
completions: [],
|
quotedCompletions: [],
|
||||||
|
unquotedCompletions: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,8 +244,20 @@ export class FlexibleQueryInput extends React.PureComponent<
|
||||||
FlexibleQueryInput.addFunctionAutoCompleter();
|
FlexibleQueryInput.addFunctionAutoCompleter();
|
||||||
if (langTools) {
|
if (langTools) {
|
||||||
langTools.addCompleter({
|
langTools.addCompleter({
|
||||||
getCompletions: (_editor: any, _session: any, _pos: any, _prefix: any, callback: any) => {
|
getCompletions: (
|
||||||
callback(null, this.state.completions);
|
_state: string,
|
||||||
|
session: Ace.EditSession,
|
||||||
|
pos: Ace.Point,
|
||||||
|
prefix: string,
|
||||||
|
callback: any,
|
||||||
|
) => {
|
||||||
|
const charBeforePrefix = session.getLine(pos.row)[pos.column - prefix.length - 1];
|
||||||
|
callback(
|
||||||
|
null,
|
||||||
|
charBeforePrefix === '"'
|
||||||
|
? this.state.unquotedCompletions
|
||||||
|
: this.state.quotedCompletions,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue