mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-03 16:00:25 +08:00
增加webssh及数据库查询
This commit is contained in:
127
db/db.go
Normal file
127
db/db.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"mayfly-go/base/model"
|
||||
"mayfly-go/models"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
var dbCache sync.Map
|
||||
|
||||
// db实例
|
||||
type DbInstance struct {
|
||||
Id uint64
|
||||
Type string
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
// 执行查询语句
|
||||
func (d *DbInstance) SelectData(sql string) ([]map[string]string, error) {
|
||||
sql = strings.Trim(sql, " ")
|
||||
if !strings.HasPrefix(sql, "SELECT") && !strings.HasPrefix(sql, "select") {
|
||||
return nil, errors.New("该sql非查询语句")
|
||||
}
|
||||
rows, err := d.db.Query(sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// rows对象一定要close掉,如果出错,不关掉则会很迅速的达到设置最大连接数,
|
||||
// 后面的链接过来直接报错或拒绝,实际上也没有起效果
|
||||
defer func() {
|
||||
if rows != nil {
|
||||
rows.Close()
|
||||
}
|
||||
}()
|
||||
cols, _ := rows.Columns()
|
||||
// 这里表示一行填充数据
|
||||
scans := make([]interface{}, len(cols))
|
||||
// 这里表示一行所有列的值,用[]byte表示
|
||||
vals := make([][]byte, len(cols))
|
||||
// 这里scans引用vals,把数据填充到[]byte里
|
||||
for k := range vals {
|
||||
scans[k] = &vals[k]
|
||||
}
|
||||
result := make([]map[string]string, 0)
|
||||
for rows.Next() {
|
||||
// 不Scan也会导致等待,该链接实际处于未工作的状态,然后也会导致连接数迅速达到最大
|
||||
err := rows.Scan(scans...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 每行数据
|
||||
rowData := make(map[string]string)
|
||||
// 把vals中的数据复制到row中
|
||||
for k, v := range vals {
|
||||
key := cols[k]
|
||||
// 这里把[]byte数据转成string
|
||||
rowData[key] = string(v)
|
||||
}
|
||||
//放入结果集
|
||||
result = append(result, rowData)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// 执行 update, insert, delete,建表等sql
|
||||
//
|
||||
// 返回影响条数和错误
|
||||
func (d *DbInstance) Exec(sql string) (int64, error) {
|
||||
res, err := d.db.Exec(sql)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
// 关闭连接,并从缓存中移除
|
||||
func (d *DbInstance) Close() {
|
||||
d.db.Close()
|
||||
dbCache.Delete(d.Id)
|
||||
}
|
||||
|
||||
// 获取dataSourceName
|
||||
func getDsn(d *models.Db) string {
|
||||
if d.Type == "mysql" {
|
||||
return fmt.Sprintf("%s:%s@%s(%s:%d)/%s", d.Username, d.Passowrd, d.Network, d.Host, d.Port, d.Database)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetDbInstance(id uint64) *DbInstance {
|
||||
// Id不为0,则为需要缓存
|
||||
needCache := id != 0
|
||||
if needCache {
|
||||
load, ok := dbCache.Load(id)
|
||||
if ok {
|
||||
return load.(*DbInstance)
|
||||
}
|
||||
}
|
||||
d := models.GetDbById(uint64(id))
|
||||
model.NotNil(d, "数据库信息不存在")
|
||||
DB, err := sql.Open(d.Type, getDsn(d))
|
||||
model.ErrIsNil(err, fmt.Sprintf("Open %s failed, err:%v\n", d.Type, err))
|
||||
perr := DB.Ping()
|
||||
if perr != nil {
|
||||
panic(model.NewBizErr(fmt.Sprintf("数据库连接失败: %s", perr.Error())))
|
||||
}
|
||||
|
||||
// 最大连接周期,超过时间的连接就close
|
||||
DB.SetConnMaxLifetime(100 * time.Second)
|
||||
// 设置最大连接数
|
||||
DB.SetMaxOpenConns(5)
|
||||
// 设置闲置连接数
|
||||
DB.SetMaxIdleConns(1)
|
||||
|
||||
dbi := &DbInstance{Id: id, Type: d.Type, db: DB}
|
||||
if needCache {
|
||||
dbCache.LoadOrStore(d.Id, dbi)
|
||||
}
|
||||
return dbi
|
||||
}
|
||||
Reference in New Issue
Block a user