2022-06-16 15:55:18 +08:00
|
|
|
|
package application
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"encoding/json"
|
|
|
|
|
|
"fmt"
|
2022-09-09 18:26:08 +08:00
|
|
|
|
"mayfly-go/internal/db/domain/entity"
|
|
|
|
|
|
"mayfly-go/internal/db/domain/repository"
|
2023-02-13 21:11:16 +08:00
|
|
|
|
sysapp "mayfly-go/internal/sys/application"
|
|
|
|
|
|
sysentity "mayfly-go/internal/sys/domain/entity"
|
|
|
|
|
|
"mayfly-go/pkg/biz"
|
2022-06-16 15:55:18 +08:00
|
|
|
|
"mayfly-go/pkg/model"
|
2023-02-13 21:11:16 +08:00
|
|
|
|
"strconv"
|
2022-06-16 15:55:18 +08:00
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/xwb1989/sqlparser"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2022-09-22 11:56:21 +08:00
|
|
|
|
type DbSqlExecReq struct {
|
|
|
|
|
|
DbId uint64
|
|
|
|
|
|
Db string
|
|
|
|
|
|
Sql string
|
|
|
|
|
|
Remark string
|
|
|
|
|
|
LoginAccount *model.LoginAccount
|
|
|
|
|
|
DbInstance *DbInstance
|
|
|
|
|
|
}
|
2022-09-09 18:26:08 +08:00
|
|
|
|
|
2022-09-22 11:56:21 +08:00
|
|
|
|
type DbSqlExecRes struct {
|
|
|
|
|
|
ColNames []string
|
|
|
|
|
|
Res []map[string]interface{}
|
|
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
2022-11-02 19:27:40 +08:00
|
|
|
|
// 合并执行结果,主要用于执行多条sql使用
|
|
|
|
|
|
func (d *DbSqlExecRes) Merge(execRes *DbSqlExecRes) {
|
|
|
|
|
|
canMerge := len(d.ColNames) == len(execRes.ColNames)
|
|
|
|
|
|
if !canMerge {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
// 列名不一致,则不合并
|
|
|
|
|
|
for i, colName := range d.ColNames {
|
|
|
|
|
|
if execRes.ColNames[i] != colName {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
d.Res = append(d.Res, execRes.Res...)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-22 11:56:21 +08:00
|
|
|
|
type DbSqlExec interface {
|
|
|
|
|
|
// 执行sql
|
|
|
|
|
|
Exec(execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
|
|
|
|
|
// 根据条件删除sql执行记录
|
|
|
|
|
|
DeleteBy(condition *entity.DbSqlExec)
|
|
|
|
|
|
|
|
|
|
|
|
// 分页获取
|
|
|
|
|
|
GetPageList(condition *entity.DbSqlExec, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-09 18:26:08 +08:00
|
|
|
|
func newDbSqlExecApp(dbExecSqlRepo repository.DbSqlExec) DbSqlExec {
|
|
|
|
|
|
return &dbSqlExecAppImpl{
|
|
|
|
|
|
dbSqlExecRepo: dbExecSqlRepo,
|
|
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-09 18:26:08 +08:00
|
|
|
|
type dbSqlExecAppImpl struct {
|
|
|
|
|
|
dbSqlExecRepo repository.DbSqlExec
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-01 12:45:21 +08:00
|
|
|
|
func createSqlExecRecord(execSqlReq *DbSqlExecReq) *entity.DbSqlExec {
|
|
|
|
|
|
dbSqlExecRecord := new(entity.DbSqlExec)
|
|
|
|
|
|
dbSqlExecRecord.DbId = execSqlReq.DbId
|
|
|
|
|
|
dbSqlExecRecord.Db = execSqlReq.Db
|
|
|
|
|
|
dbSqlExecRecord.Sql = execSqlReq.Sql
|
|
|
|
|
|
dbSqlExecRecord.Remark = execSqlReq.Remark
|
|
|
|
|
|
dbSqlExecRecord.SetBaseInfo(execSqlReq.LoginAccount)
|
|
|
|
|
|
return dbSqlExecRecord
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-22 11:56:21 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) Exec(execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error) {
|
|
|
|
|
|
sql := execSqlReq.Sql
|
2023-02-13 21:11:16 +08:00
|
|
|
|
dbSqlExecRecord := createSqlExecRecord(execSqlReq)
|
|
|
|
|
|
var execRes *DbSqlExecRes
|
|
|
|
|
|
isSelect := false
|
|
|
|
|
|
|
2022-06-16 15:55:18 +08:00
|
|
|
|
stmt, err := sqlparser.Parse(sql)
|
|
|
|
|
|
if err != nil {
|
2023-02-13 21:11:16 +08:00
|
|
|
|
// 就算解析失败也执行sql,让数据库来判断错误。如果是查询sql则简单判断是否有limit分页参数信息(兼容pgsql)
|
|
|
|
|
|
// global.Log.Warnf("sqlparse解析sql[%s]失败: %s", sql, err.Error())
|
|
|
|
|
|
lowerSql := strings.ToLower(execSqlReq.Sql)
|
|
|
|
|
|
isSelect := strings.HasPrefix(lowerSql, "select")
|
|
|
|
|
|
if isSelect {
|
|
|
|
|
|
biz.IsTrue(strings.Contains(lowerSql, "limit"), "请完善分页信息")
|
|
|
|
|
|
}
|
|
|
|
|
|
var execErr error
|
|
|
|
|
|
if isSelect || strings.HasPrefix(lowerSql, "show") {
|
|
|
|
|
|
execRes, execErr = doRead(execSqlReq)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
execRes, execErr = doExec(execSqlReq.Sql, execSqlReq.DbInstance)
|
2022-11-01 12:45:21 +08:00
|
|
|
|
}
|
2023-02-13 21:11:16 +08:00
|
|
|
|
if execErr != nil {
|
|
|
|
|
|
return nil, execErr
|
|
|
|
|
|
}
|
|
|
|
|
|
d.saveSqlExecLog(isSelect, dbSqlExecRecord)
|
|
|
|
|
|
return execRes, nil
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch stmt := stmt.(type) {
|
2022-09-22 11:56:21 +08:00
|
|
|
|
case *sqlparser.Select:
|
|
|
|
|
|
isSelect = true
|
2023-02-13 21:11:16 +08:00
|
|
|
|
execRes, err = doSelect(stmt, execSqlReq)
|
2022-09-22 11:56:21 +08:00
|
|
|
|
case *sqlparser.Show:
|
|
|
|
|
|
isSelect = true
|
2023-02-13 21:11:16 +08:00
|
|
|
|
execRes, err = doRead(execSqlReq)
|
2022-09-22 11:56:21 +08:00
|
|
|
|
case *sqlparser.OtherRead:
|
|
|
|
|
|
isSelect = true
|
2023-02-13 21:11:16 +08:00
|
|
|
|
execRes, err = doRead(execSqlReq)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
case *sqlparser.Update:
|
2022-09-22 11:56:21 +08:00
|
|
|
|
execRes, err = doUpdate(stmt, execSqlReq, dbSqlExecRecord)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
case *sqlparser.Delete:
|
2022-09-22 11:56:21 +08:00
|
|
|
|
execRes, err = doDelete(stmt, execSqlReq, dbSqlExecRecord)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
case *sqlparser.Insert:
|
2022-09-22 11:56:21 +08:00
|
|
|
|
execRes, err = doInsert(stmt, execSqlReq, dbSqlExecRecord)
|
|
|
|
|
|
default:
|
|
|
|
|
|
execRes, err = doExec(execSqlReq.Sql, execSqlReq.DbInstance)
|
|
|
|
|
|
}
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
2023-02-13 21:11:16 +08:00
|
|
|
|
d.saveSqlExecLog(isSelect, dbSqlExecRecord)
|
|
|
|
|
|
return execRes, nil
|
|
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
// 保存sql执行记录,如果是查询类则根据系统配置判断是否保存
|
|
|
|
|
|
func (d *dbSqlExecAppImpl) saveSqlExecLog(isQuery bool, dbSqlExecRecord *entity.DbSqlExec) {
|
|
|
|
|
|
if !isQuery {
|
|
|
|
|
|
d.dbSqlExecRepo.Insert(dbSqlExecRecord)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if sysapp.GetConfigApp().GetConfig(sysentity.ConfigKeyDbSaveQuerySQL).BoolValue(false) {
|
|
|
|
|
|
dbSqlExecRecord.Table = "-"
|
|
|
|
|
|
dbSqlExecRecord.OldValue = "-"
|
|
|
|
|
|
dbSqlExecRecord.Type = entity.DbSqlExecTypeQuery
|
2022-09-22 11:56:21 +08:00
|
|
|
|
d.dbSqlExecRepo.Insert(dbSqlExecRecord)
|
|
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (d *dbSqlExecAppImpl) DeleteBy(condition *entity.DbSqlExec) {
|
|
|
|
|
|
d.dbSqlExecRepo.DeleteBy(condition)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExec, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
|
|
|
|
|
|
return d.dbSqlExecRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
func doSelect(selectStmt *sqlparser.Select, execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error) {
|
|
|
|
|
|
selectExprsStr := sqlparser.String(selectStmt.SelectExprs)
|
|
|
|
|
|
if selectExprsStr == "*" || strings.Contains(selectExprsStr, ".*") ||
|
|
|
|
|
|
len(strings.Split(selectExprsStr, ",")) > 1 {
|
2023-02-18 23:02:14 +08:00
|
|
|
|
// 如果配置为0,则不校验分页参数
|
2023-02-13 21:11:16 +08:00
|
|
|
|
maxCount := sysapp.GetConfigApp().GetConfig(sysentity.ConfigKeyDbQueryMaxCount).IntValue(200)
|
2023-02-18 23:02:14 +08:00
|
|
|
|
if maxCount != 0 {
|
|
|
|
|
|
limit := selectStmt.Limit
|
|
|
|
|
|
biz.NotNil(limit, "请完善分页信息后执行")
|
|
|
|
|
|
count, err := strconv.Atoi(sqlparser.String(limit.Rowcount))
|
|
|
|
|
|
biz.ErrIsNil(err, "分页参数有误")
|
|
|
|
|
|
biz.IsTrue(count <= maxCount, fmt.Sprintf("查询结果集数需小于系统配置的%d条", maxCount))
|
|
|
|
|
|
}
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return doRead(execSqlReq)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func doRead(execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error) {
|
2022-09-22 11:56:21 +08:00
|
|
|
|
dbInstance := execSqlReq.DbInstance
|
|
|
|
|
|
sql := execSqlReq.Sql
|
|
|
|
|
|
colNames, res, err := dbInstance.SelectData(sql)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
return &DbSqlExecRes{
|
|
|
|
|
|
ColNames: colNames,
|
|
|
|
|
|
Res: res,
|
|
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func doUpdate(update *sqlparser.Update, execSqlReq *DbSqlExecReq, dbSqlExec *entity.DbSqlExec) (*DbSqlExecRes, error) {
|
|
|
|
|
|
dbInstance := execSqlReq.DbInstance
|
|
|
|
|
|
|
2022-06-16 15:55:18 +08:00
|
|
|
|
tableStr := sqlparser.String(update.TableExprs)
|
|
|
|
|
|
// 可能使用别名,故空格切割
|
|
|
|
|
|
tableName := strings.Split(tableStr, " ")[0]
|
|
|
|
|
|
where := sqlparser.String(update.Where)
|
|
|
|
|
|
|
|
|
|
|
|
updateExprs := update.Exprs
|
|
|
|
|
|
updateColumns := make([]string, 0)
|
|
|
|
|
|
for _, v := range updateExprs {
|
|
|
|
|
|
updateColumns = append(updateColumns, v.Name.Name.String())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取表主键列名,排除使用别名
|
2022-08-10 19:46:17 +08:00
|
|
|
|
primaryKey := dbInstance.GetMeta().GetPrimaryKey(tableName)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
|
|
|
|
|
updateColumnsAndPrimaryKey := strings.Join(updateColumns, ",") + "," + primaryKey
|
|
|
|
|
|
// 查询要更新字段数据的旧值,以及主键值
|
|
|
|
|
|
selectSql := fmt.Sprintf("SELECT %s FROM %s %s LIMIT 200", updateColumnsAndPrimaryKey, tableStr, where)
|
2022-11-03 14:05:04 +08:00
|
|
|
|
_, res, err := dbInstance.SelectData(selectSql)
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
bytes, _ := json.Marshal(res)
|
|
|
|
|
|
dbSqlExec.OldValue = string(bytes)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dbSqlExec.OldValue = err.Error()
|
|
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
|
|
|
|
|
dbSqlExec.Table = tableName
|
|
|
|
|
|
dbSqlExec.Type = entity.DbSqlExecTypeUpdate
|
2022-09-22 11:56:21 +08:00
|
|
|
|
|
|
|
|
|
|
return doExec(execSqlReq.Sql, dbInstance)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-22 11:56:21 +08:00
|
|
|
|
func doDelete(delete *sqlparser.Delete, execSqlReq *DbSqlExecReq, dbSqlExec *entity.DbSqlExec) (*DbSqlExecRes, error) {
|
|
|
|
|
|
dbInstance := execSqlReq.DbInstance
|
|
|
|
|
|
|
2022-06-16 15:55:18 +08:00
|
|
|
|
tableStr := sqlparser.String(delete.TableExprs)
|
|
|
|
|
|
// 可能使用别名,故空格切割
|
|
|
|
|
|
table := strings.Split(tableStr, " ")[0]
|
|
|
|
|
|
where := sqlparser.String(delete.Where)
|
|
|
|
|
|
|
|
|
|
|
|
// 查询删除数据
|
|
|
|
|
|
selectSql := fmt.Sprintf("SELECT * FROM %s %s LIMIT 200", tableStr, where)
|
|
|
|
|
|
_, res, _ := dbInstance.SelectData(selectSql)
|
|
|
|
|
|
|
|
|
|
|
|
bytes, _ := json.Marshal(res)
|
|
|
|
|
|
dbSqlExec.OldValue = string(bytes)
|
|
|
|
|
|
dbSqlExec.Table = table
|
|
|
|
|
|
dbSqlExec.Type = entity.DbSqlExecTypeDelete
|
2022-09-22 11:56:21 +08:00
|
|
|
|
|
|
|
|
|
|
return doExec(execSqlReq.Sql, dbInstance)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-22 11:56:21 +08:00
|
|
|
|
func doInsert(insert *sqlparser.Insert, execSqlReq *DbSqlExecReq, dbSqlExec *entity.DbSqlExec) (*DbSqlExecRes, error) {
|
2022-06-16 15:55:18 +08:00
|
|
|
|
tableStr := sqlparser.String(insert.Table)
|
|
|
|
|
|
// 可能使用别名,故空格切割
|
|
|
|
|
|
table := strings.Split(tableStr, " ")[0]
|
|
|
|
|
|
dbSqlExec.Table = table
|
|
|
|
|
|
dbSqlExec.Type = entity.DbSqlExecTypeInsert
|
2022-09-22 11:56:21 +08:00
|
|
|
|
|
|
|
|
|
|
return doExec(execSqlReq.Sql, execSqlReq.DbInstance)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func doExec(sql string, dbInstance *DbInstance) (*DbSqlExecRes, error) {
|
|
|
|
|
|
rowsAffected, err := dbInstance.Exec(sql)
|
2022-11-02 19:27:40 +08:00
|
|
|
|
execRes := "success"
|
2022-09-22 11:56:21 +08:00
|
|
|
|
if err != nil {
|
2022-11-02 19:27:40 +08:00
|
|
|
|
execRes = err.Error()
|
2022-09-22 11:56:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
res := make([]map[string]interface{}, 0)
|
|
|
|
|
|
resData := make(map[string]interface{})
|
2022-11-02 19:27:40 +08:00
|
|
|
|
resData["rowsAffected"] = rowsAffected
|
|
|
|
|
|
resData["sql"] = sql
|
|
|
|
|
|
resData["result"] = execRes
|
2022-09-22 11:56:21 +08:00
|
|
|
|
res = append(res, resData)
|
|
|
|
|
|
|
|
|
|
|
|
return &DbSqlExecRes{
|
2022-11-02 19:27:40 +08:00
|
|
|
|
ColNames: []string{"sql", "rowsAffected", "result"},
|
2022-09-22 11:56:21 +08:00
|
|
|
|
Res: res,
|
2022-12-17 22:24:21 +08:00
|
|
|
|
}, err
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|