package vService import ( "context" _ "dm" // 达梦数据库驱动 "fmt" "github.com/jmoiron/sqlx" "log" "strings" ) // DMDBService 数据库服务实现 type DMDBService struct { db *sqlx.DB } func NewDMDBService(dsn string) (*DMDBService, error) { db, err := sqlx.Connect("dm", dsn) if err != nil { return nil, err } return &DMDBService{db: db}, nil } func (s *DMDBService) Close() error { return s.db.Close() } func (s *DMDBService) FetchData(ctx context.Context, dbName, tableName string, limit int) ([]map[string]interface{}, error) { query := fmt.Sprintf("SELECT * FROM %s.%s WHERE ROWNUM <= %d", dbName, tableName, limit) results, err := s.QueryBySQL(ctx, dbName, query, limit) if err != nil { return nil, err } // 转换为map格式以保持兼容性 var mapResults []map[string]interface{} if len(results) > 0 { columns := results[0] for _, row := range results[1:] { rowMap := make(map[string]interface{}) for i, col := range columns { if i < len(row) { rowMap[col] = row[i] } } mapResults = append(mapResults, rowMap) } } return mapResults, nil } func (s *DMDBService) QueryBySQL(ctx context.Context, dbName string, sql string, limit int) ([][]string, error) { // 添加LIMIT子句如果SQL中没有 if !strings.Contains(strings.ToUpper(sql), "LIMIT") && !strings.Contains(strings.ToUpper(sql), "ROWNUM") { sql = fmt.Sprintf("SELECT * FROM (%s) WHERE ROWNUM <= %d", sql, limit) } rows, err := s.db.QueryxContext(ctx, sql) if err != nil { return nil, err } defer rows.Close() // 获取列名 columns, err := rows.Columns() if err != nil { return nil, err } var results [][]string // 添加列名作为第一行 results = append(results, columns) // 处理数据行 for rows.Next() { // 创建动态接收器 values := make([]interface{}, len(columns)) for i := range values { var v interface{} values[i] = &v } if err := rows.Scan(values...); err != nil { return nil, err } // 转换为字符串数组 row := make([]string, len(columns)) for i, val := range values { if val == nil { row[i] = "NULL" } else { row[i] = fmt.Sprintf("%v", *val.(*interface{})) } } results = append(results, row) } return results, nil } func (s *DMDBService) AddColumn(ctx context.Context, dbName, tableName, columnName, columnType string) error { query := fmt.Sprintf("ALTER TABLE %s.%s ADD %s %s", dbName, tableName, columnName, columnType) if _, err := s.db.ExecContext(ctx, query); err != nil { return err } return nil } func (s *DMDBService) AddComment(ctx context.Context, dbName, tableName, columnName, comment string) error { if comment != "" { commentQuery := fmt.Sprintf("COMMENT ON COLUMN %s.%s.%s IS '%s'", dbName, tableName, columnName, strings.ReplaceAll(comment, "'", "''")) if _, err := s.db.ExecContext(ctx, commentQuery); err != nil { return err } } return nil } func (s *DMDBService) DropColumn(ctx context.Context, dbName, tableName, columnName string) error { query := fmt.Sprintf("ALTER TABLE %s.%s DROP COLUMN %s", dbName, tableName, columnName) _, err := s.db.ExecContext(ctx, query) return err } // ColumnInfo 表字段信息(用于表结构查询) type ColumnInfo struct { ColumnName string `db:"COLUMN_NAME"` DataType string `db:"DATA_TYPE"` DataLength *int `db:"DATA_LENGTH"` Nullable string `db:"NULLABLE"` DataDefault *string `db:"DATA_DEFAULT"` ColumnComment string `db:"COMMENTS"` } // TableStructure 查询表结构(字段名、类型、长度、可空、默认值等) func (s *DMDBService) TableStructure(ctx context.Context, dbName, tableName string) ([]ColumnInfo, error) { // 达梦 ALL_TAB_COLUMNS / USER_TAB_COLUMNS;部分版本有注释在 ALL_COL_COMMENTS query := `SELECT c.COLUMN_NAME, c.DATA_TYPE, c.DATA_LENGTH, c.NULLABLE, c.DATA_DEFAULT, com.COMMENTS FROM ALL_TAB_COLUMNS c LEFT JOIN ALL_COL_COMMENTS com ON c.OWNER = com.OWNER AND c.TABLE_NAME = com.TABLE_NAME AND c.COLUMN_NAME = com.COLUMN_NAME WHERE c.OWNER = ? AND c.TABLE_NAME = ? ORDER BY c.COLUMN_ID` rows, err := s.db.QueryxContext(ctx, query, strings.ToUpper(dbName), strings.ToUpper(tableName)) if err != nil { return nil, err } defer rows.Close() var list []ColumnInfo for rows.Next() { var c ColumnInfo if err := rows.StructScan(&c); err != nil { return nil, err } list = append(list, c) } return list, nil } // ExecSQL 执行非查询 SQL(INSERT/UPDATE/DELETE),返回影响行数;args 为参数化占位符对应的值 func (s *DMDBService) ExecSQL(ctx context.Context, sql string, args ...interface{}) (int64, error) { var err error var affected int64 if len(args) > 0 { res, e := s.db.ExecContext(ctx, sql, args...) err = e if e == nil { affected, _ = res.RowsAffected() } } else { res, e := s.db.ExecContext(ctx, sql) err = e if e == nil { affected, _ = res.RowsAffected() } } if err != nil { return 0, err } return affected, nil } // CreateTable 创建表(columnDefs 如 "id INT PRIMARY KEY, name VARCHAR(100)") func (s *DMDBService) CreateTable(ctx context.Context, dbName, tableName, columnDefs string) error { query := fmt.Sprintf("CREATE TABLE %s.%s (%s)", dbName, tableName, columnDefs) _, err := s.db.ExecContext(ctx, query) return err } // DropTable 删除表 func (s *DMDBService) DropTable(ctx context.Context, dbName, tableName string) error { query := fmt.Sprintf("DROP TABLE %s.%s", dbName, tableName) _, err := s.db.ExecContext(ctx, query) return err } func (s *DMDBService) AllTable(ctx context.Context, dbName string) (interface{}, error) { query := fmt.Sprintf("SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = '%s'", dbName) rows, err := s.db.QueryxContext(ctx, query) if err != nil { return nil, err } defer func(rows *sqlx.Rows) { err := rows.Close() if err != nil { log.Fatalf("发生异常: %v", err) } }(rows) results, err := s.QueryBySQL(ctx, dbName, query, 1000) // 默认限制1000条表名 if err != nil { return nil, err } // 转换为map格式以保持兼容性 var mapResults []map[string]interface{} if len(results) > 0 { columns := results[0] for _, row := range results[1:] { rowMap := make(map[string]interface{}) for i, col := range columns { if i < len(row) { rowMap[col] = row[i] } } mapResults = append(mapResults, rowMap) } } return mapResults, nil }