fix(saved-sql): 修复 SQL 库连接关联丢失与历史文件不可见
* fix: 持久化并显示 SQL 库连接关联 * fix: 补充 SQL 库关联状态翻译 * chore: 修复数据标签页策略格式 --------- Co-authored-by: zipg <4047349+zipg@users.noreply.github.com>
This commit is contained in:
1 parent
580b70e1d4
commit
445b6473f4
18 files changed
+336
-115
No files matched your search
@@ -103,6 +103,10 @@ interface OpenSavedSqlOptions {
|
||||
targetMode?: SavedSqlOpenTargetMode;
|
||||
}
|
||||
|
||||
interface UpdateExecutionTargetOptions {
|
||||
persistSavedSqlTarget?: boolean;
|
||||
}
|
||||
|
||||
type DroppedTableObjectType = "TABLE" | "VIEW" | "MATERIALIZED_VIEW";
|
||||
|
||||
interface DroppedTableObjectTarget {
|
||||
@@ -2568,12 +2572,13 @@ export const useQueryStore = defineStore("query", () => {
|
||||
}
|
||||
|
||||
function applySavedSqlExecutionTarget(tab: QueryTab, target: SavedSqlExecutionTarget) {
|
||||
updateConnection(tab.id, target.connectionId, target.database);
|
||||
const options = { persistSavedSqlTarget: false };
|
||||
updateConnection(tab.id, target.connectionId, target.database, options);
|
||||
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);
|
||||
if (tab.catalog !== undefined || target.catalog !== undefined) updateCatalog(tab.id, target.catalog, target.database, options);
|
||||
else updateDatabase(tab.id, target.database, options);
|
||||
}
|
||||
updateSchema(tab.id, target.schema);
|
||||
updateSchema(tab.id, target.schema, options);
|
||||
}
|
||||
|
||||
function openSavedSql(file: SavedSqlFile, options: OpenSavedSqlOptions = {}) {
|
||||
@@ -2653,7 +2658,19 @@ export const useQueryStore = defineStore("query", () => {
|
||||
tabs.value = orderPinnedFirst(tabs.value, (item) => !!item.pinned);
|
||||
}
|
||||
|
||||
function updateDatabase(id: string, database: string) {
|
||||
function persistSavedSqlExecutionTarget(tab: QueryTab, options: UpdateExecutionTargetOptions) {
|
||||
if (options.persistSavedSqlTarget === false || tab.mode !== "query" || !tab.savedSqlId) return;
|
||||
const savedSqlStore = useSavedSqlStore();
|
||||
void savedSqlStore
|
||||
.updateFileExecutionTarget(tab.savedSqlId, {
|
||||
connectionId: tab.connectionId,
|
||||
database: tab.database,
|
||||
schema: tab.schema,
|
||||
})
|
||||
.catch((error) => console.warn("[DBX][saved-sql:target:error]", error));
|
||||
}
|
||||
|
||||
function updateDatabase(id: string, database: string, options: UpdateExecutionTargetOptions = {}) {
|
||||
const tab = tabs.value.find((t) => t.id === id);
|
||||
if (!tab || tab.database === database) return;
|
||||
rollbackTabTransaction(tab);
|
||||
@@ -2668,9 +2685,10 @@ export const useQueryStore = defineStore("query", () => {
|
||||
tab.resultSortedSql = undefined;
|
||||
clearExplain(tab);
|
||||
tab.tableMeta = undefined;
|
||||
persistSavedSqlExecutionTarget(tab, options);
|
||||
}
|
||||
|
||||
function updateCatalog(id: string, catalog: string | undefined, database: string) {
|
||||
function updateCatalog(id: string, catalog: string | undefined, database: string, options: UpdateExecutionTargetOptions = {}) {
|
||||
const tab = tabs.value.find((candidate) => candidate.id === id);
|
||||
if (!tab || (tab.catalog === catalog && tab.database === database)) return;
|
||||
rollbackTabTransaction(tab);
|
||||
@@ -2686,9 +2704,10 @@ export const useQueryStore = defineStore("query", () => {
|
||||
tab.resultSortedSql = undefined;
|
||||
clearExplain(tab);
|
||||
tab.tableMeta = undefined;
|
||||
persistSavedSqlExecutionTarget(tab, options);
|
||||
}
|
||||
|
||||
function updateSchema(id: string, schema: string | undefined) {
|
||||
function updateSchema(id: string, schema: string | undefined, options: UpdateExecutionTargetOptions = {}) {
|
||||
const tab = tabs.value.find((t) => t.id === id);
|
||||
if (!tab || tab.schema === schema) return;
|
||||
rollbackTabTransaction(tab);
|
||||
@@ -2703,9 +2722,10 @@ export const useQueryStore = defineStore("query", () => {
|
||||
}
|
||||
tab.schema = schema;
|
||||
if (tab.mode === "objects") tab.objectBrowser = { ...tab.objectBrowser, schema, viewport: undefined };
|
||||
persistSavedSqlExecutionTarget(tab, options);
|
||||
}
|
||||
|
||||
function updateConnection(id: string, connectionId: string, database = "") {
|
||||
function updateConnection(id: string, connectionId: string, database = "", options: UpdateExecutionTargetOptions = {}) {
|
||||
const tab = tabs.value.find((t) => t.id === id);
|
||||
if (!tab || tab.connectionId === connectionId) return;
|
||||
rollbackTabTransaction(tab, { resetAutoCommit: true });
|
||||
@@ -2723,6 +2743,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
tab.resultSortedSql = undefined;
|
||||
clearExplain(tab);
|
||||
tab.tableMeta = undefined;
|
||||
persistSavedSqlExecutionTarget(tab, options);
|
||||
}
|
||||
|
||||
function clearInvalidDataTabSortState(tab: QueryTab, columns: NonNullable<QueryTab["tableMeta"]>["columns"]): boolean {
|
||||
|
||||
@@ -25,6 +25,12 @@ interface SaveFileInput {
|
||||
sql: string;
|
||||
}
|
||||
|
||||
interface SavedSqlExecutionTargetInput {
|
||||
connectionId: string;
|
||||
database: string;
|
||||
schema?: string;
|
||||
}
|
||||
|
||||
function nowIso() {
|
||||
return new Date().toISOString();
|
||||
}
|
||||
@@ -95,6 +101,9 @@ export const useSavedSqlStore = defineStore("savedSql", () => {
|
||||
let pendingSync: Promise<void> | null = null;
|
||||
let initFromStoragePromise: Promise<void> | null = null;
|
||||
const pendingFolderCreates = new Map<string, Promise<SavedSqlFolder>>();
|
||||
const fileTargetRevisions = new Map<string, number>();
|
||||
const pendingFileTargetSaves = new Map<string, Promise<SavedSqlFile | undefined>>();
|
||||
const persistedFileTargets = new Map<string, SavedSqlExecutionTargetInput & { updatedAt: string }>();
|
||||
|
||||
const version = ref(0);
|
||||
function bumpVersion() {
|
||||
@@ -256,6 +265,79 @@ export const useSavedSqlStore = defineStore("savedSql", () => {
|
||||
return saved;
|
||||
}
|
||||
|
||||
function updateFileExecutionTarget(id: string, target: SavedSqlExecutionTargetInput): Promise<SavedSqlFile | undefined> {
|
||||
const existing = getFile(id);
|
||||
if (!existing) return Promise.resolve(undefined);
|
||||
if (existing.connectionId === target.connectionId && existing.database === target.database && existing.schema === target.schema) {
|
||||
return Promise.resolve(existing);
|
||||
}
|
||||
|
||||
if (!persistedFileTargets.has(id)) {
|
||||
persistedFileTargets.set(id, {
|
||||
connectionId: existing.connectionId,
|
||||
database: existing.database,
|
||||
schema: existing.schema,
|
||||
updatedAt: existing.updatedAt,
|
||||
});
|
||||
}
|
||||
const revision = (fileTargetRevisions.get(id) ?? 0) + 1;
|
||||
fileTargetRevisions.set(id, revision);
|
||||
files.value = files.value.map((file) => (file.id === id ? { ...file, ...target, updatedAt: nowIso() } : file));
|
||||
bumpVersion();
|
||||
|
||||
const previousSave = pendingFileTargetSaves.get(id) ?? Promise.resolve(undefined);
|
||||
const save = previousSave
|
||||
.catch(() => undefined)
|
||||
.then(async () => {
|
||||
if (fileTargetRevisions.get(id) !== revision) return getFile(id);
|
||||
|
||||
const loaded = await ensureFileContent(id);
|
||||
if (!loaded || fileTargetRevisions.get(id) !== revision) return getFile(id);
|
||||
|
||||
const candidate: SavedSqlFile = {
|
||||
...loaded,
|
||||
...target,
|
||||
sqlLoaded: true,
|
||||
updatedAt: nowIso(),
|
||||
};
|
||||
files.value = files.value.map((file) => (file.id === id ? candidate : file));
|
||||
bumpVersion();
|
||||
|
||||
try {
|
||||
const saved = await api.saveSavedSqlFile(candidate);
|
||||
persistedFileTargets.set(id, {
|
||||
connectionId: saved.connectionId,
|
||||
database: saved.database,
|
||||
schema: saved.schema,
|
||||
updatedAt: saved.updatedAt,
|
||||
});
|
||||
if (fileTargetRevisions.get(id) !== revision) return getFile(id);
|
||||
const current = getFile(id);
|
||||
const persisted = { ...saved, sql: current?.sql ?? saved.sql, sqlLoaded: current?.sqlLoaded ?? true };
|
||||
files.value = files.value.map((file) => (file.id === id ? persisted : file));
|
||||
bumpVersion();
|
||||
await syncToLocalDirectory();
|
||||
return persisted;
|
||||
} catch (error) {
|
||||
if (fileTargetRevisions.get(id) === revision) {
|
||||
const persistedTarget = persistedFileTargets.get(id);
|
||||
if (persistedTarget) files.value = files.value.map((file) => (file.id === id ? { ...file, ...persistedTarget } : file));
|
||||
bumpVersion();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
pendingFileTargetSaves.set(id, save);
|
||||
const cleanup = () => {
|
||||
if (pendingFileTargetSaves.get(id) !== save) return;
|
||||
pendingFileTargetSaves.delete(id);
|
||||
persistedFileTargets.delete(id);
|
||||
};
|
||||
void save.then(cleanup, cleanup);
|
||||
return save;
|
||||
}
|
||||
|
||||
async function renameFile(id: string, name: string) {
|
||||
const existing = getFile(id);
|
||||
if (!existing) return;
|
||||
@@ -555,10 +637,6 @@ export const useSavedSqlStore = defineStore("savedSql", () => {
|
||||
return allFiles.value.filter((f) => !f.folderId);
|
||||
}
|
||||
|
||||
function orphanedFileIds(activeConnectionIds: Set<string>) {
|
||||
return new Set(files.value.filter((f) => !activeConnectionIds.has(f.connectionId)).map((f) => f.id));
|
||||
}
|
||||
|
||||
return {
|
||||
folders,
|
||||
files,
|
||||
@@ -574,6 +652,7 @@ export const useSavedSqlStore = defineStore("savedSql", () => {
|
||||
renameFolder,
|
||||
deleteFolder,
|
||||
saveFile,
|
||||
updateFileExecutionTarget,
|
||||
renameFile,
|
||||
recordFileUsage,
|
||||
deleteFile,
|
||||
@@ -588,6 +667,5 @@ export const useSavedSqlStore = defineStore("savedSql", () => {
|
||||
allFiles,
|
||||
filesInFolder,
|
||||
filesWithoutFolder,
|
||||
orphanedFileIds,
|
||||
};
|
||||
});
|
||||
Reference in new issue
Block a user