mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-12 16:02:48 +08:00
@@ -471,6 +471,9 @@ var databaseFactories = map[string]databaseFactory{
|
||||
"mysql": func() Database {
|
||||
return &MySQLDB{}
|
||||
},
|
||||
"goldendb": func() Database {
|
||||
return &MySQLDB{}
|
||||
},
|
||||
"postgres": func() Database {
|
||||
return &PostgresDB{}
|
||||
},
|
||||
@@ -521,6 +524,8 @@ func normalizeDatabaseType(dbType string) string {
|
||||
return "opengauss"
|
||||
case "gaussdb", "gauss_db", "gauss-db":
|
||||
return "gaussdb"
|
||||
case "goldendb", "greatdb", "gdb":
|
||||
return "goldendb"
|
||||
case "intersystems", "intersystemsiris", "inter-systems-iris", "inter-systems":
|
||||
return "iris"
|
||||
case "chromadb", "chroma-db":
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
// coreBuiltinDrivers 是始终内置可用的核心驱动,无需额外安装即可使用。
|
||||
var coreBuiltinDrivers = map[string]struct{}{
|
||||
"mysql": {},
|
||||
"goldendb": {},
|
||||
"redis": {},
|
||||
"oracle": {},
|
||||
"postgres": {},
|
||||
@@ -69,6 +70,8 @@ func normalizeRuntimeDriverType(driverType string) string {
|
||||
return "opengauss"
|
||||
case "gaussdb", "gauss_db", "gauss-db":
|
||||
return "gaussdb"
|
||||
case "goldendb", "greatdb", "gdb":
|
||||
return "goldendb"
|
||||
case "intersystems", "intersystemsiris", "inter-systems-iris", "inter-systems":
|
||||
return "iris"
|
||||
case "elastic":
|
||||
@@ -90,6 +93,8 @@ func driverDisplayName(driverType string) string {
|
||||
switch normalizeRuntimeDriverType(driverType) {
|
||||
case "mysql":
|
||||
return "MySQL"
|
||||
case "goldendb":
|
||||
return "GoldenDB"
|
||||
case "oracle":
|
||||
return "Oracle"
|
||||
case "redis":
|
||||
|
||||
@@ -34,6 +34,11 @@ func TestBuiltinLikeDriversRemainAvailable(t *testing.T) {
|
||||
if !supported {
|
||||
t.Fatalf("kafka 应始终可用,reason=%s", reason)
|
||||
}
|
||||
|
||||
supported, reason = DriverRuntimeSupportStatus("goldendb")
|
||||
if !supported {
|
||||
t.Fatalf("goldendb 应始终可用,reason=%s", reason)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionalDriverAgentRevisionsGeneratedForOptionalDrivers(t *testing.T) {
|
||||
@@ -58,6 +63,12 @@ func TestKingbaseRuntimeAliasesNormalizeToKingbase(t *testing.T) {
|
||||
if got := normalizeDatabaseType("kingbasees"); got != "kingbase" {
|
||||
t.Fatalf("expected kingbasees database alias to normalize to kingbase, got %q", got)
|
||||
}
|
||||
if got := normalizeRuntimeDriverType("greatdb"); got != "goldendb" {
|
||||
t.Fatalf("expected greatdb runtime alias to normalize to goldendb, got %q", got)
|
||||
}
|
||||
if got := normalizeDatabaseType("gdb"); got != "goldendb" {
|
||||
t.Fatalf("expected gdb database alias to normalize to goldendb, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagedDriverRequiresInstallMarker(t *testing.T) {
|
||||
@@ -145,3 +156,13 @@ func TestMySQLBuiltinRuntimeSupportAvailable(t *testing.T) {
|
||||
t.Fatalf("mysql 属于免安装内置驱动,应可用,reason=%s", reason)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoldenDBBuiltinDatabaseFactoryUsesMySQLImplementation(t *testing.T) {
|
||||
dbInst, err := NewDatabase("goldendb")
|
||||
if err != nil {
|
||||
t.Fatalf("expected goldendb database factory, got err=%v", err)
|
||||
}
|
||||
if _, ok := dbInst.(*MySQLDB); !ok {
|
||||
t.Fatalf("expected goldendb to reuse MySQLDB implementation, got %T", dbInst)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,3 +472,54 @@ func TestMySQLDSN_URIParamsAndExplicitParamsPrecedence(t *testing.T) {
|
||||
t.Fatalf("internal topology parameter should not be passed to driver: %v", query)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyMySQLURI_GoldenDBSchemeUsesDefaultPort(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := applyMySQLURI(connection.ConnectionConfig{
|
||||
Type: "goldendb",
|
||||
URI: "goldendb://glzc:secret@gdb.local/core_ledger?characterEncoding=utf8",
|
||||
})
|
||||
|
||||
if config.Host != "gdb.local" {
|
||||
t.Fatalf("expected goldendb host from URI, got %q", config.Host)
|
||||
}
|
||||
if config.Port != 1523 {
|
||||
t.Fatalf("expected goldendb default port 1523, got %d", config.Port)
|
||||
}
|
||||
if config.Database != "core_ledger" {
|
||||
t.Fatalf("expected goldendb database from URI, got %q", config.Database)
|
||||
}
|
||||
if config.User != "glzc" {
|
||||
t.Fatalf("expected goldendb user from URI, got %q", config.User)
|
||||
}
|
||||
if config.Password != "secret" {
|
||||
t.Fatalf("expected goldendb password from URI, got %q", config.Password)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMySQLDSN_AcceptsGoldenDBURICompatibilityParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
m := &MySQLDB{}
|
||||
dsn, err := m.getDSN(connection.ConnectionConfig{
|
||||
Type: "goldendb",
|
||||
Host: "gdb.local",
|
||||
Port: 1523,
|
||||
User: "glzc",
|
||||
Password: "secret",
|
||||
Database: "core_ledger",
|
||||
URI: "goldendb://glzc:secret@gdb.local/core_ledger?characterEncoding=utf8&useSSL=false",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("getDSN failed: %v", err)
|
||||
}
|
||||
|
||||
query := parseMySQLDSNQueryForTest(t, dsn)
|
||||
if got := query.Get("charset"); got != "utf8" {
|
||||
t.Fatalf("goldendb URI characterEncoding should map to charset=utf8, got=%q", got)
|
||||
}
|
||||
if got := query.Get("tls"); got != "false" {
|
||||
t.Fatalf("goldendb URI useSSL=false should map to tls=false, got=%q", got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,39 @@ type MySQLDB struct {
|
||||
|
||||
const (
|
||||
defaultMySQLPort = 3306
|
||||
defaultGoldenDBPort = 1523
|
||||
defaultMySQLInsertBatchSize = 1000
|
||||
maxMySQLInsertBatchArgs = 60000
|
||||
)
|
||||
|
||||
var mysqlCompatibleURISchemes = []string{
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"doris",
|
||||
"diros",
|
||||
"oceanbase",
|
||||
"starrocks",
|
||||
"goldendb",
|
||||
"greatdb",
|
||||
"gdb",
|
||||
}
|
||||
|
||||
func parseMySQLCompatibleURI(raw string, allowedSchemes ...string) (*url.URL, bool) {
|
||||
return parseConnectionURI(raw, allowedSchemes...)
|
||||
}
|
||||
|
||||
func resolveMySQLCompatibleDefaultPort(config connection.ConnectionConfig) int {
|
||||
if config.Port > 0 {
|
||||
return config.Port
|
||||
}
|
||||
switch strings.ToLower(strings.TrimSpace(config.Type)) {
|
||||
case "goldendb", "greatdb", "gdb":
|
||||
return defaultGoldenDBPort
|
||||
default:
|
||||
return defaultMySQLPort
|
||||
}
|
||||
}
|
||||
|
||||
func mysqlConnectionParamsFromText(raw string) url.Values {
|
||||
return connectionParamsFromText(raw)
|
||||
}
|
||||
@@ -319,7 +344,7 @@ func hasMySQLConnectionParam(config connection.ConnectionConfig, names ...string
|
||||
return false
|
||||
}
|
||||
|
||||
if parsed, ok := parseMySQLCompatibleURI(config.URI, "mysql", "mariadb", "doris", "diros", "oceanbase", "starrocks"); ok && hasMatchingKey(parsed.Query()) {
|
||||
if parsed, ok := parseMySQLCompatibleURI(config.URI, mysqlCompatibleURISchemes...); ok && hasMatchingKey(parsed.Query()) {
|
||||
return true
|
||||
}
|
||||
return hasMatchingKey(mysqlConnectionParamsFromText(config.ConnectionParams))
|
||||
@@ -368,7 +393,7 @@ func buildMySQLCompatibleDSNWithOptions(config connection.ConnectionConfig, prot
|
||||
defaultMultiStatements = *options.defaultMultiStatements
|
||||
}
|
||||
params.Set("multiStatements", strconv.FormatBool(defaultMultiStatements))
|
||||
if parsed, ok := parseMySQLCompatibleURI(config.URI, "mysql", "doris", "diros", "oceanbase"); ok {
|
||||
if parsed, ok := parseMySQLCompatibleURI(config.URI, mysqlCompatibleURISchemes...); ok {
|
||||
mergeMySQLConnectionParams(params, parsed.Query())
|
||||
}
|
||||
mergeMySQLConnectionParams(params, mysqlConnectionParamsFromText(config.ConnectionParams))
|
||||
@@ -625,7 +650,7 @@ func applyMySQLURI(config connection.ConnectionConfig) connection.ConnectionConf
|
||||
if uriText == "" {
|
||||
return config
|
||||
}
|
||||
parsed, ok := parseMySQLCompatibleURI(uriText, "mysql")
|
||||
parsed, ok := parseMySQLCompatibleURI(uriText, mysqlCompatibleURISchemes...)
|
||||
if !ok {
|
||||
return config
|
||||
}
|
||||
@@ -643,10 +668,7 @@ func applyMySQLURI(config connection.ConnectionConfig) connection.ConnectionConf
|
||||
config.Database = dbName
|
||||
}
|
||||
|
||||
defaultPort := config.Port
|
||||
if defaultPort <= 0 {
|
||||
defaultPort = defaultMySQLPort
|
||||
}
|
||||
defaultPort := resolveMySQLCompatibleDefaultPort(config)
|
||||
|
||||
hostsFromURI := make([]string, 0, 4)
|
||||
hostText := strings.TrimSpace(parsed.Host)
|
||||
@@ -682,10 +704,7 @@ func applyMySQLURI(config connection.ConnectionConfig) connection.ConnectionConf
|
||||
}
|
||||
|
||||
func collectMySQLAddresses(config connection.ConnectionConfig) []string {
|
||||
defaultPort := config.Port
|
||||
if defaultPort <= 0 {
|
||||
defaultPort = defaultMySQLPort
|
||||
}
|
||||
defaultPort := resolveMySQLCompatibleDefaultPort(config)
|
||||
|
||||
candidates := make([]string, 0, len(config.Hosts)+1)
|
||||
if len(config.Hosts) > 0 {
|
||||
@@ -757,11 +776,12 @@ func (m *MySQLDB) Connect(config connection.ConnectionConfig) error {
|
||||
if len(addresses) == 0 {
|
||||
return fmt.Errorf("连接建立后验证失败:未找到可用的 MySQL 地址")
|
||||
}
|
||||
defaultPort := resolveMySQLCompatibleDefaultPort(runConfig)
|
||||
|
||||
var errorDetails []string
|
||||
for index, address := range addresses {
|
||||
candidateConfig := runConfig
|
||||
host, port, ok := parseHostPortWithDefault(address, defaultMySQLPort)
|
||||
host, port, ok := parseHostPortWithDefault(address, defaultPort)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user