Skip to content
Merged
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 @@ -262,6 +262,8 @@ func ParseDBType(s string) (DBType, error) {
return DBTypeRedis, nil
case "OceanBase For Oracle":
return DBTypeOceanBaseOracle, nil
case "KingBase":
return DBTypeKingBase, nil

default:
return "", fmt.Errorf("invalid db type: %s", s)
Expand All @@ -288,6 +290,7 @@ const (
DBTypeMongoDB DBType = "MongoDB"
DBTypeRedis DBType = "Redis"
DBTypeOceanBaseOracle DBType = "OceanBase For Oracle"
DBTypeKingBase DBType = "KingBase"
)

var supportedDataExportDBTypes = map[DBType]struct{}{
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 @@ -129,6 +129,7 @@ func TestParseDBType(t *testing.T) {
"PolarDB For MySQL": {input: "PolarDB For MySQL", expected: DBTypePolarDBForMySQL},
"MongoDB": {input: "MongoDB", expected: DBTypeMongoDB},
"Redis": {input: "Redis", expected: DBTypeRedis},
"KingBase": {input: "KingBase", expected: DBTypeKingBase},
// "PolarDB" 单独不应匹配
"PolarDB only": {input: "PolarDB", expectError: true},
"invalid type": {input: "UnknownDB", expectError: true},
Expand Down
15 changes: 14 additions & 1 deletion internal/sql_workbench/service/sql_workbench_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,16 @@ func (sqlWorkbenchService *SqlWorkbenchService) fillDatasourceBaseInfo(datasourc
baseInfo.DefaultSchema = &databaseName
}

// KingBase:database_name → ODC defaultSchema;缺失则失败,禁止静默空默认库
if dbService.DBType == string(pkgConst.DBTypeKingBase) {
databaseNameParam := dbService.AdditionalParams.GetParam("database_name")
if databaseNameParam == nil || databaseNameParam.Value == "" {
return nil, fmt.Errorf("KingBase 数据源 %s 缺少 AdditionalParam database_name,请在数据源 AdditionalParams 中补充", dbService.Name)
}
databaseName := databaseNameParam.Value
baseInfo.DefaultSchema = &databaseName
}

return baseInfo, nil
}

Expand Down Expand Up @@ -1187,6 +1197,8 @@ func (sqlWorkbenchService *SqlWorkbenchService) convertDBType(dmsDBType string)
return "REDIS"
case "DB2":
return "DB2"
case "KingBase":
return "KINGBASE"
default:
return dmsDBType
}
Expand All @@ -1203,7 +1215,8 @@ func (sqlWorkbenchService *SqlWorkbenchService) SupportDBType(dbType pkgConst.DB
dbType == pkgConst.DBTypePolarDBForMySQL ||
dbType == pkgConst.DBTypeGaussDB ||
dbType == pkgConst.DBTypePostgreSQL ||
dbType == pkgConst.DBTypeRedis
dbType == pkgConst.DBTypeRedis ||
dbType == pkgConst.DBTypeKingBase
}

func buildMongoDatasourceOptions(dbService *biz.DBService) (*string, interface{}, map[string]interface{}) {
Expand Down
85 changes: 85 additions & 0 deletions internal/sql_workbench/service/sql_workbench_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ func Test_convertDBType(t *testing.T) {
"MongoDB": {input: "MongoDB", expected: "MONGODB"},
"Redis": {input: "Redis", expected: "REDIS"},
"DB2": {input: "DB2", expected: "DB2"},
"KingBase": {input: "KingBase", expected: "KINGBASE"},
"Unknown passthrough": {input: "UnknownDB", expected: "UnknownDB"},
}
for name, tc := range cases {
Expand Down Expand Up @@ -183,6 +184,7 @@ func Test_SupportDBType(t *testing.T) {
"GaussDB supported": {input: pkgConst.DBTypeGaussDB, expected: true},
"GaussDBForMySQL unsupported": {input: pkgConst.DBTypeGaussDBForMySQL, expected: false},
"DB2 unsupported": {input: pkgConst.DBTypeDB2, expected: false},
"KingBase supported": {input: pkgConst.DBTypeKingBase, expected: true},
"empty string unsupported": {input: pkgConst.DBType(""), expected: false},
"unknown type unsupported": {input: pkgConst.DBType("UnknownDBType"), expected: false},
}
Expand Down Expand Up @@ -390,6 +392,89 @@ func Test_buildDatasourceBaseInfo_DB2(t *testing.T) {
}
}

// Test_buildDatasourceBaseInfo_KingBase 覆盖 KingBase → defaultSchema 契约(S1 / AC-1):
//
// (a) 正例:database_name=test → DefaultSchema=="test" 且 Type 经 convert 为 KINGBASE
// (b) 负例:缺 database_name → err 含 "database_name"
// (c) MySQL 回归:DefaultSchema == nil
func Test_buildDatasourceBaseInfo_KingBase(t *testing.T) {
svc := &SqlWorkbenchService{}
const envID = int64(1)
const datasourceName = "proj:kingbase_odc_test"

cases := map[string]struct {
dbService *biz.DBService
expectErr bool
expectErrSubstr string
expectDefaultSchema *string
expectType string
}{
"KingBase happy path": {
dbService: &biz.DBService{
Name: "kingbase_odc_test",
DBType: string(pkgConst.DBTypeKingBase),
Host: "10.186.16.126",
Port: "1522",
User: "kb_dev",
AdditionalParams: pkgParams.Params{
{Key: "database_name", Value: "test"},
},
},
expectErr: false,
expectDefaultSchema: strPtr("test"),
expectType: "KINGBASE",
},
"KingBase missing database_name": {
dbService: &biz.DBService{
Name: "kingbase-missing-db",
DBType: string(pkgConst.DBTypeKingBase),
AdditionalParams: pkgParams.Params{},
},
expectErr: true,
expectErrSubstr: "database_name",
},
"MySQL regression still no DefaultSchema": {
dbService: &biz.DBService{
Name: "mysql-1",
DBType: "MySQL",
AdditionalParams: pkgParams.Params{},
},
expectErr: false,
expectDefaultSchema: nil,
expectType: "MYSQL",
},
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
got, err := svc.fillDatasourceBaseInfo(datasourceName, tc.dbService, envID)
if tc.expectErr {
if err == nil {
t.Fatalf("expected error, got nil; baseInfo=%+v", got)
}
if tc.expectErrSubstr != "" && !strings.Contains(err.Error(), tc.expectErrSubstr) {
t.Errorf("error %q does not contain %q", err.Error(), tc.expectErrSubstr)
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got == nil {
t.Fatalf("expected non-nil baseInfo")
}
if tc.expectType != "" && got.Type != tc.expectType {
t.Errorf("Type = %q, want %q", got.Type, tc.expectType)
}
if (got.DefaultSchema == nil) != (tc.expectDefaultSchema == nil) {
t.Errorf("DefaultSchema nil mismatch: got=%v, want=%v", got.DefaultSchema, tc.expectDefaultSchema)
} else if got.DefaultSchema != nil && tc.expectDefaultSchema != nil && *got.DefaultSchema != *tc.expectDefaultSchema {
t.Errorf("DefaultSchema = %q, want %q", *got.DefaultSchema, *tc.expectDefaultSchema)
}
})
}
}

func strPtr(s string) *string {
return &s
}
Expand Down