🐛 fix(clickhouse): 修正 8132 端口连接失败

- 将 8132 纳入 ClickHouse HTTP 端口识别范围
- 同步修正协议切换日志与错误提示中的端口说明
- 补充连接协议识别回归测试并更新 backlog 记录

Fixes #338
This commit is contained in:
Syngnat
2026-04-17 12:27:20 +08:00
parent 8c79f2af0c
commit 890478eb7b
3 changed files with 83 additions and 3 deletions

View File

@@ -32,6 +32,7 @@
| #331 | 重复连接 DB一分钟重试了 60 多次 | Fixed | `ca76440` |
| #333 | AI 功能添加供应商测试正常,但问答显示失败 | Fixed | Pending |
| #337 | 自动更新无效 | Fixed | Pending |
| #338 | 连接clickhouse不能通过8132端口 | Fixed | Pending |
| #351 | 为什么没有截断和清空表的功能呀? | Fixed | Pending |
## Notes
@@ -102,6 +103,12 @@
- 处理:为更新资产解析新增“基于当前可执行文件路径推断 Linux 变体”的后缀选择逻辑;同时调整 Linux 更新脚本,解压后优先搜索与当前运行二进制同名的文件,再回退查找 `GoNavi`
- 验证:补充 `internal/app/methods_update_test.go` 回归测试,覆盖 Linux `WebKit41` 资产名选择与更新脚本目标名解析,并执行 `go test ./internal/app -run 'Test(ExpectedAssetNameForExecutableUsesLinuxWebKit41Suffix|BuildLinuxScriptPrefersTargetExecutableBasename|TestFetchLatestUpdateInfo|TestCheckForUpdates|TestBuildWindowsScript)' -count=1`
### #338
- 根因ClickHouse 连接协议识别只把 `8123/8443` 视为 HTTP 端口,`8132` 会被误判为 native导致连接阶段优先走错协议。
- 处理:将 `8132` 纳入 ClickHouse HTTP 端口识别,并同步更新自动切换日志和错误提示中的端口说明,避免排障信息继续误导。
- 验证:补充 `internal/db/clickhouse_impl_test.go` 回归测试,覆盖 `8132``8123``8443` 的 HTTP 判定以及 `9000/9440` 的 native 判定,并执行 `go test -tags gonavi_clickhouse_driver ./internal/db -run 'TestClickHouse(PingValidatesQueryPath|GetDatabasesFallsBackToCurrentDatabase|DetectClickHouseProtocolTreatsHTTPPortsAsHTTP)' -count=1`
### #330
- 根因:查询结果表格已经支持拖拽调整列宽,但 resize handle 没有提供双击自适应逻辑,导致用户只能靠手工拖拽慢慢试宽度。

View File

@@ -26,6 +26,7 @@ const (
defaultClickHouseUser = "default"
defaultClickHouseDatabase = "default"
minClickHouseReadTimeout = 5 * time.Minute
clickHouseHTTPPortHint = "8123/8132/8443"
)
type ClickHouseDB struct {
@@ -133,12 +134,21 @@ func detectClickHouseProtocol(config connection.ConnectionConfig) clickhouse.Pro
if strings.HasPrefix(uriText, "http://") || strings.HasPrefix(uriText, "https://") {
return clickhouse.HTTP
}
if config.Port == 8123 || config.Port == 8443 {
if isClickHouseHTTPPort(config.Port) {
return clickhouse.HTTP
}
return clickhouse.Native
}
func isClickHouseHTTPPort(port int) bool {
switch port {
case 8123, 8132, 8443:
return true
default:
return false
}
}
func isClickHouseProtocolMismatch(err error) bool {
if err == nil {
return false
@@ -246,14 +256,14 @@ func (c *ClickHouseDB) Connect(config connection.ConnectionConfig) error {
logger.Warnf("ClickHouse SSL 优先连接失败,已回退至明文连接")
}
if pIdx > 0 {
logger.Warnf("ClickHouse 已自动切换连接协议为 %s常见于 8123/8443 HTTP 端口)", protocol.String())
logger.Warnf("ClickHouse 已自动切换连接协议为 %s常见于 %s HTTP 端口)", protocol.String(), clickHouseHTTPPortHint)
}
return nil
}
}
_ = c.Close()
return fmt.Errorf("连接建立后验证失败(可检查 ClickHouse 端口与协议是否匹配Native=9000/9440HTTP=8123/8443%s", strings.Join(failures, ""))
return fmt.Errorf("连接建立后验证失败(可检查 ClickHouse 端口与协议是否匹配Native=9000/9440HTTP=%s%s", clickHouseHTTPPortHint, strings.Join(failures, ""))
}
func (c *ClickHouseDB) Close() error {

View File

@@ -12,6 +12,10 @@ import (
"sync"
"testing"
"time"
"GoNavi-Wails/internal/connection"
clickhouse "github.com/ClickHouse/clickhouse-go/v2"
)
const fakeClickHouseDriverName = "gonavi-fake-clickhouse"
@@ -129,6 +133,65 @@ func TestClickHouseGetDatabasesFallsBackToCurrentDatabase(t *testing.T) {
}
}
func TestDetectClickHouseProtocolTreatsHTTPPortsAsHTTP(t *testing.T) {
tests := []struct {
name string
config connection.ConnectionConfig
expected clickhouse.Protocol
}{
{
name: "http uri",
config: connection.ConnectionConfig{
URI: "http://127.0.0.1:8132/default",
},
expected: clickhouse.HTTP,
},
{
name: "default http port",
config: connection.ConnectionConfig{
Port: 8123,
},
expected: clickhouse.HTTP,
},
{
name: "alternate http port 8132",
config: connection.ConnectionConfig{
Port: 8132,
},
expected: clickhouse.HTTP,
},
{
name: "https port",
config: connection.ConnectionConfig{
Port: 8443,
},
expected: clickhouse.HTTP,
},
{
name: "native port",
config: connection.ConnectionConfig{
Port: 9000,
},
expected: clickhouse.Native,
},
{
name: "native tls port",
config: connection.ConnectionConfig{
Port: 9440,
},
expected: clickhouse.Native,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if protocol := detectClickHouseProtocol(tt.config); protocol != tt.expected {
t.Fatalf("expected protocol %s, got %s", tt.expected.String(), protocol.String())
}
})
}
}
type fakeClickHouseDriver struct{}
func (fakeClickHouseDriver) Open(name string) (driver.Conn, error) {