From 03eb26d999ca7171e8a2c3027485474c0ab01bd7 Mon Sep 17 00:00:00 2001 From: Syngnat Date: Sun, 14 Jun 2026 21:52:14 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(query-editor):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=88=87=E6=8D=A2=E6=9F=A5=E8=AF=A2=E9=A1=B5=E5=90=8E?= =?UTF-8?q?=20SQL=20=E7=BE=8E=E5=8C=96=E6=96=B9=E8=A8=80=E8=AF=AF=E5=88=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 同步查询页的 connectionId 与 dbName 状态 - 美化时按活动连接和 tab 上下文兜底选择格式化方言 - 补充 PostgreSQL ::date 场景回归测试 Close #494 --- .../QueryEditor.external-sql-save.test.tsx | 89 ++++++++++++++++++- frontend/src/components/QueryEditor.tsx | 21 ++++- 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/QueryEditor.external-sql-save.test.tsx b/frontend/src/components/QueryEditor.external-sql-save.test.tsx index 99963ff..2548ee1 100644 --- a/frontend/src/components/QueryEditor.external-sql-save.test.tsx +++ b/frontend/src/components/QueryEditor.external-sql-save.test.tsx @@ -522,8 +522,20 @@ describe('QueryEditor external SQL save', () => { backendApp.DBGetDatabases.mockResolvedValue({ success: true, data: [] }); backendApp.DBGetTables.mockResolvedValue({ success: true, data: [] }); backendApp.GenerateQueryID.mockResolvedValue('query-1'); - storeState.connections[0].config.type = 'mysql'; - storeState.connections[0].config.database = 'main'; + storeState.connections = [ + { + id: 'conn-1', + name: 'local', + config: { + type: 'mysql', + host: '127.0.0.1', + port: 3306, + user: 'root', + password: '', + database: 'main', + }, + }, + ]; storeState.appearance.uiVersion = 'legacy'; autoFetchState.visible = false; dataGridState.latestProps = null; @@ -1508,6 +1520,79 @@ describe('QueryEditor external SQL save', () => { ); }); + it('formats postgres cast syntax after switching to another query tab connection', async () => { + let renderer!: ReactTestRenderer; + storeState.connections = [ + { + id: 'conn-1', + name: 'mysql-local', + config: { + type: 'mysql', + host: '127.0.0.1', + port: 3306, + user: 'root', + password: '', + database: 'main', + }, + }, + { + id: 'conn-2', + name: 'pg-local', + config: { + type: 'postgres', + host: '127.0.0.1', + port: 5432, + user: 'postgres', + password: '', + database: 'main', + }, + }, + ]; + const pgSql = [ + 'SELECT', + ' *,', + ' is_del = 0', + 'FROM', + ' wm_stock', + 'WHERE', + ' 1 = 1', + ' AND is_del = 0', + " and create_date > '2025-06-25'::date;", + ].join('\n'); + + await act(async () => { + renderer = create(); + }); + + await act(async () => { + renderer.update( + , + ); + }); + + const formatButton = findButton(renderer, '美化'); + await act(async () => { + await formatButton.props.onClick(); + }); + + expect(messageApi.error).not.toHaveBeenCalled(); + expect(editorState.editor.executeEdits).toHaveBeenCalledWith( + 'gonavi-format-sql', + expect.arrayContaining([ + expect.objectContaining({ + text: expect.stringContaining("'2025-06-25'::date;"), + }), + ]), + ); + }); + it('shows object info via editor ctrl+q action', async () => { editorState.value = 'select users.id from users'; autoFetchState.visible = true; diff --git a/frontend/src/components/QueryEditor.tsx b/frontend/src/components/QueryEditor.tsx index 7385696..c2dac12 100644 --- a/frontend/src/components/QueryEditor.tsx +++ b/frontend/src/components/QueryEditor.tsx @@ -2047,6 +2047,19 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc currentDbRef.current = currentDb; }, [currentDb]); + useEffect(() => { + const nextConnectionId = String(tab.connectionId || '').trim(); + const nextDb = String(tab.dbName || '').trim(); + if (nextConnectionId !== currentConnectionIdRef.current) { + currentConnectionIdRef.current = nextConnectionId; + setCurrentConnectionId(nextConnectionId); + } + if (nextDb !== currentDbRef.current) { + currentDbRef.current = nextDb; + setCurrentDb(nextDb); + } + }, [tab.id, tab.connectionId, tab.dbName]); + useEffect(() => { if (isExternalSQLFileTab) return; const currentDraft = getQueryTabDraft(tab.id, query); @@ -3704,7 +3717,13 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc const handleFormat = () => { try { - const formatterLanguage = resolveQueryEditorFormatterLanguage(connections.find(c => c.id === currentConnectionId)); + const activeConnectionId = String(currentConnectionIdRef.current || '').trim(); + const tabConnectionId = String(tab.connectionId || '').trim(); + const conn = connectionsRef.current.find(c => c.id === activeConnectionId) + || (tabConnectionId && tabConnectionId !== activeConnectionId + ? connectionsRef.current.find(c => c.id === tabConnectionId) + : undefined); + const formatterLanguage = resolveQueryEditorFormatterLanguage(conn); const formatted = format(getCurrentQuery(), { language: formatterLanguage, keywordCase: sqlFormatOptions.keywordCase }); const editor = editorRef.current; const monaco = monacoRef.current;