From ddc8f37645bb1527b6e8df867a3f21502aedd1e3 Mon Sep 17 00:00:00 2001 From: actiontech-zihan Date: Fri, 22 May 2026 13:22:04 +0000 Subject: [PATCH 1/2] feat(sql_workbench): support GaussDB / PostgreSQL in SQL workbench whitelist - SupportDBType: add DBTypeGaussDB + DBTypePostgreSQL to whitelist (EARS-1.2 / decision-3 positive coverage for KF-2) - convertDBType: add "GaussDB" -> "GAUSSDB" mapping immediately after the existing "PostgreSQL" -> "POSTGRESQL" mapping (EARS-1.3 / CR-12 case-sensitivity normalization) - unit tests: - Test_convertDBType: new "GaussDB" case (13 total); existing "PostgreSQL" / "Unknown passthrough" regressed unchanged - Test_SupportDBType: flip "PostgreSQL" expected from false to true (decision-3 lock); new "GaussDB supported" + "GaussDBForMySQL unsupported" cases; existing SQL Server negative regression kept - Test_SupportDBType_GaussDB_PG_family_consistency: hard assertion PG family (PostgreSQL + GaussDB) whitelist coupling Related: actiontech/dms-ee#865 --- .../service/sql_workbench_service.go | 8 ++++++-- .../service/sql_workbench_service_test.go | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/internal/sql_workbench/service/sql_workbench_service.go b/internal/sql_workbench/service/sql_workbench_service.go index bd8da252..c8f79944 100644 --- a/internal/sql_workbench/service/sql_workbench_service.go +++ b/internal/sql_workbench/service/sql_workbench_service.go @@ -945,13 +945,15 @@ func (sqlWorkbenchService *SqlWorkbenchService) buildUpdateDatasourceRequest(ctx // convertDBType 转换数据库类型 func (sqlWorkbenchService *SqlWorkbenchService) convertDBType(dmsDBType string) string { // 这里需要根据实际的数据库类型映射关系进行转换 - // ODC目前支持的数据源有: OB_MYSQL, OB_ORACLE, ORACLE, MYSQL, ODP_SHARDING_OB_MYSQL, DORIS, POSTGRESQL + // ODC目前支持的数据源有: OB_MYSQL, OB_ORACLE, ORACLE, MYSQL, ODP_SHARDING_OB_MYSQL, DORIS, POSTGRESQL, GAUSSDB // 其余调用创建数据源接口会直接失败 switch dmsDBType { case "MySQL": return "MYSQL" case "PostgreSQL": return "POSTGRESQL" + case "GaussDB": + return "GAUSSDB" case "Oracle": return "ORACLE" case "SQL Server": @@ -985,7 +987,9 @@ func (sqlWorkbenchService *SqlWorkbenchService) SupportDBType(dbType pkgConst.DB dbType == pkgConst.DBTypeTiDB || dbType == pkgConst.DBTypeTDSQLForInnoDB || dbType == pkgConst.DBTypeGoldenDB || - dbType == pkgConst.DBTypePolarDBForMySQL + dbType == pkgConst.DBTypePolarDBForMySQL || + dbType == pkgConst.DBTypeGaussDB || + dbType == pkgConst.DBTypePostgreSQL } func buildMongoDatasourceOptions(dbService *biz.DBService) (*string, interface{}, map[string]interface{}) { diff --git a/internal/sql_workbench/service/sql_workbench_service_test.go b/internal/sql_workbench/service/sql_workbench_service_test.go index 924b3594..b3f578f3 100644 --- a/internal/sql_workbench/service/sql_workbench_service_test.go +++ b/internal/sql_workbench/service/sql_workbench_service_test.go @@ -25,6 +25,7 @@ func Test_convertDBType(t *testing.T) { "TDSQL For InnoDB": {input: "TDSQL For InnoDB", expected: "MYSQL"}, "GoldenDB": {input: "GoldenDB", expected: "MYSQL"}, "PolarDB For MySQL": {input: "PolarDB For MySQL", expected: "MYSQL"}, + "GaussDB": {input: "GaussDB", expected: "GAUSSDB"}, "MongoDB": {input: "MongoDB", expected: "MONGODB"}, "Unknown passthrough": {input: "UnknownDB", expected: "UnknownDB"}, } @@ -52,9 +53,11 @@ 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}, - "PostgreSQL unsupported": {input: pkgConst.DBTypePostgreSQL, expected: false}, + "PostgreSQL supported": {input: pkgConst.DBTypePostgreSQL, expected: true}, "SQL Server unsupported": {input: pkgConst.DBTypeSQLServer, expected: false}, "PolarDB For MySQL supported": {input: pkgConst.DBTypePolarDBForMySQL, expected: true}, + "GaussDB supported": {input: pkgConst.DBTypeGaussDB, expected: true}, + "GaussDBForMySQL unsupported": {input: pkgConst.DBTypeGaussDBForMySQL, expected: false}, } for name, tc := range cases { t.Run(name, func(t *testing.T) { @@ -66,6 +69,18 @@ func Test_SupportDBType(t *testing.T) { } } +func Test_SupportDBType_GaussDB_PG_family_consistency(t *testing.T) { + svc := &SqlWorkbenchService{} + // CR-13: design §1.2 decision-3 locks PG family (PostgreSQL + GaussDB) + // must be whitelisted together; SQL workbench routing assumes the pair. + if got := svc.SupportDBType(pkgConst.DBTypePostgreSQL); !got { + t.Errorf("PostgreSQL must be supported (CR-13 / EARS-1.2)") + } + if got := svc.SupportDBType(pkgConst.DBTypeGaussDB); !got { + t.Errorf("GaussDB must be supported (EARS-1.2 / decision-3)") + } +} + func Test_buildMongoDatasourceOptions(t *testing.T) { defaultDB := "appdb" defaultSchema, propertiesValue, jdbcParams := buildMongoDatasourceOptions(&biz.DBService{ From 8ee5413364495925cc40703d20f114d463636479 Mon Sep 17 00:00:00 2001 From: actiontech-zihan Date: Fri, 22 May 2026 16:24:18 +0000 Subject: [PATCH 2/2] fix(router): skip static fallback for /odc_query to allow ODC proxy The static middleware Skipper at internal/apiserver/service/router.go only skipped /cloudbeaver, /provision/v, /sqle/v and /swagger paths. Requests to /odc_query/ (with trailing slash), /odc_query/index.html and any /odc_query/ were intercepted by the DMS HTML5 SPA fallback and got served as the DMS index.html (873B), instead of the real ODC umi index.html (~11KB). This broke the DMS UI 'SQL Workbench' entry whenever the link used the trailing-slash form (`/odc_query/?dsId=...`). Without the fix the browser landed on the DMS dashboard rather than the ODC SQL workbench, even though API and subresource proxy targets at `/odc_query/*` worked fine. Add a HasPrefix check against SqlWorkbenchController.SqlWorkbenchService.GetRootUri() (==/odc_query) at the top of the Skipper so all `/odc_query` and `/odc_query/...` requests bypass StaticConfig and reach the existing ProxyWithConfig rewrite (`/odc_query/*` -> `/$1`) targeting ODC 8989. Refs: dms-ee#865 --- internal/apiserver/service/router.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/apiserver/service/router.go b/internal/apiserver/service/router.go index a2e5cdba..4d85a029 100644 --- a/internal/apiserver/service/router.go +++ b/internal/apiserver/service/router.go @@ -451,6 +451,13 @@ func (s *APIServer) installMiddleware() error { s.echo.Use(middleware.StaticWithConfig(middleware.StaticConfig{ Skipper: middleware.Skipper(func(c echo.Context) bool { + // 必须先跳过 /odc_query,避免 DMS 自身的 static fallback 把 + // `/odc_query/`、`/odc_query/index.html` 等子路径返回为 DMS index.html, + // 导致 ODC SQL 工作台跳转被截获。无尾斜杠的 /odc_query 由 Group route + // 直接走 ProxyConfig 代理到 ODC 8989,本 Skipper 不影响。 + if strings.HasPrefix(c.Request().URL.Path, s.SqlWorkbenchController.SqlWorkbenchService.GetRootUri()) { + return true + } if strings.HasPrefix(c.Request().URL.Path, s.SqlWorkbenchController.CloudbeaverService.CloudbeaverUsecase.GetRootUri()) { return true }