2022-06-16 15:55:18 +08:00
|
|
|
|
package application
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2023-11-07 21:05:21 +08:00
|
|
|
|
"context"
|
2022-06-16 15:55:18 +08:00
|
|
|
|
"fmt"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
"mayfly-go/internal/db/application/dto"
|
2023-08-31 21:49:20 +08:00
|
|
|
|
"mayfly-go/internal/db/config"
|
2024-01-12 13:15:30 +08:00
|
|
|
|
"mayfly-go/internal/db/dbm/dbi"
|
2024-10-16 17:24:50 +08:00
|
|
|
|
"mayfly-go/internal/db/dbm/sqlparser"
|
|
|
|
|
|
"mayfly-go/internal/db/dbm/sqlparser/sqlstmt"
|
2022-09-09 18:26:08 +08:00
|
|
|
|
"mayfly-go/internal/db/domain/entity"
|
|
|
|
|
|
"mayfly-go/internal/db/domain/repository"
|
2024-11-20 22:43:53 +08:00
|
|
|
|
"mayfly-go/internal/db/imsg"
|
2024-02-29 22:12:50 +08:00
|
|
|
|
flowapp "mayfly-go/internal/flow/application"
|
|
|
|
|
|
flowentity "mayfly-go/internal/flow/domain/entity"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
msgapp "mayfly-go/internal/msg/application"
|
|
|
|
|
|
msgdto "mayfly-go/internal/msg/application/dto"
|
2023-12-07 01:07:34 +08:00
|
|
|
|
"mayfly-go/pkg/contextx"
|
2023-10-26 17:15:49 +08:00
|
|
|
|
"mayfly-go/pkg/errorx"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
"mayfly-go/pkg/i18n"
|
2024-01-29 04:20:23 +00:00
|
|
|
|
"mayfly-go/pkg/logx"
|
2022-06-16 15:55:18 +08:00
|
|
|
|
"mayfly-go/pkg/model"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
"mayfly-go/pkg/utils/anyx"
|
2024-10-16 17:24:50 +08:00
|
|
|
|
"mayfly-go/pkg/utils/collx"
|
2024-01-09 21:37:56 +08:00
|
|
|
|
"mayfly-go/pkg/utils/jsonx"
|
2024-12-08 13:04:23 +08:00
|
|
|
|
"mayfly-go/pkg/utils/stringx"
|
|
|
|
|
|
"mayfly-go/pkg/ws"
|
2022-06-16 15:55:18 +08:00
|
|
|
|
"strings"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
type sqlExecParam struct {
|
|
|
|
|
|
DbConn *dbi.DbConn
|
|
|
|
|
|
Sql string // 执行的sql
|
|
|
|
|
|
Stmt sqlstmt.Stmt // 解析后的sql stmt
|
|
|
|
|
|
Procdef *flowentity.Procdef // 流程定义
|
|
|
|
|
|
|
|
|
|
|
|
SqlExecRecord *entity.DbSqlExec // sql执行记录
|
2022-09-22 11:56:21 +08:00
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
// progressCategory sql文件执行进度消息类型
|
|
|
|
|
|
const progressCategory = "execSqlFileProgress"
|
|
|
|
|
|
|
|
|
|
|
|
// progressMsg sql文件执行进度消息
|
|
|
|
|
|
type progressMsg struct {
|
|
|
|
|
|
Id string `json:"id"`
|
|
|
|
|
|
Title string `json:"title"`
|
|
|
|
|
|
ExecutedStatements int `json:"executedStatements"`
|
|
|
|
|
|
Terminated bool `json:"terminated"`
|
2022-11-02 19:27:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-22 11:56:21 +08:00
|
|
|
|
type DbSqlExec interface {
|
2024-02-29 22:12:50 +08:00
|
|
|
|
flowapp.FlowBizHandler
|
|
|
|
|
|
|
2022-09-22 11:56:21 +08:00
|
|
|
|
// 执行sql
|
2024-12-08 13:04:23 +08:00
|
|
|
|
Exec(ctx context.Context, execSqlReq *dto.DbSqlExecReq) ([]*dto.DbSqlExecRes, error)
|
|
|
|
|
|
|
|
|
|
|
|
// ExecReader 从reader中读取sql并执行
|
|
|
|
|
|
ExecReader(ctx context.Context, execReader *dto.SqlReaderExec) error
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
|
|
|
|
|
// 根据条件删除sql执行记录
|
2024-05-05 14:53:30 +08:00
|
|
|
|
DeleteBy(ctx context.Context, condition *entity.DbSqlExec) error
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
|
|
|
|
|
// 分页获取
|
2023-10-26 17:15:49 +08:00
|
|
|
|
GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-09 18:26:08 +08:00
|
|
|
|
type dbSqlExecAppImpl struct {
|
2024-12-16 23:29:18 +08:00
|
|
|
|
dbApp Db `inject:"T"`
|
|
|
|
|
|
dbSqlExecRepo repository.DbSqlExec `inject:"T"`
|
2024-02-29 22:12:50 +08:00
|
|
|
|
|
2024-12-16 23:29:18 +08:00
|
|
|
|
flowProcdefApp flowapp.Procdef `inject:"T"`
|
|
|
|
|
|
msgApp msgapp.Msg `inject:"T"`
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func createSqlExecRecord(ctx context.Context, execSqlReq *dto.DbSqlExecReq, sql string) *entity.DbSqlExec {
|
2022-11-01 12:45:21 +08:00
|
|
|
|
dbSqlExecRecord := new(entity.DbSqlExec)
|
|
|
|
|
|
dbSqlExecRecord.DbId = execSqlReq.DbId
|
|
|
|
|
|
dbSqlExecRecord.Db = execSqlReq.Db
|
2024-10-16 17:24:50 +08:00
|
|
|
|
dbSqlExecRecord.Sql = sql
|
2022-11-01 12:45:21 +08:00
|
|
|
|
dbSqlExecRecord.Remark = execSqlReq.Remark
|
2024-02-29 22:12:50 +08:00
|
|
|
|
dbSqlExecRecord.Status = entity.DbSqlExecStatusSuccess
|
2024-01-09 17:31:21 +08:00
|
|
|
|
dbSqlExecRecord.FillBaseInfo(model.IdGenTypeNone, contextx.GetLoginAccount(ctx))
|
2022-11-01 12:45:21 +08:00
|
|
|
|
return dbSqlExecRecord
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) Exec(ctx context.Context, execSqlReq *dto.DbSqlExecReq) ([]*dto.DbSqlExecRes, error) {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
dbConn := execSqlReq.DbConn
|
|
|
|
|
|
execSql := execSqlReq.Sql
|
|
|
|
|
|
sp := dbConn.GetDialect().GetSQLParser()
|
2023-02-13 21:11:16 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
var flowProcdef *flowentity.Procdef
|
|
|
|
|
|
if execSqlReq.CheckFlow {
|
|
|
|
|
|
flowProcdef = d.flowProcdefApp.GetProcdefByCodePath(ctx, dbConn.Info.CodePath...)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
allExecRes := make([]*dto.DbSqlExecRes, 0)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
|
|
|
|
|
|
stmts, err := sp.Parse(execSql)
|
2024-10-18 12:32:53 +08:00
|
|
|
|
// sql解析失败,则使用默认方式切割
|
2022-06-16 15:55:18 +08:00
|
|
|
|
if err != nil {
|
2024-10-18 12:32:53 +08:00
|
|
|
|
sqlparser.SQLSplit(strings.NewReader(execSql), func(oneSql string) error {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
var execRes *dto.DbSqlExecRes
|
2024-10-16 17:24:50 +08:00
|
|
|
|
var err error
|
|
|
|
|
|
|
|
|
|
|
|
dbSqlExecRecord := createSqlExecRecord(ctx, execSqlReq, oneSql)
|
|
|
|
|
|
dbSqlExecRecord.Type = entity.DbSqlExecTypeOther
|
|
|
|
|
|
sqlExec := &sqlExecParam{DbConn: dbConn, Sql: oneSql, Procdef: flowProcdef, SqlExecRecord: dbSqlExecRecord}
|
|
|
|
|
|
|
|
|
|
|
|
if isSelect(oneSql) {
|
|
|
|
|
|
execRes, err = d.doSelect(ctx, sqlExec)
|
|
|
|
|
|
} else if isUpdate(oneSql) {
|
|
|
|
|
|
execRes, err = d.doUpdate(ctx, sqlExec)
|
|
|
|
|
|
} else if isDelete(oneSql) {
|
|
|
|
|
|
execRes, err = d.doDelete(ctx, sqlExec)
|
|
|
|
|
|
} else if isInsert(oneSql) {
|
|
|
|
|
|
execRes, err = d.doInsert(ctx, sqlExec)
|
|
|
|
|
|
} else if isOtherQuery(oneSql) {
|
|
|
|
|
|
execRes, err = d.doOtherRead(ctx, sqlExec)
|
2024-10-18 17:15:58 +08:00
|
|
|
|
} else if isDDL(oneSql) {
|
|
|
|
|
|
execRes, err = d.doExecDDL(ctx, sqlExec)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
execRes, err = d.doExec(ctx, dbConn, oneSql)
|
|
|
|
|
|
}
|
|
|
|
|
|
// 执行错误
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
if execRes == nil {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
execRes = &dto.DbSqlExecRes{Sql: oneSql}
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
execRes.ErrorMsg = err.Error()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
d.saveSqlExecLog(dbSqlExecRecord, dbSqlExecRecord.Res)
|
2023-03-15 11:41:03 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
allExecRes = append(allExecRes, execRes)
|
2024-10-18 12:32:53 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
})
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return allExecRes, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, stmt := range stmts {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
var execRes *dto.DbSqlExecRes
|
2024-10-16 17:24:50 +08:00
|
|
|
|
var err error
|
|
|
|
|
|
|
|
|
|
|
|
sql := stmt.GetText()
|
|
|
|
|
|
dbSqlExecRecord := createSqlExecRecord(ctx, execSqlReq, sql)
|
|
|
|
|
|
dbSqlExecRecord.Type = entity.DbSqlExecTypeOther
|
|
|
|
|
|
sqlExec := &sqlExecParam{DbConn: dbConn, Sql: sql, Procdef: flowProcdef, Stmt: stmt, SqlExecRecord: dbSqlExecRecord}
|
|
|
|
|
|
|
|
|
|
|
|
switch stmt.(type) {
|
|
|
|
|
|
case *sqlstmt.SimpleSelectStmt:
|
|
|
|
|
|
execRes, err = d.doSelect(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.UnionSelectStmt:
|
|
|
|
|
|
execRes, err = d.doSelect(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.OtherReadStmt:
|
|
|
|
|
|
execRes, err = d.doOtherRead(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.UpdateStmt:
|
|
|
|
|
|
execRes, err = d.doUpdate(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.DeleteStmt:
|
|
|
|
|
|
execRes, err = d.doDelete(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.InsertStmt:
|
|
|
|
|
|
execRes, err = d.doInsert(ctx, sqlExec)
|
2024-10-18 17:15:58 +08:00
|
|
|
|
case *sqlstmt.DdlStmt:
|
|
|
|
|
|
execRes, err = d.doExecDDL(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.CreateDatabase:
|
|
|
|
|
|
execRes, err = d.doExecDDL(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.CreateTable:
|
|
|
|
|
|
execRes, err = d.doExecDDL(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.CreateIndex:
|
|
|
|
|
|
execRes, err = d.doExecDDL(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.AlterDatabase:
|
|
|
|
|
|
execRes, err = d.doExecDDL(ctx, sqlExec)
|
|
|
|
|
|
case *sqlstmt.AlterTable:
|
|
|
|
|
|
execRes, err = d.doExecDDL(ctx, sqlExec)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
default:
|
|
|
|
|
|
execRes, err = d.doExec(ctx, dbConn, sql)
|
2022-11-01 12:45:21 +08:00
|
|
|
|
}
|
2024-03-02 19:08:19 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
if execRes == nil {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
execRes = &dto.DbSqlExecRes{Sql: sql}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
execRes.ErrorMsg = err.Error()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
d.saveSqlExecLog(dbSqlExecRecord, execRes.Res)
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
allExecRes = append(allExecRes, execRes)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
|
|
|
|
|
|
return allExecRes, nil
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) ExecReader(ctx context.Context, execReader *dto.SqlReaderExec) error {
|
|
|
|
|
|
dbConn := execReader.DbConn
|
|
|
|
|
|
|
|
|
|
|
|
clientId := execReader.ClientId
|
|
|
|
|
|
filename := stringx.Truncate(execReader.Filename, 20, 10, "...")
|
|
|
|
|
|
la := contextx.GetLoginAccount(ctx)
|
|
|
|
|
|
needSendMsg := la != nil && clientId != ""
|
|
|
|
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
|
errInfo := anyx.ToString(err)
|
|
|
|
|
|
logx.Errorf("exec sql reader error: %s", errInfo)
|
|
|
|
|
|
if needSendMsg {
|
|
|
|
|
|
errInfo = stringx.Truncate(errInfo, 300, 10, "...")
|
|
|
|
|
|
d.msgApp.CreateAndSend(la, msgdto.ErrSysMsg(i18n.T(imsg.SqlScriptRunFail), fmt.Sprintf("[%s][%s] execution failure: [%s]", filename, dbConn.Info.GetLogDesc(), errInfo)).WithClientId(clientId))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
executedStatements := 0
|
|
|
|
|
|
progressId := stringx.Rand(32)
|
|
|
|
|
|
if needSendMsg {
|
|
|
|
|
|
defer ws.SendJsonMsg(ws.UserId(la.Id), clientId, msgdto.InfoSysMsg(i18n.T(imsg.SqlScripRunProgress), &progressMsg{
|
|
|
|
|
|
Id: progressId,
|
|
|
|
|
|
Title: filename,
|
|
|
|
|
|
ExecutedStatements: executedStatements,
|
|
|
|
|
|
Terminated: true,
|
|
|
|
|
|
}).WithCategory(progressCategory))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err := sqlparser.SQLSplit(execReader.Reader, func(sql string) error {
|
|
|
|
|
|
if executedStatements%50 == 0 {
|
|
|
|
|
|
if needSendMsg {
|
|
|
|
|
|
ws.SendJsonMsg(ws.UserId(la.Id), clientId, msgdto.InfoSysMsg(i18n.T(imsg.SqlScripRunProgress), &progressMsg{
|
|
|
|
|
|
Id: progressId,
|
|
|
|
|
|
Title: filename,
|
|
|
|
|
|
ExecutedStatements: executedStatements,
|
|
|
|
|
|
Terminated: false,
|
|
|
|
|
|
}).WithCategory(progressCategory))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
executedStatements++
|
|
|
|
|
|
if _, err := dbConn.Exec(sql); err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if needSendMsg {
|
|
|
|
|
|
d.msgApp.CreateAndSend(la, msgdto.SuccessSysMsg(i18n.T(imsg.SqlScriptRunSuccess), "execution success").WithClientId(clientId))
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
type FlowDbExecSqlBizForm struct {
|
|
|
|
|
|
DbId uint64 `json:"dbId"` // 库id
|
|
|
|
|
|
DbName string `json:"dbName"` // 库名
|
|
|
|
|
|
Sql string `json:"sql"` // sql
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (d *dbSqlExecAppImpl) FlowBizHandle(ctx context.Context, bizHandleParam *flowapp.BizHandleParam) (any, error) {
|
|
|
|
|
|
procinst := bizHandleParam.Procinst
|
|
|
|
|
|
bizKey := procinst.BizKey
|
|
|
|
|
|
procinstStatus := procinst.Status
|
2024-03-02 19:08:19 +08:00
|
|
|
|
|
2024-02-29 22:12:50 +08:00
|
|
|
|
logx.Debugf("DbSqlExec FlowBizHandle -> bizKey: %s, procinstStatus: %s", bizKey, flowentity.ProcinstStatusEnum.GetDesc(procinstStatus))
|
2024-10-16 17:24:50 +08:00
|
|
|
|
// 流程非完成状态不处理
|
|
|
|
|
|
if procinstStatus != flowentity.ProcinstStatusCompleted {
|
|
|
|
|
|
return nil, nil
|
2024-02-29 22:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
execSqlBizForm, err := jsonx.To(procinst.BizForm, new(FlowDbExecSqlBizForm))
|
|
|
|
|
|
if err != nil {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBiz("failed to parse the business form information: %s", err.Error())
|
2024-02-29 22:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
dbConn, err := d.dbApp.GetDbConn(execSqlBizForm.DbId, execSqlBizForm.DbName)
|
2024-02-29 22:12:50 +08:00
|
|
|
|
if err != nil {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return nil, err
|
2024-02-29 22:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
execRes, err := d.Exec(contextx.NewLoginAccount(&model.LoginAccount{Id: procinst.CreatorId, Username: procinst.Creator}), &dto.DbSqlExecReq{
|
2024-10-16 17:24:50 +08:00
|
|
|
|
DbId: execSqlBizForm.DbId,
|
|
|
|
|
|
Db: execSqlBizForm.DbName,
|
|
|
|
|
|
Sql: execSqlBizForm.Sql,
|
|
|
|
|
|
DbConn: dbConn,
|
|
|
|
|
|
Remark: procinst.Remark,
|
|
|
|
|
|
CheckFlow: false,
|
|
|
|
|
|
})
|
2024-02-29 22:12:50 +08:00
|
|
|
|
if err != nil {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return nil, err
|
2024-02-29 22:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
// 存在一条错误的sql,则表示业务处理失败
|
|
|
|
|
|
for _, er := range execRes {
|
|
|
|
|
|
if er.ErrorMsg != "" {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return execRes, errorx.NewBizI(ctx, imsg.ErrExistRunFailSql)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return execRes, nil
|
2024-02-29 22:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-05 14:53:30 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) DeleteBy(ctx context.Context, condition *entity.DbSqlExec) error {
|
|
|
|
|
|
return d.dbSqlExecRepo.DeleteByCond(ctx, condition)
|
2024-02-29 22:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
|
|
|
|
|
return d.dbSqlExecRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-13 21:11:16 +08:00
|
|
|
|
// 保存sql执行记录,如果是查询类则根据系统配置判断是否保存
|
2024-10-16 17:24:50 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) saveSqlExecLog(dbSqlExecRecord *entity.DbSqlExec, res any) {
|
|
|
|
|
|
if dbSqlExecRecord.Type != entity.DbSqlExecTypeQuery {
|
|
|
|
|
|
dbSqlExecRecord.Res = jsonx.ToStr(res)
|
2024-01-23 19:30:28 +08:00
|
|
|
|
d.dbSqlExecRepo.Insert(context.TODO(), dbSqlExecRecord)
|
2023-02-13 21:11:16 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
2024-03-07 17:26:11 +08:00
|
|
|
|
|
|
|
|
|
|
if config.GetDbms().QuerySqlSave {
|
2023-02-13 21:11:16 +08:00
|
|
|
|
dbSqlExecRecord.Table = "-"
|
|
|
|
|
|
dbSqlExecRecord.OldValue = "-"
|
|
|
|
|
|
dbSqlExecRecord.Type = entity.DbSqlExecTypeQuery
|
2024-01-23 19:30:28 +08:00
|
|
|
|
d.dbSqlExecRepo.Insert(context.TODO(), dbSqlExecRecord)
|
2022-09-22 11:56:21 +08:00
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) doSelect(ctx context.Context, sqlExecParam *sqlExecParam) (*dto.DbSqlExecRes, error) {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
maxCount := config.GetDbms().MaxResultSet
|
|
|
|
|
|
selectStmt := sqlExecParam.Stmt
|
|
|
|
|
|
selectSql := sqlExecParam.Sql
|
|
|
|
|
|
sqlExecParam.SqlExecRecord.Type = entity.DbSqlExecTypeQuery
|
|
|
|
|
|
|
|
|
|
|
|
if procdef := sqlExecParam.Procdef; procdef != nil {
|
|
|
|
|
|
if needStartProc := procdef.MatchCondition(DbSqlExecFlowBizType, collx.Kvs("stmtType", "select")); needStartProc {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrNeedSubmitWorkTicket)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if selectStmt != nil {
|
|
|
|
|
|
needCheckLimit := false
|
|
|
|
|
|
var limit *sqlstmt.Limit
|
|
|
|
|
|
switch stmt := selectStmt.(type) {
|
|
|
|
|
|
case *sqlstmt.SimpleSelectStmt:
|
|
|
|
|
|
qs := stmt.QuerySpecification
|
|
|
|
|
|
limit = qs.Limit
|
2024-10-28 12:13:41 +08:00
|
|
|
|
if qs.SelectElements != nil && (qs.SelectElements.Star != "" || len(qs.SelectElements.Elements) > 1) {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
needCheckLimit = true
|
|
|
|
|
|
}
|
|
|
|
|
|
case *sqlstmt.UnionSelectStmt:
|
|
|
|
|
|
limit = stmt.Limit
|
|
|
|
|
|
selectSql = selectStmt.GetText()
|
|
|
|
|
|
needCheckLimit = true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-18 23:02:14 +08:00
|
|
|
|
// 如果配置为0,则不校验分页参数
|
2024-10-16 17:24:50 +08:00
|
|
|
|
if needCheckLimit && maxCount != 0 {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if limit == nil {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrNoLimitStmt)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
if limit.RowCount > maxCount {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrLimitInvalid, "count", maxCount)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2023-02-18 23:02:14 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
if maxCount != 0 {
|
|
|
|
|
|
if !strings.Contains(selectSql, "limit") &&
|
|
|
|
|
|
// 兼容oracle rownum分页
|
|
|
|
|
|
!strings.Contains(selectSql, "rownum") &&
|
|
|
|
|
|
// 兼容mssql offset分页
|
|
|
|
|
|
!strings.Contains(selectSql, "offset") &&
|
|
|
|
|
|
// 兼容mssql top 分页 with result as ({query sql}) select top 100 * from result
|
|
|
|
|
|
!strings.Contains(selectSql, " top ") {
|
|
|
|
|
|
// 判断是不是count语句
|
|
|
|
|
|
if !strings.Contains(selectSql, "count(") {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrNoLimitStmt)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doQuery(ctx, sqlExecParam.DbConn, selectSql)
|
2023-02-13 21:11:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) doOtherRead(ctx context.Context, sqlExecParam *sqlExecParam) (*dto.DbSqlExecRes, error) {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
selectSql := sqlExecParam.Sql
|
|
|
|
|
|
sqlExecParam.SqlExecRecord.Type = entity.DbSqlExecTypeQuery
|
|
|
|
|
|
|
|
|
|
|
|
if procdef := sqlExecParam.Procdef; procdef != nil {
|
|
|
|
|
|
if needStartProc := procdef.MatchCondition(DbSqlExecFlowBizType, collx.Kvs("stmtType", "read")); needStartProc {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrNeedSubmitWorkTicket)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
}
|
2022-09-22 11:56:21 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
|
|
|
|
|
|
return d.doQuery(ctx, sqlExecParam.DbConn, selectSql)
|
2022-09-22 11:56:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) doExecDDL(ctx context.Context, sqlExecParam *sqlExecParam) (*dto.DbSqlExecRes, error) {
|
2024-10-18 17:15:58 +08:00
|
|
|
|
selectSql := sqlExecParam.Sql
|
|
|
|
|
|
sqlExecParam.SqlExecRecord.Type = entity.DbSqlExecTypeDDL
|
|
|
|
|
|
|
|
|
|
|
|
if procdef := sqlExecParam.Procdef; procdef != nil {
|
|
|
|
|
|
if needStartProc := procdef.MatchCondition(DbSqlExecFlowBizType, collx.Kvs("stmtType", "ddl")); needStartProc {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrNeedSubmitWorkTicket)
|
2024-10-18 17:15:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return d.doExec(ctx, sqlExecParam.DbConn, selectSql)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) doUpdate(ctx context.Context, sqlExecParam *sqlExecParam) (*dto.DbSqlExecRes, error) {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
dbConn := sqlExecParam.DbConn
|
2022-09-22 11:56:21 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
if procdef := sqlExecParam.Procdef; procdef != nil {
|
|
|
|
|
|
if needStartProc := procdef.MatchCondition(DbSqlExecFlowBizType, collx.Kvs("stmtType", "update")); needStartProc {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrNeedSubmitWorkTicket)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
}
|
2024-01-29 04:20:23 +00:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
|
|
|
|
|
|
execRecord := sqlExecParam.SqlExecRecord
|
|
|
|
|
|
execRecord.Type = entity.DbSqlExecTypeUpdate
|
|
|
|
|
|
|
|
|
|
|
|
stmt := sqlExecParam.Stmt
|
|
|
|
|
|
if stmt == nil {
|
|
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
updatestmt, ok := stmt.(*sqlstmt.UpdateStmt)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
tableSources := updatestmt.TableSources.TableSources
|
|
|
|
|
|
// 不支持多表更新记录旧值
|
|
|
|
|
|
if len(tableSources) != 1 {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
logx.ErrorContext(ctx, "update SQL - logging old values only supports single-table updates")
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tableName := ""
|
|
|
|
|
|
tableAlias := ""
|
|
|
|
|
|
if tableSourceBase, ok := tableSources[0].(*sqlstmt.TableSourceBase); ok {
|
|
|
|
|
|
if atmoTableItem, ok := tableSourceBase.TableSourceItem.(*sqlstmt.AtomTableItem); ok {
|
|
|
|
|
|
tableName = atmoTableItem.TableName.Identifier.Value
|
|
|
|
|
|
tableAlias = atmoTableItem.Alias
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if tableName == "" {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
logx.ErrorContext(ctx, "update SQL - failed to get table name")
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
|
|
|
|
|
execRecord.Table = tableName
|
|
|
|
|
|
|
|
|
|
|
|
whereStr := updatestmt.Where.GetText()
|
|
|
|
|
|
if whereStr == "" {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
logx.ErrorContext(ctx, "update SQL - there is no where condition")
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取表主键列名,排除使用别名
|
2024-11-01 17:27:22 +08:00
|
|
|
|
primaryKey, err := dbConn.GetMetadata().GetPrimaryKey(tableName)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err != nil {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
logx.ErrorfContext(ctx, "update SQL - failed to get primary key column: %s", err.Error())
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
updateColumns := collx.ArrayMap[*sqlstmt.UpdatedElement, string](updatestmt.UpdatedElements, func(ue *sqlstmt.UpdatedElement) string {
|
|
|
|
|
|
return ue.ColumnName.GetText()
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
primaryKeyColumn := primaryKey
|
|
|
|
|
|
if tableAlias != "" {
|
|
|
|
|
|
primaryKeyColumn = tableAlias + "." + primaryKey
|
|
|
|
|
|
}
|
|
|
|
|
|
updateColumnsAndPrimaryKey := strings.Join(updateColumns, ",") + "," + primaryKeyColumn
|
2022-06-16 15:55:18 +08:00
|
|
|
|
// 查询要更新字段数据的旧值,以及主键值
|
2024-10-16 17:24:50 +08:00
|
|
|
|
selectSql := fmt.Sprintf("SELECT %s FROM %s where %s", updateColumnsAndPrimaryKey, tableName+" "+tableAlias, whereStr)
|
2024-01-29 04:20:23 +00:00
|
|
|
|
|
|
|
|
|
|
// WalkQuery查出最多200条数据
|
|
|
|
|
|
maxRec := 200
|
|
|
|
|
|
nowRec := 0
|
|
|
|
|
|
res := make([]map[string]any, 0)
|
2024-04-17 21:28:28 +08:00
|
|
|
|
_, err = dbConn.WalkQueryRows(ctx, selectSql, func(row map[string]any, columns []*dbi.QueryColumn) error {
|
2024-01-29 04:20:23 +00:00
|
|
|
|
nowRec++
|
|
|
|
|
|
res = append(res, row)
|
|
|
|
|
|
if nowRec == maxRec {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
return errorx.NewBiz(fmt.Sprintf("update SQL - the maximum number of updated queries is exceeded: %d", maxRec))
|
2024-01-29 04:20:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
logx.ErrorfContext(ctx, "update SQL - failed to get the updated old value: %s", err.Error())
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
2022-11-03 14:05:04 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
execRecord.OldValue = jsonx.ToStr(res)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) doDelete(ctx context.Context, sqlExecParam *sqlExecParam) (*dto.DbSqlExecRes, error) {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
if procdef := sqlExecParam.Procdef; procdef != nil {
|
|
|
|
|
|
if needStartProc := procdef.MatchCondition(DbSqlExecFlowBizType, collx.Kvs("stmtType", "delete")); needStartProc {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrNeedSubmitWorkTicket)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-09-22 11:56:21 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
dbConn := sqlExecParam.DbConn
|
|
|
|
|
|
execRecord := sqlExecParam.SqlExecRecord
|
|
|
|
|
|
execRecord.Type = entity.DbSqlExecTypeDelete
|
|
|
|
|
|
|
|
|
|
|
|
stmt := sqlExecParam.Stmt
|
|
|
|
|
|
if stmt == nil {
|
|
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
deletestmt, ok := stmt.(*sqlstmt.DeleteStmt)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tableSources := deletestmt.TableSources.TableSources
|
|
|
|
|
|
// 不支持多表删除记录旧值
|
|
|
|
|
|
if len(tableSources) != 1 {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
logx.ErrorContext(ctx, "delete SQL - logging old values only supports single-table deletion")
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tableName := ""
|
|
|
|
|
|
tableAlias := ""
|
|
|
|
|
|
if tableSourceBase, ok := tableSources[0].(*sqlstmt.TableSourceBase); ok {
|
|
|
|
|
|
if atmoTableItem, ok := tableSourceBase.TableSourceItem.(*sqlstmt.AtomTableItem); ok {
|
|
|
|
|
|
tableName = atmoTableItem.TableName.Identifier.Value
|
|
|
|
|
|
tableAlias = atmoTableItem.Alias
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if tableName == "" {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
logx.ErrorContext(ctx, "delete SQL - failed to get table name")
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
|
|
|
|
|
execRecord.Table = tableName
|
|
|
|
|
|
|
|
|
|
|
|
whereStr := deletestmt.Where.GetText()
|
|
|
|
|
|
if whereStr == "" {
|
2024-12-08 13:04:23 +08:00
|
|
|
|
logx.ErrorContext(ctx, "delete SQL - there is no where condition")
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
|
|
|
|
|
// 查询删除数据
|
2024-10-16 17:24:50 +08:00
|
|
|
|
selectSql := fmt.Sprintf("SELECT * FROM %s where %s LIMIT 200", tableName+" "+tableAlias, whereStr)
|
2023-12-07 01:07:34 +08:00
|
|
|
|
_, res, _ := dbConn.QueryContext(ctx, selectSql)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
execRecord.OldValue = jsonx.ToStr(res)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) doInsert(ctx context.Context, sqlExecParam *sqlExecParam) (*dto.DbSqlExecRes, error) {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
if procdef := sqlExecParam.Procdef; procdef != nil {
|
|
|
|
|
|
if needStartProc := procdef.MatchCondition(DbSqlExecFlowBizType, collx.Kvs("stmtType", "insert")); needStartProc {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return nil, errorx.NewBizI(ctx, imsg.ErrNeedSubmitWorkTicket)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-09-22 11:56:21 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
dbConn := sqlExecParam.DbConn
|
|
|
|
|
|
execRecord := sqlExecParam.SqlExecRecord
|
|
|
|
|
|
execRecord.Type = entity.DbSqlExecTypeInsert
|
2022-09-22 11:56:21 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
stmt := sqlExecParam.Stmt
|
|
|
|
|
|
if stmt == nil {
|
|
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
2024-05-08 21:04:25 +08:00
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
insertstmt, ok := stmt.(*sqlstmt.InsertStmt)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return d.doExec(ctx, dbConn, sqlExecParam.Sql)
|
2024-02-29 22:12:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-16 17:24:50 +08:00
|
|
|
|
execRecord.Table = insertstmt.TableName.Identifier.Value
|
|
|
|
|
|
|
|
|
|
|
|
return d.doExec(ctx, sqlExecParam.DbConn, sqlExecParam.Sql)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) doQuery(ctx context.Context, dbConn *dbi.DbConn, sql string) (*dto.DbSqlExecRes, error) {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
cols, res, err := dbConn.QueryContext(ctx, sql)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
2024-12-08 13:04:23 +08:00
|
|
|
|
return &dto.DbSqlExecRes{
|
2024-10-16 17:24:50 +08:00
|
|
|
|
Sql: sql,
|
|
|
|
|
|
Columns: cols,
|
|
|
|
|
|
Res: res,
|
|
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
func (d *dbSqlExecAppImpl) doExec(ctx context.Context, dbConn *dbi.DbConn, sql string) (*dto.DbSqlExecRes, error) {
|
2023-12-07 01:07:34 +08:00
|
|
|
|
rowsAffected, err := dbConn.ExecContext(ctx, sql)
|
2022-09-22 11:56:21 +08:00
|
|
|
|
if err != nil {
|
2024-10-16 17:24:50 +08:00
|
|
|
|
return nil, err
|
2022-09-22 11:56:21 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
|
2023-06-01 12:31:32 +08:00
|
|
|
|
res := make([]map[string]any, 0)
|
2024-10-16 17:24:50 +08:00
|
|
|
|
res = append(res, collx.Kvs("rowsAffected", rowsAffected))
|
2022-09-22 11:56:21 +08:00
|
|
|
|
|
2024-12-08 13:04:23 +08:00
|
|
|
|
return &dto.DbSqlExecRes{
|
2024-01-12 13:15:30 +08:00
|
|
|
|
Columns: []*dbi.QueryColumn{
|
2023-12-14 21:27:11 +08:00
|
|
|
|
{Name: "rowsAffected", Type: "number"},
|
|
|
|
|
|
},
|
|
|
|
|
|
Res: res,
|
2024-10-16 17:24:50 +08:00
|
|
|
|
Sql: sql,
|
2022-12-17 22:24:21 +08:00
|
|
|
|
}, err
|
2022-06-16 15:55:18 +08:00
|
|
|
|
}
|
2024-10-16 17:24:50 +08:00
|
|
|
|
|
|
|
|
|
|
func isSelect(sql string) bool {
|
|
|
|
|
|
return strings.Contains(strings.ToLower(sql[:10]), "select")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func isUpdate(sql string) bool {
|
|
|
|
|
|
return strings.Contains(strings.ToLower(sql[:10]), "update")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func isDelete(sql string) bool {
|
|
|
|
|
|
return strings.Contains(strings.ToLower(sql[:10]), "delete")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func isInsert(sql string) bool {
|
|
|
|
|
|
return strings.Contains(strings.ToLower(sql[:10]), "insert")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func isOtherQuery(sql string) bool {
|
|
|
|
|
|
sqlPrefix := strings.ToLower(sql[:10])
|
|
|
|
|
|
return strings.Contains(sqlPrefix, "explain") || strings.Contains(sqlPrefix, "show")
|
|
|
|
|
|
}
|
2024-10-18 17:15:58 +08:00
|
|
|
|
|
|
|
|
|
|
func isDDL(sql string) bool {
|
|
|
|
|
|
sqlPrefix := strings.ToLower(sql[:10])
|
|
|
|
|
|
return strings.Contains(sqlPrefix, "create") || strings.Contains(sqlPrefix, "alter") ||
|
|
|
|
|
|
strings.Contains(sqlPrefix, "drop") || strings.Contains(sqlPrefix, "truncate") || strings.Contains(sqlPrefix, "rename")
|
|
|
|
|
|
}
|