增加webssh及数据库查询

This commit is contained in:
meilin.huang
2021-01-08 15:37:32 +08:00
parent 111612b7f2
commit 4c2e6b6155
60 changed files with 4347 additions and 2222 deletions

127
db/db.go Normal file
View 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
}