🐛 fix(sidebar): 修复视图缺失元数据时定位失败

This commit is contained in:
Syngnat
2026-06-09 23:51:36 +08:00
parent c742b4d61e
commit 73e93e955c
3 changed files with 81 additions and 3 deletions

View File

@@ -2790,7 +2790,7 @@ const Sidebar: React.FC<{
});
return;
} else if (node.type === 'view' || node.type === 'materialized-view') {
const { viewName, dbName, id } = node.dataRef;
const { viewName, dbName, id, schemaName } = node.dataRef;
addTab({
id: node.key,
title: viewName,
@@ -2799,6 +2799,8 @@ const Sidebar: React.FC<{
dbName,
tableName: viewName,
objectType: node.type === 'materialized-view' ? 'materialized-view' : 'view',
schemaName,
sidebarLocateKey: String(node.key || ''),
});
return;
} else if (node.type === 'saved-query') {
@@ -4346,7 +4348,7 @@ const Sidebar: React.FC<{
// --- 视图操作 ---
const openViewDefinition = (node: any) => {
const { viewName, dbName, id } = node.dataRef;
const { viewName, dbName, id, schemaName } = node.dataRef;
const isMaterialized = node.type === 'materialized-view' || node.dataRef?.objectKind === 'materialized-view';
addTab({
id: `view-def-${id}-${dbName}-${viewName}`,
@@ -4356,6 +4358,8 @@ const Sidebar: React.FC<{
dbName,
viewName,
viewKind: isMaterialized ? 'materialized' : 'view',
schemaName,
sidebarLocateKey: String(node.key || ''),
});
};

View File

@@ -96,6 +96,21 @@ describe('sidebarLocate', () => {
})).toBeNull();
});
it('keeps table-style view tabs on the views branch', () => {
expect(normalizeSidebarLocateObjectRequestFromTab({
id: 'legacy-view-tab-id',
type: 'table',
connectionId: 'conn-1',
dbName: 'GDB_APP',
tableName: 'V_ACCOUNT',
objectType: 'view',
})).toMatchObject({
tabId: 'legacy-view-tab-id',
tableName: 'V_ACCOUNT',
objectGroup: 'views',
});
});
it('builds locate requests from trigger and routine tabs', () => {
expect(normalizeSidebarLocateObjectRequestFromTab({
id: 'trigger-conn-1-main-audit.users_bi',
@@ -690,6 +705,52 @@ describe('sidebarLocate', () => {
]);
});
it('finds a schema-qualified view request by visual title when the node has no schema metadata', () => {
const target = resolveSidebarLocateTarget({
tabId: 'stale-view-tab-id',
connectionId: 'conn-1',
dbName: 'GDB_APP',
tableName: 'SYSDBA.V_ACCOUNT',
schemaName: 'SYSDBA',
objectGroup: 'views',
}, { groupBySchema: false });
const tree = [
{
key: 'conn-1',
children: [
{
key: 'conn-1-GDB_APP',
dataRef: { id: 'conn-1', dbName: 'GDB_APP' },
children: [
{
key: 'conn-1-GDB_APP-views',
children: [
{
key: 'conn-1-GDB_APP-view-generated-key',
title: 'V_ACCOUNT',
type: 'view',
dataRef: {
id: 'conn-1',
dbName: 'GDB_APP',
},
},
],
},
],
},
],
},
];
expect(findSidebarNodePathForLocate(tree, target)).toEqual([
'conn-1',
'conn-1-GDB_APP',
'conn-1-GDB_APP-views',
'conn-1-GDB_APP-view-generated-key',
]);
});
it('falls back from a schema-qualified view request to a bare table-like node in the same database', () => {
const target = resolveSidebarLocateTarget({
tabId: 'stale-view-tab-id',

View File

@@ -60,6 +60,7 @@ export interface SidebarLocateTabLike {
schemaName?: string;
sidebarLocateKey?: string;
filePath?: string;
objectType?: string;
}
const toTrimmedString = (value: unknown): string => String(value ?? '').trim();
@@ -167,7 +168,11 @@ export const normalizeSidebarLocateObjectRequestFromTab = (tab: SidebarLocateTab
schemaName: tab.schemaName,
objectGroup: tab.type === 'view-def'
? (tab.viewKind === 'materialized' ? 'materializedViews' : 'views')
: (tab.type === 'trigger' ? 'triggers' : (tab.type === 'routine-def' ? 'routines' : undefined)),
: (tab.type === 'trigger'
? 'triggers'
: (tab.type === 'routine-def'
? 'routines'
: (tab.objectType === 'materialized-view' ? 'materializedViews' : (tab.objectType === 'view' ? 'views' : undefined)))),
});
};
@@ -278,6 +283,14 @@ const matchesLocateObjectName = (
return true;
}
if (
options.allowUnqualifiedSchemaMatch
&& !resolvedNodeSchema
&& normalizeLocateName(nodeObject) === normalizeLocateName(targetObject)
) {
return true;
}
if (!resolvedTargetSchema) {
if (options.allowUnqualifiedSchemaMatch) {
return normalizeLocateName(nodeObject) === normalizeLocateName(targetObject);