mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
query error markers
This commit is contained in:
parent
2f820d8dac
commit
1a7f06342f
@ -101,8 +101,9 @@ class TableWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class StreamHandler {
|
class StreamHandler {
|
||||||
constructor(resultIndexHolder, resolve) {
|
constructor(resultIndexHolder, resolve, startLine) {
|
||||||
this.recordset = this.recordset.bind(this);
|
this.recordset = this.recordset.bind(this);
|
||||||
|
this.startLine = startLine;
|
||||||
this.row = this.row.bind(this);
|
this.row = this.row.bind(this);
|
||||||
// this.error = this.error.bind(this);
|
// this.error = this.error.bind(this);
|
||||||
this.done = this.done.bind(this);
|
this.done = this.done.bind(this);
|
||||||
@ -155,14 +156,20 @@ class StreamHandler {
|
|||||||
this.resolve();
|
this.resolve();
|
||||||
}
|
}
|
||||||
info(info) {
|
info(info) {
|
||||||
|
if (info.line != null) {
|
||||||
|
info = {
|
||||||
|
...info,
|
||||||
|
line: this.startLine + info.line,
|
||||||
|
};
|
||||||
|
}
|
||||||
process.send({ msgtype: 'info', info });
|
process.send({ msgtype: 'info', info });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleStream(driver, resultIndexHolder, sql) {
|
function handleStream(driver, resultIndexHolder, sqlItem) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const handler = new StreamHandler(resultIndexHolder, resolve);
|
const handler = new StreamHandler(resultIndexHolder, resolve, sqlItem.trimStart.line);
|
||||||
driver.stream(systemConnection, sql, handler);
|
driver.stream(systemConnection, sqlItem.text, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +228,10 @@ async function handleExecuteQuery({ sql }) {
|
|||||||
const resultIndexHolder = {
|
const resultIndexHolder = {
|
||||||
value: 0,
|
value: 0,
|
||||||
};
|
};
|
||||||
for (const sqlItem of splitQuery(sql, driver.getQuerySplitterOptions('stream'))) {
|
for (const sqlItem of splitQuery(sql, {
|
||||||
|
...driver.getQuerySplitterOptions('stream'),
|
||||||
|
returnRichInfo: true,
|
||||||
|
})) {
|
||||||
await handleStream(driver, resultIndexHolder, sqlItem);
|
await handleStream(driver, resultIndexHolder, sqlItem);
|
||||||
// const handler = new StreamHandler(resultIndex);
|
// const handler = new StreamHandler(resultIndex);
|
||||||
// const stream = await driver.stream(systemConnection, sqlItem, handler);
|
// const stream = await driver.stream(systemConnection, sqlItem, handler);
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
let changeIndex = 0;
|
let changeIndex = 0;
|
||||||
let rowCountLoaded = null;
|
let rowCountLoaded = null;
|
||||||
|
|
||||||
const throttleLoadNext = _.throttle(() => domGrid.resetLoadedAll(), 500);
|
const throttleLoadNext = _.throttle(() => domGrid?.resetLoadedAll(), 500);
|
||||||
|
|
||||||
const handleJslDataStats = stats => {
|
const handleJslDataStats = stats => {
|
||||||
if (stats.changeIndex < changeIndex) return;
|
if (stats.changeIndex < changeIndex) return;
|
||||||
|
@ -156,6 +156,7 @@
|
|||||||
export let splitterOptions = null;
|
export let splitterOptions = null;
|
||||||
export let onKeyDown = null;
|
export let onKeyDown = null;
|
||||||
export let onExecuteFragment = null;
|
export let onExecuteFragment = null;
|
||||||
|
export let errorMessages = null;
|
||||||
|
|
||||||
const tabVisible: any = getContext('tabVisible');
|
const tabVisible: any = getContext('tabVisible');
|
||||||
|
|
||||||
@ -184,16 +185,28 @@
|
|||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentCommandText(): string {
|
export function getCurrentCommandText(): { text: string; line?: number } {
|
||||||
if (currentPart != null) return currentPart.text;
|
if (currentPart != null) {
|
||||||
if (!editor) return '';
|
return {
|
||||||
|
text: currentPart.text,
|
||||||
|
line: currentPart.trimStart.line,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!editor) return { text: '' };
|
||||||
const selectedText = editor.getSelectedText();
|
const selectedText = editor.getSelectedText();
|
||||||
if (selectedText) return selectedText;
|
if (selectedText)
|
||||||
|
return {
|
||||||
|
text: selectedText,
|
||||||
|
line: editor.getSelectionRange().start.row,
|
||||||
|
};
|
||||||
if (editor.getHighlightActiveLine()) {
|
if (editor.getHighlightActiveLine()) {
|
||||||
const line = editor.getSelectionRange().start.row;
|
const line = editor.getSelectionRange().start.row;
|
||||||
return editor.session.getLine(line);
|
return {
|
||||||
|
text: editor.session.getLine(line),
|
||||||
|
line,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return '';
|
return { text: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCodeCompletionCommandText() {
|
export function getCodeCompletionCommandText() {
|
||||||
@ -292,13 +305,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateAnnotations() {
|
function updateAnnotations() {
|
||||||
editor.session.setAnnotations(
|
editor?.session?.setAnnotations([
|
||||||
(queryParts || []).map(part => ({
|
...(queryParts || [])
|
||||||
row: part.trimStart.line,
|
.filter(part => !(errorMessages || []).find(err => err.line == part.trimStart.line))
|
||||||
text: part.text,
|
.map(part => ({
|
||||||
className: 'ace-gutter-sql-run',
|
row: part.trimStart.line,
|
||||||
}))
|
text: part.text,
|
||||||
);
|
className: 'ace-gutter-sql-run',
|
||||||
|
})),
|
||||||
|
...(errorMessages || []).map(error => ({
|
||||||
|
row: error.line,
|
||||||
|
text: error.message,
|
||||||
|
type: 'error',
|
||||||
|
})),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
errorMessages;
|
||||||
|
updateAnnotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleContextMenu = e => {
|
const handleContextMenu = e => {
|
||||||
@ -455,10 +480,10 @@
|
|||||||
|
|
||||||
const part = (queryParts || []).find(part => part.trimStart.line == row);
|
const part = (queryParts || []).find(part => part.trimStart.line == row);
|
||||||
if (part && onExecuteFragment) {
|
if (part && onExecuteFragment) {
|
||||||
onExecuteFragment(part.text);
|
onExecuteFragment(part.text, part.trimStart.line);
|
||||||
e.stop();
|
e.stop();
|
||||||
editor.moveCursorTo(part.trimStart.line, 0);
|
editor.moveCursorTo(part.trimStart.line, 0);
|
||||||
editor.selection.clearSelection()
|
editor.selection.clearSelection();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
export let items: any[];
|
export let items: any[];
|
||||||
export let showProcedure = false;
|
export let showProcedure = false;
|
||||||
export let showLine = false;
|
export let showLine = false;
|
||||||
|
export let startLine = 0;
|
||||||
|
|
||||||
$: time0 = items[0] && new Date(items[0].time).getTime();
|
$: time0 = items[0] && new Date(items[0].time).getTime();
|
||||||
|
|
||||||
@ -58,7 +59,7 @@
|
|||||||
<td>{row.procedure || ''}</td>
|
<td>{row.procedure || ''}</td>
|
||||||
{/if}
|
{/if}
|
||||||
{#if showLine}
|
{#if showLine}
|
||||||
<td>{row.line || ''}</td>
|
<td>{row.line == null ? '' : row.line + 1 + startLine}</td>
|
||||||
{/if}
|
{/if}
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -13,8 +13,11 @@
|
|||||||
export let eventName;
|
export let eventName;
|
||||||
export let executeNumber;
|
export let executeNumber;
|
||||||
export let showNoMessagesAlert = false;
|
export let showNoMessagesAlert = false;
|
||||||
|
export let startLine = 0;
|
||||||
|
export let onChangeErrors = null;
|
||||||
|
|
||||||
const cachedMessagesRef = createRef([]);
|
const cachedMessagesRef = createRef([]);
|
||||||
|
const lastErrorMessageCountRef = createRef(0);
|
||||||
|
|
||||||
let displayedMessages = [];
|
let displayedMessages = [];
|
||||||
|
|
||||||
@ -44,11 +47,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (onChangeErrors) {
|
||||||
|
const errors = displayedMessages.filter(x => x.severity == 'error');
|
||||||
|
if (lastErrorMessageCountRef.get() != errors.length) {
|
||||||
|
onChangeErrors(
|
||||||
|
errors.map(err => ({
|
||||||
|
...err,
|
||||||
|
line: err.line == null ? null : err.line + startLine,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
lastErrorMessageCountRef.set(errors.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$: $effect;
|
$: $effect;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if showNoMessagesAlert && (!displayedMessages || displayedMessages.length == 0)}
|
{#if showNoMessagesAlert && (!displayedMessages || displayedMessages.length == 0)}
|
||||||
<ErrorInfo message="No messages" icon="img alert" />
|
<ErrorInfo message="No messages" icon="img alert" />
|
||||||
{:else}
|
{:else}
|
||||||
<MessageView items={displayedMessages} on:messageclick {showProcedure} {showLine} />
|
<MessageView items={displayedMessages} on:messageclick {showProcedure} {showLine} {startLine} />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
return domEditor.getEditor();
|
return domEditor.getEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentCommandText(): string {
|
export function getCurrentCommandText(): { text: string; line?: number } {
|
||||||
return domEditor.getCurrentCommandText();
|
return domEditor.getCurrentCommandText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,10 +86,11 @@
|
|||||||
|
|
||||||
let busy = false;
|
let busy = false;
|
||||||
let executeNumber = 0;
|
let executeNumber = 0;
|
||||||
|
let executeStartLine = 0;
|
||||||
let visibleResultTabs = false;
|
let visibleResultTabs = false;
|
||||||
let sessionId = null;
|
let sessionId = null;
|
||||||
let resultCount;
|
let resultCount;
|
||||||
|
let errorMessages;
|
||||||
let domEditor;
|
let domEditor;
|
||||||
|
|
||||||
$: connection = useConnectionInfo({ conid });
|
$: connection = useConnectionInfo({ conid });
|
||||||
@ -143,13 +144,14 @@
|
|||||||
return !!conid && (!$connection?.isReadOnly || driver?.readOnlySessions);
|
return !!conid && (!$connection?.isReadOnly || driver?.readOnlySessions);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function executeCore(sql) {
|
async function executeCore(sql, startLine = 0) {
|
||||||
if (busy) return;
|
if (busy) return;
|
||||||
if (!sql || !sql.trim()) {
|
if (!sql || !sql.trim()) {
|
||||||
showSnackbarError('Skipped executing empty query');
|
showSnackbarError('Skipped executing empty query');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
executeStartLine = startLine;
|
||||||
executeNumber++;
|
executeNumber++;
|
||||||
visibleResultTabs = true;
|
visibleResultTabs = true;
|
||||||
|
|
||||||
@ -179,13 +181,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function executeCurrent() {
|
export async function executeCurrent() {
|
||||||
const sql = domEditor.getCurrentCommandText();
|
const cmd = domEditor.getCurrentCommandText();
|
||||||
await executeCore(sql);
|
await executeCore(cmd.text, cmd.line);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function execute() {
|
export async function execute() {
|
||||||
const selectedText = domEditor.getEditor().getSelectedText();
|
const selectedText = domEditor.getEditor().getSelectedText();
|
||||||
await executeCore(selectedText || $editorValue);
|
const startLine = domEditor.getEditor().getSelectionRange().start.row;
|
||||||
|
await executeCore(selectedText || $editorValue, selectedText ? startLine : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function kill() {
|
export async function kill() {
|
||||||
@ -257,6 +260,10 @@
|
|||||||
: null,
|
: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function handleChangeErrors(errors) {
|
||||||
|
errorMessages = errors;
|
||||||
|
}
|
||||||
|
|
||||||
function createMenu() {
|
function createMenu() {
|
||||||
return [
|
return [
|
||||||
{ command: 'query.execute' },
|
{ command: 'query.execute' },
|
||||||
@ -289,13 +296,17 @@
|
|||||||
splitterOptions={driver?.getQuerySplitterOptions('script')}
|
splitterOptions={driver?.getQuerySplitterOptions('script')}
|
||||||
value={$editorState.value || ''}
|
value={$editorState.value || ''}
|
||||||
menu={createMenu()}
|
menu={createMenu()}
|
||||||
on:input={e => setEditorData(e.detail)}
|
on:input={e => {
|
||||||
|
setEditorData(e.detail);
|
||||||
|
errorMessages = [];
|
||||||
|
}}
|
||||||
on:focus={() => {
|
on:focus={() => {
|
||||||
activator.activate();
|
activator.activate();
|
||||||
invalidateCommands();
|
invalidateCommands();
|
||||||
}}
|
}}
|
||||||
bind:this={domEditor}
|
bind:this={domEditor}
|
||||||
onExecuteFragment={sql => executeCore(sql)}
|
onExecuteFragment={(sql, startLine) => executeCore(sql, startLine)}
|
||||||
|
{errorMessages}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<AceEditor
|
<AceEditor
|
||||||
@ -319,8 +330,10 @@
|
|||||||
eventName={sessionId ? `session-info-${sessionId}` : null}
|
eventName={sessionId ? `session-info-${sessionId}` : null}
|
||||||
on:messageClick={handleMesageClick}
|
on:messageClick={handleMesageClick}
|
||||||
{executeNumber}
|
{executeNumber}
|
||||||
|
startLine={executeStartLine}
|
||||||
showProcedure
|
showProcedure
|
||||||
showLine
|
showLine
|
||||||
|
onChangeErrors={handleChangeErrors}
|
||||||
/>
|
/>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</ResultTabs>
|
</ResultTabs>
|
||||||
|
@ -134,7 +134,7 @@ async function tediousStream(pool, sql, options) {
|
|||||||
const { message, lineNumber, procName } = info;
|
const { message, lineNumber, procName } = info;
|
||||||
options.info({
|
options.info({
|
||||||
message,
|
message,
|
||||||
line: lineNumber,
|
line: lineNumber != null && lineNumber > 0 ? lineNumber - 1 : lineNumber,
|
||||||
procedure: procName,
|
procedure: procName,
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
severity: 'info',
|
severity: 'info',
|
||||||
@ -144,7 +144,7 @@ async function tediousStream(pool, sql, options) {
|
|||||||
const { message, lineNumber, procName } = error;
|
const { message, lineNumber, procName } = error;
|
||||||
options.info({
|
options.info({
|
||||||
message,
|
message,
|
||||||
line: lineNumber,
|
line: lineNumber != null && lineNumber > 0 ? lineNumber - 1 : lineNumber,
|
||||||
procedure: procName,
|
procedure: procName,
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
severity: 'error',
|
severity: 'error',
|
||||||
|
@ -112,11 +112,10 @@ const drivers = driverBases.map(driverBase => ({
|
|||||||
|
|
||||||
const handleError = error => {
|
const handleError = error => {
|
||||||
console.log('ERROR', error);
|
console.log('ERROR', error);
|
||||||
const { message, lineNumber, procName } = error;
|
const { message } = error;
|
||||||
options.info({
|
options.info({
|
||||||
message,
|
message,
|
||||||
line: lineNumber,
|
line: 0,
|
||||||
procedure: procName,
|
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
severity: 'error',
|
severity: 'error',
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user