| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package drivers
- import (
- "context"
- "dbview/service/internal/common/databases/meta"
- "fmt"
- "math"
- "regexp"
- "strconv"
- "sync"
- )
- type Connection interface {
- Close() error
- Ping(context.Context) error
- }
- // 驱动接口 - 所有数据库驱动必须实现
- type Driver interface {
- Open(config *meta.ConnectionConfig) (Connection, error)
- Version() string
- }
- // 驱动注册表
- type DriverRegistry struct {
- drivers map[string]map[string]Driver // 格式: dbType -> version -> Driver
- mu sync.RWMutex
- }
- var globalRegistry = &DriverRegistry{
- drivers: make(map[string]map[string]Driver),
- }
- // RegisterDriver 将指定数据库类型与版本的驱动注册进全局注册表(线程安全)。
- // 参数:
- // - dbType: 数据库类型标识,如 mysql、postgres。
- // - version: 驱动适配的版本号,如 v8、8.0。
- // - driver: 实际的驱动实现实例。
- //
- // 返回值:无;若类型+版本重复注册会直接 panic,提示冲突原因。
- func RegisterDriver(dbType, version string, driver Driver) {
- globalRegistry.mu.Lock()
- defer globalRegistry.mu.Unlock()
- if _, ok := globalRegistry.drivers[dbType]; !ok {
- globalRegistry.drivers[dbType] = make(map[string]Driver)
- }
- // 防止重复注册
- if _, exists := globalRegistry.drivers[dbType][version]; exists {
- panic(fmt.Sprintf("数据库驱动注册冲突:类型 %s 的版本 %s 已存在,请勿重复加载", dbType, version))
- }
- globalRegistry.drivers[dbType][version] = driver
- }
- // Connect 根据数据库类型与版本规范创建连接实例。
- // 参数:
- // - dbType: 数据库类型标识。
- // - DbVersion: 版本字符串,可为精确或语义化版本描述。
- // - config: 连接配置,包含Host/Port/用户名等信息。
- //
- // 返回值:
- // - Connection: 成功时返回可用于执行数据库操作的连接包装。
- // - error: 若无匹配驱动或打开失败则返回相应错误。
- func Connect(dbType, DbVersion string, config *meta.ConnectionConfig) (Connection, error) {
- driver, err := GetDriver(dbType, DbVersion)
- if err != nil {
- return nil, err
- }
- return driver.Open(config)
- }
- // GetDriver 从注册表中获取指定数据库类型与版本规范的驱动。
- // 参数:
- // - dbType: 数据库类型标识。
- // - versionSpec: 版本规范,支持精确版本与语义化匹配(如 v8、8.0、8)。
- //
- // 返回值:
- // - Driver: 找到时返回对应驱动实例。
- // - error: 当类型或版本不存在时返回详细错误提示。
- func GetDriver(dbType, versionSpec string) (Driver, error) {
- globalRegistry.mu.RLock()
- defer globalRegistry.mu.RUnlock()
- versions, ok := globalRegistry.drivers[dbType]
- if !ok {
- return nil, fmt.Errorf("未找到数据库类型 %s 对应的驱动实现,请确认驱动已正确注册", dbType)
- }
- // 精确匹配
- if driver, ok := versions[versionSpec]; ok {
- return driver, nil
- }
- // 模糊化版本匹配:提取数字序列并按首个数字的距离最小化来选择最近的版本。
- // 例如:传入 "8.0.27",已注册的 "v8" 或 "8" 会匹配(首个数字均为 8)。
- // 优先级:完全数字匹配 -> 最小首位数字差 -> 报错。
- extractNums := func(s string) []int {
- re := regexp.MustCompile(`\d+`)
- parts := re.FindAllString(s, -1)
- out := make([]int, 0, len(parts))
- for _, p := range parts {
- if n, err := strconv.Atoi(p); err == nil {
- out = append(out, n)
- }
- }
- return out
- }
- specNums := extractNums(versionSpec)
- if len(specNums) == 0 {
- return nil, fmt.Errorf("未找到数据库类型 %s 对应的版本 %s 驱动实现,请确认驱动已正确注册", dbType, versionSpec)
- }
- var best Driver
- bestDiff := math.MaxInt32
- found := false
- for ver, drv := range versions {
- vnums := extractNums(ver)
- if len(vnums) == 0 {
- continue
- }
- // 如果任何数字完全匹配(首位或任一位),优先返回
- for _, vn := range vnums {
- if vn == specNums[0] {
- return drv, nil
- }
- }
- // 否则以首位数字差作为距离度量
- diff := int(math.Abs(float64(vnums[0] - specNums[0])))
- if diff < bestDiff {
- bestDiff = diff
- best = drv
- found = true
- }
- }
- if found {
- return best, nil
- }
- return nil, fmt.Errorf("未找到数据库类型 %s 对应的版本 %s 驱动实现,请确认驱动已正确注册", dbType, versionSpec)
- }
- // GetRegisteredDrivers 返回当前注册表中所有数据库类型及其可用版本列表。
- // 返回值:map,键为数据库类型,值为该类型下已注册的版本切片,用于调试或展示。
- func GetRegisteredDrivers() map[string][]string {
- globalRegistry.mu.RLock()
- defer globalRegistry.mu.RUnlock()
- driversCopy := make(map[string][]string)
- for dbType, versions := range globalRegistry.drivers {
- for version := range versions {
- driversCopy[dbType] = append(driversCopy[dbType], version)
- }
- }
- return driversCopy
- }
|