From 68efabc991a1d7dbe58f57e8318f100336e82b4b Mon Sep 17 00:00:00 2001 From: actiontech-zihan Date: Tue, 26 May 2026 05:35:38 +0000 Subject: [PATCH] fix(dms): normalize GaussDB db_type alias for db_services filter and UpdateDBService (#2877) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 sqle-ee #2877 Batch 1 复测发现的两个串联 bug: bug-A: db_services API 的 filter_by_db_type 入参与落库的主形态字面值不一致 - DMS 落库使用主形态 "GaussDB / openGauss"(DBTypeGaussDB 常量) - SQLE plugin / driver_options 接口暴露给前端的字面值是 "GaussDB" - 前端按 "GaussDB" 调 db_services?filter_by_db_type=GaussDB → 返回空 修复:在 internal/dms/service/db_service.go 的 filter_by_db_type 处加 pkgConst.NormalizeDBType 归一 bug-C: UpdateDBService 校验 db_type 时不接受 alias - GetDriverParamsByDBType 用调用方原值匹配 driver_options.DBType, GaussDB 与 GaussDB / openGauss 都不能命中 - UpdateDBServiceByArgs 还有一处 ds.DBType != updateDBService.DBType 会因字面值不一致直接报 "update db service db type is unsupported" 修复:在 GetDriverParamsByDBType 与 UpdateDBServiceByArgs 校验处 都用 NormalizeDBType 做归一比较 新增 internal/dms/pkg/constant.NormalizeDBType + 单测,覆盖 GaussDB / openGauss alias 双向归一与其它 DBType passthrough,避免字面值漂移再次拖垮上下游契约。 Refs #2877 --- internal/dms/biz/db_service.go | 11 +++++++-- internal/dms/pkg/constant/const.go | 29 ++++++++++++++++++++++++ internal/dms/pkg/constant/const_test.go | 30 +++++++++++++++++++++++++ internal/dms/service/db_service.go | 4 +++- 4 files changed, 71 insertions(+), 3 deletions(-) diff --git a/internal/dms/biz/db_service.go b/internal/dms/biz/db_service.go index bdc4d5d8c..dbfc64285 100644 --- a/internal/dms/biz/db_service.go +++ b/internal/dms/biz/db_service.go @@ -529,8 +529,13 @@ func (d *DBServiceUsecase) GetDriverParamsByDBType(ctx context.Context, dbType s if err != nil { return nil, err } + // 同时接受调用方传入的主形态与别名(如 "GaussDB / openGauss" / "GaussDB" 都接受), + // 与 driver_options 接口实际暴露的字面值进行同形态比对。详见 #2877 bug-C。 + normalized := pkgConst.NormalizeDBType(dbType) for _, driverOptions := range databaseOptions { - if driverOptions.DBType == dbType { + if driverOptions.DBType == dbType || + driverOptions.DBType == normalized || + pkgConst.NormalizeDBType(driverOptions.DBType) == normalized { return convertAdditionParamsToParams(driverOptions.Params), nil } @@ -715,7 +720,9 @@ func (d *DBServiceUsecase) UpdateDBServiceByArgs(ctx context.Context, dbServiceU // check { - if ds.DBType != updateDBService.DBType { + // 允许调用方传入 alias(如 "GaussDB"),与落库的主形态(如 + // "GaussDB / openGauss")做归一化比较,详见 #2877 bug-C。 + if pkgConst.NormalizeDBType(ds.DBType) != pkgConst.NormalizeDBType(updateDBService.DBType) { return fmt.Errorf("update db service db type is unsupported") } diff --git a/internal/dms/pkg/constant/const.go b/internal/dms/pkg/constant/const.go index 187416003..e7642fd54 100644 --- a/internal/dms/pkg/constant/const.go +++ b/internal/dms/pkg/constant/const.go @@ -264,6 +264,35 @@ func ParseDBType(s string) (DBType, error) { } } +// dbTypeAliasMap 将上下游(如 SQLE plugin / 前端规范化后的 db_type)使用的别名映射回 +// DMS 内部落库使用的主形态。例如 GaussDB / openGauss 的 DBType 常量为 +// "GaussDB / openGauss",但 SQLE plugin 与 driver_options 接口暴露给前端的字面值是 +// "GaussDB",前端再以 "GaussDB" 作为 filter 条件回查 db_services / 在编辑数据源时回写 +// db_type,会因字面值不一致而失败(issue #2877 bug-A / bug-C)。 +// +// 当前只覆盖 GaussDB;如未来新增其它需要 alias 的 DBType,在此处补充。 +var dbTypeAliasMap = map[string]DBType{ + "GaussDB": DBTypeGaussDB, + "GaussDB / openGauss": DBTypeGaussDB, + "openGauss": DBTypeGaussDB, +} + +// NormalizeDBType 将传入的 db_type 字符串归一化为 DMS 内部落库使用的主形态。 +// - 命中 DBType 枚举常量本身(如 "MySQL")直接返回; +// - 命中已知 alias(如 "GaussDB" / "openGauss")映射为主形态 DBTypeGaussDB; +// - 其它字符串保持原样返回,由调用方决定是否走 ParseDBType / 白名单校验。 +// +// 该函数只做"形态归一",不做合法性校验;不会返回 error。 +func NormalizeDBType(s string) string { + if s == "" { + return s + } + if v, ok := dbTypeAliasMap[s]; ok { + return string(v) + } + return s +} + const ( DBTypeMySQL DBType = "MySQL" DBTypePostgreSQL DBType = "PostgreSQL" diff --git a/internal/dms/pkg/constant/const_test.go b/internal/dms/pkg/constant/const_test.go index 71c14a9bd..0376cb5f3 100644 --- a/internal/dms/pkg/constant/const_test.go +++ b/internal/dms/pkg/constant/const_test.go @@ -152,3 +152,33 @@ func TestParseDBType(t *testing.T) { }) } } + +// TestNormalizeDBType 验证 db_type alias 归一化覆盖 #2877 bug-A / bug-C 的核心契约。 +func TestNormalizeDBType(t *testing.T) { + cases := []struct { + name string + in string + want string + }{ + // GaussDB 别名归一为主形态 + {"alias-GaussDB", "GaussDB", string(DBTypeGaussDB)}, + {"alias-openGauss", "openGauss", string(DBTypeGaussDB)}, + // 主形态保持不变 + {"canonical-GaussDB", string(DBTypeGaussDB), string(DBTypeGaussDB)}, + {"canonical-MySQL", string(DBTypeMySQL), string(DBTypeMySQL)}, + // 其它已存在的 DBType 不受影响 + {"PostgreSQL", "PostgreSQL", "PostgreSQL"}, + {"DM", string(DBTypeDM), string(DBTypeDM)}, + // 未知值 / 空串保持原样 + {"unknown", "UnknownDB", "UnknownDB"}, + {"empty", "", ""}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got := NormalizeDBType(tc.in) + if got != tc.want { + t.Errorf("NormalizeDBType(%q) = %q, want %q", tc.in, got, tc.want) + } + }) + } +} diff --git a/internal/dms/service/db_service.go b/internal/dms/service/db_service.go index 33d29bca8..89e16df45 100644 --- a/internal/dms/service/db_service.go +++ b/internal/dms/service/db_service.go @@ -557,10 +557,12 @@ func (d *DMSService) ListDBServices(ctx context.Context, req *dmsCommonV2.ListDB } if req.FilterByDBType != "" { + // 将上下游传入的 db_type 别名(如 "GaussDB")归一为 DMS 内部落库的主形态 + // (如 "GaussDB / openGauss"),避免字面值不一致导致 filter 命中失败。详见 #2877 bug-A。 andConditions = append(andConditions, pkgConst.FilterCondition{ Field: string(biz.DBServiceFieldDBType), Operator: pkgConst.FilterOperatorEqual, - Value: req.FilterByDBType, + Value: pkgConst.NormalizeDBType(req.FilterByDBType), }) }