feat(saved-sql): run queries in the current database

This commit is contained in:
zhangyc authored and GitHub committed 2026-07-31 01:57:39 +08:00
1 parent 4062f11a26
commit e2ba75b102
22 files changed
+501 -51

No files matched your search

+30 -23
View File
@@ -64,6 +64,7 @@ import { appendDebugLog } from "@/lib/backend/debugLog";
import { formatError } from "@/lib/backend/errorUtils";
import { createSavedSqlEditorPosition, initSavedSqlEditorPositions, restoreSavedSqlEditorPosition, saveSavedSqlEditorPosition } from "@/lib/app/savedSqlEditorPosition";
import { ensureSqlExtension } from "@/lib/savedSql/savedSqlFileName";
import { resolveSavedSqlExecutionTarget, savedSqlExecutionTargetFromTab, type SavedSqlExecutionTarget, type SavedSqlOpenTargetMode } from "@/lib/savedSql/savedSqlExecutionTarget";
import { safeLocalStorageGet, safeLocalStorageRemove } from "@/lib/backend/safeStorage";
import { sqlTextFingerprint } from "@/lib/sql/sqlTextFingerprint";
import type { SavedSqlFile } from "@/types/database";
@@ -95,6 +96,10 @@ interface BuildQueryResultExportRequestOptions {
exportColumnTypes?: Array<string | null | undefined>;
}
interface OpenSavedSqlOptions {
targetMode?: SavedSqlOpenTargetMode;
}
type DroppedTableObjectType = "TABLE" | "VIEW" | "MATERIALIZED_VIEW";
interface DroppedTableObjectTarget {
@@ -2437,7 +2442,26 @@ export const useQueryStore = defineStore("query", () => {
refreshExternalSqlFileTitles();
}
function openSavedSql(file: SavedSqlFile) {
function currentSavedSqlExecutionTarget(): SavedSqlExecutionTarget | undefined {
const activeTab = tabs.value.find((tab) => tab.id === activeTabId.value);
const target = savedSqlExecutionTargetFromTab(activeTab);
if (!target || !useConnectionStore().getConfig(target.connectionId)) return undefined;
return target;
}
function applySavedSqlExecutionTarget(tab: QueryTab, target: SavedSqlExecutionTarget) {
updateConnection(tab.id, target.connectionId, target.database);
if (tab.catalog !== target.catalog || tab.database !== target.database) {
if (tab.catalog !== undefined || target.catalog !== undefined) updateCatalog(tab.id, target.catalog, target.database);
else updateDatabase(tab.id, target.database);
}
updateSchema(tab.id, target.schema);
}
function openSavedSql(file: SavedSqlFile, options: OpenSavedSqlOptions = {}) {
const targetMode = options.targetMode ?? useSettingsStore().editorSettings.savedSqlOpenTargetMode;
const currentTarget = targetMode === "current" ? currentSavedSqlExecutionTarget() : undefined;
const target = resolveSavedSqlExecutionTarget(file, targetMode, currentTarget);
const existing = tabs.value.find((tab) => tab.savedSqlId === file.id);
if (existing) {
persistSavedSqlEditorPosition(existing);
@@ -2448,6 +2472,7 @@ export const useQueryStore = defineStore("query", () => {
existing.editorSelection = restored.selection;
existing.editorViewport = restored.viewport;
}
applySavedSqlExecutionTarget(existing, target);
switchTab(existing.id);
return existing.id;
}
@@ -2458,9 +2483,10 @@ export const useQueryStore = defineStore("query", () => {
id,
title: file.name,
customTitle: true,
connectionId: file.connectionId,
database: file.database,
schema: file.schema,
connectionId: target.connectionId,
database: target.database,
schema: target.schema,
catalog: target.catalog,
sql: file.sql,
savedSqlId: file.id,
originalSql: file.sql,
@@ -2484,9 +2510,6 @@ export const useQueryStore = defineStore("query", () => {
const file = await savedSqlStore.ensureFileContent(tab.savedSqlId!);
if (!file) continue;
tab.title = tab.customTitle ? tab.title : file.name;
tab.connectionId = file.connectionId;
tab.database = file.database;
tab.schema = file.schema;
tab.sql = file.sql;
tab.originalSql = file.sql;
const restored = restoreSavedSqlEditorPosition(file.id, file.sql);
@@ -2582,22 +2605,6 @@ export const useQueryStore = defineStore("query", () => {
tab.resultSortedSql = undefined;
clearExplain(tab);
tab.tableMeta = undefined;
// Sync connection change back to the saved SQL file if this tab is linked
if (tab.savedSqlId) {
const savedSqlStore = useSavedSqlStore();
void savedSqlStore.ensureFileContent(tab.savedSqlId).then((existing) => {
if (!existing) return;
return savedSqlStore.saveFile({
id: existing.id,
connectionId,
name: existing.name,
database,
schema: existing.schema,
sql: existing.sql,
});
});
}
}
function clearInvalidDataTabSortState(tab: QueryTab, columns: NonNullable<QueryTab["tableMeta"]>["columns"]): boolean {
+6
View File
@@ -10,6 +10,7 @@ import { normalizeSidebarHiddenTablePrefixes } from "@/lib/sidebar/sidebarTableN
import type { ConnectionListSortMode } from "@/lib/sidebar/connectionListSort";
import { DEFAULT_SQL_FORMATTER_SETTINGS, normalizeSqlFormatterSettings, type SqlFormatterSettings } from "@/lib/sql/sqlFormatterConfig";
import { normalizeSqlVariableSyntaxOverrides, type SqlVariableSyntaxOverrides } from "@/lib/sql/sqlVariableSyntax";
import type { SavedSqlOpenTargetMode } from "@/lib/savedSql/savedSqlExecutionTarget";
import type { SidebarActivation } from "@/lib/sidebar/treeNodeClick";
import type { SqlSnippet, TableInfoTab } from "@/types/database";
import { DEFAULT_SQL_SNIPPETS } from "@/lib/sql/sqlCompletion";
@@ -20,6 +21,7 @@ import { safeLocalStorageGet, safeLocalStorageRemove } from "@/lib/backend/safeS
import type { AiProvider, AiApiStyle, AiAuthMethod, AiEffortLevel, AiReasoningLevel, AiConfiguredModel, AiConfig, AiTestConnectionResult, AiConfigItem, AiChatSelectionState, AiEffortSelection, AiModelEffortPreference } from "@/types/ai";
export type { AiProvider, AiApiStyle, AiAuthMethod, AiEffortLevel, AiReasoningLevel, AiConfiguredModel, AiConfig, AiTestConnectionResult, AiConfigItem, AiChatSelectionState, AiEffortSelection };
export type { SavedSqlOpenTargetMode };
export interface DesktopSettings {
show_tray_icon: boolean;
@@ -452,6 +454,7 @@ export interface EditorSettings {
sqlSemanticDiagnosticsEnabled: boolean;
confirmDangerousSqlExecution: boolean;
confirmUnsavedSqlClose: boolean;
savedSqlOpenTargetMode: SavedSqlOpenTargetMode;
compactTabTitle: boolean;
tabLayout: TabLayoutMode;
appLayout: "separated" | "classic";
@@ -628,6 +631,7 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
sqlSemanticDiagnosticsEnabled: SQL_SEMANTIC_DIAGNOSTICS_AUTO_ENABLED,
confirmDangerousSqlExecution: true,
confirmUnsavedSqlClose: true,
savedSqlOpenTargetMode: "saved",
compactTabTitle: false,
tabLayout: "scroll",
appLayout: "classic",
@@ -935,6 +939,7 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
sqlSemanticDiagnosticsEnabled: sqlSemanticDiagnosticsEnabledForMode(sqlSemanticDiagnosticsMode),
confirmDangerousSqlExecution: settings.confirmDangerousSqlExecution ?? DEFAULT_EDITOR_SETTINGS.confirmDangerousSqlExecution,
confirmUnsavedSqlClose: settings.confirmUnsavedSqlClose ?? DEFAULT_EDITOR_SETTINGS.confirmUnsavedSqlClose,
savedSqlOpenTargetMode: settings.savedSqlOpenTargetMode === "current" ? "current" : DEFAULT_EDITOR_SETTINGS.savedSqlOpenTargetMode,
compactTabTitle: settings.compactTabTitle ?? DEFAULT_EDITOR_SETTINGS.compactTabTitle,
tabLayout: normalizeTabLayout(settings.tabLayout),
appLayout: settings.appLayout ?? DEFAULT_EDITOR_SETTINGS.appLayout,
@@ -1416,6 +1421,7 @@ export const useSettingsStore = defineStore("settings", () => {
}
if (partial.confirmDangerousSqlExecution !== undefined) editorSettings.value.confirmDangerousSqlExecution = partial.confirmDangerousSqlExecution;
if (partial.confirmUnsavedSqlClose !== undefined) editorSettings.value.confirmUnsavedSqlClose = partial.confirmUnsavedSqlClose;
if (partial.savedSqlOpenTargetMode !== undefined) editorSettings.value.savedSqlOpenTargetMode = partial.savedSqlOpenTargetMode === "current" ? "current" : "saved";
if (partial.compactTabTitle !== undefined) editorSettings.value.compactTabTitle = partial.compactTabTitle;
if (partial.tabLayout !== undefined) editorSettings.value.tabLayout = normalizeTabLayout(partial.tabLayout);
if (partial.appLayout !== undefined) editorSettings.value.appLayout = partial.appLayout;