fix(editor): preserve SQL selection when executing from toolbar

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-08-30 03:05:43 +08:00
1 parent 22775f3639
commit d5f4eadf7a
6 files changed
+69 -6

No files matched your search

@@ -870,6 +870,18 @@ function emitExecutionRequest(source: SqlExecutionOverride, openInNewResultTab =
}
}
/**
* Captures a manual selection before a toolbar click can cause a platform
* focus transition. The snapshot is immutable, so downstream execution keeps
* the exact SQL and source offsets that were visible when the button was
* pressed.
*/
function captureExecutionSnapshot(): SqlExecutionSnapshot | undefined {
const currentView = view.value;
if (!currentView || currentView.state.selection.main.empty) return undefined;
return sqlExecutionSnapshotFromView(currentView);
}
function requestExecute(options: RequestExecuteOptions = {}) {
executionViewportOwnership.cancelPendingRequest();
const currentView = view.value;
@@ -6525,6 +6537,7 @@ defineExpose({
shouldBlockExecutionShortcut,
requestExecute,
requestExecuteInNewResultTab,
captureExecutionSnapshot,
pasteClipboardAsSqlInCondition,
focusStatementRange,
previewStatementRange,
@@ -1123,6 +1123,10 @@ function requestQueryEditorExecute() {
return queryEditorRef.value?.requestExecute();
}
function captureQueryEditorExecutionSnapshot() {
return queryEditorRef.value?.captureExecutionSnapshot();
}
function requestQueryEditorExecuteInNewResultTab() {
return queryEditorRef.value?.requestExecuteInNewResultTab();
}
@@ -1175,6 +1179,7 @@ defineExpose({
refreshQueryEditorCompletionCache,
handleModRTarget,
requestQueryEditorExecute,
captureQueryEditorExecutionSnapshot,
requestQueryEditorExecuteInNewResultTab,
shouldBlockQueryEditorExecutionShortcut,
acceptQueryEditorExecutionViewport,
@@ -43,7 +43,8 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
execute: [];
execute: [source: "pointer" | "keyboard"];
executePointerDown: [];
cancel: [];
explain: [];
"update:explainMode": [mode: "explain" | "autotrace"];
@@ -251,6 +252,20 @@ function databaseOptionIsProduction(database: string): boolean {
if (!database || props.activeConnection?.is_production) return false;
return productionContextForDatabase(props.activeConnection, database).reason === "database";
}
function onExecutePointerDown(event: MouseEvent) {
if (props.activeTab.isExecuting || event.button !== 0) return;
emit("executePointerDown");
}
function onExecuteClick(event: MouseEvent) {
if (props.activeTab.isExecuting) {
emit("cancel");
return;
}
emit("execute", event.detail > 0 ? "pointer" : "keyboard");
}
async function changeCatalog(selectedCatalog: string) {
const connection = props.activeConnection;
if (!connection) return;
@@ -276,8 +291,8 @@ async function changeCatalog(selectedCatalog: string) {
class="h-6 w-6"
:class="executeButtonClass"
:disabled="activeTab.isCancelling || activeTab.isExplaining || (!activeTab.isExecuting && !executableSql.trim())"
@mousedown.prevent
@click="activeTab.isExecuting ? emit('cancel') : emit('execute')"
@mousedown.prevent="onExecutePointerDown"
@click="onExecuteClick"
>
<Loader2 v-if="activeTab.isCancelling" class="h-3.5 w-3.5 animate-spin" />
<Square v-else-if="activeTab.isExecuting" class="h-3.5 w-3.5 fill-current" />