From e8ad34d2f03dfe3c7da6546aa8b06b37a44a7f2a Mon Sep 17 00:00:00 2001 From: Syngnat <92659908+Syngnat@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:47:50 +0800 Subject: [PATCH 1/4] fix(oceanbase): extend default Oracle query timeout --- internal/app/db_context.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/app/db_context.go b/internal/app/db_context.go index e47f3fb6..98323571 100644 --- a/internal/app/db_context.go +++ b/internal/app/db_context.go @@ -9,6 +9,8 @@ import ( "GoNavi-Wails/internal/db" ) +const defaultOceanBaseOracleQueryTimeoutSeconds = 120 + func normalizeRunConfig(config connection.ConnectionConfig, dbName string) connection.ConnectionConfig { runConfig := config name := strings.TrimSpace(dbName) @@ -54,6 +56,10 @@ func applyOceanBaseOracleCurrentSchemaInit(config connection.ConnectionConfig, s if normalizedSchema == "" { return config } + if config.Timeout <= 0 { + // OceanBase Oracle 查询经常需要经过 OBProxy/Oracle driver 的读等待;默认 30s 容易把慢查询误报成 driver: bad connection。 + config.Timeout = defaultOceanBaseOracleQueryTimeoutSeconds + } values, err := url.ParseQuery(strings.TrimSpace(config.ConnectionParams)) if err != nil { return config From b6189274545222c4b70cd1de8c47f3b2f49abf43 Mon Sep 17 00:00:00 2001 From: Syngnat <92659908+Syngnat@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:48:27 +0800 Subject: [PATCH 2/4] test(oceanbase): cover Oracle query timeout default --- internal/app/db_context_oceanbase_oracle_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/app/db_context_oceanbase_oracle_test.go b/internal/app/db_context_oceanbase_oracle_test.go index bd831bac..3f3cebc8 100644 --- a/internal/app/db_context_oceanbase_oracle_test.go +++ b/internal/app/db_context_oceanbase_oracle_test.go @@ -20,6 +20,9 @@ func TestNormalizeRunConfig_OceanBaseOracleAddsCurrentSchemaInit(t *testing.T) { if runConfig.Database != "OBORCL" { t.Fatalf("expected OceanBase Oracle service name to stay OBORCL, got %q", runConfig.Database) } + if runConfig.Timeout != defaultOceanBaseOracleQueryTimeoutSeconds { + t.Fatalf("expected OceanBase Oracle default query timeout %d, got %d", defaultOceanBaseOracleQueryTimeoutSeconds, runConfig.Timeout) + } values, err := url.ParseQuery(runConfig.ConnectionParams) if err != nil { t.Fatalf("unexpected connection params parse error: %v", err) @@ -30,17 +33,21 @@ func TestNormalizeRunConfig_OceanBaseOracleAddsCurrentSchemaInit(t *testing.T) { } } -func TestNormalizeRunConfig_OceanBaseOraclePreservesExistingInit(t *testing.T) { +func TestNormalizeRunConfig_OceanBaseOraclePreservesExplicitTimeoutAndExistingInit(t *testing.T) { t.Parallel() config := connection.ConnectionConfig{ Type: "oceanbase", Database: "OBORCL", OceanBaseProtocol: "oracle", + Timeout: 45, ConnectionParams: "init=ALTER+SESSION+SET+NLS_DATE_FORMAT%3D%27YYYY-MM-DD%27&timeout=10s", } runConfig := normalizeRunConfig(config, "sbdev") + if runConfig.Timeout != 45 { + t.Fatalf("expected explicit timeout to be preserved, got %d", runConfig.Timeout) + } values, err := url.ParseQuery(runConfig.ConnectionParams) if err != nil { t.Fatalf("unexpected connection params parse error: %v", err) From 9ae35e5fec376c18aab586a9aa8823d1f8343e7d Mon Sep 17 00:00:00 2001 From: Syngnat <92659908+Syngnat@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:49:39 +0800 Subject: [PATCH 3/4] fix(query-editor): classify driver bad connection as timeout --- frontend/src/utils/sqlErrorSemantics.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/utils/sqlErrorSemantics.ts b/frontend/src/utils/sqlErrorSemantics.ts index 987ff53d..f6f5f8c2 100644 --- a/frontend/src/utils/sqlErrorSemantics.ts +++ b/frontend/src/utils/sqlErrorSemantics.ts @@ -135,6 +135,7 @@ const SQL_ERROR_RULES: SqlErrorSemanticRule[] = [ /context cancelled/i, /timeout/i, /timed out/i, + /driver:\s*bad connection/i, ], }, { From 7ee86981657e858b43469dbafcb55d6bd2f5abd0 Mon Sep 17 00:00:00 2001 From: Syngnat <92659908+Syngnat@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:50:57 +0800 Subject: [PATCH 4/4] test(query-editor): cover bad connection timeout semantics --- frontend/src/utils/sqlErrorSemantics.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontend/src/utils/sqlErrorSemantics.test.ts b/frontend/src/utils/sqlErrorSemantics.test.ts index 819229b4..02d1b3f3 100644 --- a/frontend/src/utils/sqlErrorSemantics.test.ts +++ b/frontend/src/utils/sqlErrorSemantics.test.ts @@ -37,6 +37,13 @@ describe('formatSqlExecutionError', () => { expect(formatted).toContain('Raw error: driver returned unexpected status 123'); }); + it('recognizes driver bad connection during SQL execution as timeout semantics', () => { + const formatted = formatSqlExecutionError('第 1 条语句执行失败:driver: bad connection'); + + expect(formatted).toContain('Semantic meaning: Query timed out or was canceled'); + expect(formatted).toContain('Raw error: 第 1 条语句执行失败:driver: bad connection'); + }); + it('recognizes localized connection-timeout wrappers as timeout semantics', () => { const translate = (key: string, params?: Record) => { if (key === 'query_editor.sql_error.wrapper.semantic_line') {