Merge pull request 'feat: sql构建支持 FOR UPDATE/迁移日志实现' (#12) from feature/upgrade_base_dao into master

Reviewed-on: #12
This commit is contained in:
2025-10-12 17:33:50 +08:00
6 changed files with 204 additions and 184 deletions

View File

@ -7,9 +7,11 @@ package database
import ( import (
"errors" "errors"
"reflect"
"git.zhangdeman.cn/zhangdeman/database/define" "git.zhangdeman.cn/zhangdeman/database/define"
"gorm.io/gorm" "gorm.io/gorm"
"reflect" "gorm.io/gorm/clause"
) )
// BaseDao 基础dao层 // BaseDao 基础dao层
@ -283,6 +285,10 @@ func (b *BaseDao) setTxCondition(inputTx *gorm.DB, optionFuncList ...define.SetO
tx = tx.Where(o.Where) tx = tx.Where(o.Where)
} }
if o.ForUpdate {
tx = tx.Clauses(clause.Locking{Strength: "UPDATE"})
}
// between // between
for field, betweenVal := range o.Between { for field, betweenVal := range o.Between {
tx = tx.Where("`"+field+"` BETWEEN ? AND ?", betweenVal[0], betweenVal[1]) tx = tx.Where("`"+field+"` BETWEEN ? AND ?", betweenVal[0], betweenVal[1])

View File

@ -34,6 +34,7 @@ type Option struct {
Like map[string]string `json:"like"` // like 语句 Like map[string]string `json:"like"` // like 语句
NotLike map[string]string `json:"not_like"` // not like 语句 NotLike map[string]string `json:"not_like"` // not like 语句
NotEqual map[string]any `json:"not_equal"` // != 语句 NotEqual map[string]any `json:"not_equal"` // != 语句
ForUpdate bool `json:"for_update"` // 加互斥锁
Order []string `json:"order"` // 排序规则 Order []string `json:"order"` // 排序规则
OR [][]SetOption `json:"or"` // or 语句, or 和其他属性 and 关系, 内部 OR 关系 OR [][]SetOption `json:"or"` // or 语句, or 和其他属性 and 关系, 内部 OR 关系
} }

20
go.sum
View File

@ -42,8 +42,6 @@ github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIp
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
@ -54,8 +52,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688= github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU= github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
@ -137,8 +133,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
@ -161,29 +157,19 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.21.0 h1:iTC9o7+wP6cPWpDWkivCvQFGAHDQ59SrSxsLPcnkArw=
golang.org/x/arch v0.21.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI= golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
@ -191,8 +177,6 @@ golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

176
logger/gorm_v2.go Normal file
View File

@ -0,0 +1,176 @@
// Package logger ...
//
// Description : logger ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-10-12 17:23
package logger
import (
"context"
"fmt"
"strings"
"time"
"git.zhangdeman.cn/zhangdeman/consts"
"gorm.io/gorm"
"go.uber.org/zap/zapcore"
"go.uber.org/zap"
loggerPkg "git.zhangdeman.cn/zhangdeman/logger"
"gorm.io/gorm/logger"
)
// NewGormV2 获取日志实例
func NewGormV2(loggerLevel consts.LogLevel, consoleOutput bool, encoder zapcore.Encoder, splitConfig *loggerPkg.RotateLogConfig, traceIDField string, skip int) (logger.Interface, error) {
logConfList := []loggerPkg.SetLoggerOptionFunc{loggerPkg.WithEncoder(encoder), loggerPkg.WithCallerSkip(skip), loggerPkg.WithCaller()}
if consoleOutput {
logConfList = append(logConfList, loggerPkg.WithConsoleOutput())
}
logInstance, err := loggerPkg.NewLogger(loggerLevel, splitConfig, logConfList...)
if nil != err {
return nil, err
}
if len(traceIDField) == 0 {
traceIDField = "trace_id"
}
return &Gorm{
instance: logInstance,
traceIDField: traceIDField,
}, nil
}
// NewGormLoggerWithInstance 获取gorm日志实现
func NewGormLoggerWithInstance(outCtx context.Context, dbClient *gorm.DB, instance *zap.Logger, node string, extraCtxFieldList []string) logger.Interface {
nodeArr := strings.Split(node, "|")
i := &Gorm{
dbClient: dbClient,
instance: instance,
traceIDField: consts.GinTraceIDField,
extraCtxFieldList: extraCtxFieldList,
flag: "",
node: node,
outCtx: outCtx,
}
if len(nodeArr) >= 2 {
i.node = nodeArr[1]
i.flag = nodeArr[0]
}
return i
}
// Gorm v2 版本库日志实现
type Gorm struct {
dbClient *gorm.DB
instance *zap.Logger // 日志实例
traceIDField string // 串联请求上下文的的ID
extraCtxFieldList []string // 从请求上线问提取的字段
flag string // 数据库标识
node string // 数据库节点 master / slave
outCtx context.Context
}
// LogMode ...
func (g *Gorm) LogMode(level logger.LogLevel) logger.Interface {
return g
}
// Info 日志
func (g *Gorm) Info(ctx context.Context, s string, i ...any) {
g.write(ctx, s, consts.LogLevelInfo, map[string]any{
"log_data": i,
})
}
// Warn ...
func (g *Gorm) Warn(ctx context.Context, s string, i ...any) {
g.write(ctx, s, consts.LogLevelWarn, map[string]any{
"log_data": i,
})
}
// Error 日志
func (g *Gorm) Error(ctx context.Context, s string, i ...any) {
g.write(ctx, s, consts.LogLevelError, map[string]any{
"log_data": i,
})
}
// Trace Trace 记录
func (g *Gorm) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
start := begin.UnixNano()
end := time.Now().UnixNano()
sql := ""
affectRows := int64(0)
if nil != fc {
sql, affectRows = fc()
}
logData := map[string]any{
"db_flag": g.flag,
"db_node": g.node,
"begin_time": start,
"finish_time": end,
"used_time": (end - start) / 1e6,
"sql": sql,
"affect_rows": affectRows,
"err": "",
}
if nil != err {
logData["err"] = err.Error()
}
g.write(ctx, "SQL执行记录", consts.LogLevelInfo, logData)
}
// write ...
func (g *Gorm) write(ctx context.Context, message string, level consts.LogLevel, data map[string]any) {
if len(message) == 0 {
message = "SQL执行记录"
}
if nil == g.instance {
// 未设置日志实例
return
}
if nil == data {
data = make(map[string]any)
}
if nil != data["sql"] {
sqlStr := strings.TrimSpace(fmt.Sprintf("%v", data["sql"]))
sqlArr := strings.Split(sqlStr, " ")
if len(sqlArr) > 0 {
data["sql_type"] = strings.ToUpper(sqlArr[0])
}
}
if nil == g.outCtx {
g.outCtx = context.Background()
}
dataList := loggerPkg.ZapLogDataList(loggerPkg.NewLogData(g.outCtx, consts.LogTypeDatabase, "", data))
switch level {
case consts.LogLevelDebug:
g.instance.Debug(message, dataList...)
case consts.LogLevelInfo:
g.instance.Info(message, dataList...)
case consts.LogLevelWarn:
g.instance.Warn(message, dataList...)
case consts.LogLevelError:
g.instance.Error(message, dataList...)
case consts.LogLevelPanic:
g.instance.Panic(message, dataList...)
default:
g.instance.Info(message, dataList...)
}
}
// GetGormSQL 获取trace fn
func GetGormSQL(dbClient *gorm.DB) func() (string, int64) {
return func() (string, int64) {
return dbClient.Dialector.Explain(dbClient.Statement.SQL.String(), dbClient.Statement.Vars...), dbClient.RowsAffected
}
}

130
option.go
View File

@ -11,19 +11,23 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"reflect"
"strings"
"git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/database/define" "git.zhangdeman.cn/zhangdeman/database/define"
"git.zhangdeman.cn/zhangdeman/op_type" "git.zhangdeman.cn/zhangdeman/op_type"
"git.zhangdeman.cn/zhangdeman/serialize" "git.zhangdeman.cn/zhangdeman/serialize"
"reflect"
"strings"
) )
// WithForUpdate 查询语句增加互斥锁
func WithForUpdate(forUpdate bool) define.SetOption {
return func(o *define.Option) {
o.ForUpdate = forUpdate
}
}
// WithModel ... // WithModel ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:18 2024/1/15
func WithModel(model any) define.SetOption { func WithModel(model any) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
o.Model = model o.Model = model
@ -31,10 +35,6 @@ func WithModel(model any) define.SetOption {
} }
// WithTable 设置查询的表名 // WithTable 设置查询的表名
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:56 2023/3/22
func WithTable(tableName string) define.SetOption { func WithTable(tableName string) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
o.Table = tableName o.Table = tableName
@ -42,10 +42,6 @@ func WithTable(tableName string) define.SetOption {
} }
// WithWhere 设置where条件 // WithWhere 设置where条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:17 2022/5/15
func WithWhere[T op_type.BaseType](where map[string]T) define.SetOption { func WithWhere[T op_type.BaseType](where map[string]T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.Where { if nil == o.Where {
@ -58,10 +54,6 @@ func WithWhere[T op_type.BaseType](where map[string]T) define.SetOption {
} }
// WithLimit 设置limit条件 // WithLimit 设置limit条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:00 2022/5/15
func WithLimit[T op_type.Int](limit T, offset T) define.SetOption { func WithLimit[T op_type.Int](limit T, offset T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
o.Limit = int(limit) o.Limit = int(limit)
@ -77,10 +69,6 @@ func WithClearLimit() define.SetOption {
} }
// WithLimitByPageAndSize 通过page和size构建条件 // WithLimitByPageAndSize 通过page和size构建条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:42 2023/10/14
func WithLimitByPageAndSize[T op_type.Int](page T, size T) define.SetOption { func WithLimitByPageAndSize[T op_type.Int](page T, size T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if size > 0 { if size > 0 {
@ -94,10 +82,6 @@ func WithLimitByPageAndSize[T op_type.Int](page T, size T) define.SetOption {
} }
// WithIn 设置in条件 // WithIn 设置in条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:23 2022/5/15
func WithIn[T op_type.Array](field string, value T) define.SetOption { func WithIn[T op_type.Array](field string, value T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == value { if nil == value {
@ -113,11 +97,7 @@ func WithIn[T op_type.Array](field string, value T) define.SetOption {
} }
} }
// WithBatchIn ... // WithBatchIn 批量设置IN条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:24 2022/5/15
func WithBatchIn[T op_type.Array](batchIn map[string]T) define.SetOption { func WithBatchIn[T op_type.Array](batchIn map[string]T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.In { if nil == o.In {
@ -130,10 +110,6 @@ func WithBatchIn[T op_type.Array](batchIn map[string]T) define.SetOption {
} }
// WithNotIn 设置 notin 条件 // WithNotIn 设置 notin 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:18 2022/5/15
func WithNotIn[T op_type.Array](field string, value T) define.SetOption { func WithNotIn[T op_type.Array](field string, value T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.NotIn { if nil == o.NotIn {
@ -147,10 +123,6 @@ func WithNotIn[T op_type.Array](field string, value T) define.SetOption {
} }
// WithBatchNotIn 批量设置 NOT IN // WithBatchNotIn 批量设置 NOT IN
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:23 2022/5/15
func WithBatchNotIn[T op_type.Array](data map[string]T) define.SetOption { func WithBatchNotIn[T op_type.Array](data map[string]T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.NotIn { if nil == o.NotIn {
@ -166,10 +138,6 @@ func WithBatchNotIn[T op_type.Array](data map[string]T) define.SetOption {
} }
// WithStart >= 条件 // WithStart >= 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:01 2022/5/15
func WithStart(field string, value any) define.SetOption { func WithStart(field string, value any) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.Start { if nil == o.Start {
@ -180,10 +148,6 @@ func WithStart(field string, value any) define.SetOption {
} }
// WithBatchStart 批量设置起始条件 // WithBatchStart 批量设置起始条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:03 2022/5/15
func WithBatchStart(data map[string]any) define.SetOption { func WithBatchStart(data map[string]any) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.Start { if nil == o.Start {
@ -196,10 +160,6 @@ func WithBatchStart(data map[string]any) define.SetOption {
} }
// WithEnd 设置 < 条件 // WithEnd 设置 < 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:07 2022/5/15
func WithEnd(field string, value any) define.SetOption { func WithEnd(field string, value any) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.End { if nil == o.End {
@ -210,10 +170,6 @@ func WithEnd(field string, value any) define.SetOption {
} }
// WithBatchEnd 批量设置 < 条件 // WithBatchEnd 批量设置 < 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:10 2022/5/15
func WithBatchEnd(data map[string]any) define.SetOption { func WithBatchEnd(data map[string]any) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.End { if nil == o.End {
@ -226,10 +182,6 @@ func WithBatchEnd(data map[string]any) define.SetOption {
} }
// WithLike 设置 like 查询条件 // WithLike 设置 like 查询条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:16 2022/5/15
func WithLike(field string, value string) define.SetOption { func WithLike(field string, value string) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.Like { if nil == o.Like {
@ -243,10 +195,6 @@ func WithLike(field string, value string) define.SetOption {
} }
// WithBatchLike 批量设置like条件 // WithBatchLike 批量设置like条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:19 2022/5/15
func WithBatchLike(data map[string]string) define.SetOption { func WithBatchLike(data map[string]string) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.Like { if nil == o.Like {
@ -262,10 +210,6 @@ func WithBatchLike(data map[string]string) define.SetOption {
} }
// WithNotLike NOT LIKE 语句 // WithNotLike NOT LIKE 语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:50 2022/5/15
func WithNotLike(field string, value string) define.SetOption { func WithNotLike(field string, value string) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.NotLike { if nil == o.NotLike {
@ -279,10 +223,6 @@ func WithNotLike(field string, value string) define.SetOption {
} }
// WithBatchNotLike ... // WithBatchNotLike ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:52 2022/5/15
func WithBatchNotLike(data map[string]string) define.SetOption { func WithBatchNotLike(data map[string]string) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.NotLike { if nil == o.NotLike {
@ -298,10 +238,6 @@ func WithBatchNotLike(data map[string]string) define.SetOption {
} }
// WithNotEqual 设置不等于语句 // WithNotEqual 设置不等于语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:31 2022/5/15
func WithNotEqual[T op_type.BaseType](field string, value T) define.SetOption { func WithNotEqual[T op_type.BaseType](field string, value T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.NotEqual { if nil == o.NotEqual {
@ -312,10 +248,6 @@ func WithNotEqual[T op_type.BaseType](field string, value T) define.SetOption {
} }
// WithBatchNotEqual 批量设置不等于条件 // WithBatchNotEqual 批量设置不等于条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:33 2022/5/15
func WithBatchNotEqual[T op_type.BaseType](data map[string]T) define.SetOption { func WithBatchNotEqual[T op_type.BaseType](data map[string]T) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.NotEqual { if nil == o.NotEqual {
@ -328,10 +260,6 @@ func WithBatchNotEqual[T op_type.BaseType](data map[string]T) define.SetOption {
} }
// WithOR 设置OR语句 // WithOR 设置OR语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:03 2022/7/23
func WithOR(orConditionList ...define.SetOption) define.SetOption { func WithOR(orConditionList ...define.SetOption) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.OR { if nil == o.OR {
@ -342,10 +270,6 @@ func WithOR(orConditionList ...define.SetOption) define.SetOption {
} }
// WithOrder 设置排序规则 // WithOrder 设置排序规则
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:15 2022/10/20
func WithOrder(orderRuleList ...string) define.SetOption { func WithOrder(orderRuleList ...string) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if len(orderRuleList) != 2 { if len(orderRuleList) != 2 {
@ -364,28 +288,16 @@ func WithOrder(orderRuleList ...string) define.SetOption {
} }
// WithOrderDesc 降序排序 // WithOrderDesc 降序排序
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:09 2023/4/3
func WithOrderDesc(field string) define.SetOption { func WithOrderDesc(field string) define.SetOption {
return WithOrder(field, "DESC") return WithOrder(field, "DESC")
} }
// WithOrderAsc 升序排序 // WithOrderAsc 升序排序
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:09 2023/4/3
func WithOrderAsc(field string) define.SetOption { func WithOrderAsc(field string) define.SetOption {
return WithOrder(field, "ASC") return WithOrder(field, "ASC")
} }
// newOption 生成新的option // newOption 生成新的option
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:46 2024/8/9
func newOption(setOptionList ...define.SetOption) *define.Option { func newOption(setOptionList ...define.SetOption) *define.Option {
o := &define.Option{} o := &define.Option{}
for _, item := range setOptionList { for _, item := range setOptionList {
@ -395,10 +307,6 @@ func newOption(setOptionList ...define.SetOption) *define.Option {
} }
// optionToSql 基于 option 配置生成sql // optionToSql 基于 option 配置生成sql
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:46 2024/8/9
func optionToSql(o *define.Option) (sqlBuildResult string, bindValue []any) { func optionToSql(o *define.Option) (sqlBuildResult string, bindValue []any) {
bindValue = make([]any, 0) bindValue = make([]any, 0)
sqlBuildResultBlockList := make([]string, 0) sqlBuildResultBlockList := make([]string, 0)
@ -486,10 +394,6 @@ func optionToSql(o *define.Option) (sqlBuildResult string, bindValue []any) {
} }
// parseInSql 解析in语句需要绑定占位符以及数据 // parseInSql 解析in语句需要绑定占位符以及数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:07 2024/8/9
func parseInSql(fieldValue any) (string, []any) { func parseInSql(fieldValue any) (string, []any) {
byteData, _ := json.Marshal(fieldValue) byteData, _ := json.Marshal(fieldValue)
var dataList []any var dataList []any
@ -505,10 +409,6 @@ func parseInSql(fieldValue any) (string, []any) {
} }
// WithBetween between 语句 // WithBetween between 语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:52 2024/8/23
func WithBetween(field string, left any, right any) define.SetOption { func WithBetween(field string, left any, right any) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.Between { if nil == o.Between {
@ -519,10 +419,6 @@ func WithBetween(field string, left any, right any) define.SetOption {
} }
// WithNotBetween not between 语句 // WithNotBetween not between 语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:52 2024/8/23
func WithNotBetween(field string, left any, right any) define.SetOption { func WithNotBetween(field string, left any, right any) define.SetOption {
return func(o *define.Option) { return func(o *define.Option) {
if nil == o.NotBetween { if nil == o.NotBetween {
@ -533,10 +429,6 @@ func WithNotBetween(field string, left any, right any) define.SetOption {
} }
// WithAnyCondition 设置任意查询条件, 仅 where 子句 in / not in / like / not like / == / != // WithAnyCondition 设置任意查询条件, 仅 where 子句 in / not in / like / not like / == / !=
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:48 2024/8/23
func WithAnyCondition(column string, operate string, value any) (define.SetOption, error) { func WithAnyCondition(column string, operate string, value any) (define.SetOption, error) {
if nil == value { if nil == value {
return nil, errors.New("value is nil") return nil, errors.New("value is nil")

View File

@ -11,24 +11,21 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"strings"
"sync"
"time"
"git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/database/define" "git.zhangdeman.cn/zhangdeman/database/define"
"git.zhangdeman.cn/zhangdeman/logger/wrapper" "git.zhangdeman.cn/zhangdeman/database/logger"
"go.uber.org/zap" "go.uber.org/zap"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
gormLogger "gorm.io/gorm/logger" gormLogger "gorm.io/gorm/logger"
"strings"
"sync"
"time"
) )
// DBClient 包装日志实例 // DBClient 包装日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:09 PM 2021/12/24
type DBClient struct { type DBClient struct {
DbFlag string // 数据库标识 DbFlag string // 数据库标识
LoggerInstance *zap.Logger // 日志实例 LoggerInstance *zap.Logger // 日志实例
@ -42,10 +39,6 @@ type DBClient struct {
} }
// Init 初始化客户端 // Init 初始化客户端
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:44 2024/8/20
func (dc *DBClient) Init(databaseConfig *define.Database, cacheTableStructureConfig *define.CacheTableStructureConfig) error { func (dc *DBClient) Init(databaseConfig *define.Database, cacheTableStructureConfig *define.CacheTableStructureConfig) error {
dc.lock = &sync.RWMutex{} dc.lock = &sync.RWMutex{}
dc.cacheTableStructureConfig = cacheTableStructureConfig dc.cacheTableStructureConfig = cacheTableStructureConfig
@ -76,10 +69,6 @@ func (dc *DBClient) Init(databaseConfig *define.Database, cacheTableStructureCon
} }
// GetMaster 获取主库连接 // GetMaster 获取主库连接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:28 PM 2021/12/24
func (dc *DBClient) GetMaster(ctx context.Context) *gorm.DB { func (dc *DBClient) GetMaster(ctx context.Context) *gorm.DB {
session := dc.master.Session(&gorm.Session{}) session := dc.master.Session(&gorm.Session{})
session.Logger = dc.getLogger(ctx, session, "master") session.Logger = dc.getLogger(ctx, session, "master")
@ -87,10 +76,6 @@ func (dc *DBClient) GetMaster(ctx context.Context) *gorm.DB {
} }
// GetSlave 获取从库链接 // GetSlave 获取从库链接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:29 PM 2021/12/24
func (dc *DBClient) GetSlave(ctx context.Context) *gorm.DB { func (dc *DBClient) GetSlave(ctx context.Context) *gorm.DB {
session := dc.slave.Session(&gorm.Session{}) session := dc.slave.Session(&gorm.Session{})
session.Logger = dc.getLogger(ctx, session, "slave") session.Logger = dc.getLogger(ctx, session, "slave")
@ -98,12 +83,8 @@ func (dc *DBClient) GetSlave(ctx context.Context) *gorm.DB {
} }
// getLogger 获取日志实例 // getLogger 获取日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:45 PM 2021/12/24
func (dc *DBClient) getLogger(ctx context.Context, dbClient *gorm.DB, node string) gormLogger.Interface { func (dc *DBClient) getLogger(ctx context.Context, dbClient *gorm.DB, node string) gormLogger.Interface {
return wrapper.NewGormLoggerWithInstance(ctx, dbClient, dc.LoggerInstance, dc.DbFlag+"|"+node, dc.ExtraFieldList) return logger.NewGormLoggerWithInstance(ctx, dbClient, dc.LoggerInstance, dc.DbFlag+"|"+node, dc.ExtraFieldList)
} }
// GetDatabaseClient 获取数据库连接 // GetDatabaseClient 获取数据库连接
@ -142,16 +123,12 @@ func (dc *DBClient) GetDatabaseClient(conf *define.Driver, logInstance *zap.Logg
} }
dbInstance.SetMaxIdleConns(conf.Connection.MaxIdle) dbInstance.SetMaxIdleConns(conf.Connection.MaxIdle)
dbInstance.SetMaxOpenConns(conf.Connection.MaxOpen) dbInstance.SetMaxOpenConns(conf.Connection.MaxOpen)
instance.Logger = wrapper.NewGormLoggerWithInstance(nil, instance, logInstance, "", nil) instance.Logger = logger.NewGormLoggerWithInstance(nil, instance, logInstance, "", nil)
return instance, nil return instance, nil
} }
// buildConnectionDSN 构建连接信息 // buildConnectionDSN 构建连接信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:42 2022/6/11
func (dc *DBClient) buildConnectionDSN(conf *define.Driver) string { func (dc *DBClient) buildConnectionDSN(conf *define.Driver) string {
if conf.DBType == consts.DatabaseDriverSqlite3 { if conf.DBType == consts.DatabaseDriverSqlite3 {
// 兼容sqlite3 // 兼容sqlite3
@ -170,10 +147,6 @@ func (dc *DBClient) buildConnectionDSN(conf *define.Driver) string {
} }
// CacheDataTableStructureConfig ... // CacheDataTableStructureConfig ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:03 2024/8/21
func (dc *DBClient) CacheDataTableStructureConfig() *define.CacheTableStructureConfig { func (dc *DBClient) CacheDataTableStructureConfig() *define.CacheTableStructureConfig {
if nil == dc.cacheTableStructureConfig { if nil == dc.cacheTableStructureConfig {
return &define.CacheTableStructureConfig{Enable: false, SyncTimeInterval: 3600} return &define.CacheTableStructureConfig{Enable: false, SyncTimeInterval: 3600}
@ -185,10 +158,6 @@ func (dc *DBClient) CacheDataTableStructureConfig() *define.CacheTableStructureC
} }
// GetTableFieldList 获取表结构配置 // GetTableFieldList 获取表结构配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:07 2024/8/21
func (dc *DBClient) GetTableFieldList(tableName string) ([]*define.ColumnConfig, error) { func (dc *DBClient) GetTableFieldList(tableName string) ([]*define.ColumnConfig, error) {
if !dc.CacheDataTableStructureConfig().Enable { if !dc.CacheDataTableStructureConfig().Enable {
// 未启用缓存, 返回空list // 未启用缓存, 返回空list
@ -203,10 +172,6 @@ func (dc *DBClient) GetTableFieldList(tableName string) ([]*define.ColumnConfig,
} }
// syncDbTableStructure 缓存表结构 // syncDbTableStructure 缓存表结构
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:17 2024/8/21
func (dc *DBClient) syncDbTableStructure(ignoreErr bool) error { func (dc *DBClient) syncDbTableStructure(ignoreErr bool) error {
if !dc.CacheDataTableStructureConfig().Enable { if !dc.CacheDataTableStructureConfig().Enable {
// 自动同步不可用 // 自动同步不可用
@ -256,10 +221,6 @@ func (dc *DBClient) syncDbTableStructure(ignoreErr bool) error {
} }
// SetTableStructure 设置表结构, 一旦调用人工设置, 则将终止自动同步 // SetTableStructure 设置表结构, 一旦调用人工设置, 则将终止自动同步
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:06 2024/8/23
func (dc *DBClient) SetTableStructure(tableConfigTable map[string][]*define.ColumnConfig) { func (dc *DBClient) SetTableStructure(tableConfigTable map[string][]*define.ColumnConfig) {
if nil != dc.cacheTableStructureConfig { if nil != dc.cacheTableStructureConfig {
// 关闭自动同步 // 关闭自动同步