mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
fix(plugin-sql-editor): reduce server calls
This commit is contained in:
@@ -316,6 +316,11 @@ export class SQLParser {
|
||||
return this;
|
||||
}
|
||||
|
||||
isEndsWithDelimiter(): boolean {
|
||||
this.update();
|
||||
return this.scriptDelimiters.some(delimiter => this.parsedScript?.endsWith(delimiter));
|
||||
}
|
||||
|
||||
private update() {
|
||||
if (this.parsedScript !== this.script) {
|
||||
this.parse(this.script);
|
||||
|
||||
+68
-14
@@ -18,14 +18,19 @@ import { action } from 'mobx';
|
||||
import type { IControlledCodeMirror } from 'react-codemirror2';
|
||||
|
||||
import { useExecutor, useObservableRef } from '@cloudbeaver/core-blocks';
|
||||
import { throttleAsync } from '@cloudbeaver/core-utils';
|
||||
import type { SqlCompletionProposal } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import type { SQLCodeEditorController } from '../SQLCodeEditor/SQLCodeEditorController';
|
||||
import type { ISQLEditorData } from '../useSqlEditor';
|
||||
|
||||
interface ISQLCodeEditorPanelData {
|
||||
proposalsWordFrom: Position | null;
|
||||
proposalsWord: string | null;
|
||||
proposalsMode: boolean | null;
|
||||
proposals: SqlCompletionProposal[] | null;
|
||||
readonly activeSuggest: boolean;
|
||||
readonly bindings: Omit<IControlledCodeMirror, 'value'>;
|
||||
closeHint(): void;
|
||||
}
|
||||
|
||||
interface ISQLCodeEditorPanelDataPrivate extends ISQLCodeEditorPanelData {
|
||||
@@ -46,6 +51,7 @@ export function useSQLCodeEditorPanel(
|
||||
controller: SQLCodeEditorController | null
|
||||
): ISQLCodeEditorPanelData {
|
||||
const editorPanelData = useObservableRef<ISQLCodeEditorPanelDataPrivate>(() => ({
|
||||
proposals: null,
|
||||
activeSuggest: true,
|
||||
options: {
|
||||
theme: 'material',
|
||||
@@ -121,7 +127,7 @@ export function useSQLCodeEditorPanel(
|
||||
const nextCursor = editor.getCursor('from');
|
||||
|
||||
if (nextCursor.line !== lastChange.from.line) {
|
||||
editor.closeHint();
|
||||
this.closeHint();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -155,7 +161,7 @@ export function useSQLCodeEditorPanel(
|
||||
cursor = from;
|
||||
|
||||
if (closeCharacters.test(ch) || from.line !== cursor.line) {
|
||||
editor.closeHint();
|
||||
this.closeHint();
|
||||
} else {
|
||||
editor.state.completionActive.update();
|
||||
}
|
||||
@@ -167,6 +173,16 @@ export function useSQLCodeEditorPanel(
|
||||
this.highlightActiveQuery();
|
||||
},
|
||||
|
||||
closeHint() {
|
||||
const editor = this.controller?.getEditor();
|
||||
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.closeHint();
|
||||
},
|
||||
|
||||
async showHint(activeSuggest: boolean) {
|
||||
const editor = this.controller?.getEditor();
|
||||
|
||||
@@ -191,24 +207,62 @@ export function useSQLCodeEditorPanel(
|
||||
},
|
||||
|
||||
|
||||
getHandleAutocomplete: throttleAsync(async function getHandleAutocomplete(
|
||||
async getHandleAutocomplete(
|
||||
editor: Editor,
|
||||
options: ShowHintOptions
|
||||
): Promise<Hints | undefined> {
|
||||
const cursor = editor.getCursor('from');
|
||||
const cursorPosition = getAbsolutePosition(editor, cursor);
|
||||
const [from, to, word] = getWordRange(editor, cursor);
|
||||
|
||||
let proposals = await editorPanelData.data.getHintProposals(cursorPosition, !options.completeSingle);
|
||||
|
||||
proposals = proposals.filter(
|
||||
({ displayString }) => displayString.toLocaleLowerCase() !== word.toLocaleLowerCase()
|
||||
const cursorPosition = getAbsolutePosition(
|
||||
editor, word.length > 0
|
||||
? { ...from, ch: from.ch + 1 }
|
||||
: from
|
||||
);
|
||||
|
||||
if (proposals.length === 0) {
|
||||
return;
|
||||
const proposalWord = word.slice(0, 1);
|
||||
let proposals = editorPanelData.proposals;
|
||||
|
||||
if (
|
||||
proposals === null
|
||||
|| editorPanelData.proposalsWord !== proposalWord
|
||||
|| editorPanelData.proposalsMode !== options.completeSingle
|
||||
|| editorPanelData.proposalsWordFrom?.ch !== from.ch
|
||||
|| editorPanelData.proposalsWordFrom.line !== from.line
|
||||
|| !word.startsWith(editorPanelData.proposalsWord)
|
||||
) {
|
||||
const proposalsMode = options.completeSingle ?? false;
|
||||
editorPanelData.proposalsMode = proposalsMode;
|
||||
editorPanelData.proposalsWord = proposalWord;
|
||||
editorPanelData.proposalsWordFrom = from;
|
||||
editorPanelData.proposals = [];
|
||||
|
||||
proposals = await editorPanelData.data.getHintProposals(cursorPosition, !options.completeSingle);
|
||||
|
||||
if (
|
||||
editorPanelData.proposalsWord === proposalWord
|
||||
&& editorPanelData.proposalsWordFrom === from
|
||||
&& editorPanelData.proposalsMode === proposalsMode
|
||||
) {
|
||||
editorPanelData.proposals = proposals;
|
||||
|
||||
if (editor.state.completionActive && proposals.length > 0) {
|
||||
editor.state.completionActive.update();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proposals = proposals.filter(
|
||||
({ displayString }) => (
|
||||
displayString.toLocaleLowerCase() !== word.toLocaleLowerCase()
|
||||
&& displayString.toLocaleLowerCase().startsWith(word.toLocaleLowerCase())
|
||||
)
|
||||
);
|
||||
|
||||
// if (proposals.length === 0) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const hints: Hints = {
|
||||
from,
|
||||
to,
|
||||
@@ -219,7 +273,7 @@ export function useSQLCodeEditorPanel(
|
||||
};
|
||||
|
||||
return hints;
|
||||
}, 1000 / 3),
|
||||
},
|
||||
|
||||
highlightActiveQuery() {
|
||||
this.controller?.highlightSegment(true);
|
||||
@@ -249,7 +303,7 @@ export function useSQLCodeEditorPanel(
|
||||
useExecutor({
|
||||
executor: data.onExecute,
|
||||
handlers: [function updateHighlight() {
|
||||
controller?.getEditor()?.closeHint();
|
||||
editorPanelData.closeHint();
|
||||
controller?.resetLineStateHighlight();
|
||||
}],
|
||||
});
|
||||
|
||||
@@ -188,7 +188,7 @@ export function useSqlEditor(state: ISqlEditorTabState): ISQLEditorData {
|
||||
this.onUpdate.execute();
|
||||
},
|
||||
|
||||
async getHintProposals(position, simple) {
|
||||
getHintProposals: throttleAsync(async function getHintProposals(this: ISQLEditorDataPrivate, position, simple) {
|
||||
if (!this.state.executionContext) {
|
||||
return [];
|
||||
}
|
||||
@@ -204,7 +204,7 @@ export function useSqlEditor(state: ISqlEditorTabState): ISQLEditorData {
|
||||
);
|
||||
|
||||
return proposals;
|
||||
},
|
||||
}, 1000 / 3),
|
||||
|
||||
async formatScript(): Promise<void> {
|
||||
if (this.isDisabled || this.isScriptEmpty || !this.state.executionContext) {
|
||||
@@ -225,8 +225,8 @@ export function useSqlEditor(state: ISqlEditorTabState): ISQLEditorData {
|
||||
|
||||
this.setQuery(
|
||||
query.substring(0, script.begin)
|
||||
+ formatted
|
||||
+ query.substring(script.end)
|
||||
+ formatted
|
||||
+ query.substring(script.end)
|
||||
);
|
||||
} finally {
|
||||
this.readonlyState = false;
|
||||
@@ -333,7 +333,9 @@ export function useSqlEditor(state: ISqlEditorTabState): ISQLEditorData {
|
||||
setQuery(query: string): void {
|
||||
this.state.query = query;
|
||||
this.parser.setScript(query);
|
||||
this.updateParserScriptsThrottle();
|
||||
if (this.parser.isEndsWithDelimiter()) {
|
||||
this.updateParserScriptsThrottle();
|
||||
}
|
||||
this.onUpdate.execute();
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user