mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-22 08:50:17 +08:00
- DSN 注入 sql_mode='ANSI_QUOTES':让元数据查询的 AS "OWNER" 与 ApplyChanges 的 "schema"."table" 在 MySQL wire 上被识别为标识符 - sql_mode 加入 mysql driver 参数白名单,避免被 mergeMySQLConnectionParam 过滤丢弃 - 加载 Oracle 列元数据失败不再静默,改为返回带 ALL_TAB_COLUMNS 诊断提示的明确错误 - 修复 stripOceanBaseConnectionParamsForCache 未剥离 # 片段导致与 resolveOceanBaseProtocolParam 行为不一致 - 锁定 mysql ParseDSN 对 sys@oracle001#cluster:p@ss 类租户凭据切分的 invariant,防止未来误加 url.QueryEscape - 同步 OceanBase agent revision,强制旧 driver-agent 被运行时校验拒绝
142 lines
3.9 KiB
Go
142 lines
3.9 KiB
Go
package app
|
|
|
|
import (
|
|
"net/url"
|
|
"strings"
|
|
|
|
"GoNavi-Wails/internal/connection"
|
|
)
|
|
|
|
func normalizeOceanBaseProtocolForApp(raw string) string {
|
|
normalized := strings.ToLower(strings.TrimSpace(raw))
|
|
switch normalized {
|
|
case "oracle", "oracle-mode", "oracle_mode", "oboracle":
|
|
return "oracle"
|
|
case "mysql", "mysql-compatible", "mysql_compatible", "mysql-mode", "mysql_mode", "obmysql":
|
|
return "mysql"
|
|
default:
|
|
return normalized
|
|
}
|
|
}
|
|
|
|
func isSupportedOceanBaseProtocolForApp(protocol string) bool {
|
|
return protocol == "mysql" || protocol == "oracle"
|
|
}
|
|
|
|
func resolveOceanBaseProtocolForApp(config connection.ConnectionConfig) string {
|
|
if !strings.EqualFold(strings.TrimSpace(config.Type), "oceanbase") {
|
|
return ""
|
|
}
|
|
explicitProtocol := ""
|
|
if explicit := strings.TrimSpace(config.OceanBaseProtocol); explicit != "" {
|
|
explicitProtocol = normalizeOceanBaseProtocolForApp(explicit)
|
|
if !isSupportedOceanBaseProtocolForApp(explicitProtocol) {
|
|
return explicitProtocol
|
|
}
|
|
}
|
|
if protocol := resolveOceanBaseProtocolParam(config.ConnectionParams); protocol != "" {
|
|
if !isSupportedOceanBaseProtocolForApp(protocol) {
|
|
return protocol
|
|
}
|
|
if explicitProtocol != "" {
|
|
return explicitProtocol
|
|
}
|
|
return protocol
|
|
}
|
|
if protocol := resolveOceanBaseProtocolParam(config.URI); protocol != "" {
|
|
if !isSupportedOceanBaseProtocolForApp(protocol) {
|
|
return protocol
|
|
}
|
|
if explicitProtocol != "" {
|
|
return explicitProtocol
|
|
}
|
|
return protocol
|
|
}
|
|
if explicitProtocol != "" {
|
|
return explicitProtocol
|
|
}
|
|
return "mysql"
|
|
}
|
|
|
|
func resolveOceanBaseProtocolParam(raw string) string {
|
|
text := strings.TrimSpace(raw)
|
|
if text == "" {
|
|
return ""
|
|
}
|
|
if queryIndex := strings.Index(text, "?"); queryIndex >= 0 {
|
|
text = text[queryIndex+1:]
|
|
}
|
|
if hashIndex := strings.Index(text, "#"); hashIndex >= 0 {
|
|
text = text[:hashIndex]
|
|
}
|
|
values, err := url.ParseQuery(strings.TrimLeft(strings.TrimSpace(text), "?&"))
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
for _, key := range []string{"protocol", "oceanBaseProtocol", "oceanbaseProtocol", "tenantMode", "compatMode", "mode"} {
|
|
if value := strings.TrimSpace(values.Get(key)); value != "" {
|
|
return normalizeOceanBaseProtocolForApp(value)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func stripOceanBaseConnectionParamsForCache(raw string) string {
|
|
text := strings.TrimSpace(raw)
|
|
if text == "" {
|
|
return ""
|
|
}
|
|
if queryIndex := strings.Index(text, "?"); queryIndex >= 0 {
|
|
text = text[queryIndex+1:]
|
|
}
|
|
if hashIndex := strings.Index(text, "#"); hashIndex >= 0 {
|
|
text = text[:hashIndex]
|
|
}
|
|
values, err := url.ParseQuery(strings.TrimLeft(text, "?&"))
|
|
if err != nil {
|
|
return text
|
|
}
|
|
if len(values) == 0 {
|
|
return ""
|
|
}
|
|
for _, key := range []string{"protocol", "oceanBaseProtocol", "oceanbaseProtocol", "tenantMode", "compatMode", "mode"} {
|
|
values.Del(key)
|
|
}
|
|
return values.Encode()
|
|
}
|
|
|
|
func normalizeOceanBaseConnectionParamsForCache(raw string) string {
|
|
normalized := stripOceanBaseConnectionParamsForCache(raw)
|
|
protocol := resolveOceanBaseProtocolParam(raw)
|
|
if protocol != "" && !strings.EqualFold(protocol, "mysql") {
|
|
values, err := url.ParseQuery(strings.TrimLeft(strings.TrimSpace(normalized), "?&"))
|
|
if err != nil {
|
|
values = url.Values{}
|
|
}
|
|
values.Set("protocol", protocol)
|
|
return values.Encode()
|
|
}
|
|
return normalized
|
|
}
|
|
|
|
func normalizeOceanBaseConnectionParamsForCacheWithProtocol(raw string, protocol string) string {
|
|
resolvedProtocol := normalizeOceanBaseProtocolForApp(protocol)
|
|
if resolvedProtocol == "" {
|
|
return normalizeOceanBaseConnectionParamsForCache(raw)
|
|
}
|
|
normalized := stripOceanBaseConnectionParamsForCache(raw)
|
|
if strings.EqualFold(resolvedProtocol, "mysql") {
|
|
return normalized
|
|
}
|
|
values, err := url.ParseQuery(strings.TrimLeft(strings.TrimSpace(normalized), "?&"))
|
|
if err != nil {
|
|
values = url.Values{}
|
|
}
|
|
values.Set("protocol", resolvedProtocol)
|
|
return values.Encode()
|
|
}
|
|
|
|
func isOceanBaseOracleProtocol(config connection.ConnectionConfig) bool {
|
|
return resolveOceanBaseProtocolForApp(config) == "oracle"
|
|
}
|