mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-10 23:11:40 +08:00
🐛 fix(oceanbase): 修复 Oracle 协议保存与连接链路
- 测试连接统一走 RPC 配置构造,确保 OceanBase Oracle 协议生效 - 保存连接时同步写入 oceanBaseProtocol 与 protocol 参数 - 编辑回显支持从显式字段、连接参数和 URI 恢复协议 - 双击连接时清理旧树缓存,避免复用 MySQL 协议子节点 - 补充 OceanBase 协议解析与缓存 key 隔离测试
This commit is contained in:
@@ -180,7 +180,9 @@ func normalizeCacheKeyConfig(config connection.ConnectionConfig) connection.Conn
|
||||
normalized.ID = ""
|
||||
normalized.Type = strings.ToLower(strings.TrimSpace(normalized.Type))
|
||||
if normalized.Type == "oceanbase" {
|
||||
normalized.ConnectionParams = normalizeOceanBaseConnectionParamsForCache(normalized.ConnectionParams)
|
||||
protocol := resolveOceanBaseProtocolForApp(normalized)
|
||||
normalized.ConnectionParams = normalizeOceanBaseConnectionParamsForCacheWithProtocol(normalized.ConnectionParams, protocol)
|
||||
normalized.OceanBaseProtocol = ""
|
||||
}
|
||||
// timeout 仅用于 Query/Ping 控制,不应作为物理连接复用键的一部分。
|
||||
normalized.Timeout = 0
|
||||
|
||||
@@ -139,6 +139,24 @@ func TestGetCacheKey_KeepOceanBaseProtocolIsolation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCacheKey_KeepOceanBaseExplicitProtocolIsolation(t *testing.T) {
|
||||
base := connection.ConnectionConfig{
|
||||
Type: "oceanbase",
|
||||
Host: "ob.local",
|
||||
Port: 2881,
|
||||
User: "sys@oracle001",
|
||||
Database: "ORCL",
|
||||
}
|
||||
modified := base
|
||||
modified.OceanBaseProtocol = "oracle"
|
||||
|
||||
left := getCacheKey(base)
|
||||
right := getCacheKey(modified)
|
||||
if left == right {
|
||||
t.Fatalf("expected different cache key for explicit OceanBase Oracle protocol")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCacheKey_KeepOceanBaseDefaultProtocolEquivalentToMySQL(t *testing.T) {
|
||||
base := connection.ConnectionConfig{
|
||||
Type: "oceanbase",
|
||||
@@ -157,6 +175,24 @@ func TestGetCacheKey_KeepOceanBaseDefaultProtocolEquivalentToMySQL(t *testing.T)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCacheKey_KeepOceanBaseDefaultProtocolEquivalentToExplicitMySQL(t *testing.T) {
|
||||
base := connection.ConnectionConfig{
|
||||
Type: "oceanbase",
|
||||
Host: "ob.local",
|
||||
Port: 2881,
|
||||
User: "root@test",
|
||||
Database: "app",
|
||||
}
|
||||
modified := base
|
||||
modified.OceanBaseProtocol = "mysql"
|
||||
|
||||
left := getCacheKey(base)
|
||||
right := getCacheKey(modified)
|
||||
if left != right {
|
||||
t.Fatalf("expected default OceanBase protocol to equal explicit mysql, got %s vs %s", left, right)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCacheKey_OceanBaseProtocolParamWinsOverAliases(t *testing.T) {
|
||||
base := connection.ConnectionConfig{
|
||||
Type: "oceanbase",
|
||||
|
||||
@@ -54,9 +54,9 @@ func TestNormalizeRunConfig_OceanBaseOracleKeepsServiceName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := connection.ConnectionConfig{
|
||||
Type: "oceanbase",
|
||||
Database: "OBORCL",
|
||||
ConnectionParams: "protocol=oracle",
|
||||
Type: "oceanbase",
|
||||
Database: "OBORCL",
|
||||
OceanBaseProtocol: "oracle",
|
||||
}
|
||||
runConfig := normalizeRunConfig(config, "SYS")
|
||||
|
||||
@@ -69,8 +69,8 @@ func TestNormalizeSchemaAndTable_OceanBaseOracleUsesSchemaFromDatabaseTree(t *te
|
||||
t.Parallel()
|
||||
|
||||
schema, table := normalizeSchemaAndTable(connection.ConnectionConfig{
|
||||
Type: "oceanbase",
|
||||
ConnectionParams: "protocol=oracle",
|
||||
Type: "oceanbase",
|
||||
OceanBaseProtocol: "oracle",
|
||||
}, "SYS", "ORDERS")
|
||||
|
||||
if schema != "SYS" || table != "ORDERS" {
|
||||
|
||||
@@ -90,8 +90,8 @@ func TestResolveDDLDBType_OceanBaseOracleProtocol(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := connection.ConnectionConfig{
|
||||
Type: "oceanbase",
|
||||
ConnectionParams: "protocol=oracle",
|
||||
Type: "oceanbase",
|
||||
OceanBaseProtocol: "oracle",
|
||||
}
|
||||
if got := resolveDDLDBType(cfg); got != "oracle" {
|
||||
t.Fatalf("expected OceanBase Oracle protocol to use oracle DDL dialect, got %q", got)
|
||||
|
||||
@@ -11,11 +11,29 @@ func normalizeOceanBaseProtocolForApp(raw string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(raw)) {
|
||||
case "oracle", "oracle-mode", "oracle_mode", "oboracle":
|
||||
return "oracle"
|
||||
case "mysql", "mysql-compatible", "mysql_compatible", "mysql-mode", "mysql_mode":
|
||||
return "mysql"
|
||||
default:
|
||||
return "mysql"
|
||||
}
|
||||
}
|
||||
|
||||
func resolveOceanBaseProtocolForApp(config connection.ConnectionConfig) string {
|
||||
if !strings.EqualFold(strings.TrimSpace(config.Type), "oceanbase") {
|
||||
return ""
|
||||
}
|
||||
if explicit := strings.TrimSpace(config.OceanBaseProtocol); explicit != "" {
|
||||
return normalizeOceanBaseProtocolForApp(explicit)
|
||||
}
|
||||
if protocol := resolveOceanBaseProtocolParam(config.ConnectionParams); protocol != "" {
|
||||
return protocol
|
||||
}
|
||||
if protocol := resolveOceanBaseProtocolParam(config.URI); protocol != "" {
|
||||
return protocol
|
||||
}
|
||||
return "mysql"
|
||||
}
|
||||
|
||||
func resolveOceanBaseProtocolParam(raw string) string {
|
||||
text := strings.TrimSpace(raw)
|
||||
if text == "" {
|
||||
@@ -61,15 +79,19 @@ func normalizeOceanBaseConnectionParamsForCache(raw string) string {
|
||||
return values.Encode()
|
||||
}
|
||||
|
||||
func isOceanBaseOracleProtocol(config connection.ConnectionConfig) bool {
|
||||
if !strings.EqualFold(strings.TrimSpace(config.Type), "oceanbase") {
|
||||
return false
|
||||
func normalizeOceanBaseConnectionParamsForCacheWithProtocol(raw string, protocol string) string {
|
||||
normalized := normalizeOceanBaseConnectionParamsForCache(raw)
|
||||
if !strings.EqualFold(protocol, "oracle") {
|
||||
return normalized
|
||||
}
|
||||
if protocol := resolveOceanBaseProtocolParam(config.ConnectionParams); protocol != "" {
|
||||
return protocol == "oracle"
|
||||
values, err := url.ParseQuery(strings.TrimLeft(strings.TrimSpace(normalized), "?&"))
|
||||
if err != nil {
|
||||
values = url.Values{}
|
||||
}
|
||||
if protocol := resolveOceanBaseProtocolParam(config.URI); protocol != "" {
|
||||
return protocol == "oracle"
|
||||
}
|
||||
return false
|
||||
values.Set("protocol", "oracle")
|
||||
return values.Encode()
|
||||
}
|
||||
|
||||
func isOceanBaseOracleProtocol(config connection.ConnectionConfig) bool {
|
||||
return resolveOceanBaseProtocolForApp(config) == "oracle"
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ type ConnectionConfig struct {
|
||||
RedisDB int `json:"redisDB,omitempty"` // Redis database index (0-15)
|
||||
URI string `json:"uri,omitempty"` // Connection URI for copy/paste
|
||||
ClickHouseProtocol string `json:"clickHouseProtocol,omitempty"` // auto | http | native
|
||||
OceanBaseProtocol string `json:"oceanBaseProtocol,omitempty"` // mysql | oracle
|
||||
Hosts []string `json:"hosts,omitempty"` // Multi-host addresses: host:port
|
||||
Topology string `json:"topology,omitempty"` // single | replica | cluster
|
||||
MySQLReplicaUser string `json:"mysqlReplicaUser,omitempty"` // MySQL replica auth user
|
||||
|
||||
@@ -171,6 +171,9 @@ func resolveOceanBaseProtocolFromValues(values url.Values) string {
|
||||
}
|
||||
|
||||
func resolveOceanBaseProtocol(config connection.ConnectionConfig) string {
|
||||
if explicit := strings.TrimSpace(config.OceanBaseProtocol); explicit != "" {
|
||||
return normalizeOceanBaseProtocol(explicit)
|
||||
}
|
||||
if protocol := resolveOceanBaseProtocolFromValues(connectionParamsFromText(config.ConnectionParams)); protocol != "" {
|
||||
return protocol
|
||||
}
|
||||
@@ -213,6 +216,7 @@ func stripOceanBaseProtocolURI(raw string) string {
|
||||
|
||||
func withoutOceanBaseProtocolParams(config connection.ConnectionConfig) connection.ConnectionConfig {
|
||||
next := config
|
||||
next.OceanBaseProtocol = ""
|
||||
next.ConnectionParams = stripOceanBaseProtocolParams(config.ConnectionParams)
|
||||
next.URI = stripOceanBaseProtocolURI(config.URI)
|
||||
return next
|
||||
|
||||
@@ -56,6 +56,15 @@ func TestResolveOceanBaseProtocol(t *testing.T) {
|
||||
},
|
||||
want: oceanBaseProtocolMySQL,
|
||||
},
|
||||
{
|
||||
name: "explicit config protocol wins over params",
|
||||
config: connection.ConnectionConfig{
|
||||
Type: "oceanbase",
|
||||
OceanBaseProtocol: "oracle",
|
||||
ConnectionParams: "protocol=mysql",
|
||||
},
|
||||
want: oceanBaseProtocolOracle,
|
||||
},
|
||||
{
|
||||
name: "protocol key wins over compatibility aliases",
|
||||
config: connection.ConnectionConfig{
|
||||
|
||||
Reference in New Issue
Block a user