fix(navigator): preserve table identity when opening objects
This commit is contained in:
parent
552e1741db
commit
e226a5670e
|
|
@ -50,6 +50,18 @@ async function openTableTarget(target: NavigationTarget, options: { tableInfoTab
|
|||
})();
|
||||
const targetTab = queryStore.tabs.find((tab) => tab.id === tabId);
|
||||
if (targetTab) targetTab.tableInfoTab = options.tableInfoTab;
|
||||
// Stamp the new table identity synchronously so SQL rebuilds (refresh,
|
||||
// filters, row count) never read a stale tableMeta from a reused tab or
|
||||
// fall back to parsing the schema-qualified tab title (issue #3613).
|
||||
queryStore.setTableMeta(tabId, {
|
||||
schema: target.schema,
|
||||
catalog: target.catalog,
|
||||
database: target.database,
|
||||
tableName: target.tableName,
|
||||
tableType: target.tableType ?? "TABLE",
|
||||
columns: [],
|
||||
primaryKeys: [],
|
||||
});
|
||||
queryStore.setExecuting(tabId, true);
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,19 @@ import type { QueryTab, ColumnInfo } from "@/types/database";
|
|||
|
||||
export type DataTabTableMeta = NonNullable<QueryTab["tableMeta"]>;
|
||||
|
||||
// Data tabs opened from the object browser are titled "<schema>.<table>".
|
||||
// When the tab has no usable tableMeta yet, strip the schema prefix so SQL
|
||||
// rebuilt from this fallback does not qualify the table twice
|
||||
// (e.g. [dbo].[dbo.users] on SQL Server — see issue #3613).
|
||||
function titleTableName(tab: QueryTab): string {
|
||||
const title = tab.title.trim();
|
||||
const schema = tab.schema?.trim();
|
||||
if (schema && title.length > schema.length + 1 && title.startsWith(`${schema}.`)) {
|
||||
return title.slice(schema.length + 1);
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
function fallbackColumnInfo(name: string): ColumnInfo {
|
||||
return {
|
||||
name,
|
||||
|
|
@ -16,7 +29,7 @@ function fallbackColumnInfo(name: string): ColumnInfo {
|
|||
export function tableMetaForDataTab(tab: QueryTab | undefined): DataTabTableMeta | undefined {
|
||||
if (!tab || tab.mode !== "data") return undefined;
|
||||
if (tab.tableMeta?.columns.length) return tab.tableMeta;
|
||||
const tableName = tab.title.trim();
|
||||
const tableName = tab.tableMeta?.tableName.trim() || titleTableName(tab);
|
||||
if (!tableName) return undefined;
|
||||
|
||||
// Keep filters usable when the table identity loaded but its column metadata did not.
|
||||
|
|
|
|||
|
|
@ -122,6 +122,35 @@ test("uses result columns when persisted table metadata has no columns", () => {
|
|||
);
|
||||
});
|
||||
|
||||
test("prefers the tableMeta table name over a schema-qualified tab title", () => {
|
||||
// Data tabs opened from the object browser are titled "<schema>.<table>";
|
||||
// rebuilding SQL from the title would qualify the table twice (issue #3613).
|
||||
const tableMeta = {
|
||||
schema: "dbo",
|
||||
tableName: "wcs_dispatch_task",
|
||||
columns: [],
|
||||
primaryKeys: [],
|
||||
};
|
||||
|
||||
const meta = tableMetaForDataTab(tab({ title: "dbo.wcs_dispatch_task", schema: "dbo", tableMeta }));
|
||||
|
||||
assert.equal(meta?.tableName, "wcs_dispatch_task");
|
||||
assert.equal(meta?.schema, "dbo");
|
||||
});
|
||||
|
||||
test("strips the schema prefix from the tab title when no tableMeta exists", () => {
|
||||
const meta = tableMetaForDataTab(tab({ title: "dbo.wcs_dispatch_task", schema: "dbo" }));
|
||||
|
||||
assert.equal(meta?.tableName, "wcs_dispatch_task");
|
||||
assert.equal(meta?.schema, "dbo");
|
||||
});
|
||||
|
||||
test("keeps a dotted tab title intact when it does not start with the schema", () => {
|
||||
const meta = tableMetaForDataTab(tab({ title: "audit.2024_log", schema: "public" }));
|
||||
|
||||
assert.equal(meta?.tableName, "audit.2024_log");
|
||||
});
|
||||
|
||||
test("does not infer table metadata for query tabs", () => {
|
||||
assert.equal(tableMetaForDataTab(tab({ mode: "query" })), undefined);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue