diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index e7d9627355..aef095dd2c 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -11034,7 +11034,7 @@ function copyDdl() { function openTableStructureEditor() { if (!props.connectionId || !props.database || !props.tableMeta?.tableName || !canOpenTableStructureEditor.value) return; - queryStore.openTableStructure(props.connectionId, props.database, props.tableMeta.schema, props.tableMeta.tableName, activeTableInfoTab.value, undefined, props.tableMeta.catalog); + queryStore.openTableStructure(props.connectionId, props.database, props.tableMeta.schema, props.tableMeta.tableName, activeTableInfoTab.value, undefined, props.tableMeta.catalog, (props.tableMeta.tableType || "").toUpperCase() === "VIEW" ? "view" : "table"); } function toggleDdlWrap() { diff --git a/apps/desktop/src/components/grid/__tests__/DataGridEditTableStructureShortcut.spec.ts b/apps/desktop/src/components/grid/__tests__/DataGridEditTableStructureShortcut.spec.ts index 1986a89dff..191bd45810 100644 --- a/apps/desktop/src/components/grid/__tests__/DataGridEditTableStructureShortcut.spec.ts +++ b/apps/desktop/src/components/grid/__tests__/DataGridEditTableStructureShortcut.spec.ts @@ -167,7 +167,7 @@ describe("DataGrid edit-table-structure shortcut", () => { expect(event.defaultPrevented).toBe(true); expect(bubbled).not.toHaveBeenCalled(); expect(openTableStructure).toHaveBeenCalledOnce(); - expect(openTableStructure).toHaveBeenCalledWith("connection-1", "app", "public", "users", "ddl", undefined, "warehouse"); + expect(openTableStructure).toHaveBeenCalledWith("connection-1", "app", "public", "users", "ddl", undefined, "warehouse", "table"); }); it("uses a configured shortcut and leaves the default key untouched", async () => { diff --git a/apps/desktop/src/components/layout/ContentArea.vue b/apps/desktop/src/components/layout/ContentArea.vue index b6003e060c..8ea28b0762 100644 --- a/apps/desktop/src/components/layout/ContentArea.vue +++ b/apps/desktop/src/components/layout/ContentArea.vue @@ -964,6 +964,24 @@ function onHandleViewTableData(target: SqlObjectNavigationTarget) { emit("viewTableData", props.activeTab.id, target); } +/** + * The structure/DDL editor only owns the object identity, so build the + * navigation target from the active tab and reuse the same "view data" path as + * the SQL editor context menu (issue #6724). + */ +function onHandleStructureViewData() { + const tab = props.activeTab; + const meta = tab.tableMeta; + const tableName = tab.structureTableName || meta?.tableName; + if (!tableName) return; + emit("viewTableData", tab.id, { + name: tableName, + database: meta?.database || tab.database, + schema: meta?.schema || tab.schema, + type: tab.structureTableType === "view" ? "view" : "table", + }); +} + function onHandleViewTableDdl(target: SqlObjectNavigationTarget) { emit("viewTableDdl", props.activeTab.id, target); } @@ -2804,6 +2822,7 @@ defineExpose({ @saved="(commentChanged) => emit('structureEditorSaved', activeTab.id, commentChanged)" @close="emit('structureEditorClose', activeTab.id)" @open-settings="(initialTab, initialSection) => emit('openSettings', initialTab, initialSection)" + @view-data="onHandleStructureViewData" /> diff --git a/apps/desktop/src/components/structure/TableStructureEditor.charsetCollation.spec.ts b/apps/desktop/src/components/structure/TableStructureEditor.charsetCollation.spec.ts index 515e0d01e8..35b7086ee0 100644 --- a/apps/desktop/src/components/structure/TableStructureEditor.charsetCollation.spec.ts +++ b/apps/desktop/src/components/structure/TableStructureEditor.charsetCollation.spec.ts @@ -49,6 +49,7 @@ vi.mock("@lucide/vue", async () => { Pencil: Icon, Plus: Icon, RefreshCw: Icon, + Rows3: Icon, Save: Icon, Search: Icon, Settings: Icon, diff --git a/apps/desktop/src/components/structure/TableStructureEditor.primaryKey.spec.ts b/apps/desktop/src/components/structure/TableStructureEditor.primaryKey.spec.ts index 7da9243bb6..573c520c9b 100644 --- a/apps/desktop/src/components/structure/TableStructureEditor.primaryKey.spec.ts +++ b/apps/desktop/src/components/structure/TableStructureEditor.primaryKey.spec.ts @@ -55,6 +55,7 @@ vi.mock("@lucide/vue", async () => { Maximize2: Icon, Plus: Icon, RefreshCw: Icon, + Rows3: Icon, Save: Icon, Search: Icon, Settings: Icon, diff --git a/apps/desktop/src/components/structure/TableStructureEditor.vue b/apps/desktop/src/components/structure/TableStructureEditor.vue index 630c088770..870dc30c77 100644 --- a/apps/desktop/src/components/structure/TableStructureEditor.vue +++ b/apps/desktop/src/components/structure/TableStructureEditor.vue @@ -10,7 +10,7 @@ import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; -import { AlertTriangle, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ClipboardList, Copy, Database, Info, KeyRound, ListChevronsUpDown, Loader2, Maximize2, Pencil, Plus, RefreshCw, RotateCcw, Save, Search, Settings, SlidersHorizontal, Trash2, UserRound, X } from "@lucide/vue"; +import { AlertTriangle, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ClipboardList, Copy, Database, Info, KeyRound, ListChevronsUpDown, Loader2, Maximize2, Pencil, Plus, RefreshCw, RotateCcw, Rows3, Save, Search, Settings, SlidersHorizontal, Trash2, UserRound, X } from "@lucide/vue"; import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; @@ -173,6 +173,8 @@ const emit = defineEmits<{ saved: [commentChanged: boolean]; close: []; openSettings: [initialTab?: string, initialSection?: string]; + /** Jump from the DDL view to the table's data tab (issue #6724). */ + viewData: []; }>(); const activeTab = ref("columns"); @@ -4412,6 +4414,10 @@ watch( {{ t("structureEditor.triggers") }}
+
diff --git a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.concurrentTransition.spec.ts b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.concurrentTransition.spec.ts index 0b871ae9b4..f64531b49c 100644 --- a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.concurrentTransition.spec.ts +++ b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.concurrentTransition.spec.ts @@ -48,6 +48,7 @@ vi.mock("@lucide/vue", async () => { Maximize2: Icon, Plus: Icon, RefreshCw: Icon, + Rows3: Icon, Save: Icon, Search: Icon, Settings: Icon, diff --git a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.ddlTab.spec.ts b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.ddlTab.spec.ts index 20b54694e7..6ec7cc4fb6 100644 --- a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.ddlTab.spec.ts +++ b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.ddlTab.spec.ts @@ -66,6 +66,7 @@ vi.mock("@lucide/vue", async () => { Plus: Icon, RefreshCw: Icon, RotateCcw: Icon, + Rows3: Icon, Save: Icon, Search: Icon, Settings: Icon, diff --git a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.ddlTabLifecycle.spec.ts b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.ddlTabLifecycle.spec.ts index db0a475237..12f9aaca26 100644 --- a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.ddlTabLifecycle.spec.ts +++ b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.ddlTabLifecycle.spec.ts @@ -50,6 +50,7 @@ vi.mock("@lucide/vue", async () => { Plus: Icon, RefreshCw: Icon, RotateCcw: Icon, + Rows3: Icon, Save: Icon, Search: Icon, Settings: Icon, diff --git a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.initialTab.spec.ts b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.initialTab.spec.ts index 08e249b440..21a5929f15 100644 --- a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.initialTab.spec.ts +++ b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.initialTab.spec.ts @@ -56,6 +56,7 @@ vi.mock("@lucide/vue", async () => { Plus: Icon, RefreshCw: Icon, RotateCcw: Icon, + Rows3: Icon, Save: Icon, Search: Icon, Settings: Icon, diff --git a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.metadataRevalidation.spec.ts b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.metadataRevalidation.spec.ts index 83cea5db69..1ef769e9c7 100644 --- a/apps/desktop/src/components/structure/__tests__/TableStructureEditor.metadataRevalidation.spec.ts +++ b/apps/desktop/src/components/structure/__tests__/TableStructureEditor.metadataRevalidation.spec.ts @@ -59,6 +59,7 @@ vi.mock("@lucide/vue", async () => { Plus: Icon, RefreshCw: Icon, RotateCcw: Icon, + Rows3: Icon, Save: Icon, Search: Icon, Settings: Icon, diff --git a/apps/desktop/src/stores/queryStore.ts b/apps/desktop/src/stores/queryStore.ts index b068c910db..a3b28c7cc9 100644 --- a/apps/desktop/src/stores/queryStore.ts +++ b/apps/desktop/src/stores/queryStore.ts @@ -2433,6 +2433,7 @@ export const useQueryStore = defineStore("query", () => { resultAutoSave: t.resultAutoSave, uiState: t.uiState, structureTableName: t.structureTableName, + structureTableType: t.structureTableType, structureDraft: t.structureDraft, objectBrowser: t.objectBrowser, objectSource: t.objectSource, @@ -3680,7 +3681,7 @@ export const useQueryStore = defineStore("query", () => { tab.structureInitialTabRequestId = (tab.structureInitialTabRequestId ?? 0) + 1; } - function openTableStructure(connectionId: string, database: string, schema?: string, tableName?: string, initialTab?: TableInfoTab, initialTarget?: TableStructureEditorTarget, catalog?: string) { + function openTableStructure(connectionId: string, database: string, schema?: string, tableName?: string, initialTab?: TableInfoTab, initialTarget?: TableStructureEditorTarget, catalog?: string, tableType?: "table" | "view") { const resolvedTableName = tableName || ""; if (resolvedTableName) { const existing = tabs.value.find((tab) => tab.mode === "structure" && tab.connectionId === connectionId && tab.database === database && (tab.catalog || "") === (catalog || "") && (tab.schema || "") === (schema || "") && (tab.structureTableName || "") === resolvedTableName); @@ -3706,6 +3707,7 @@ export const useQueryStore = defineStore("query", () => { isExplaining: false, mode: "structure", structureTableName: resolvedTableName, + structureTableType: tableType, structureInitialTab: initialTab, structureInitialTabRequestId: initialTab || initialTarget?.name ? 1 : undefined, structureInitialTarget: initialTarget?.name ? initialTarget : undefined, @@ -4362,6 +4364,7 @@ export const useQueryStore = defineStore("query", () => { nacosNamespace: original.nacosNamespace, nacosNamespaceName: original.nacosNamespaceName, structureTableName: original.structureTableName, + structureTableType: original.structureTableType, structureDraft: original.structureDraft ? cloneTabDraft(original.structureDraft) : undefined, objectBrowser: original.objectBrowser ? { ...original.objectBrowser } : undefined, objectSource: original.objectSource ? { ...original.objectSource } : undefined, diff --git a/apps/desktop/src/types/database.ts b/apps/desktop/src/types/database.ts index e0b26390af..82febaf396 100644 --- a/apps/desktop/src/types/database.ts +++ b/apps/desktop/src/types/database.ts @@ -1780,6 +1780,8 @@ export interface QueryTab { nacosTargetRequestId?: number; nacosConfigEditorViewport?: NacosConfigEditorViewport; structureTableName?: string; + /** Navigation type of the opened structure object; views matter for "view data" routing. */ + structureTableType?: "table" | "view"; structureInitialTab?: TableInfoTab; structureInitialTabRequestId?: number; structureInitialTarget?: TableStructureEditorTarget; diff --git a/docs/screenshots/issue-6724-ddl-jump-to-data-result.png b/docs/screenshots/issue-6724-ddl-jump-to-data-result.png new file mode 100644 index 0000000000..cec349e3fa Binary files /dev/null and b/docs/screenshots/issue-6724-ddl-jump-to-data-result.png differ diff --git a/docs/screenshots/issue-6724-ddl-view-data-button.png b/docs/screenshots/issue-6724-ddl-view-data-button.png new file mode 100644 index 0000000000..f2a575a6f1 Binary files /dev/null and b/docs/screenshots/issue-6724-ddl-view-data-button.png differ