Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions internal/dms/pkg/constant/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ func ParseDBType(s string) (DBType, error) {
return DBTypePolarDBForMySQL, nil
case "MongoDB":
return DBTypeMongoDB, nil
case "Redis":
return DBTypeRedis, nil
case "OceanBase For Oracle":
return DBTypeOceanBaseOracle, nil

Expand All @@ -284,6 +286,7 @@ const (
DBTypeHANA DBType = "HANA"
DBTypePolarDBForMySQL DBType = "PolarDB For MySQL"
DBTypeMongoDB DBType = "MongoDB"
DBTypeRedis DBType = "Redis"
DBTypeOceanBaseOracle DBType = "OceanBase For Oracle"
)

Expand Down
1 change: 1 addition & 0 deletions internal/dms/pkg/constant/const_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ func TestParseDBType(t *testing.T) {
// PolarDB-MySQL 新增 (Issue #826)
"PolarDB For MySQL": {input: "PolarDB For MySQL", expected: DBTypePolarDBForMySQL},
"MongoDB": {input: "MongoDB", expected: DBTypeMongoDB},
"Redis": {input: "Redis", expected: DBTypeRedis},
// "PolarDB" 单独不应匹配
"PolarDB only": {input: "PolarDB", expectError: true},
"invalid type": {input: "UnknownDB", expectError: true},
Expand Down
44 changes: 43 additions & 1 deletion internal/sql_workbench/service/sql_workbench_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,12 @@ const (
mongoTLSEnabledParam = "tls"
mongoDirectConnectionParam = "direct_connection"
mongoTLSSkipVerifyParam = "tls_skip_verify"
redisDefaultDatabaseParam = "default_database"
redisTLSEnabledParam = "tls"
redisTLSInsecureParam = "tls_insecure"
redisScanCountParam = "scan_count"
redisKeySeparatorParam = "key_separator"
redisCommandTimeoutParam = "command_timeout_ms"
)

// buildDatasourceBaseInfo 构建数据源基础信息
Expand Down Expand Up @@ -898,6 +904,10 @@ func (sqlWorkbenchService *SqlWorkbenchService) fillDatasourceBaseInfo(datasourc
baseInfo.DefaultSchema, baseInfo.Properties, baseInfo.JDBCParams = buildMongoDatasourceOptions(dbService)
}

if dbService.DBType == string(pkgConst.DBTypeRedis) {
baseInfo.DefaultSchema, baseInfo.Properties, baseInfo.JDBCParams = buildRedisDatasourceOptions(dbService)
}

// DB2 特殊处理:从 AdditionalParams.database_name 取默认 schema 透传到 ODC
if dbService.DBType == "DB2" {
databaseNameParam := dbService.AdditionalParams.GetParam("database_name")
Expand Down Expand Up @@ -993,6 +1003,8 @@ func (sqlWorkbenchService *SqlWorkbenchService) convertDBType(dmsDBType string)
return "MYSQL"
case "MongoDB":
return "MONGODB"
case "Redis":
return "REDIS"
case "DB2":
return "DB2"
default:
Expand All @@ -1010,7 +1022,8 @@ func (sqlWorkbenchService *SqlWorkbenchService) SupportDBType(dbType pkgConst.DB
dbType == pkgConst.DBTypeGoldenDB ||
dbType == pkgConst.DBTypePolarDBForMySQL ||
dbType == pkgConst.DBTypeGaussDB ||
dbType == pkgConst.DBTypePostgreSQL
dbType == pkgConst.DBTypePostgreSQL ||
dbType == pkgConst.DBTypeRedis
}

func buildMongoDatasourceOptions(dbService *biz.DBService) (*string, interface{}, map[string]interface{}) {
Expand Down Expand Up @@ -1050,6 +1063,35 @@ func buildMongoDatasourceOptions(dbService *biz.DBService) (*string, interface{}
return defaultSchema, nil, jdbcParams
}

func buildRedisDatasourceOptions(dbService *biz.DBService) (*string, interface{}, map[string]interface{}) {
defaultDatabase := dbService.AdditionalParams.GetParam(redisDefaultDatabaseParam).String()
var defaultSchema *string
jdbcParams := map[string]interface{}{}
if defaultDatabase != "" {
defaultSchema = &defaultDatabase
jdbcParams["defaultDatabase"] = defaultDatabase
}
if tlsParam := dbService.AdditionalParams.GetParam(redisTLSEnabledParam); tlsParam != nil && tlsParam.String() != "" {
jdbcParams["tls"] = tlsParam.Bool()
}
if dbService.AdditionalParams.GetParam(redisTLSInsecureParam).Bool() {
jdbcParams["tlsInsecure"] = true
}
if scanCount := dbService.AdditionalParams.GetParam(redisScanCountParam).String(); scanCount != "" {
jdbcParams["scanCount"] = scanCount
}
if keySeparator := dbService.AdditionalParams.GetParam(redisKeySeparatorParam).String(); keySeparator != "" {
jdbcParams["keySeparator"] = keySeparator
}
if timeout := dbService.AdditionalParams.GetParam(redisCommandTimeoutParam).String(); timeout != "" {
jdbcParams["commandTimeoutMs"] = timeout
}
if len(jdbcParams) == 0 {
return defaultSchema, nil, nil
}
return defaultSchema, nil, jdbcParams
}

func interfacePtr(v interface{}) *interface{} {
if v == nil {
return nil
Expand Down
58 changes: 53 additions & 5 deletions internal/sql_workbench/service/sql_workbench_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func Test_convertDBType(t *testing.T) {
"PolarDB For MySQL": {input: "PolarDB For MySQL", expected: "MYSQL"},
"GaussDB": {input: "GaussDB", expected: "GAUSSDB"},
"MongoDB": {input: "MongoDB", expected: "MONGODB"},
"Redis": {input: "Redis", expected: "REDIS"},
"DB2": {input: "DB2", expected: "DB2"},
"Unknown passthrough": {input: "UnknownDB", expected: "UnknownDB"},
}
Expand Down Expand Up @@ -55,6 +56,7 @@ func Test_SupportDBType(t *testing.T) {
"TDSQL supported": {input: pkgConst.DBTypeTDSQLForInnoDB, expected: true},
"GoldenDB supported": {input: pkgConst.DBTypeGoldenDB, expected: true},
"MongoDB unsupported": {input: pkgConst.DBTypeMongoDB, expected: false},
"Redis supported": {input: pkgConst.DBTypeRedis, expected: true},
"PostgreSQL supported": {input: pkgConst.DBTypePostgreSQL, expected: true},
"SQL Server unsupported": {input: pkgConst.DBTypeSQLServer, expected: false},
"PolarDB For MySQL supported": {input: pkgConst.DBTypePolarDBForMySQL, expected: true},
Expand Down Expand Up @@ -140,6 +142,52 @@ func Test_buildMongoDatasourceOptions_tlsOnly(t *testing.T) {
}
}

func Test_buildRedisDatasourceOptions(t *testing.T) {
defaultDB := "2"
defaultSchema, propertiesValue, jdbcParams := buildRedisDatasourceOptions(&biz.DBService{
DBType: string(pkgConst.DBTypeRedis),
Host: "127.0.0.1",
Port: "6379",
AdditionalParams: pkgParams.Params{
&pkgParams.Param{Key: redisDefaultDatabaseParam, Value: defaultDB, Type: pkgParams.ParamTypeString},
&pkgParams.Param{Key: redisTLSEnabledParam, Value: "true", Type: pkgParams.ParamTypeBool},
&pkgParams.Param{Key: redisTLSInsecureParam, Value: "true", Type: pkgParams.ParamTypeBool},
&pkgParams.Param{Key: redisScanCountParam, Value: "200", Type: pkgParams.ParamTypeString},
&pkgParams.Param{Key: redisKeySeparatorParam, Value: ":", Type: pkgParams.ParamTypeString},
&pkgParams.Param{Key: redisCommandTimeoutParam, Value: "3000", Type: pkgParams.ParamTypeString},
},
})
if defaultSchema == nil || *defaultSchema != defaultDB {
t.Fatalf("unexpected default schema: %#v", defaultSchema)
}
if propertiesValue != nil {
t.Fatalf("expected nil properties, got %#v", propertiesValue)
}
if jdbcParams["defaultDatabase"] != defaultDB || jdbcParams["tls"] != true || jdbcParams["tlsInsecure"] != true {
t.Fatalf("unexpected redis base params: %#v", jdbcParams)
}
if jdbcParams["scanCount"] != "200" || jdbcParams["keySeparator"] != ":" || jdbcParams["commandTimeoutMs"] != "3000" {
t.Fatalf("unexpected redis tuning params: %#v", jdbcParams)
}
}

func Test_buildRedisDatasourceOptions_noSensitiveProperties(t *testing.T) {
_, propertiesValue, jdbcParams := buildRedisDatasourceOptions(&biz.DBService{
DBType: string(pkgConst.DBTypeRedis),
User: "default",
Password: "secret",
AdditionalParams: pkgParams.Params{
&pkgParams.Param{Key: redisTLSEnabledParam, Value: "false", Type: pkgParams.ParamTypeBool},
},
})
if propertiesValue != nil {
t.Fatalf("expected redis properties to stay nil, got %#v", propertiesValue)
}
if _, ok := jdbcParams["password"]; ok {
t.Fatalf("redis password leaked into jdbc params: %#v", jdbcParams)
}
}

// Test_buildDatasourceBaseInfo_DB2 覆盖 buildDatasourceBaseInfo 中 DB2 / 回归 4 组 case:
//
// (a) DB2 正例:AdditionalParam database_name=testdb → baseInfo.DefaultSchema=="testdb"
Expand All @@ -154,11 +202,11 @@ func Test_buildDatasourceBaseInfo_DB2(t *testing.T) {
const datasourceName = "proj:ds"

cases := map[string]struct {
dbService *biz.DBService
expectErr bool
expectErrSubstr string
expectDefaultSchema *string
expectServiceName *string
dbService *biz.DBService
expectErr bool
expectErrSubstr string
expectDefaultSchema *string
expectServiceName *string
}{
"DB2 happy path": {
dbService: &biz.DBService{
Expand Down