diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8dc685b..ec38a17 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -149,12 +149,16 @@ jobs: TARGET_PLATFORM="${{ matrix.platform }}" GOOS="${TARGET_PLATFORM%%/*}" GOARCH="${TARGET_PLATFORM##*/}" - DRIVERS=(mariadb diros sphinx sqlserver sqlite duckdb dameng kingbase highgo vastbase mongodb tdengine clickhouse) + DRIVERS=(mariadb doris sphinx sqlserver sqlite duckdb dameng kingbase highgo vastbase mongodb tdengine clickhouse) OUTDIR="drivers/${{ matrix.os_name }}" mkdir -p "$OUTDIR" for DRIVER in "${DRIVERS[@]}"; do - TAG="gonavi_${DRIVER}_driver" + BUILD_DRIVER="$DRIVER" + if [ "$DRIVER" = "doris" ]; then + BUILD_DRIVER="diros" + fi + TAG="gonavi_${BUILD_DRIVER}_driver" OUTPUT="${DRIVER}-driver-agent-${GOOS}-${GOARCH}" if [ "$GOOS" = "windows" ]; then OUTPUT="${OUTPUT}.exe" diff --git a/docs/driver-manifest.json b/docs/driver-manifest.json index aaef2d8..1f0302a 100644 --- a/docs/driver-manifest.json +++ b/docs/driver-manifest.json @@ -7,11 +7,11 @@ "checksumPolicy": "off", "downloadUrl": "builtin://activate/mariadb" }, - "diros": { + "doris": { "engine": "go", "version": "1.9.3", "checksumPolicy": "off", - "downloadUrl": "builtin://activate/diros" + "downloadUrl": "builtin://activate/doris" }, "sphinx": { "engine": "go", diff --git a/frontend/src/components/ConnectionModal.tsx b/frontend/src/components/ConnectionModal.tsx index 025b343..a89d7f4 100644 --- a/frontend/src/components/ConnectionModal.tsx +++ b/frontend/src/components/ConnectionModal.tsx @@ -15,6 +15,7 @@ const MAX_TIMEOUT_SECONDS = 3600; const getDefaultPortByType = (type: string) => { switch (type) { case 'mysql': return 3306; + case 'doris': case 'diros': return 9030; case 'sphinx': return 9306; case 'clickhouse': return 9000; @@ -480,7 +481,7 @@ const ConnectionModal: React.FC<{ const getUriPlaceholder = () => { if (dbType === 'mysql' || dbType === 'mariadb' || dbType === 'diros' || dbType === 'sphinx') { const defaultPort = getDefaultPortByType(dbType); - const scheme = dbType === 'diros' ? 'diros' : 'mysql'; + const scheme = dbType === 'diros' ? 'doris' : 'mysql'; return `${scheme}://user:pass@127.0.0.1:${defaultPort},127.0.0.2:${defaultPort}/db_name?topology=replica`; } if (isFileDatabaseType(dbType)) { @@ -525,7 +526,7 @@ const ConnectionModal: React.FC<{ } const dbPath = database ? `/${encodeURIComponent(database)}` : '/'; const query = params.toString(); - const scheme = type === 'diros' ? 'diros' : 'mysql'; + const scheme = type === 'diros' ? 'doris' : 'mysql'; return `${scheme}://${encodedAuth}${hosts.join(',')}${dbPath}${query ? `?${query}` : ''}`; } @@ -1155,7 +1156,7 @@ const ConnectionModal: React.FC<{ { label: '关系型数据库', items: [ { key: 'mysql', name: 'MySQL', icon: }, { key: 'mariadb', name: 'MariaDB', icon: }, - { key: 'diros', name: 'Diros', icon: }, + { key: 'diros', name: 'Doris', icon: }, { key: 'sphinx', name: 'Sphinx', icon: }, { key: 'clickhouse', name: 'ClickHouse', icon: }, { key: 'postgres', name: 'PostgreSQL', icon: }, diff --git a/frontend/src/store.ts b/frontend/src/store.ts index 76854c3..88e2d4a 100644 --- a/frontend/src/store.ts +++ b/frontend/src/store.ts @@ -24,6 +24,7 @@ const DEFAULT_GLOBAL_PROXY: GlobalProxyConfig = { const SUPPORTED_CONNECTION_TYPES = new Set([ 'mysql', 'mariadb', + 'doris', 'diros', 'sphinx', 'clickhouse', @@ -47,6 +48,7 @@ const getDefaultPortByType = (type: string): number => { case 'mysql': case 'mariadb': return 3306; + case 'doris': case 'diros': return 9030; case 'duckdb': @@ -150,6 +152,9 @@ const sanitizeAddressList = (value: unknown): string[] => { const normalizeConnectionType = (value: unknown): string => { const type = toTrimmedString(value).toLowerCase(); + if (type === 'doris') { + return 'diros'; + } return SUPPORTED_CONNECTION_TYPES.has(type) ? type : DEFAULT_CONNECTION_TYPE; }; @@ -241,7 +246,8 @@ const sanitizeSavedConnection = (value: unknown, index: number): SavedConnection const raw = value as Record; const config = sanitizeConnectionConfig(resolveConnectionConfigPayload(raw)); const id = toTrimmedString(raw.id, `conn-${index + 1}`) || `conn-${index + 1}`; - const fallbackName = config.host ? `${config.type}-${config.host}` : `连接-${index + 1}`; + const displayType = config.type === 'diros' ? 'doris' : config.type; + const fallbackName = config.host ? `${displayType}-${config.host}` : `连接-${index + 1}`; const name = toTrimmedString(raw.name, fallbackName) || fallbackName; const includeDatabases = sanitizeStringArray(raw.includeDatabases, 256); const includeRedisDatabases = sanitizeNumberArray(raw.includeRedisDatabases, 0, 15); diff --git a/internal/app/methods_db.go b/internal/app/methods_db.go index 8263b2b..6d20bdc 100644 --- a/internal/app/methods_db.go +++ b/internal/app/methods_db.go @@ -210,7 +210,7 @@ func (a *App) RenameDatabase(config connection.ConnectionConfig, oldName string, dbType := resolveDDLDBType(config) switch dbType { case "mysql", "mariadb", "diros", "sphinx": - return connection.QueryResult{Success: false, Message: "MySQL/MariaDB/Diros/Sphinx 不支持直接重命名数据库,请新建库后迁移数据"} + return connection.QueryResult{Success: false, Message: "MySQL/MariaDB/Doris/Sphinx 不支持直接重命名数据库,请新建库后迁移数据"} case "postgres", "kingbase", "highgo", "vastbase": if strings.EqualFold(strings.TrimSpace(config.Database), oldName) { return connection.QueryResult{Success: false, Message: "当前连接正在使用目标数据库,请先连接到其他数据库后再重命名"} diff --git a/internal/app/methods_driver.go b/internal/app/methods_driver.go index 350a21c..cef721a 100644 --- a/internal/app/methods_driver.go +++ b/internal/app/methods_driver.go @@ -214,7 +214,7 @@ const builtinDriverManifestJSON = `{ "drivers": { "mysql": { "engine": "go", "version": "1.9.3", "checksumPolicy": "off" }, "mariadb": { "engine": "go", "version": "1.9.3", "checksumPolicy": "off", "downloadUrl": "builtin://activate/mariadb" }, - "diros": { "engine": "go", "version": "1.9.3", "checksumPolicy": "off", "downloadUrl": "builtin://activate/diros" }, + "doris": { "engine": "go", "version": "1.9.3", "checksumPolicy": "off", "downloadUrl": "builtin://activate/doris" }, "sphinx": { "engine": "go", "version": "1.9.3", "checksumPolicy": "off", "downloadUrl": "builtin://activate/sphinx" }, "sqlserver": { "engine": "go", "version": "1.9.6", "checksumPolicy": "off", "downloadUrl": "builtin://activate/sqlserver" }, "sqlite": { "engine": "go", "version": "1.44.3", "checksumPolicy": "off", "downloadUrl": "builtin://activate/sqlite" }, @@ -456,7 +456,7 @@ func (a *App) ResolveDriverPackageDownloadURL(driverType string, repositoryURL s if engine == driverEngineGo && !definition.BuiltIn { urlText := strings.TrimSpace(definition.DefaultDownloadURL) if urlText == "" { - urlText = fmt.Sprintf("builtin://activate/%s", definition.Type) + urlText = fmt.Sprintf("builtin://activate/%s", optionalDriverPublicTypeName(definition.Type)) } data := map[string]interface{}{ "url": urlText, @@ -530,14 +530,14 @@ func (a *App) GetDriverVersionPackageSize(driverType string, version string) con if sizeByAsset, err := loadReleaseAssetSizesCached("tag:"+tag, func() (*githubRelease, error) { return fetchReleaseByTag(tag) }); err == nil { - sizeBytes = sizeByAsset[assetName] + sizeBytes = resolveOptionalDriverAssetSize(sizeByAsset, normalizedType) if sizeBytes > 0 { sizeSource = "tag" } } if sizeBytes <= 0 { if sizeByAsset, err := loadReleaseAssetSizesCached("latest", fetchLatestReleaseForDriverAssets); err == nil { - sizeBytes = sizeByAsset[assetName] + sizeBytes = resolveOptionalDriverAssetSize(sizeByAsset, normalizedType) if sizeBytes > 0 { sizeSource = "latest" } @@ -762,7 +762,7 @@ func (a *App) DownloadDriverPackage(driverType string, version string, downloadU urlText = strings.TrimSpace(definition.DefaultDownloadURL) } if urlText == "" { - urlText = fmt.Sprintf("builtin://activate/%s", definition.Type) + urlText = fmt.Sprintf("builtin://activate/%s", optionalDriverPublicTypeName(definition.Type)) } selectedVersion := resolveDriverInstallVersion(version, urlText, definition) @@ -1068,7 +1068,7 @@ func allDriverDefinitionsWithPackages(packages map[string]pinnedDriverPackage) [ // 其他数据源需要先在驱动管理中“安装启用”。 buildOptionalGoDriverDefinition("mariadb", "MariaDB", packages), - buildOptionalGoDriverDefinition("diros", "Diros", packages), + buildOptionalGoDriverDefinition("diros", "Doris", packages), buildOptionalGoDriverDefinition("sphinx", "Sphinx", packages), buildOptionalGoDriverDefinition("sqlserver", "SQL Server", packages), buildOptionalGoDriverDefinition("sqlite", "SQLite", packages), @@ -1246,7 +1246,7 @@ func resolveDriverVersionOptions(definition driverDefinition, repositoryURL stri urlText = strings.TrimSpace(definition.DefaultDownloadURL) } if urlText == "" && effectiveDriverEngine(definition) == driverEngineGo { - urlText = fmt.Sprintf("builtin://activate/%s", driverType) + urlText = fmt.Sprintf("builtin://activate/%s", optionalDriverPublicTypeName(driverType)) } if versionText == "" { versionText = resolveDriverInstallVersion("", urlText, definition) @@ -1383,7 +1383,7 @@ func resolveVersionedDriverOption(definition driverDefinition, version string, s urlText := strings.TrimSpace(definition.DefaultDownloadURL) if urlText == "" && effectiveDriverEngine(definition) == driverEngineGo { - urlText = fmt.Sprintf("builtin://activate/%s", driverType) + urlText = fmt.Sprintf("builtin://activate/%s", optionalDriverPublicTypeName(driverType)) } if urlText == "" { return "", "", false @@ -1430,13 +1430,13 @@ func resolveDriverVersionPackageSizeBytes(definition driverDefinition, option dr tag := "v" + version if sizeByAsset, ok := readReleaseAssetSizesFromCache("tag:" + tag); ok { - return sizeByAsset[assetName] + return resolveOptionalDriverAssetSize(sizeByAsset, driverType) } // 下拉版本列表要求快速返回:仅复用已有缓存,不在这里触发网络请求。 if strings.EqualFold(strings.TrimSpace(option.Source), "latest") { if sizeByAsset, ok := readReleaseAssetSizesFromCache("latest"); ok { - return sizeByAsset[assetName] + return resolveOptionalDriverAssetSize(sizeByAsset, driverType) } } return 0 @@ -1665,13 +1665,14 @@ func resolveDriverVersionOptionsFromReleases(definition driverDefinition) []driv } assetName := optionalDriverReleaseAssetName(driverType) + assetNames := optionalDriverReleaseAssetNames(driverType) result := make([]driverVersionOptionItem, 0, len(releases)) for _, release := range releases { if release.Prerelease { continue } tag := strings.TrimSpace(release.TagName) - if tag == "" || !releaseContainsAsset(release, assetName) { + if tag == "" || !releaseContainsAnyAsset(release, assetNames) { continue } result = append(result, driverVersionOptionItem{ @@ -1748,14 +1749,24 @@ func fetchDriverReleaseList() ([]githubRelease, error) { return releases, nil } -func releaseContainsAsset(release githubRelease, assetName string) bool { - name := strings.TrimSpace(assetName) - if name == "" { +func releaseContainsAnyAsset(release githubRelease, assetNames []string) bool { + normalizedNames := make([]string, 0, len(assetNames)) + for _, assetName := range assetNames { + name := strings.TrimSpace(assetName) + if name == "" { + continue + } + normalizedNames = append(normalizedNames, name) + } + if len(normalizedNames) == 0 { return false } for _, asset := range release.Assets { - if strings.EqualFold(strings.TrimSpace(asset.Name), name) { - return true + assetName := strings.TrimSpace(asset.Name) + for _, expected := range normalizedNames { + if strings.EqualFold(assetName, expected) { + return true + } } } return false @@ -2323,18 +2334,23 @@ func resolveLocalDriverAgentFromDirectory(directoryPath string, driverType strin } displayName := resolveDriverDisplayName(displayDefinition) platformDir := optionalDriverBundlePlatformDir(stdRuntime.GOOS) + assetNameCandidates := optionalDriverReleaseAssetNames(normalizedType) + baseNameCandidates := optionalDriverExecutableBaseNames(normalizedType) assetName := optionalDriverReleaseAssetName(normalizedType) - baseName := optionalDriverExecutableBaseName(normalizedType) exactRelativePath := filepath.ToSlash(filepath.Join(platformDir, assetName)) - exactPath := filepath.Join(root, platformDir, assetName) - if exactInfo, err := os.Stat(exactPath); err == nil && !exactInfo.IsDir() { - return exactPath, exactRelativePath, nil + for _, candidateName := range assetNameCandidates { + exactPath := filepath.Join(root, platformDir, candidateName) + if exactInfo, err := os.Stat(exactPath); err == nil && !exactInfo.IsDir() { + return exactPath, filepath.ToSlash(filepath.Join(platformDir, candidateName)), nil + } } - rootAssetPath := filepath.Join(root, assetName) - if rootAssetInfo, err := os.Stat(rootAssetPath); err == nil && !rootAssetInfo.IsDir() { - return rootAssetPath, filepath.ToSlash(assetName), nil + for _, candidateName := range assetNameCandidates { + rootAssetPath := filepath.Join(root, candidateName) + if rootAssetInfo, err := os.Stat(rootAssetPath); err == nil && !rootAssetInfo.IsDir() { + return rootAssetPath, filepath.ToSlash(candidateName), nil + } } assetCandidates := make([]localDriverCandidate, 0, 8) @@ -2375,12 +2391,17 @@ func resolveLocalDriverAgentFromDirectory(directoryPath string, driverType strin inPlatformDir: inPlatformDir, } - if strings.EqualFold(name, assetName) { - assetCandidates = append(assetCandidates, candidate) - return nil + for _, candidateName := range assetNameCandidates { + if strings.EqualFold(name, candidateName) { + assetCandidates = append(assetCandidates, candidate) + return nil + } } - if strings.EqualFold(name, baseName) { - baseCandidates = append(baseCandidates, candidate) + for _, candidateName := range baseNameCandidates { + if strings.EqualFold(name, candidateName) { + baseCandidates = append(baseCandidates, candidate) + return nil + } } return nil }) @@ -2425,8 +2446,8 @@ func resolveLocalDriverAgentFromDirectory(directoryPath string, driverType strin "目录中未找到 %s 代理文件(优先路径 %s,候选文件名 %s / %s)", displayName, exactRelativePath, - assetName, - baseName, + strings.Join(assetNameCandidates, " | "), + strings.Join(baseNameCandidates, " | "), ) } @@ -2440,24 +2461,31 @@ func installOptionalDriverAgentFromLocalZip(zipPath string, definition driverDef defer reader.Close() entryPath := optionalDriverBundleEntryPath(driverType) - expectedBaseName := optionalDriverReleaseAssetName(driverType) + entryPaths := optionalDriverBundleEntryPaths(driverType) + expectedBaseNames := optionalDriverReleaseAssetNames(driverType) findEntry := func() *zip.File { for _, file := range reader.File { name := filepath.ToSlash(strings.TrimPrefix(strings.TrimSpace(file.Name), "./")) - if name == entryPath { - return file + for _, expectedPath := range entryPaths { + if name == expectedPath { + return file + } } } for _, file := range reader.File { name := filepath.ToSlash(strings.TrimPrefix(strings.TrimSpace(file.Name), "./")) - if strings.EqualFold(name, entryPath) { - return file + for _, expectedPath := range entryPaths { + if strings.EqualFold(name, expectedPath) { + return file + } } } for _, file := range reader.File { name := filepath.ToSlash(strings.TrimPrefix(strings.TrimSpace(file.Name), "./")) - if strings.EqualFold(filepath.Base(name), expectedBaseName) { - return file + for _, expectedName := range expectedBaseNames { + if strings.EqualFold(filepath.Base(name), expectedName) { + return file + } } } return nil @@ -2651,24 +2679,31 @@ func downloadOptionalDriverAgentFromBundle(a *App, definition driverDefinition, defer reader.Close() entryPath := optionalDriverBundleEntryPath(driverType) - expectedBaseName := optionalDriverReleaseAssetName(driverType) + entryPaths := optionalDriverBundleEntryPaths(driverType) + expectedBaseNames := optionalDriverReleaseAssetNames(driverType) findEntry := func() *zip.File { for _, file := range reader.File { name := filepath.ToSlash(strings.TrimPrefix(strings.TrimSpace(file.Name), "./")) - if name == entryPath { - return file + for _, expectedPath := range entryPaths { + if name == expectedPath { + return file + } } } for _, file := range reader.File { name := filepath.ToSlash(strings.TrimPrefix(strings.TrimSpace(file.Name), "./")) - if strings.EqualFold(name, entryPath) { - return file + for _, expectedPath := range entryPaths { + if strings.EqualFold(name, expectedPath) { + return file + } } } for _, file := range reader.File { name := filepath.ToSlash(strings.TrimPrefix(strings.TrimSpace(file.Name), "./")) - if strings.EqualFold(filepath.Base(name), expectedBaseName) { - return file + for _, expectedName := range expectedBaseNames { + if strings.EqualFold(filepath.Base(name), expectedName) { + return file + } } } return nil @@ -2819,22 +2854,93 @@ func fileExists(path string) bool { return err == nil && !info.IsDir() } -func optionalDriverExecutableBaseName(driverType string) string { - name := fmt.Sprintf("%s-driver-agent", normalizeDriverType(driverType)) +func optionalDriverPublicTypeName(driverType string) string { + switch normalizeDriverType(driverType) { + case "diros": + return "doris" + default: + return normalizeDriverType(driverType) + } +} + +func optionalDriverExecutableBaseNameForType(typeName string) string { + base := strings.TrimSpace(typeName) + if base == "" { + base = "unknown" + } + name := fmt.Sprintf("%s-driver-agent", base) if stdRuntime.GOOS == "windows" { return name + ".exe" } return name } -func optionalDriverReleaseAssetName(driverType string) string { - name := fmt.Sprintf("%s-driver-agent-%s-%s", normalizeDriverType(driverType), stdRuntime.GOOS, stdRuntime.GOARCH) - if stdRuntime.GOOS == "windows" { +func optionalDriverReleaseAssetNameForType(typeName string, goos string, goarch string) string { + base := strings.TrimSpace(typeName) + if base == "" { + base = "unknown" + } + name := fmt.Sprintf("%s-driver-agent-%s-%s", base, goos, goarch) + if strings.EqualFold(goos, "windows") { return name + ".exe" } return name } +func optionalDriverExecutableBaseNames(driverType string) []string { + names := make([]string, 0, 2) + seen := make(map[string]struct{}, 2) + appendName := func(typeName string) { + name := optionalDriverExecutableBaseNameForType(typeName) + if strings.TrimSpace(name) == "" { + return + } + if _, ok := seen[name]; ok { + return + } + seen[name] = struct{}{} + names = append(names, name) + } + + appendName(optionalDriverPublicTypeName(driverType)) + return names +} + +func optionalDriverReleaseAssetNames(driverType string) []string { + names := make([]string, 0, 2) + seen := make(map[string]struct{}, 2) + appendName := func(typeName string) { + name := optionalDriverReleaseAssetNameForType(typeName, stdRuntime.GOOS, stdRuntime.GOARCH) + if strings.TrimSpace(name) == "" { + return + } + if _, ok := seen[name]; ok { + return + } + seen[name] = struct{}{} + names = append(names, name) + } + + appendName(optionalDriverPublicTypeName(driverType)) + return names +} + +func optionalDriverExecutableBaseName(driverType string) string { + names := optionalDriverExecutableBaseNames(driverType) + if len(names) == 0 { + return optionalDriverExecutableBaseNameForType("") + } + return names[0] +} + +func optionalDriverReleaseAssetName(driverType string) string { + names := optionalDriverReleaseAssetNames(driverType) + if len(names) == 0 { + return optionalDriverReleaseAssetNameForType("", stdRuntime.GOOS, stdRuntime.GOARCH) + } + return names[0] +} + func optionalDriverBundlePlatformDir(goos string) string { switch strings.ToLower(strings.TrimSpace(goos)) { case "windows": @@ -2848,8 +2954,41 @@ func optionalDriverBundlePlatformDir(goos string) string { } } +func optionalDriverBundleEntryPaths(driverType string) []string { + platformDir := optionalDriverBundlePlatformDir(stdRuntime.GOOS) + assetNames := optionalDriverReleaseAssetNames(driverType) + result := make([]string, 0, len(assetNames)) + seen := make(map[string]struct{}, len(assetNames)) + for _, assetName := range assetNames { + entry := filepath.ToSlash(filepath.Join(platformDir, assetName)) + if _, ok := seen[entry]; ok { + continue + } + seen[entry] = struct{}{} + result = append(result, entry) + } + return result +} + func optionalDriverBundleEntryPath(driverType string) string { - return filepath.ToSlash(filepath.Join(optionalDriverBundlePlatformDir(stdRuntime.GOOS), optionalDriverReleaseAssetName(driverType))) + paths := optionalDriverBundleEntryPaths(driverType) + if len(paths) == 0 { + return filepath.ToSlash(filepath.Join(optionalDriverBundlePlatformDir(stdRuntime.GOOS), optionalDriverReleaseAssetName(driverType))) + } + return paths[0] +} + +func resolveOptionalDriverAssetSize(sizeByAsset map[string]int64, driverType string) int64 { + if len(sizeByAsset) == 0 { + return 0 + } + for _, assetName := range optionalDriverReleaseAssetNames(driverType) { + sizeBytes := sizeByAsset[assetName] + if sizeBytes > 0 { + return sizeBytes + } + } + return 0 } func resolveOptionalDriverBundleDownloadURLs() []string { @@ -2898,12 +3037,16 @@ func resolveOptionalDriverAgentDownloadURLs(definition driverDefinition, rawURL } } - assetName := optionalDriverReleaseAssetName(driverType) + assetNames := optionalDriverReleaseAssetNames(driverType) currentVersion := normalizeVersion(getCurrentVersion()) if currentVersion != "" && currentVersion != "0.0.0" { - appendURL(fmt.Sprintf("https://github.com/Syngnat/GoNavi/releases/download/v%s/%s", currentVersion, assetName)) + for _, assetName := range assetNames { + appendURL(fmt.Sprintf("https://github.com/Syngnat/GoNavi/releases/download/v%s/%s", currentVersion, assetName)) + } + } + for _, assetName := range assetNames { + appendURL(fmt.Sprintf("https://github.com/Syngnat/GoNavi/releases/latest/download/%s", assetName)) } - appendURL(fmt.Sprintf("https://github.com/Syngnat/GoNavi/releases/latest/download/%s", assetName)) return candidates } @@ -2932,8 +3075,23 @@ func findExistingOptionalDriverAgentCandidate(definition driverDefinition, targe func resolveOptionalDriverAgentCandidatePaths(definition driverDefinition) []string { driverType := normalizeDriverType(definition.Type) - name := optionalDriverExecutableBaseName(driverType) - assetName := optionalDriverReleaseAssetName(driverType) + names := optionalDriverExecutableBaseNames(driverType) + assetNames := optionalDriverReleaseAssetNames(driverType) + pathTypeNames := make([]string, 0, 2) + seenPathType := make(map[string]struct{}, 2) + appendPathType := func(typeName string) { + trimmed := strings.TrimSpace(typeName) + if trimmed == "" { + return + } + if _, ok := seenPathType[trimmed]; ok { + return + } + seenPathType[trimmed] = struct{}{} + pathTypeNames = append(pathTypeNames, trimmed) + } + appendPathType(optionalDriverPublicTypeName(driverType)) + candidates := make([]string, 0, 12) appendPath := func(pathText string) { trimmed := strings.TrimSpace(pathText) @@ -2948,18 +3106,36 @@ func resolveOptionalDriverAgentCandidatePaths(definition driverDefinition) []str resolved = evalPath } exeDir := filepath.Dir(resolved) - appendPath(filepath.Join(exeDir, name)) - appendPath(filepath.Join(exeDir, assetName)) - appendPath(filepath.Join(exeDir, "drivers", driverType, name)) - appendPath(filepath.Join(exeDir, "drivers", driverType, assetName)) + for _, name := range names { + appendPath(filepath.Join(exeDir, name)) + } + for _, assetName := range assetNames { + appendPath(filepath.Join(exeDir, assetName)) + } + for _, typeName := range pathTypeNames { + for _, name := range names { + appendPath(filepath.Join(exeDir, "drivers", typeName, name)) + } + for _, assetName := range assetNames { + appendPath(filepath.Join(exeDir, "drivers", typeName, assetName)) + } + } resourcesDir := filepath.Clean(filepath.Join(exeDir, "..", "Resources")) - appendPath(filepath.Join(resourcesDir, "drivers", driverType, name)) - appendPath(filepath.Join(resourcesDir, "drivers", driverType, assetName)) + for _, typeName := range pathTypeNames { + for _, name := range names { + appendPath(filepath.Join(resourcesDir, "drivers", typeName, name)) + } + for _, assetName := range assetNames { + appendPath(filepath.Join(resourcesDir, "drivers", typeName, assetName)) + } + } } if wd, err := os.Getwd(); err == nil && strings.TrimSpace(wd) != "" { - appendPath(filepath.Join(wd, "dist", assetName)) - appendPath(filepath.Join(wd, assetName)) + for _, assetName := range assetNames { + appendPath(filepath.Join(wd, "dist", assetName)) + appendPath(filepath.Join(wd, assetName)) + } } unique := make([]string, 0, len(candidates)) @@ -3075,8 +3251,7 @@ func preloadOptionalDriverPackageSizes(definitions []driverDefinition) map[strin fillFromSizes := func(sizeByAsset map[string]int64, driverTypes []string) []string { missing := make([]string, 0, len(driverTypes)) for _, driverType := range driverTypes { - assetName := optionalDriverReleaseAssetName(driverType) - sizeBytes := sizeByAsset[assetName] + sizeBytes := resolveOptionalDriverAssetSize(sizeByAsset, driverType) if sizeBytes > 0 { result[driverType] = sizeBytes continue diff --git a/internal/db/diros_impl.go b/internal/db/diros_impl.go index 30eb116..38ac270 100644 --- a/internal/db/diros_impl.go +++ b/internal/db/diros_impl.go @@ -21,7 +21,7 @@ const ( defaultDirosPort = 9030 ) -// DirosDB 使用独立 driver 名称(diros)接入,底层协议兼容 MySQL。 +// DirosDB 使用独立 driver 名称(diros)接入,底层协议兼容 MySQL(对外显示为 Doris)。 type DirosDB struct { MySQLDB } @@ -146,7 +146,7 @@ func (d *DirosDB) getDSN(config connection.ConnectionConfig) string { protocol = netName address = normalizeMySQLAddress(config.Host, config.Port) } else { - logger.Warnf("注册 Diros SSH 网络失败,将尝试直连:地址=%s:%d 用户=%s,原因:%v", config.Host, config.Port, config.User, err) + logger.Warnf("注册 Doris SSH 网络失败,将尝试直连:地址=%s:%d 用户=%s,原因:%v", config.Host, config.Port, config.User, err) } } @@ -177,7 +177,7 @@ func (d *DirosDB) Connect(config connection.ConnectionConfig) error { runConfig := applyDirosURI(config) addresses := collectDirosAddresses(runConfig) if len(addresses) == 0 { - return fmt.Errorf("连接建立后验证失败:未找到可用的 Diros 地址") + return fmt.Errorf("连接建立后验证失败:未找到可用的 Doris 地址") } var errorDetails []string @@ -214,7 +214,7 @@ func (d *DirosDB) Connect(config connection.ConnectionConfig) error { } if len(errorDetails) == 0 { - return fmt.Errorf("连接建立后验证失败:未找到可用的 Diros 地址") + return fmt.Errorf("连接建立后验证失败:未找到可用的 Doris 地址") } return fmt.Errorf("连接建立后验证失败:%s", strings.Join(errorDetails, ";")) } diff --git a/internal/db/driver_support.go b/internal/db/driver_support.go index 4ffe820..517a81a 100644 --- a/internal/db/driver_support.go +++ b/internal/db/driver_support.go @@ -61,7 +61,7 @@ func driverDisplayName(driverType string) string { case "mariadb": return "MariaDB" case "diros": - return "Diros" + return "Doris" case "sphinx": return "Sphinx" case "postgres":