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;