diff --git a/internal/db/dameng_impl.go b/internal/db/dameng_impl.go index 5080540..5cceb0a 100644 --- a/internal/db/dameng_impl.go +++ b/internal/db/dameng_impl.go @@ -8,6 +8,7 @@ import ( "fmt" "net" "net/url" + "sort" "strconv" "strings" "time" @@ -204,24 +205,82 @@ func (d *DamengDB) Exec(query string) (int64, error) { } func (d *DamengDB) GetDatabases() ([]string, error) { - // DM: List Users/Schemas - data, _, err := d.Query("SELECT username FROM dba_users") - if err != nil { - // Fallback if dba_users not accessible - data, _, err = d.Query("SELECT username FROM all_users") + // 达梦将「用户/模式」作为数据库列表来源,不同权限下可见口径不同。 + // 这里采用多查询口径聚合,避免仅依赖单一视图导致“少库”。 + queries := []string{ + "SELECT USERNAME AS DATABASE_NAME FROM SYS.DBA_USERS ORDER BY USERNAME", + "SELECT USERNAME AS DATABASE_NAME FROM DBA_USERS ORDER BY USERNAME", + "SELECT USERNAME AS DATABASE_NAME FROM ALL_USERS ORDER BY USERNAME", + "SELECT USERNAME AS DATABASE_NAME FROM USER_USERS", + "SELECT DISTINCT OWNER AS DATABASE_NAME FROM ALL_TABLES ORDER BY OWNER", + } + + seen := make(map[string]struct{}) + dbs := make([]string, 0, 64) + var lastErr error + success := false + + for _, q := range queries { + data, _, err := d.Query(q) if err != nil { - return nil, err + lastErr = err + continue + } + success = true + for _, row := range data { + name := getDamengRowString(row, "DATABASE_NAME", "USERNAME", "OWNER", "SCHEMA_NAME") + if name == "" { + // 回退到第一列,兼容驱动返回列名差异。 + for _, v := range row { + text := strings.TrimSpace(fmt.Sprintf("%v", v)) + if text == "" || strings.EqualFold(text, "") { + continue + } + name = text + break + } + } + if name == "" { + continue + } + key := strings.ToUpper(name) + if _, ok := seen[key]; ok { + continue + } + seen[key] = struct{}{} + dbs = append(dbs, name) } } - var dbs []string - for _, row := range data { - if val, ok := row["USERNAME"]; ok { - dbs = append(dbs, fmt.Sprintf("%v", val)) - } + + if !success && lastErr != nil { + return nil, lastErr } + + sort.Slice(dbs, func(i, j int) bool { + return strings.ToUpper(dbs[i]) < strings.ToUpper(dbs[j]) + }) return dbs, nil } +func getDamengRowString(row map[string]interface{}, keys ...string) string { + if len(row) == 0 { + return "" + } + for _, key := range keys { + for k, v := range row { + if !strings.EqualFold(strings.TrimSpace(k), strings.TrimSpace(key)) { + continue + } + text := strings.TrimSpace(fmt.Sprintf("%v", v)) + if text == "" || strings.EqualFold(text, "") { + return "" + } + return text + } + } + return "" +} + func (d *DamengDB) GetTables(dbName string) ([]string, error) { query := fmt.Sprintf("SELECT owner, table_name FROM all_tables WHERE owner = '%s' ORDER BY table_name", strings.ToUpper(dbName)) if dbName == "" {