fix(tabs): reuse data tabs only for the same table

This commit is contained in:
zipg authored and GitHub committed 2026-08-03 17:05:56 +08:00
1 parent 6e4363be36
commit 51560c49ae
16 files changed
+115 -23

No files matched your search

@@ -221,6 +221,10 @@ describe("query execution schema", () => {
});
describe("object tree node schema", () => {
it("ignores database-shaped schema metadata for MySQL tables", () => {
expect(connectionObjectTreeNodeSchema({ db_type: "mysql" }, "app", "app")).toBeUndefined();
});
it("uses the SQLite database alias to qualify attached tables", () => {
expect(connectionObjectTreeNodeSchema({ db_type: "sqlite" }, "analytics")).toBe("analytics");
});
@@ -52,11 +52,11 @@ describe("dataTabOpenPolicy", () => {
const existing = dataTab("users", "users");
existing.tableMeta = { schema: "public", tableName: "users", columns: [], primaryKeys: [] };
expect(findExistingDataTabCandidate([existing], usersTarget, { openMode: "new-tab", reuseScope: "database" })).toBeUndefined();
expect(findExistingDataTabCandidate([existing], usersTarget, { openMode: "new-tab", reuseScope: "same-table" })).toBeUndefined();
expect(findExistingDataTabCandidate([existing], usersTarget, { openMode: "new-tab", reuseScope: "none" })).toBeUndefined();
});
it("applies none, same-table, and database reuse scopes independently", () => {
it("only reuses the same table when reuse is enabled", () => {
const sameTable = dataTab("users", "users");
sameTable.tableMeta = { schema: "public", tableName: "users", columns: [], primaryKeys: [] };
const otherTable = dataTab("orders", "orders");
@@ -64,7 +64,13 @@ describe("dataTabOpenPolicy", () => {
expect(findExistingDataTabCandidate([sameTable], usersTarget, { openMode: "default", reuseScope: "none" })).toBeUndefined();
expect(findExistingDataTabCandidate([sameTable], usersTarget, { openMode: "default", reuseScope: "same-table" })).toEqual({ tab: sameTable, match: "same-table" });
expect(findExistingDataTabCandidate([otherTable], usersTarget, { openMode: "default", reuseScope: "same-table" })).toBeUndefined();
expect(findExistingDataTabCandidate([otherTable], usersTarget, { openMode: "default", reuseScope: "database" })).toEqual({ tab: otherTable, match: "database" });
});
it("does not reuse a same-name table from another schema", () => {
const archiveUsers = dataTab("archive-users", "users", "archive");
archiveUsers.tableMeta = { schema: "archive", tableName: "users", columns: [], primaryKeys: [] };
expect(findExistingDataTabCandidate([archiveUsers], usersTarget, { openMode: "default", reuseScope: "same-table" })).toBeUndefined();
});
it("allows metadata to update a tab that still points to the requested table", () => {
+4 -4
View File
@@ -175,11 +175,11 @@ export function metadataSchemaForConnection(connection: JdbcDialectConnection |
export function connectionObjectTreeNodeSchema(connection: JdbcDialectConnection | undefined, database: string, schema?: string): string | undefined {
if (connection?.db_type === "jdbc" && inferJdbcDialect(connection) === "databend") return schema || database;
if (connectionUsesDatabaseObjectTreeMode(connection)) return undefined;
if (schema) return schema;
const type = effectiveDatabaseTypeForConnection(connection);
if (type === "informix") return undefined;
if (type === "sqlite") return database;
return isSchemaAware(type) ? database : undefined;
if (type === "informix") return schema || undefined;
if (type === "sqlite") return schema || database;
if (!type) return schema;
return isSchemaAware(type) ? schema || database : undefined;
}
/** Maps a database type to the corresponding CodeMirror SQL dialect name used by QueryEditor and DdlViewDialog. */
@@ -2,7 +2,7 @@ import { matchesModifierOnlyShortcut, type ShortcutLikeEvent } from "@/lib/edito
import type { QueryTab, TreeNodeType } from "@/types/database";
export type DataTabOpenMode = "default" | "new-tab";
export type DataTabReuseScope = "none" | "same-table" | "database";
export type DataTabReuseScope = "none" | "same-table";
type DataTabLike = Pick<QueryTab, "id" | "mode" | "connectionId" | "database" | "schema" | "title" | "tableMeta" | "tableMetaUpdatedAt">;
@@ -16,7 +16,7 @@ export interface DataTabTarget {
export type ExistingDataTabCandidate<T extends DataTabLike> = {
tab: T;
match: "same-table" | "database";
match: "same-table";
};
const dataNodeTypes = new Set<TreeNodeType>(["table", "view", "materialized_view"]);
@@ -53,8 +53,5 @@ export function findExistingDataTabCandidate<T extends DataTabLike>(tabs: T[], t
const sameTable = tabs.find((tab) => isSameTable(tab, target));
if (sameTable) return { tab: sameTable, match: "same-table" };
if (options.reuseScope === "same-table") return undefined;
const sameDatabase = tabs.find((tab) => isSameDatabase(tab, target));
return sameDatabase ? { tab: sameDatabase, match: "database" } : undefined;
return undefined;
}