From 5f6843c4dab3b37e1f4382e46fbefedf6e7a36f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=AD=9D=E4=B9=89?= Date: Wed, 31 Jul 2024 16:48:11 +0800 Subject: [PATCH 01/40] =?UTF-8?q?=E6=8F=90=E4=BA=A4go.mod?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go.mod b/go.mod index a9a8e83defc..06870dee969 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,6 @@ module github.com/gogf/gf/v2 +//增加一个注释 go 1.18 require ( From 999f822367e0cc402bce2ec4094df8d928334aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=AD=9D=E4=B9=89?= Date: Tue, 13 Aug 2024 17:37:47 +0800 Subject: [PATCH 02/40] =?UTF-8?q?session=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/gf/go.sum | 14 ++++ config/config.yaml | 100 ++++++++++++++++++++++++++++ go.mod | 4 ++ go.sum | 10 +++ os/gsession/gsession_session.go | 27 ++++++++ os/gsession/gsession_z_unit_test.go | 62 +++++++++++++++++ 6 files changed, 217 insertions(+) create mode 100644 config/config.yaml diff --git a/cmd/gf/go.sum b/cmd/gf/go.sum index 8ccde0d559c..b7fbdec7d6d 100644 --- a/cmd/gf/go.sum +++ b/cmd/gf/go.sum @@ -39,6 +39,20 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.7.2 h1:ieOB/AaYmRyLnFc/t5HMMpWXTEJ+A9O+d9AcWnIizQs= +github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.7.2/go.mod h1:TfTV5FErx1SGjQM100MkuO390Iy+BO1sPZ0OMm2Q5N4= +github.com/gogf/gf/contrib/drivers/mssql/v2 v2.7.2 h1:+rnLsVwFCNG294D3dJmhbfPz7dG+qA7JOnlL6cYk55Y= +github.com/gogf/gf/contrib/drivers/mssql/v2 v2.7.2/go.mod h1:nxAQjtQtcbGrF705gkTxdc032c/MNY28sCyWYQrD1Fw= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.2 h1:GpE2JuHVoNJD4lNP1omC1+TKXNCSvXr5oil1bNULYd0= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.2/go.mod h1:0h3UmNAmA8hnjvTyozZelSWWxiAjGDQttzZqMhkCkJo= +github.com/gogf/gf/contrib/drivers/oracle/v2 v2.7.2 h1:EAcV1aIbFyZwsFkXmqVuOoz5JwuTybDNRFpTDNKQtLo= +github.com/gogf/gf/contrib/drivers/oracle/v2 v2.7.2/go.mod h1:XUo35CiDBTJ9T3K5VkiEnQzphEPq+lRHft6s8XWun74= +github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.2 h1:tI4V57XyvKIpCX8WUtyGlh6aN+rFcg2reKnDqbhxuLA= +github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.2/go.mod h1:IB+g+oXMF6SZQQY4Ec8Kh3c3LddfEkgIsmYBAc3CsKM= +github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.7.2 h1:P/1w0jayiYZUd3X7EFuZ7r5FinBupNhWf8BzJkB2V9Y= +github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.7.2/go.mod h1:TSNhyUnkedVxHOHbFlr4hVMxpNXklF80kz1gjLlCIuE= +github.com/gogf/gf/v2 v2.7.2 h1:uZDfyblasI12lZUtFd1mfxsIr8b14cd/F88DJUTCSDM= +github.com/gogf/gf/v2 v2.7.2/go.mod h1:EBXneAg/wes86rfeh68XC0a2JBNQylmT7Sp6/8Axk88= github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f h1:7xfXR/BhG3JDqO1s45n65Oyx9t4E/UqDOXep6jXdLCM= github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f/go.mod h1:HnYoio6S7VaFJdryKcD/r9HgX+4QzYfr00XiXUo/xz0= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= diff --git a/config/config.yaml b/config/config.yaml new file mode 100644 index 00000000000..9413be4070d --- /dev/null +++ b/config/config.yaml @@ -0,0 +1,100 @@ +app_env: "local" +server: + serverBg: + address: ":8803" + serverRoot: "resource/public" + dumpRouterMap: false + routeOverWrite: true + openapiPath: "/api.json" + swaggerPath: "/swagger" + NameToUriType: 3 + maxHeaderBytes: "20KB" + clientMaxBodySize: "50MB" + serverApi: + address: ":8804" + serverRoot: "resource/public" + dumpRouterMap: false + routeOverWrite: true + openapiPath: "/api.json" + swaggerPath: "/swagger" + NameToUriType: 3 + maxHeaderBytes: "20KB" + clientMaxBodySize: "50MB" + + # Sessions配置 + sessionMaxAge: "24h" # Session有效期。默认为24小时 + sessionIdName: "wb2gsid" # SessionId的键名名称。默认为gfsessionid + sessionCookieOutput: true # Session特性开启时,是否将SessionId返回到Cookie中。默认true + sessionPath: "/tmp/gsessions" # Session存储的文件目录路径。默认为当前系统临时目录下的gsessions目录 + + # Logging配置 + logPath: "resource/log/server" # 日志文件存储目录路径,建议使用绝对路径。默认为空,表示关闭 + logStdout: true # 日志是否输出到终端。默认为true + errorStack: true # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true + errorLogEnabled: true # 是否记录异常日志信息到日志中。默认为true + errorLogPattern: "error-{Ymd}.log" # 异常错误日志文件格式。默认为"error-{Ymd}.log" + accessLogEnabled: true # 是否记录访问日志。默认为false + accessLogPattern: "access-{Ymd}.log" # 访问日志文件格式。默认为"access-{Ymd}.log" + +# redis 耗时监控,超过此值报警,单位毫秒 +redis_exec_max_time: 100 +# db 耗时监控,超过此值报警,单位毫秒 +db_exec_max_time: 1000 + +logger: + path: "resource/log/run" + file: "{Y-m-d}.log" + level: "all" + stdout: true + +# Database. +database: + logger: + level: "all" + stdout: false + Path: "resource/log/sql" + + + wb2_games: + - link: "mysql:root:123456@tcp(192.168.0.10:3306)/wb2_games?charset=utf8&parseTime=true&loc=Local&multiStatements=true" + role: master + maxIdle: 3 + maxOpen: 10 + debug: true + - link: "mysql:pt_admin:123456@tcp(192.168.2.99:3306)/wb2_games?charset=utf8&parseTime=true&loc=Local&multiStatements=true" + role: slave + maxIdle: 3 + maxOpen: 10 + debug: true + wb2_games_log: + - link: "mysql:pt_admin:123456@tcp(192.168.2.99:3306)/wb2_games_log?charset=utf8&parseTime=true&loc=Local&multiStatements=true" + role: master + maxIdle: 3 + maxOpen: 10 + debug: true + - link: "mysql:pt_admin:123456@tcp(192.168.2.99:3306)/wb2_games_log?charset=utf8&parseTime=true&loc=Local&multiStatements=true" + role: slave + maxIdle: 3 + maxOpen: 10 + debug: true + +# link: "mysql:root:123456@tcp(192.168.0.10:3306)/gfastv32?charset=utf8mb4&parseTime=true&loc=Local" +# debug: true +# charset: "utf8mb4" #数据库编码 +# dryRun: false #空跑 +# maxIdle: 10 #连接池最大闲置的连接数 +# maxOpen: 10 #连接池最大打开的连接数 +# maxLifetime: "30s" #(单位秒)连接对象可重复使用的时间长度 + +# Redis 配置示例 +# redis 从库配置最大个数,示例: default_1: +redis_slave_max_index: 1 +redis: + # 单实例配置 + default: + address: 192.168.5.1:6379 + db: 8 + pass: 123456 + idleTimeout: 600 + minIdle: 2 + waitTimeout: 30 \ No newline at end of file diff --git a/go.mod b/go.mod index 06870dee969..419c1e05dd3 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/emirpasic/gods v1.18.1 github.com/fatih/color v1.16.0 github.com/fsnotify/fsnotify v1.7.0 + github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2 github.com/gorilla/websocket v1.5.1 github.com/grokify/html-strip-tags-go v0.1.0 github.com/magiconair/properties v1.8.7 @@ -22,10 +23,13 @@ require ( ) require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/redis/go-redis/v9 v9.2.1 // indirect golang.org/x/sys v0.19.0 // indirect ) diff --git a/go.sum b/go.sum index b0003fe6b3e..93605cc6a78 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,14 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= @@ -14,6 +20,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2 h1:V1hdGnyjU9kT0I3DDDFDl6Ll8yC6aAIFJa/lMQwB8V4= +github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2/go.mod h1:XzkPv3G8TdKczqoB/ydR3bxvBRdQLQNCOCEgxso/c3o= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= @@ -31,6 +39,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= diff --git a/os/gsession/gsession_session.go b/os/gsession/gsession_session.go index c89b4239c43..3a91ba84638 100644 --- a/os/gsession/gsession_session.go +++ b/os/gsession/gsession_session.go @@ -8,6 +8,7 @@ package gsession import ( "context" + "fmt" "time" "github.com/gogf/gf/v2/container/gmap" @@ -82,6 +83,7 @@ func (s *Session) init() error { // // NOTE that this function must be called ever after a session request done. func (s *Session) Close() error { + fmt.Println("") if s.manager.storage == nil { return nil } @@ -155,6 +157,31 @@ func (s *Session) Remove(keys ...string) (err error) { return nil } +func (s *Session) RegenSession(delOld ...bool) (newSid string, err error) { + oldDel := false + if len(delOld) > 0 { + oldDel = delOld[0] + } + if s.id == "" { + if err = s.init(); err != nil { + return newSid, err + } + } else { + if oldDel { + s.RemoveAll() + } + s.id = "" + s.start = false + s.data.Clear() + if err = s.init(); err != nil { + return newSid, err + } + } + newSid = s.id + s.dirty = false + return newSid, err +} + // RemoveAll deletes all key-value pairs from this session. func (s *Session) RemoveAll() (err error) { if s.id == "" { diff --git a/os/gsession/gsession_z_unit_test.go b/os/gsession/gsession_z_unit_test.go index 54940183cc0..c915a42a513 100644 --- a/os/gsession/gsession_z_unit_test.go +++ b/os/gsession/gsession_z_unit_test.go @@ -7,9 +7,15 @@ package gsession import ( + "fmt" + "github.com/gogf/gf/v2/database/gredis" + "github.com/gogf/gf/v2/os/gctx" "testing" + "time" "github.com/gogf/gf/v2/test/gtest" + + _ "github.com/gogf/gf/contrib/nosql/redis/v2" ) func Test_NewSessionId(t *testing.T) { @@ -20,3 +26,59 @@ func Test_NewSessionId(t *testing.T) { t.Assert(len(id1), 32) }) } + +func TestSession_RegenSession(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + + config := &gredis.Config{ + Address: "192.168.5.1:6379", + Db: 10, + Pass: "123456", + IdleTimeout: 600, + MinIdle: 2, + WaitTimeout: 30, + } + rds, erRds := gredis.New(config) + if erRds != nil { + fmt.Println("err:", erRds) + return + } + storage := NewStorageRedisHashTable(rds, "tsid:") + sManger := New(time.Second*600, storage) + sid := "" //"19t8ieo1300d3eh4xqsnlbw100xj9q7q" + session := sManger.New(gctx.New(), sid) + sid, _ = session.Id() + fmt.Println(sid) + session.Set("score", 6666666) + session.Set("name", "erretre") + session.Close() + score := session.MustGet("score") + fmt.Println("score:", score.String()) + name := session.MustGet("name") + fmt.Println("name:", name.String()) + data, _ := session.Data() + fmt.Println(fmt.Sprintf("%+v", data)) + + newSid, errNewSid := session.RegenSession(true) + if errNewSid != nil { + fmt.Println("regen session err:", errNewSid) + return + } + fmt.Println("new sid:", newSid) + session.Set("score", "99999999999") + session.Set("tttt", 999999) + session.Close() + + newScore, _ := session.Get("score") + fmt.Println("newScore:", newScore, " newSid:", session.id) + + tttt, _ := session.Get("tttt") + fmt.Println("tttt:", tttt, " newSid:", session.id) + + oldSid := sid + sessionOld := sManger.New(gctx.New(), oldSid) + oldData, _ := sessionOld.Data() + fmt.Println("oldData:", oldData, " oldSid:", oldSid) + //time.Sleep(time.Second * 2) + }) +} From 5c0a9ce162031b318467ec052f127057796ed01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=AD=9D=E4=B9=89?= Date: Wed, 14 Aug 2024 18:06:37 +0800 Subject: [PATCH 03/40] =?UTF-8?q?session=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=B9=E6=B3=95=20=E4=BF=AE=E6=94=B9=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=9B=BF=E6=8D=A2=E5=92=8C=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=97=A0=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- i18n/gi18n/gi18n_manager.go | 16 +++++++++++++++- i18n/gi18n/gi18n_z_unit_test.go | 13 +++++++++++++ i18n/gi18n/testdata/i18n-file/zh-CN.json | 3 ++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/i18n/gi18n/gi18n_manager.go b/i18n/gi18n/gi18n_manager.go index 20d90340564..f2de2ce0ea4 100644 --- a/i18n/gi18n/gi18n_manager.go +++ b/i18n/gi18n/gi18n_manager.go @@ -9,6 +9,7 @@ package gi18n import ( "context" "fmt" + "github.com/gogf/gf/v2/text/gstr" "strings" "sync" @@ -166,8 +167,21 @@ func (m *Manager) Tf(ctx context.Context, format string, values ...interface{}) // TranslateFormat translates, formats and returns the `format` with configured language // and given `values`. +// When values[0] is of type map[string]string, parameter replacement is order-independent. +// the values' format :{key} func (m *Manager) TranslateFormat(ctx context.Context, format string, values ...interface{}) string { - return fmt.Sprintf(m.Translate(ctx, format), values...) + result := m.Translate(ctx, format) + if len(values) > 0 { + val := values[0] + if valMapStrStr, ok := val.(map[string]string); ok { + for k, v := range valMapStrStr { + rpStr := ":" + k + result = gstr.Replace(result, rpStr, v) + } + return result + } + } + return fmt.Sprintf(result, values...) } // Translate translates `content` with configured language. diff --git a/i18n/gi18n/gi18n_z_unit_test.go b/i18n/gi18n/gi18n_z_unit_test.go index af44d226bf7..23b6001ac60 100644 --- a/i18n/gi18n/gi18n_z_unit_test.go +++ b/i18n/gi18n/gi18n_z_unit_test.go @@ -7,6 +7,7 @@ package gi18n_test import ( + "fmt" "time" "github.com/gogf/gf/v2/encoding/gbase64" @@ -121,6 +122,18 @@ func Test_DefaultManager(t *testing.T) { }) } +func Test_MapStrStrRelace(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + i18n := gi18n.New(gi18n.Options{ + Path: gtest.DataPath("i18n-file"), + }) + i18n.SetLanguage("zh-CN") + str := i18n.Tf(context.Background(), "replace_map_test", map[string]string{"score": "3000", "name": "blue"}) + fmt.Println(str) + t.Assert(str, "hello 3000 blue is ok") + }) +} + func Test_Instance(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gi18n.Instance() diff --git a/i18n/gi18n/testdata/i18n-file/zh-CN.json b/i18n/gi18n/testdata/i18n-file/zh-CN.json index e840042887a..7170f6795a1 100644 --- a/i18n/gi18n/testdata/i18n-file/zh-CN.json +++ b/i18n/gi18n/testdata/i18n-file/zh-CN.json @@ -2,5 +2,6 @@ "你好": "hello", "世界": "world", "hello": "你好", - "world": "世界" + "world": "世界", + "replace_map_test": "hello :score :name is ok" } \ No newline at end of file From 8f7f13a54aa029547735e5c29ae657c2fb49414d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=AD=9D=E4=B9=89?= Date: Wed, 14 Aug 2024 18:41:34 +0800 Subject: [PATCH 04/40] =?UTF-8?q?session=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=B9=E6=B3=95=20=E4=BF=AE=E6=94=B9=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=9B=BF=E6=8D=A2=E5=92=8C=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=97=A0=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/gsession/gsession_z_unit_test.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/os/gsession/gsession_z_unit_test.go b/os/gsession/gsession_z_unit_test.go index c915a42a513..1c51527d753 100644 --- a/os/gsession/gsession_z_unit_test.go +++ b/os/gsession/gsession_z_unit_test.go @@ -7,13 +7,8 @@ package gsession import ( - "fmt" - "github.com/gogf/gf/v2/database/gredis" - "github.com/gogf/gf/v2/os/gctx" - "testing" - "time" - "github.com/gogf/gf/v2/test/gtest" + "testing" _ "github.com/gogf/gf/contrib/nosql/redis/v2" ) @@ -30,7 +25,7 @@ func Test_NewSessionId(t *testing.T) { func TestSession_RegenSession(t *testing.T) { gtest.C(t, func(t *gtest.T) { - config := &gredis.Config{ + /*config := &gredis.Config{ Address: "192.168.5.1:6379", Db: 10, Pass: "123456", @@ -78,7 +73,7 @@ func TestSession_RegenSession(t *testing.T) { oldSid := sid sessionOld := sManger.New(gctx.New(), oldSid) oldData, _ := sessionOld.Data() - fmt.Println("oldData:", oldData, " oldSid:", oldSid) + fmt.Println("oldData:", oldData, " oldSid:", oldSid)*/ //time.Sleep(time.Second * 2) }) } From f26b5c7d039001c1122f8473465993a40b496de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=AD=9D=E4=B9=89?= Date: Thu, 15 Aug 2024 09:22:34 +0800 Subject: [PATCH 05/40] =?UTF-8?q?session=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=B9=E6=B3=95=20=E4=BF=AE=E6=94=B9=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=9B=BF=E6=8D=A2=E5=92=8C=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=97=A0=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/gsession/gsession_session.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/os/gsession/gsession_session.go b/os/gsession/gsession_session.go index 3a91ba84638..d8752712248 100644 --- a/os/gsession/gsession_session.go +++ b/os/gsession/gsession_session.go @@ -168,7 +168,11 @@ func (s *Session) RegenSession(delOld ...bool) (newSid string, err error) { } } else { if oldDel { - s.RemoveAll() + err = s.RemoveAll() + if err != nil { + + return newSid, err + } } s.id = "" s.start = false From d132f4e7f62a381e5c1d5cb44ada8d87179a2a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=AD=9D=E4=B9=89?= Date: Thu, 15 Aug 2024 09:32:28 +0800 Subject: [PATCH 06/40] =?UTF-8?q?session=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=B9=E6=B3=95=20=E4=BF=AE=E6=94=B9=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=9B=BF=E6=8D=A2=E5=92=8C=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=97=A0=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/gsession/gsession_session.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/os/gsession/gsession_session.go b/os/gsession/gsession_session.go index d8752712248..ddc34c1ee7c 100644 --- a/os/gsession/gsession_session.go +++ b/os/gsession/gsession_session.go @@ -168,9 +168,7 @@ func (s *Session) RegenSession(delOld ...bool) (newSid string, err error) { } } else { if oldDel { - err = s.RemoveAll() - if err != nil { - + if err = s.RemoveAll(); err != nil { return newSid, err } } From 0435e2a02f9c93d787608a82efe226f893b7b83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=AD=9D=E4=B9=89?= Date: Thu, 15 Aug 2024 16:59:39 +0800 Subject: [PATCH 07/40] =?UTF-8?q?session=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=B9=E6=B3=95=20=E4=BF=AE=E6=94=B9=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=9B=BF=E6=8D=A2=E5=92=8C=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=97=A0=E5=85=B3=20=E8=BF=98=E5=8E=9F=E6=97=A0=E5=85=B3?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + cmd/gf/go.mod | 3 ++ config/config.yaml | 100 --------------------------------------------- go.mod | 5 --- go.sum | 10 ----- 5 files changed, 4 insertions(+), 115 deletions(-) delete mode 100644 config/config.yaml diff --git a/.gitignore b/.gitignore index 1c8cc1fb07f..f09b95e71cd 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ go.work.sum node_modules .docusaurus output +config/* \ No newline at end of file diff --git a/cmd/gf/go.mod b/cmd/gf/go.mod index a8d4038f120..75c6ad581fc 100644 --- a/cmd/gf/go.mod +++ b/cmd/gf/go.mod @@ -4,6 +4,7 @@ go 1.18 require ( github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.7.2 + github.com/gogf/gf/contrib/drivers/dm/v2 v2.7.1 github.com/gogf/gf/contrib/drivers/mssql/v2 v2.7.2 github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.2 github.com/gogf/gf/contrib/drivers/oracle/v2 v2.7.2 @@ -18,6 +19,7 @@ require ( require ( aead.dev/minisign v0.2.0 // indirect + gitee.com/chunanyong/dm v1.8.12 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/ClickHouse/clickhouse-go/v2 v2.0.15 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect @@ -31,6 +33,7 @@ require ( github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/golang/snappy v0.0.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect diff --git a/config/config.yaml b/config/config.yaml deleted file mode 100644 index 9413be4070d..00000000000 --- a/config/config.yaml +++ /dev/null @@ -1,100 +0,0 @@ -app_env: "local" -server: - serverBg: - address: ":8803" - serverRoot: "resource/public" - dumpRouterMap: false - routeOverWrite: true - openapiPath: "/api.json" - swaggerPath: "/swagger" - NameToUriType: 3 - maxHeaderBytes: "20KB" - clientMaxBodySize: "50MB" - serverApi: - address: ":8804" - serverRoot: "resource/public" - dumpRouterMap: false - routeOverWrite: true - openapiPath: "/api.json" - swaggerPath: "/swagger" - NameToUriType: 3 - maxHeaderBytes: "20KB" - clientMaxBodySize: "50MB" - - # Sessions配置 - sessionMaxAge: "24h" # Session有效期。默认为24小时 - sessionIdName: "wb2gsid" # SessionId的键名名称。默认为gfsessionid - sessionCookieOutput: true # Session特性开启时,是否将SessionId返回到Cookie中。默认true - sessionPath: "/tmp/gsessions" # Session存储的文件目录路径。默认为当前系统临时目录下的gsessions目录 - - # Logging配置 - logPath: "resource/log/server" # 日志文件存储目录路径,建议使用绝对路径。默认为空,表示关闭 - logStdout: true # 日志是否输出到终端。默认为true - errorStack: true # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true - errorLogEnabled: true # 是否记录异常日志信息到日志中。默认为true - errorLogPattern: "error-{Ymd}.log" # 异常错误日志文件格式。默认为"error-{Ymd}.log" - accessLogEnabled: true # 是否记录访问日志。默认为false - accessLogPattern: "access-{Ymd}.log" # 访问日志文件格式。默认为"access-{Ymd}.log" - -# redis 耗时监控,超过此值报警,单位毫秒 -redis_exec_max_time: 100 -# db 耗时监控,超过此值报警,单位毫秒 -db_exec_max_time: 1000 - -logger: - path: "resource/log/run" - file: "{Y-m-d}.log" - level: "all" - stdout: true - -# Database. -database: - logger: - level: "all" - stdout: false - Path: "resource/log/sql" - - - wb2_games: - - link: "mysql:root:123456@tcp(192.168.0.10:3306)/wb2_games?charset=utf8&parseTime=true&loc=Local&multiStatements=true" - role: master - maxIdle: 3 - maxOpen: 10 - debug: true - - link: "mysql:pt_admin:123456@tcp(192.168.2.99:3306)/wb2_games?charset=utf8&parseTime=true&loc=Local&multiStatements=true" - role: slave - maxIdle: 3 - maxOpen: 10 - debug: true - wb2_games_log: - - link: "mysql:pt_admin:123456@tcp(192.168.2.99:3306)/wb2_games_log?charset=utf8&parseTime=true&loc=Local&multiStatements=true" - role: master - maxIdle: 3 - maxOpen: 10 - debug: true - - link: "mysql:pt_admin:123456@tcp(192.168.2.99:3306)/wb2_games_log?charset=utf8&parseTime=true&loc=Local&multiStatements=true" - role: slave - maxIdle: 3 - maxOpen: 10 - debug: true - -# link: "mysql:root:123456@tcp(192.168.0.10:3306)/gfastv32?charset=utf8mb4&parseTime=true&loc=Local" -# debug: true -# charset: "utf8mb4" #数据库编码 -# dryRun: false #空跑 -# maxIdle: 10 #连接池最大闲置的连接数 -# maxOpen: 10 #连接池最大打开的连接数 -# maxLifetime: "30s" #(单位秒)连接对象可重复使用的时间长度 - -# Redis 配置示例 -# redis 从库配置最大个数,示例: default_1: -redis_slave_max_index: 1 -redis: - # 单实例配置 - default: - address: 192.168.5.1:6379 - db: 8 - pass: 123456 - idleTimeout: 600 - minIdle: 2 - waitTimeout: 30 \ No newline at end of file diff --git a/go.mod b/go.mod index 419c1e05dd3..a9a8e83defc 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,5 @@ module github.com/gogf/gf/v2 -//增加一个注释 go 1.18 require ( @@ -9,7 +8,6 @@ require ( github.com/emirpasic/gods v1.18.1 github.com/fatih/color v1.16.0 github.com/fsnotify/fsnotify v1.7.0 - github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2 github.com/gorilla/websocket v1.5.1 github.com/grokify/html-strip-tags-go v0.1.0 github.com/magiconair/properties v1.8.7 @@ -23,13 +21,10 @@ require ( ) require ( - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/redis/go-redis/v9 v9.2.1 // indirect golang.org/x/sys v0.19.0 // indirect ) diff --git a/go.sum b/go.sum index 93605cc6a78..b0003fe6b3e 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,8 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= -github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= @@ -20,8 +14,6 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2 h1:V1hdGnyjU9kT0I3DDDFDl6Ll8yC6aAIFJa/lMQwB8V4= -github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2/go.mod h1:XzkPv3G8TdKczqoB/ydR3bxvBRdQLQNCOCEgxso/c3o= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= @@ -39,8 +31,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= -github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= From 373b052b0edf84559e26068d852657bf5c7107d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=AD=9D=E4=B9=89?= Date: Fri, 16 Aug 2024 15:26:55 +0800 Subject: [PATCH 08/40] =?UTF-8?q?session=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=B9=E6=B3=95=20=E4=BF=AE=E6=94=B9=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=9B=BF=E6=8D=A2=E5=92=8C=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=97=A0=E5=85=B3=20=E8=BF=98=E5=8E=9F=E6=97=A0=E5=85=B3?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20=E5=A4=84=E7=90=86=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E4=B8=8D=E9=80=9A=E8=BF=87=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- net/gclient/gclient_z_example_test.go | 31 ++++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/net/gclient/gclient_z_example_test.go b/net/gclient/gclient_z_example_test.go index 48e63c50589..1dc7771934a 100644 --- a/net/gclient/gclient_z_example_test.go +++ b/net/gclient/gclient_z_example_test.go @@ -137,7 +137,7 @@ func init() { if err != nil { panic(err) } - time.Sleep(time.Millisecond * 500) + time.Sleep(time.Millisecond * 2000) } func ExampleNew() { @@ -195,7 +195,7 @@ func ExampleNew_MultiConn_Recommend() { if r, err := client.Get(ctx, "http://127.0.0.1:8999/var/json"); err != nil { panic(err) } else { - fmt.Println(r.ReadAllString()) + fmt.Print(r.ReadAllString()) r.Close() } } @@ -272,9 +272,9 @@ func ExampleClient_ContentJson() { } ) // Post using JSON string. - fmt.Println(g.Client().ContentJson().PostContent(ctx, url, jsonStr)) + fmt.Print(g.Client().ContentJson().PostContent(ctx, url, jsonStr)) // Post using JSON map. - fmt.Println(g.Client().ContentJson().PostContent(ctx, url, jsonMap)) + fmt.Print(g.Client().ContentJson().PostContent(ctx, url, jsonMap)) // Output: // Content-Type: application/json, id: 10000 @@ -289,7 +289,7 @@ func ExampleClient_Post() { panic(err) } defer r1.Close() - fmt.Println(r1.ReadAllString()) + fmt.Print(r1.ReadAllString()) // Send with map parameter. r2, err := g.Client().Post(ctx, url, g.Map{ @@ -300,7 +300,7 @@ func ExampleClient_Post() { panic(err) } defer r2.Close() - fmt.Println(r2.ReadAllString()) + fmt.Print(r2.ReadAllString()) // Output: // POST: form: 10000, john @@ -425,7 +425,7 @@ func ExampleClient_Get() { panic(err) } defer r1.Close() - fmt.Println(r1.ReadAllString()) + fmt.Print(r1.ReadAllString()) // Send with string parameter in request body. r2, err := g.Client().Get(ctx, url, "id=10000&name=john") @@ -433,7 +433,7 @@ func ExampleClient_Get() { panic(err) } defer r2.Close() - fmt.Println(r2.ReadAllString()) + fmt.Print(r2.ReadAllString()) // Send with map parameter. r3, err := g.Client().Get(ctx, url, g.Map{ @@ -444,7 +444,7 @@ func ExampleClient_Get() { panic(err) } defer r3.Close() - fmt.Println(r3.ReadAllString()) + fmt.Print(r3.ReadAllString()) // Output: // GET: query: 10000, john @@ -596,16 +596,16 @@ func ExampleClient_Proxy() { client2 := g.Client() _, err = client2.Proxy("socks5://127.0.0.1:1080").Get(ctx, "http://127.0.0.1:8999") - fmt.Println(err != nil) + fmt.Print(err != nil) client3 := g.Client() _, err = client3.Proxy("").Get(ctx, "http://127.0.0.1:8999") - fmt.Println(err != nil) + fmt.Print(err != nil) client4 := g.Client() url := "http://127.0.0.1:1081" + string([]byte{0x7f}) _, err = client4.Proxy(url).Get(ctx, "http://127.0.0.1:8999") - fmt.Println(err != nil) + fmt.Print(err != nil) // Output: // true @@ -639,7 +639,7 @@ func ExampleClient_Prefix() { "http://127.0.0.1:%d/api/v1/", s.GetListenedPort(), )) - fmt.Println(string(client.GetBytes(ctx, "prefix"))) + fmt.Print(string(client.GetBytes(ctx, "prefix"))) fmt.Println(string(client.GetBytes(ctx, "hello"))) // Output: @@ -742,7 +742,7 @@ func ExampleClient_SetRedirectLimit() { "name": "john", }) if err == nil { - fmt.Println(resp.ReadAllString()) + fmt.Print(resp.ReadAllString()) resp.Close() } @@ -752,12 +752,13 @@ func ExampleClient_SetRedirectLimit() { "name": "john", }) if err == nil { - fmt.Println(resp.ReadAllString()) + fmt.Print(resp.ReadAllString()) resp.Close() } // Output: // Found + // // hello world } From 8f7c1f4ab2ad88cac28a97ddeb0085195a9b7e46 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Thu, 26 Sep 2024 14:05:08 +0800 Subject: [PATCH 09/40] =?UTF-8?q?=E6=92=A4=E9=94=80=E5=AF=B9=E5=A4=9A?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E7=BF=BB=E8=AF=91=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- i18n/gi18n/gi18n_manager.go | 16 +--------------- i18n/gi18n/gi18n_z_unit_test.go | 13 ------------- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/i18n/gi18n/gi18n_manager.go b/i18n/gi18n/gi18n_manager.go index f2de2ce0ea4..20d90340564 100644 --- a/i18n/gi18n/gi18n_manager.go +++ b/i18n/gi18n/gi18n_manager.go @@ -9,7 +9,6 @@ package gi18n import ( "context" "fmt" - "github.com/gogf/gf/v2/text/gstr" "strings" "sync" @@ -167,21 +166,8 @@ func (m *Manager) Tf(ctx context.Context, format string, values ...interface{}) // TranslateFormat translates, formats and returns the `format` with configured language // and given `values`. -// When values[0] is of type map[string]string, parameter replacement is order-independent. -// the values' format :{key} func (m *Manager) TranslateFormat(ctx context.Context, format string, values ...interface{}) string { - result := m.Translate(ctx, format) - if len(values) > 0 { - val := values[0] - if valMapStrStr, ok := val.(map[string]string); ok { - for k, v := range valMapStrStr { - rpStr := ":" + k - result = gstr.Replace(result, rpStr, v) - } - return result - } - } - return fmt.Sprintf(result, values...) + return fmt.Sprintf(m.Translate(ctx, format), values...) } // Translate translates `content` with configured language. diff --git a/i18n/gi18n/gi18n_z_unit_test.go b/i18n/gi18n/gi18n_z_unit_test.go index 23b6001ac60..af44d226bf7 100644 --- a/i18n/gi18n/gi18n_z_unit_test.go +++ b/i18n/gi18n/gi18n_z_unit_test.go @@ -7,7 +7,6 @@ package gi18n_test import ( - "fmt" "time" "github.com/gogf/gf/v2/encoding/gbase64" @@ -122,18 +121,6 @@ func Test_DefaultManager(t *testing.T) { }) } -func Test_MapStrStrRelace(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - i18n := gi18n.New(gi18n.Options{ - Path: gtest.DataPath("i18n-file"), - }) - i18n.SetLanguage("zh-CN") - str := i18n.Tf(context.Background(), "replace_map_test", map[string]string{"score": "3000", "name": "blue"}) - fmt.Println(str) - t.Assert(str, "hello 3000 blue is ok") - }) -} - func Test_Instance(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gi18n.Instance() From 660e8748fd21187b57bbefefef624909de6e78af Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Mon, 9 Dec 2024 10:44:36 +0800 Subject: [PATCH 10/40] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=A4=87=E6=B3=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modify_bak | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 modify_bak diff --git a/modify_bak b/modify_bak new file mode 100644 index 00000000000..b124146f218 --- /dev/null +++ b/modify_bak @@ -0,0 +1,40 @@ +撤销修改 +gi18n_manager.go + +// TranslateFormat translates, formats and returns the `format` with configured language +// and given `values`. +// When values[0] is of type map[string]string, parameter replacement is order-independent. +// the values' format :{key} +func (m *Manager) TranslateFormat(ctx context.Context, format string, values ...interface{}) string { + result := m.Translate(ctx, format) + if len(values) > 0 { + val := values[0] + if valMapStrStr, ok := val.(map[string]string); ok { + for k, v := range valMapStrStr { + rpStr := ":" + k + result = gstr.Replace(result, rpStr, v) + } + return result + } + } + return fmt.Sprintf(result, values...) +} + +gi18n_z_unit_test.go +撤销修改 +func Test_MapStrStrRelace(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + i18n := gi18n.New(gi18n.Options{ + Path: gtest.DataPath("i18n-file"), + }) + i18n.SetLanguage("zh-CN") + str := i18n.Tf(context.Background(), "replace_map_test", map[string]string{"score": "3000", "name": "blue"}) + fmt.Println(str) + t.Assert(str, "hello 3000 blue is ok") + }) +} + + + +修改内容 + fix(i18n/gi18n_manager): TranslateFormat bug fixed \ No newline at end of file From 988dd05baab28fc1e6c46485c66dc394b3f53774 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Mon, 16 Dec 2024 14:06:57 +0800 Subject: [PATCH 11/40] =?UTF-8?q?master=E4=BF=9D=E6=8C=81=E5=92=8Cgf?= =?UTF-8?q?=E7=9A=84master=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/gsession/gsession_session.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/os/gsession/gsession_session.go b/os/gsession/gsession_session.go index e43439db4ea..88e27d05230 100644 --- a/os/gsession/gsession_session.go +++ b/os/gsession/gsession_session.go @@ -154,33 +154,6 @@ func (s *Session) Remove(keys ...string) (err error) { return nil } -func (s *Session) RegenSession(delOld ...bool) (newSid string, err error) { - oldDel := false - if len(delOld) > 0 { - oldDel = delOld[0] - } - if s.id == "" { - if err = s.init(); err != nil { - return newSid, err - } - } else { - if oldDel { - if err = s.RemoveAll(); err != nil { - return newSid, err - } - } - s.id = "" - s.start = false - s.data.Clear() - if err = s.init(); err != nil { - return newSid, err - } - } - newSid = s.id - s.dirty = false - return newSid, err -} - // RemoveAll deletes all key-value pairs from this session. func (s *Session) RemoveAll() (err error) { if s.id == "" { From 53394593bca8a599792409d757aa59703ab33688 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Mon, 16 Dec 2024 14:14:28 +0800 Subject: [PATCH 12/40] =?UTF-8?q?master=E4=BF=9D=E6=8C=81=E5=92=8Cgf?= =?UTF-8?q?=E7=9A=84master=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- i18n/gi18n/testdata/i18n-file/zh-CN.json | 3 +- modify_bak | 40 ------------------------ 2 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 modify_bak diff --git a/i18n/gi18n/testdata/i18n-file/zh-CN.json b/i18n/gi18n/testdata/i18n-file/zh-CN.json index 7170f6795a1..e840042887a 100644 --- a/i18n/gi18n/testdata/i18n-file/zh-CN.json +++ b/i18n/gi18n/testdata/i18n-file/zh-CN.json @@ -2,6 +2,5 @@ "你好": "hello", "世界": "world", "hello": "你好", - "world": "世界", - "replace_map_test": "hello :score :name is ok" + "world": "世界" } \ No newline at end of file diff --git a/modify_bak b/modify_bak deleted file mode 100644 index b124146f218..00000000000 --- a/modify_bak +++ /dev/null @@ -1,40 +0,0 @@ -撤销修改 -gi18n_manager.go - -// TranslateFormat translates, formats and returns the `format` with configured language -// and given `values`. -// When values[0] is of type map[string]string, parameter replacement is order-independent. -// the values' format :{key} -func (m *Manager) TranslateFormat(ctx context.Context, format string, values ...interface{}) string { - result := m.Translate(ctx, format) - if len(values) > 0 { - val := values[0] - if valMapStrStr, ok := val.(map[string]string); ok { - for k, v := range valMapStrStr { - rpStr := ":" + k - result = gstr.Replace(result, rpStr, v) - } - return result - } - } - return fmt.Sprintf(result, values...) -} - -gi18n_z_unit_test.go -撤销修改 -func Test_MapStrStrRelace(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - i18n := gi18n.New(gi18n.Options{ - Path: gtest.DataPath("i18n-file"), - }) - i18n.SetLanguage("zh-CN") - str := i18n.Tf(context.Background(), "replace_map_test", map[string]string{"score": "3000", "name": "blue"}) - fmt.Println(str) - t.Assert(str, "hello 3000 blue is ok") - }) -} - - - -修改内容 - fix(i18n/gi18n_manager): TranslateFormat bug fixed \ No newline at end of file From cd2c6e42100cdb3be2d2063efbae7bbe1521769e Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Mon, 16 Dec 2024 14:15:11 +0800 Subject: [PATCH 13/40] =?UTF-8?q?master=E4=BF=9D=E6=8C=81=E5=92=8Cgf?= =?UTF-8?q?=E7=9A=84master=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/gsession/gsession_session.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/os/gsession/gsession_session.go b/os/gsession/gsession_session.go index 88e27d05230..1844b51de2b 100644 --- a/os/gsession/gsession_session.go +++ b/os/gsession/gsession_session.go @@ -8,7 +8,6 @@ package gsession import ( "context" - "fmt" "time" "github.com/gogf/gf/v2/container/gmap" @@ -83,7 +82,6 @@ func (s *Session) init() error { // // NOTE that this function must be called ever after a session request done. func (s *Session) Close() error { - fmt.Println("") if s.manager.storage == nil { return nil } From e978c48be3bccc9b5facadba253f7b739ba4053c Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Mon, 16 Dec 2024 14:18:23 +0800 Subject: [PATCH 14/40] =?UTF-8?q?master=E4=BF=9D=E6=8C=81=E5=92=8Cgf?= =?UTF-8?q?=E7=9A=84master=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- net/gclient/gclient_z_example_test.go | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/net/gclient/gclient_z_example_test.go b/net/gclient/gclient_z_example_test.go index 1dc7771934a..48e63c50589 100644 --- a/net/gclient/gclient_z_example_test.go +++ b/net/gclient/gclient_z_example_test.go @@ -137,7 +137,7 @@ func init() { if err != nil { panic(err) } - time.Sleep(time.Millisecond * 2000) + time.Sleep(time.Millisecond * 500) } func ExampleNew() { @@ -195,7 +195,7 @@ func ExampleNew_MultiConn_Recommend() { if r, err := client.Get(ctx, "http://127.0.0.1:8999/var/json"); err != nil { panic(err) } else { - fmt.Print(r.ReadAllString()) + fmt.Println(r.ReadAllString()) r.Close() } } @@ -272,9 +272,9 @@ func ExampleClient_ContentJson() { } ) // Post using JSON string. - fmt.Print(g.Client().ContentJson().PostContent(ctx, url, jsonStr)) + fmt.Println(g.Client().ContentJson().PostContent(ctx, url, jsonStr)) // Post using JSON map. - fmt.Print(g.Client().ContentJson().PostContent(ctx, url, jsonMap)) + fmt.Println(g.Client().ContentJson().PostContent(ctx, url, jsonMap)) // Output: // Content-Type: application/json, id: 10000 @@ -289,7 +289,7 @@ func ExampleClient_Post() { panic(err) } defer r1.Close() - fmt.Print(r1.ReadAllString()) + fmt.Println(r1.ReadAllString()) // Send with map parameter. r2, err := g.Client().Post(ctx, url, g.Map{ @@ -300,7 +300,7 @@ func ExampleClient_Post() { panic(err) } defer r2.Close() - fmt.Print(r2.ReadAllString()) + fmt.Println(r2.ReadAllString()) // Output: // POST: form: 10000, john @@ -425,7 +425,7 @@ func ExampleClient_Get() { panic(err) } defer r1.Close() - fmt.Print(r1.ReadAllString()) + fmt.Println(r1.ReadAllString()) // Send with string parameter in request body. r2, err := g.Client().Get(ctx, url, "id=10000&name=john") @@ -433,7 +433,7 @@ func ExampleClient_Get() { panic(err) } defer r2.Close() - fmt.Print(r2.ReadAllString()) + fmt.Println(r2.ReadAllString()) // Send with map parameter. r3, err := g.Client().Get(ctx, url, g.Map{ @@ -444,7 +444,7 @@ func ExampleClient_Get() { panic(err) } defer r3.Close() - fmt.Print(r3.ReadAllString()) + fmt.Println(r3.ReadAllString()) // Output: // GET: query: 10000, john @@ -596,16 +596,16 @@ func ExampleClient_Proxy() { client2 := g.Client() _, err = client2.Proxy("socks5://127.0.0.1:1080").Get(ctx, "http://127.0.0.1:8999") - fmt.Print(err != nil) + fmt.Println(err != nil) client3 := g.Client() _, err = client3.Proxy("").Get(ctx, "http://127.0.0.1:8999") - fmt.Print(err != nil) + fmt.Println(err != nil) client4 := g.Client() url := "http://127.0.0.1:1081" + string([]byte{0x7f}) _, err = client4.Proxy(url).Get(ctx, "http://127.0.0.1:8999") - fmt.Print(err != nil) + fmt.Println(err != nil) // Output: // true @@ -639,7 +639,7 @@ func ExampleClient_Prefix() { "http://127.0.0.1:%d/api/v1/", s.GetListenedPort(), )) - fmt.Print(string(client.GetBytes(ctx, "prefix"))) + fmt.Println(string(client.GetBytes(ctx, "prefix"))) fmt.Println(string(client.GetBytes(ctx, "hello"))) // Output: @@ -742,7 +742,7 @@ func ExampleClient_SetRedirectLimit() { "name": "john", }) if err == nil { - fmt.Print(resp.ReadAllString()) + fmt.Println(resp.ReadAllString()) resp.Close() } @@ -752,13 +752,12 @@ func ExampleClient_SetRedirectLimit() { "name": "john", }) if err == nil { - fmt.Print(resp.ReadAllString()) + fmt.Println(resp.ReadAllString()) resp.Close() } // Output: // Found - // // hello world } From 9d0aae64a722eeb1c874d592048030110c78ced2 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Mon, 16 Dec 2024 14:19:26 +0800 Subject: [PATCH 15/40] =?UTF-8?q?master=E4=BF=9D=E6=8C=81=E5=92=8Cgf?= =?UTF-8?q?=E7=9A=84master=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/gf/go.sum | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/cmd/gf/go.sum b/cmd/gf/go.sum index 70ca436106e..c6b3aab8fe9 100644 --- a/cmd/gf/go.sum +++ b/cmd/gf/go.sum @@ -39,20 +39,6 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.7.2 h1:ieOB/AaYmRyLnFc/t5HMMpWXTEJ+A9O+d9AcWnIizQs= -github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.7.2/go.mod h1:TfTV5FErx1SGjQM100MkuO390Iy+BO1sPZ0OMm2Q5N4= -github.com/gogf/gf/contrib/drivers/mssql/v2 v2.7.2 h1:+rnLsVwFCNG294D3dJmhbfPz7dG+qA7JOnlL6cYk55Y= -github.com/gogf/gf/contrib/drivers/mssql/v2 v2.7.2/go.mod h1:nxAQjtQtcbGrF705gkTxdc032c/MNY28sCyWYQrD1Fw= -github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.2 h1:GpE2JuHVoNJD4lNP1omC1+TKXNCSvXr5oil1bNULYd0= -github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.2/go.mod h1:0h3UmNAmA8hnjvTyozZelSWWxiAjGDQttzZqMhkCkJo= -github.com/gogf/gf/contrib/drivers/oracle/v2 v2.7.2 h1:EAcV1aIbFyZwsFkXmqVuOoz5JwuTybDNRFpTDNKQtLo= -github.com/gogf/gf/contrib/drivers/oracle/v2 v2.7.2/go.mod h1:XUo35CiDBTJ9T3K5VkiEnQzphEPq+lRHft6s8XWun74= -github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.2 h1:tI4V57XyvKIpCX8WUtyGlh6aN+rFcg2reKnDqbhxuLA= -github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.2/go.mod h1:IB+g+oXMF6SZQQY4Ec8Kh3c3LddfEkgIsmYBAc3CsKM= -github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.7.2 h1:P/1w0jayiYZUd3X7EFuZ7r5FinBupNhWf8BzJkB2V9Y= -github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.7.2/go.mod h1:TSNhyUnkedVxHOHbFlr4hVMxpNXklF80kz1gjLlCIuE= -github.com/gogf/gf/v2 v2.7.2 h1:uZDfyblasI12lZUtFd1mfxsIr8b14cd/F88DJUTCSDM= -github.com/gogf/gf/v2 v2.7.2/go.mod h1:EBXneAg/wes86rfeh68XC0a2JBNQylmT7Sp6/8Axk88= github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f h1:7xfXR/BhG3JDqO1s45n65Oyx9t4E/UqDOXep6jXdLCM= github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f/go.mod h1:HnYoio6S7VaFJdryKcD/r9HgX+4QzYfr00XiXUo/xz0= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -205,4 +191,4 @@ modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6 modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= -modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= +modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= \ No newline at end of file From 0a487b99eb275e0be5b4a68281f9a15e0b4c12b0 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Mon, 16 Dec 2024 14:20:11 +0800 Subject: [PATCH 16/40] =?UTF-8?q?master=E4=BF=9D=E6=8C=81=E5=92=8Cgf?= =?UTF-8?q?=E7=9A=84master=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 97c0d5ddcde..0b27cbfc34d 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,4 @@ go.work.sum # Ignore for docs node_modules .docusaurus -output -config/* \ No newline at end of file +output \ No newline at end of file From 843876a0551c324735b8ccbfae0278c5399cf492 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Mon, 16 Dec 2024 14:29:50 +0800 Subject: [PATCH 17/40] =?UTF-8?q?master=E4=BF=9D=E6=8C=81=E5=92=8Cgf?= =?UTF-8?q?=E7=9A=84master=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- cmd/gf/go.sum | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 0b27cbfc34d..2428b8d621d 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,4 @@ go.work.sum # Ignore for docs node_modules .docusaurus -output \ No newline at end of file +output diff --git a/cmd/gf/go.sum b/cmd/gf/go.sum index c6b3aab8fe9..e66bcfaa11f 100644 --- a/cmd/gf/go.sum +++ b/cmd/gf/go.sum @@ -191,4 +191,4 @@ modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6 modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= -modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= \ No newline at end of file +modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= From 6e77f6048c5dc149c861fb79c7dc42c2c86aa0f1 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Tue, 17 Dec 2024 13:35:03 +0800 Subject: [PATCH 18/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 266 +++++++++++++++++- contrib/drivers/mssql/mssql_tools.go | 22 ++ .../drivers/mssql/mssql_z_unit_basic_test.go | 16 ++ .../drivers/mssql/mssql_z_unit_init_test.go | 28 +- 4 files changed, 326 insertions(+), 6 deletions(-) create mode 100644 contrib/drivers/mssql/mssql_tools.go diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index 7b71dab42f1..9f9d3612eae 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -10,6 +10,8 @@ import ( "context" "database/sql" "fmt" + "github.com/gogf/gf/v2/container/gmap" + "github.com/gogf/gf/v2/util/gconv" "strings" "github.com/gogf/gf/v2/container/gset" @@ -19,7 +21,21 @@ import ( "github.com/gogf/gf/v2/text/gstr" ) -// DoInsert inserts or updates data for given table. +var ( + createdFiledNames = []string{"created_at", "create_at"} +) + +const ( + autoIncrementName = "auto_increment" + mssqlOutPutKey = "OUTPUT" + mssqlInsertedObjName = "INSERTED" + mssqlAffectFd = " 1 as AffectCount" + affectCountFieldName = "AffectCount" + mssqlPrimaryKeyName = "PRI" + fdId = "ID" +) + +// DoInsert inserts or updates data for given table. rewrite db.core.DoInsert func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionSave: @@ -30,10 +46,254 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gcode.CodeNotSupported, `Replace operation is not supported by mssql driver`, ) + //default: + // return d.Core.DoInsert(ctx, link, table, list, option) + } + var ( + keys []string // Field names. + values []string // Value holder string array, like: (?,?,?) + params []interface{} // Values that will be committed to underlying database driver. + onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement. + ) + // Group the list by fields. Different fields to different list. + // It here uses ListMap to keep sequence for data inserting. + var keyListMap = gmap.NewListMap() + for _, item := range list { + var ( + tmpKeys = make([]string, 0) + tmpKeysInSequenceStr string + ) + for k := range item { + tmpKeys = append(tmpKeys, k) + } + keys, err = d.fieldsToSequence(ctx, table, tmpKeys) + if err != nil { + return nil, err + } + tmpKeysInSequenceStr = gstr.Join(keys, ",") + + if !keyListMap.Contains(tmpKeysInSequenceStr) { + keyListMap.Set(tmpKeysInSequenceStr, make(gdb.List, 0)) + } + tmpKeysInSequenceList := keyListMap.Get(tmpKeysInSequenceStr).(gdb.List) + tmpKeysInSequenceList = append(tmpKeysInSequenceList, item) + keyListMap.Set(tmpKeysInSequenceStr, tmpKeysInSequenceList) + } + if keyListMap.Size() > 1 { + var ( + tmpResult sql.Result + sqlResult gdb.SqlResult + rowsAffected int64 + ) + keyListMap.Iterator(func(key, value interface{}) bool { + tmpResult, err = d.DoInsert(ctx, link, table, value.(gdb.List), option) + if err != nil { + return false + } + rowsAffected, err = tmpResult.RowsAffected() + if err != nil { + return false + } + sqlResult.Result = tmpResult + sqlResult.Affected += rowsAffected + return true + }) + return &sqlResult, nil + } + // Prepare the batch result pointer. + var ( + charL, charR = d.GetDB().GetChars() + batchResult = new(gdb.SqlResult) + keysStr = charL + strings.Join(keys, charR+","+charL) + charR + operation = gdb.GetInsertOperationByOption(option.InsertOption) + ) + if option.InsertOption == gdb.InsertOptionSave { + onDuplicateStr = d.formatOnDuplicate(keys, option) + } + var ( + listLength = len(list) + valueHolder = make([]string, 0) + ) + for i := 0; i < listLength; i++ { + values = values[:0] + // Note that the map type is unordered, + // so it should use slice+key to retrieve the value. + for _, k := range keys { + if s, ok := list[i][k].(gdb.Raw); ok { + values = append(values, gconv.String(s)) + } else { + values = append(values, "?") + params = append(params, list[i][k]) + } + } + valueHolder = append(valueHolder, "("+gstr.Join(values, ",")+")") + // Batch package checks: It meets the batch number, or it is the last element. + if len(valueHolder) == option.BatchCount || (i == listLength-1 && len(valueHolder) > 0) { + var ( + //stdSqlResult sql.Result + stdSqlResult gdb.Result + //affectedRows int64 + retResult interface{} + ) + + stdSqlResult, err = d.GetDB().DoQuery(ctx, link, fmt.Sprintf( + "%s INTO %s(%s) %s VALUES%s %s ", + operation, d.QuotePrefixTableName(table), keysStr, + d.GetInsertOutputSql(ctx, table), + gstr.Join(valueHolder, ","), + onDuplicateStr, + ), params...) + if err != nil { + retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} + return retResult.(sql.Result), err + } + var ( + aCount int64 + lId int64 + ) + if len(stdSqlResult) == 0 { + err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) + retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} + return retResult.(sql.Result), err + } + aCount = stdSqlResult[0].GMap().GetVar(affectCountFieldName).Int64() + lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() + //fmt.Println(fmt.Sprintf("---------------------------type:%d", stdSqlResult[0].GMap().Get("ID").(int64))) + retResult = &MssqlResult{lastInsertId: lId, rowsAffected: aCount} + + batchResult.Result = retResult.(sql.Result) + batchResult.Affected += aCount + + params = params[:0] + valueHolder = valueHolder[:0] + } + } + return batchResult, nil +} + +type MssqlResult struct { + lastInsertId int64 + rowsAffected int64 + err error +} + +func (r *MssqlResult) LastInsertId() (int64, error) { + return r.lastInsertId, r.err +} + +func (r *MssqlResult) RowsAffected() (int64, error) { + return r.rowsAffected, r.err +} + +func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { + fds, errFd := m.GetDB().TableFields(ctx, table) + if errFd != nil { + return "" + } + extraSqlAry := make([]string, 0) + extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s %s", mssqlOutPutKey, mssqlAffectFd)) + incrNo := 0 + if len(fds) > 0 { + for _, fd := range fds { + if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { + incrNoStr := "" + if incrNo == 0 { + incrNoStr = " as ID" + } + + extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) + incrNo++ + } + //fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) + } + } + //fmt.Println(extraSqlAry) + return strings.Join(extraSqlAry, ",") + //";select ID = convert(bigint, SCOPE_IDENTITY()), AffectCount = @@ROWCOUNT;" +} - default: - return d.Core.DoInsert(ctx, link, table, list, option) +func (d *Driver) fieldsToSequence(ctx context.Context, table string, fields []string) ([]string, error) { + var ( + fieldSet = gset.NewStrSetFrom(fields) + fieldsResultInSequence = make([]string, 0) + tableFields, err = d.GetDB().TableFields(ctx, table) + ) + if err != nil { + return nil, err + } + // Sort the fields in order. + var fieldsOfTableInSequence = make([]string, len(tableFields)) + for _, field := range tableFields { + fieldsOfTableInSequence[field.Index] = field.Name + } + // Sort the input fields. + for _, fieldName := range fieldsOfTableInSequence { + if fieldSet.Contains(fieldName) { + fieldsResultInSequence = append(fieldsResultInSequence, fieldName) + } + } + return fieldsResultInSequence, nil +} + +func (d *Driver) formatOnDuplicate(columns []string, option gdb.DoInsertOption) string { + var onDuplicateStr string + if option.OnDuplicateStr != "" { + onDuplicateStr = option.OnDuplicateStr + } else if len(option.OnDuplicateMap) > 0 { + for k, v := range option.OnDuplicateMap { + if len(onDuplicateStr) > 0 { + onDuplicateStr += "," + } + switch v.(type) { + case gdb.Raw, *gdb.Raw: + onDuplicateStr += fmt.Sprintf( + "%s=%s", + d.QuoteWord(k), + v, + ) + default: + onDuplicateStr += fmt.Sprintf( + "%s=VALUES(%s)", + d.QuoteWord(k), + d.QuoteWord(gconv.String(v)), + ) + } + } + } else { + for _, column := range columns { + // If it's SAVE operation, do not automatically update the creating time. + if d.isSoftCreatedFieldName(column) { + continue + } + if len(onDuplicateStr) > 0 { + onDuplicateStr += "," + } + onDuplicateStr += fmt.Sprintf( + "%s=VALUES(%s)", + d.QuoteWord(column), + d.QuoteWord(column), + ) + } + } + return fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", onDuplicateStr) +} + +func (d *Driver) isSoftCreatedFieldName(fieldName string) bool { + if fieldName == "" { + return false + } + if config := d.GetDB().GetConfig(); config.CreatedAt != "" { + if equalFoldWithoutChars(fieldName, config.CreatedAt) { + return true + } + return gstr.InArray(append([]string{config.CreatedAt}, createdFiledNames...), fieldName) + } + for _, v := range createdFiledNames { + if equalFoldWithoutChars(fieldName, v) { + return true + } } + return false } // doSave support upsert for SQL server diff --git a/contrib/drivers/mssql/mssql_tools.go b/contrib/drivers/mssql/mssql_tools.go new file mode 100644 index 00000000000..410d599b2e8 --- /dev/null +++ b/contrib/drivers/mssql/mssql_tools.go @@ -0,0 +1,22 @@ +package mssql + +import "strings" + +// RemoveSymbols removes all symbols from string and lefts only numbers and letters. +func removeSymbols(s string) string { + var b = make([]rune, 0, len(s)) + for _, c := range s { + if c > 127 { + b = append(b, c) + } else if (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') { + b = append(b, c) + } + } + return string(b) +} + +// equalFoldWithoutChars checks string `s1` and `s2` equal case-insensitively, +// with/without chars '-'/'_'/'.'/' '. +func equalFoldWithoutChars(s1, s2 string) bool { + return strings.EqualFold(removeSymbols(s1), removeSymbols(s2)) +} diff --git a/contrib/drivers/mssql/mssql_z_unit_basic_test.go b/contrib/drivers/mssql/mssql_z_unit_basic_test.go index f00e6c84713..37697723154 100644 --- a/contrib/drivers/mssql/mssql_z_unit_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_basic_test.go @@ -10,6 +10,7 @@ import ( "context" "database/sql" "fmt" + "github.com/gogf/gf/v2/os/gctx" "testing" "time" @@ -148,6 +149,21 @@ func TestDoInsert(t *testing.T) { }) } +func TestDoInsertGetId(t *testing.T) { + //先创建表 + createInsertAndGetIdTableForTest() + gtest.C(t, func(t *gtest.T) { + table := "ip_to_id" + data := map[string]interface{}{ + "ip": "192.168.179.1", + } + id, err := db.InsertAndGetId(gctx.New(), table, data) + t.AssertNil(err) + t.AssertGT(id, 0) + //fmt.Println("id:", id) + }) +} + func Test_DB_Ping(t *testing.T) { gtest.C(t, func(t *gtest.T) { err1 := db.PingMaster() diff --git a/contrib/drivers/mssql/mssql_z_unit_init_test.go b/contrib/drivers/mssql/mssql_z_unit_init_test.go index eec9b76fe68..afae39bdc6f 100644 --- a/contrib/drivers/mssql/mssql_z_unit_init_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_init_test.go @@ -31,17 +31,17 @@ const ( TestSchema2 = "test2" TableNamePrefix1 = "gf_" TestDbUser = "sa" - TestDbPass = "LoremIpsum86" + TestDbPass = "LoremIpsum86" //"theone@123" CreateTime = "2018-10-24 10:00:00" ) func init() { node := gdb.ConfigNode{ - Host: "127.0.0.1", + Host: "127.0.0.1", //192.168.5.72 127.0.0.1 Port: "1433", User: TestDbUser, Pass: TestDbPass, - Name: "test", + Name: "test", //"QPLogDB" Type: "mssql", Role: "master", Charset: "utf8", @@ -147,3 +147,25 @@ func dropTable(table string) { gtest.Fatal(err) } } + +func createInsertAndGetIdTableForTest() (name string) { + + if _, err := db.Exec(context.Background(), ` +IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='ip_to_id' and xtype='U') +begin + CREATE TABLE [ip_to_id]( + [id] [int] IDENTITY(1,1) NOT NULL, + [ip] [varchar](128) NULL, + CONSTRAINT [PK_ip_to_id] PRIMARY KEY CLUSTERED + ( + [id] ASC + )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + ) ON [PRIMARY] +end + `); err != nil { + gtest.Fatal(err) + } + + db.Schema(db.GetConfig().Name) + return +} From f8fe824bd32c1d0b615fcd3fc72851f688786b7a Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Tue, 17 Dec 2024 15:38:03 +0800 Subject: [PATCH 19/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index 9f9d3612eae..fbc47a9fd34 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -148,17 +148,19 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list return retResult.(sql.Result), err } var ( - aCount int64 - lId int64 + aCount int64 // affect count + lId int64 // last insert id ) if len(stdSqlResult) == 0 { err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} return retResult.(sql.Result), err } + // get affect count aCount = stdSqlResult[0].GMap().GetVar(affectCountFieldName).Int64() + // get last_insert_id lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() - //fmt.Println(fmt.Sprintf("---------------------------type:%d", stdSqlResult[0].GMap().Get("ID").(int64))) + retResult = &MssqlResult{lastInsertId: lId, rowsAffected: aCount} batchResult.Result = retResult.(sql.Result) @@ -171,6 +173,7 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list return batchResult, nil } +// MssqlResult instance of sql.Result type MssqlResult struct { lastInsertId int64 rowsAffected int64 @@ -185,6 +188,7 @@ func (r *MssqlResult) RowsAffected() (int64, error) { return r.rowsAffected, r.err } +// GetInsertOutputSql gen get last_insert_id code func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { fds, errFd := m.GetDB().TableFields(ctx, table) if errFd != nil { @@ -195,10 +199,11 @@ func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { incrNo := 0 if len(fds) > 0 { for _, fd := range fds { + // has primary key and is auto-incement if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { incrNoStr := "" - if incrNo == 0 { - incrNoStr = " as ID" + if incrNo == 0 { //fixed first field named id, convenient to get + incrNoStr = fmt.Sprintf(" as %s", fdId) } extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) From a9b92b401ee1b9b1cbba93b2ec4e9a8349940943 Mon Sep 17 00:00:00 2001 From: houseme Date: Tue, 17 Dec 2024 16:15:04 +0800 Subject: [PATCH 20/40] Update mssql_do_insert.go --- contrib/drivers/mssql/mssql_do_insert.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index fbc47a9fd34..d05e8860e39 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -10,15 +10,15 @@ import ( "context" "database/sql" "fmt" - "github.com/gogf/gf/v2/container/gmap" - "github.com/gogf/gf/v2/util/gconv" "strings" + "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" ) var ( From cc68d1116f5cb65a6efc6af21adc1b653f4ccd7f Mon Sep 17 00:00:00 2001 From: houseme Date: Tue, 17 Dec 2024 16:16:29 +0800 Subject: [PATCH 21/40] Update mssql_z_unit_basic_test.go --- contrib/drivers/mssql/mssql_z_unit_basic_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/drivers/mssql/mssql_z_unit_basic_test.go b/contrib/drivers/mssql/mssql_z_unit_basic_test.go index eced7288d76..14505d8eed8 100644 --- a/contrib/drivers/mssql/mssql_z_unit_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_basic_test.go @@ -10,13 +10,13 @@ import ( "context" "database/sql" "fmt" - "github.com/gogf/gf/v2/os/gctx" "testing" "time" "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/encoding/gxml" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/test/gtest" ) From a40964259b1d08810a179db3540bbfbdd593054b Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 09:48:33 +0800 Subject: [PATCH 22/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E5=8E=BB=E9=99=A4=E9=87=8D=E5=A4=8D=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 248 +----------------- .../drivers/mssql/mssql_z_unit_init_test.go | 7 +- database/gdb/gdb_core.go | 93 ++++++- 3 files changed, 88 insertions(+), 260 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index fbc47a9fd34..2d5bd69acd6 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -10,8 +10,6 @@ import ( "context" "database/sql" "fmt" - "github.com/gogf/gf/v2/container/gmap" - "github.com/gogf/gf/v2/util/gconv" "strings" "github.com/gogf/gf/v2/container/gset" @@ -25,16 +23,6 @@ var ( createdFiledNames = []string{"created_at", "create_at"} ) -const ( - autoIncrementName = "auto_increment" - mssqlOutPutKey = "OUTPUT" - mssqlInsertedObjName = "INSERTED" - mssqlAffectFd = " 1 as AffectCount" - affectCountFieldName = "AffectCount" - mssqlPrimaryKeyName = "PRI" - fdId = "ID" -) - // DoInsert inserts or updates data for given table. rewrite db.core.DoInsert func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) { switch option.InsertOption { @@ -46,241 +34,9 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gcode.CodeNotSupported, `Replace operation is not supported by mssql driver`, ) - //default: - // return d.Core.DoInsert(ctx, link, table, list, option) - } - var ( - keys []string // Field names. - values []string // Value holder string array, like: (?,?,?) - params []interface{} // Values that will be committed to underlying database driver. - onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement. - ) - // Group the list by fields. Different fields to different list. - // It here uses ListMap to keep sequence for data inserting. - var keyListMap = gmap.NewListMap() - for _, item := range list { - var ( - tmpKeys = make([]string, 0) - tmpKeysInSequenceStr string - ) - for k := range item { - tmpKeys = append(tmpKeys, k) - } - keys, err = d.fieldsToSequence(ctx, table, tmpKeys) - if err != nil { - return nil, err - } - tmpKeysInSequenceStr = gstr.Join(keys, ",") - - if !keyListMap.Contains(tmpKeysInSequenceStr) { - keyListMap.Set(tmpKeysInSequenceStr, make(gdb.List, 0)) - } - tmpKeysInSequenceList := keyListMap.Get(tmpKeysInSequenceStr).(gdb.List) - tmpKeysInSequenceList = append(tmpKeysInSequenceList, item) - keyListMap.Set(tmpKeysInSequenceStr, tmpKeysInSequenceList) - } - if keyListMap.Size() > 1 { - var ( - tmpResult sql.Result - sqlResult gdb.SqlResult - rowsAffected int64 - ) - keyListMap.Iterator(func(key, value interface{}) bool { - tmpResult, err = d.DoInsert(ctx, link, table, value.(gdb.List), option) - if err != nil { - return false - } - rowsAffected, err = tmpResult.RowsAffected() - if err != nil { - return false - } - sqlResult.Result = tmpResult - sqlResult.Affected += rowsAffected - return true - }) - return &sqlResult, nil - } - // Prepare the batch result pointer. - var ( - charL, charR = d.GetDB().GetChars() - batchResult = new(gdb.SqlResult) - keysStr = charL + strings.Join(keys, charR+","+charL) + charR - operation = gdb.GetInsertOperationByOption(option.InsertOption) - ) - if option.InsertOption == gdb.InsertOptionSave { - onDuplicateStr = d.formatOnDuplicate(keys, option) - } - var ( - listLength = len(list) - valueHolder = make([]string, 0) - ) - for i := 0; i < listLength; i++ { - values = values[:0] - // Note that the map type is unordered, - // so it should use slice+key to retrieve the value. - for _, k := range keys { - if s, ok := list[i][k].(gdb.Raw); ok { - values = append(values, gconv.String(s)) - } else { - values = append(values, "?") - params = append(params, list[i][k]) - } - } - valueHolder = append(valueHolder, "("+gstr.Join(values, ",")+")") - // Batch package checks: It meets the batch number, or it is the last element. - if len(valueHolder) == option.BatchCount || (i == listLength-1 && len(valueHolder) > 0) { - var ( - //stdSqlResult sql.Result - stdSqlResult gdb.Result - //affectedRows int64 - retResult interface{} - ) - - stdSqlResult, err = d.GetDB().DoQuery(ctx, link, fmt.Sprintf( - "%s INTO %s(%s) %s VALUES%s %s ", - operation, d.QuotePrefixTableName(table), keysStr, - d.GetInsertOutputSql(ctx, table), - gstr.Join(valueHolder, ","), - onDuplicateStr, - ), params...) - if err != nil { - retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} - return retResult.(sql.Result), err - } - var ( - aCount int64 // affect count - lId int64 // last insert id - ) - if len(stdSqlResult) == 0 { - err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) - retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} - return retResult.(sql.Result), err - } - // get affect count - aCount = stdSqlResult[0].GMap().GetVar(affectCountFieldName).Int64() - // get last_insert_id - lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() - - retResult = &MssqlResult{lastInsertId: lId, rowsAffected: aCount} - - batchResult.Result = retResult.(sql.Result) - batchResult.Affected += aCount - - params = params[:0] - valueHolder = valueHolder[:0] - } - } - return batchResult, nil -} - -// MssqlResult instance of sql.Result -type MssqlResult struct { - lastInsertId int64 - rowsAffected int64 - err error -} - -func (r *MssqlResult) LastInsertId() (int64, error) { - return r.lastInsertId, r.err -} - -func (r *MssqlResult) RowsAffected() (int64, error) { - return r.rowsAffected, r.err -} - -// GetInsertOutputSql gen get last_insert_id code -func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { - fds, errFd := m.GetDB().TableFields(ctx, table) - if errFd != nil { - return "" - } - extraSqlAry := make([]string, 0) - extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s %s", mssqlOutPutKey, mssqlAffectFd)) - incrNo := 0 - if len(fds) > 0 { - for _, fd := range fds { - // has primary key and is auto-incement - if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { - incrNoStr := "" - if incrNo == 0 { //fixed first field named id, convenient to get - incrNoStr = fmt.Sprintf(" as %s", fdId) - } - - extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) - incrNo++ - } - //fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) - } - } - //fmt.Println(extraSqlAry) - return strings.Join(extraSqlAry, ",") - //";select ID = convert(bigint, SCOPE_IDENTITY()), AffectCount = @@ROWCOUNT;" -} - -func (d *Driver) fieldsToSequence(ctx context.Context, table string, fields []string) ([]string, error) { - var ( - fieldSet = gset.NewStrSetFrom(fields) - fieldsResultInSequence = make([]string, 0) - tableFields, err = d.GetDB().TableFields(ctx, table) - ) - if err != nil { - return nil, err - } - // Sort the fields in order. - var fieldsOfTableInSequence = make([]string, len(tableFields)) - for _, field := range tableFields { - fieldsOfTableInSequence[field.Index] = field.Name - } - // Sort the input fields. - for _, fieldName := range fieldsOfTableInSequence { - if fieldSet.Contains(fieldName) { - fieldsResultInSequence = append(fieldsResultInSequence, fieldName) - } - } - return fieldsResultInSequence, nil -} - -func (d *Driver) formatOnDuplicate(columns []string, option gdb.DoInsertOption) string { - var onDuplicateStr string - if option.OnDuplicateStr != "" { - onDuplicateStr = option.OnDuplicateStr - } else if len(option.OnDuplicateMap) > 0 { - for k, v := range option.OnDuplicateMap { - if len(onDuplicateStr) > 0 { - onDuplicateStr += "," - } - switch v.(type) { - case gdb.Raw, *gdb.Raw: - onDuplicateStr += fmt.Sprintf( - "%s=%s", - d.QuoteWord(k), - v, - ) - default: - onDuplicateStr += fmt.Sprintf( - "%s=VALUES(%s)", - d.QuoteWord(k), - d.QuoteWord(gconv.String(v)), - ) - } - } - } else { - for _, column := range columns { - // If it's SAVE operation, do not automatically update the creating time. - if d.isSoftCreatedFieldName(column) { - continue - } - if len(onDuplicateStr) > 0 { - onDuplicateStr += "," - } - onDuplicateStr += fmt.Sprintf( - "%s=VALUES(%s)", - d.QuoteWord(column), - d.QuoteWord(column), - ) - } + default: + return d.Core.DoInsert(ctx, link, table, list, option) } - return fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", onDuplicateStr) } func (d *Driver) isSoftCreatedFieldName(fieldName string) bool { diff --git a/contrib/drivers/mssql/mssql_z_unit_init_test.go b/contrib/drivers/mssql/mssql_z_unit_init_test.go index f9e9b7230ab..cc15215ebc4 100644 --- a/contrib/drivers/mssql/mssql_z_unit_init_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_init_test.go @@ -31,17 +31,17 @@ const ( TestSchema2 = "test2" TableNamePrefix1 = "gf_" TestDbUser = "sa" - TestDbPass = "LoremIpsum86" //"theone@123" + TestDbPass = "theone@123" //"LoremIpsum86" CreateTime = "2018-10-24 10:00:00" ) func init() { node := gdb.ConfigNode{ - Host: "127.0.0.1", //192.168.5.72 127.0.0.1 + Host: "192.168.5.72", //192.168.5.72 127.0.0.1 Port: "1433", User: TestDbUser, Pass: TestDbPass, - Name: "test", //"QPLogDB" + Name: "QPLogDB", //"test" Type: "mssql", Role: "master", Charset: "utf8", @@ -148,6 +148,7 @@ func dropTable(table string) { } } +// createInsertAndGetIdTableForTest test for InsertAndGetId func createInsertAndGetIdTableForTest() (name string) { if _, err := db.Exec(context.Background(), ` diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index f75ff878f37..fb1ecd7f8ce 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -29,6 +29,16 @@ import ( "github.com/gogf/gf/v2/util/gutil" ) +const ( + autoIncrementName = "auto_increment" + mssqlOutPutKey = "OUTPUT" + mssqlInsertedObjName = "INSERTED" + mssqlAffectFd = " 1 as AffectCount" + affectCountFieldName = "AffectCount" + mssqlPrimaryKeyName = "PRI" + fdId = "ID" +) + // GetCore returns the underlying *Core object. func (c *Core) GetCore() *Core { return c @@ -521,25 +531,42 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, // Batch package checks: It meets the batch number, or it is the last element. if len(valueHolders) == option.BatchCount || (i == listLength-1 && len(valueHolders) > 0) { var ( - stdSqlResult sql.Result - affectedRows int64 + //stdSqlResult sql.Result + stdSqlResult Result + //affectedRows int64 + retResult interface{} ) - stdSqlResult, err = c.db.DoExec(ctx, link, fmt.Sprintf( - "%s INTO %s(%s) VALUES%s %s", + + stdSqlResult, err = c.db.DoQuery(ctx, link, fmt.Sprintf( + "%s INTO %s(%s) %s VALUES%s %s ", operation, c.QuotePrefixTableName(table), keysStr, + c.GetInsertOutputSql(ctx, table), gstr.Join(valueHolders, ","), onDuplicateStr, ), params...) if err != nil { - return stdSqlResult, err + retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} + return retResult.(sql.Result), err } - if affectedRows, err = stdSqlResult.RowsAffected(); err != nil { - err = gerror.WrapCode(gcode.CodeDbOperationError, err, `sql.Result.RowsAffected failed`) - return stdSqlResult, err - } else { - batchResult.Result = stdSqlResult - batchResult.Affected += affectedRows + var ( + aCount int64 // affect count + lId int64 // last insert id + ) + if len(stdSqlResult) == 0 { + err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) + retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} + return retResult.(sql.Result), err } + // get affect count + aCount = stdSqlResult[0].GMap().GetVar(affectCountFieldName).Int64() + // get last_insert_id + lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() + + retResult = &MssqlResult{lastInsertId: lId, rowsAffected: aCount} + + batchResult.Result = retResult.(sql.Result) + batchResult.Affected += aCount + params = params[:0] valueHolders = valueHolders[:0] } @@ -547,6 +574,50 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, return batchResult, nil } +// MssqlResult instance of sql.Result +type MssqlResult struct { + lastInsertId int64 + rowsAffected int64 + err error +} + +func (r *MssqlResult) LastInsertId() (int64, error) { + return r.lastInsertId, r.err +} + +func (r *MssqlResult) RowsAffected() (int64, error) { + return r.rowsAffected, r.err +} + +// GetInsertOutputSql gen get last_insert_id code +func (c *Core) GetInsertOutputSql(ctx context.Context, table string) string { + fds, errFd := c.GetDB().TableFields(ctx, table) + if errFd != nil { + return "" + } + extraSqlAry := make([]string, 0) + extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s %s", mssqlOutPutKey, mssqlAffectFd)) + incrNo := 0 + if len(fds) > 0 { + for _, fd := range fds { + // has primary key and is auto-incement + if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { + incrNoStr := "" + if incrNo == 0 { //fixed first field named id, convenient to get + incrNoStr = fmt.Sprintf(" as %s", fdId) + } + + extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) + incrNo++ + } + //fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) + } + } + //fmt.Println(extraSqlAry) + return strings.Join(extraSqlAry, ",") + //";select ID = convert(bigint, SCOPE_IDENTITY()), AffectCount = @@ROWCOUNT;" +} + // Update does "UPDATE ... " statement for the table. // // The parameter `data` can be type of string/map/gmap/struct/*struct, etc. From 4916d295ce361ddb974805bd64e23a17cf8ba1cb Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 09:49:42 +0800 Subject: [PATCH 23/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E5=8E=BB=E9=99=A4=E9=87=8D=E5=A4=8D=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_z_unit_init_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/drivers/mssql/mssql_z_unit_init_test.go b/contrib/drivers/mssql/mssql_z_unit_init_test.go index cc15215ebc4..a7171332eb7 100644 --- a/contrib/drivers/mssql/mssql_z_unit_init_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_init_test.go @@ -31,17 +31,17 @@ const ( TestSchema2 = "test2" TableNamePrefix1 = "gf_" TestDbUser = "sa" - TestDbPass = "theone@123" //"LoremIpsum86" + TestDbPass = "LoremIpsum86" //"theone@123" CreateTime = "2018-10-24 10:00:00" ) func init() { node := gdb.ConfigNode{ - Host: "192.168.5.72", //192.168.5.72 127.0.0.1 + Host: "127.0.0.1", //192.168.5.72 127.0.0.1 Port: "1433", User: TestDbUser, Pass: TestDbPass, - Name: "QPLogDB", //"test" + Name: "test", //"QPLogDB", // Type: "mssql", Role: "master", Charset: "utf8", From 017e6c40c9666ad3f75145f45174c31b68277d6d Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 10:09:01 +0800 Subject: [PATCH 24/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 250 ++++++++++++++++++++++- database/gdb/gdb_core.go | 93 +-------- 2 files changed, 257 insertions(+), 86 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index ad8ec2e96ee..fbc47a9fd34 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -10,21 +10,31 @@ import ( "context" "database/sql" "fmt" + "github.com/gogf/gf/v2/container/gmap" + "github.com/gogf/gf/v2/util/gconv" "strings" - "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" - "github.com/gogf/gf/v2/util/gconv" ) var ( createdFiledNames = []string{"created_at", "create_at"} ) +const ( + autoIncrementName = "auto_increment" + mssqlOutPutKey = "OUTPUT" + mssqlInsertedObjName = "INSERTED" + mssqlAffectFd = " 1 as AffectCount" + affectCountFieldName = "AffectCount" + mssqlPrimaryKeyName = "PRI" + fdId = "ID" +) + // DoInsert inserts or updates data for given table. rewrite db.core.DoInsert func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) { switch option.InsertOption { @@ -36,9 +46,241 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gcode.CodeNotSupported, `Replace operation is not supported by mssql driver`, ) - default: - return d.Core.DoInsert(ctx, link, table, list, option) + //default: + // return d.Core.DoInsert(ctx, link, table, list, option) + } + var ( + keys []string // Field names. + values []string // Value holder string array, like: (?,?,?) + params []interface{} // Values that will be committed to underlying database driver. + onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement. + ) + // Group the list by fields. Different fields to different list. + // It here uses ListMap to keep sequence for data inserting. + var keyListMap = gmap.NewListMap() + for _, item := range list { + var ( + tmpKeys = make([]string, 0) + tmpKeysInSequenceStr string + ) + for k := range item { + tmpKeys = append(tmpKeys, k) + } + keys, err = d.fieldsToSequence(ctx, table, tmpKeys) + if err != nil { + return nil, err + } + tmpKeysInSequenceStr = gstr.Join(keys, ",") + + if !keyListMap.Contains(tmpKeysInSequenceStr) { + keyListMap.Set(tmpKeysInSequenceStr, make(gdb.List, 0)) + } + tmpKeysInSequenceList := keyListMap.Get(tmpKeysInSequenceStr).(gdb.List) + tmpKeysInSequenceList = append(tmpKeysInSequenceList, item) + keyListMap.Set(tmpKeysInSequenceStr, tmpKeysInSequenceList) + } + if keyListMap.Size() > 1 { + var ( + tmpResult sql.Result + sqlResult gdb.SqlResult + rowsAffected int64 + ) + keyListMap.Iterator(func(key, value interface{}) bool { + tmpResult, err = d.DoInsert(ctx, link, table, value.(gdb.List), option) + if err != nil { + return false + } + rowsAffected, err = tmpResult.RowsAffected() + if err != nil { + return false + } + sqlResult.Result = tmpResult + sqlResult.Affected += rowsAffected + return true + }) + return &sqlResult, nil + } + // Prepare the batch result pointer. + var ( + charL, charR = d.GetDB().GetChars() + batchResult = new(gdb.SqlResult) + keysStr = charL + strings.Join(keys, charR+","+charL) + charR + operation = gdb.GetInsertOperationByOption(option.InsertOption) + ) + if option.InsertOption == gdb.InsertOptionSave { + onDuplicateStr = d.formatOnDuplicate(keys, option) + } + var ( + listLength = len(list) + valueHolder = make([]string, 0) + ) + for i := 0; i < listLength; i++ { + values = values[:0] + // Note that the map type is unordered, + // so it should use slice+key to retrieve the value. + for _, k := range keys { + if s, ok := list[i][k].(gdb.Raw); ok { + values = append(values, gconv.String(s)) + } else { + values = append(values, "?") + params = append(params, list[i][k]) + } + } + valueHolder = append(valueHolder, "("+gstr.Join(values, ",")+")") + // Batch package checks: It meets the batch number, or it is the last element. + if len(valueHolder) == option.BatchCount || (i == listLength-1 && len(valueHolder) > 0) { + var ( + //stdSqlResult sql.Result + stdSqlResult gdb.Result + //affectedRows int64 + retResult interface{} + ) + + stdSqlResult, err = d.GetDB().DoQuery(ctx, link, fmt.Sprintf( + "%s INTO %s(%s) %s VALUES%s %s ", + operation, d.QuotePrefixTableName(table), keysStr, + d.GetInsertOutputSql(ctx, table), + gstr.Join(valueHolder, ","), + onDuplicateStr, + ), params...) + if err != nil { + retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} + return retResult.(sql.Result), err + } + var ( + aCount int64 // affect count + lId int64 // last insert id + ) + if len(stdSqlResult) == 0 { + err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) + retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} + return retResult.(sql.Result), err + } + // get affect count + aCount = stdSqlResult[0].GMap().GetVar(affectCountFieldName).Int64() + // get last_insert_id + lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() + + retResult = &MssqlResult{lastInsertId: lId, rowsAffected: aCount} + + batchResult.Result = retResult.(sql.Result) + batchResult.Affected += aCount + + params = params[:0] + valueHolder = valueHolder[:0] + } + } + return batchResult, nil +} + +// MssqlResult instance of sql.Result +type MssqlResult struct { + lastInsertId int64 + rowsAffected int64 + err error +} + +func (r *MssqlResult) LastInsertId() (int64, error) { + return r.lastInsertId, r.err +} + +func (r *MssqlResult) RowsAffected() (int64, error) { + return r.rowsAffected, r.err +} + +// GetInsertOutputSql gen get last_insert_id code +func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { + fds, errFd := m.GetDB().TableFields(ctx, table) + if errFd != nil { + return "" + } + extraSqlAry := make([]string, 0) + extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s %s", mssqlOutPutKey, mssqlAffectFd)) + incrNo := 0 + if len(fds) > 0 { + for _, fd := range fds { + // has primary key and is auto-incement + if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { + incrNoStr := "" + if incrNo == 0 { //fixed first field named id, convenient to get + incrNoStr = fmt.Sprintf(" as %s", fdId) + } + + extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) + incrNo++ + } + //fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) + } + } + //fmt.Println(extraSqlAry) + return strings.Join(extraSqlAry, ",") + //";select ID = convert(bigint, SCOPE_IDENTITY()), AffectCount = @@ROWCOUNT;" +} + +func (d *Driver) fieldsToSequence(ctx context.Context, table string, fields []string) ([]string, error) { + var ( + fieldSet = gset.NewStrSetFrom(fields) + fieldsResultInSequence = make([]string, 0) + tableFields, err = d.GetDB().TableFields(ctx, table) + ) + if err != nil { + return nil, err + } + // Sort the fields in order. + var fieldsOfTableInSequence = make([]string, len(tableFields)) + for _, field := range tableFields { + fieldsOfTableInSequence[field.Index] = field.Name + } + // Sort the input fields. + for _, fieldName := range fieldsOfTableInSequence { + if fieldSet.Contains(fieldName) { + fieldsResultInSequence = append(fieldsResultInSequence, fieldName) + } + } + return fieldsResultInSequence, nil +} + +func (d *Driver) formatOnDuplicate(columns []string, option gdb.DoInsertOption) string { + var onDuplicateStr string + if option.OnDuplicateStr != "" { + onDuplicateStr = option.OnDuplicateStr + } else if len(option.OnDuplicateMap) > 0 { + for k, v := range option.OnDuplicateMap { + if len(onDuplicateStr) > 0 { + onDuplicateStr += "," + } + switch v.(type) { + case gdb.Raw, *gdb.Raw: + onDuplicateStr += fmt.Sprintf( + "%s=%s", + d.QuoteWord(k), + v, + ) + default: + onDuplicateStr += fmt.Sprintf( + "%s=VALUES(%s)", + d.QuoteWord(k), + d.QuoteWord(gconv.String(v)), + ) + } + } + } else { + for _, column := range columns { + // If it's SAVE operation, do not automatically update the creating time. + if d.isSoftCreatedFieldName(column) { + continue + } + if len(onDuplicateStr) > 0 { + onDuplicateStr += "," + } + onDuplicateStr += fmt.Sprintf( + "%s=VALUES(%s)", + d.QuoteWord(column), + d.QuoteWord(column), + ) + } } + return fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", onDuplicateStr) } func (d *Driver) isSoftCreatedFieldName(fieldName string) bool { diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index fb1ecd7f8ce..f75ff878f37 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -29,16 +29,6 @@ import ( "github.com/gogf/gf/v2/util/gutil" ) -const ( - autoIncrementName = "auto_increment" - mssqlOutPutKey = "OUTPUT" - mssqlInsertedObjName = "INSERTED" - mssqlAffectFd = " 1 as AffectCount" - affectCountFieldName = "AffectCount" - mssqlPrimaryKeyName = "PRI" - fdId = "ID" -) - // GetCore returns the underlying *Core object. func (c *Core) GetCore() *Core { return c @@ -531,42 +521,25 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, // Batch package checks: It meets the batch number, or it is the last element. if len(valueHolders) == option.BatchCount || (i == listLength-1 && len(valueHolders) > 0) { var ( - //stdSqlResult sql.Result - stdSqlResult Result - //affectedRows int64 - retResult interface{} + stdSqlResult sql.Result + affectedRows int64 ) - - stdSqlResult, err = c.db.DoQuery(ctx, link, fmt.Sprintf( - "%s INTO %s(%s) %s VALUES%s %s ", + stdSqlResult, err = c.db.DoExec(ctx, link, fmt.Sprintf( + "%s INTO %s(%s) VALUES%s %s", operation, c.QuotePrefixTableName(table), keysStr, - c.GetInsertOutputSql(ctx, table), gstr.Join(valueHolders, ","), onDuplicateStr, ), params...) if err != nil { - retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} - return retResult.(sql.Result), err + return stdSqlResult, err } - var ( - aCount int64 // affect count - lId int64 // last insert id - ) - if len(stdSqlResult) == 0 { - err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) - retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} - return retResult.(sql.Result), err + if affectedRows, err = stdSqlResult.RowsAffected(); err != nil { + err = gerror.WrapCode(gcode.CodeDbOperationError, err, `sql.Result.RowsAffected failed`) + return stdSqlResult, err + } else { + batchResult.Result = stdSqlResult + batchResult.Affected += affectedRows } - // get affect count - aCount = stdSqlResult[0].GMap().GetVar(affectCountFieldName).Int64() - // get last_insert_id - lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() - - retResult = &MssqlResult{lastInsertId: lId, rowsAffected: aCount} - - batchResult.Result = retResult.(sql.Result) - batchResult.Affected += aCount - params = params[:0] valueHolders = valueHolders[:0] } @@ -574,50 +547,6 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, return batchResult, nil } -// MssqlResult instance of sql.Result -type MssqlResult struct { - lastInsertId int64 - rowsAffected int64 - err error -} - -func (r *MssqlResult) LastInsertId() (int64, error) { - return r.lastInsertId, r.err -} - -func (r *MssqlResult) RowsAffected() (int64, error) { - return r.rowsAffected, r.err -} - -// GetInsertOutputSql gen get last_insert_id code -func (c *Core) GetInsertOutputSql(ctx context.Context, table string) string { - fds, errFd := c.GetDB().TableFields(ctx, table) - if errFd != nil { - return "" - } - extraSqlAry := make([]string, 0) - extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s %s", mssqlOutPutKey, mssqlAffectFd)) - incrNo := 0 - if len(fds) > 0 { - for _, fd := range fds { - // has primary key and is auto-incement - if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { - incrNoStr := "" - if incrNo == 0 { //fixed first field named id, convenient to get - incrNoStr = fmt.Sprintf(" as %s", fdId) - } - - extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) - incrNo++ - } - //fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) - } - } - //fmt.Println(extraSqlAry) - return strings.Join(extraSqlAry, ",") - //";select ID = convert(bigint, SCOPE_IDENTITY()), AffectCount = @@ROWCOUNT;" -} - // Update does "UPDATE ... " statement for the table. // // The parameter `data` can be type of string/map/gmap/struct/*struct, etc. From 7d6b181fe33c5341ea4fa84a3bef16763f6c20d9 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 10:38:15 +0800 Subject: [PATCH 25/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index fbc47a9fd34..db8c0c6bdea 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -144,7 +144,7 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list onDuplicateStr, ), params...) if err != nil { - retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} + retResult = &InsertResult{lastInsertId: 0, rowsAffected: 0, err: err} return retResult.(sql.Result), err } var ( @@ -153,7 +153,7 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list ) if len(stdSqlResult) == 0 { err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) - retResult = &MssqlResult{lastInsertId: 0, rowsAffected: 0, err: err} + retResult = &InsertResult{lastInsertId: 0, rowsAffected: 0, err: err} return retResult.(sql.Result), err } // get affect count @@ -161,7 +161,7 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list // get last_insert_id lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() - retResult = &MssqlResult{lastInsertId: lId, rowsAffected: aCount} + retResult = &InsertResult{lastInsertId: lId, rowsAffected: aCount} batchResult.Result = retResult.(sql.Result) batchResult.Affected += aCount @@ -173,18 +173,18 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list return batchResult, nil } -// MssqlResult instance of sql.Result -type MssqlResult struct { +// InsertResult instance of sql.Result +type InsertResult struct { lastInsertId int64 rowsAffected int64 err error } -func (r *MssqlResult) LastInsertId() (int64, error) { +func (r *InsertResult) LastInsertId() (int64, error) { return r.lastInsertId, r.err } -func (r *MssqlResult) RowsAffected() (int64, error) { +func (r *InsertResult) RowsAffected() (int64, error) { return r.rowsAffected, r.err } From 13d1670a6ff8b478d9faa51c1927cd7eeb9b6636 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 10:54:08 +0800 Subject: [PATCH 26/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index db8c0c6bdea..fb74bd2836f 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -130,10 +130,8 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list // Batch package checks: It meets the batch number, or it is the last element. if len(valueHolder) == option.BatchCount || (i == listLength-1 && len(valueHolder) > 0) { var ( - //stdSqlResult sql.Result stdSqlResult gdb.Result - //affectedRows int64 - retResult interface{} + retResult interface{} ) stdSqlResult, err = d.GetDB().DoQuery(ctx, link, fmt.Sprintf( From 8bb5c9bf2523f230408680f44c6c0dda92c73462 Mon Sep 17 00:00:00 2001 From: houseme Date: Wed, 18 Dec 2024 10:58:58 +0800 Subject: [PATCH 27/40] Update mssql_do_insert.go --- contrib/drivers/mssql/mssql_do_insert.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index fb74bd2836f..b243813a6d7 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -10,15 +10,15 @@ import ( "context" "database/sql" "fmt" - "github.com/gogf/gf/v2/container/gmap" - "github.com/gogf/gf/v2/util/gconv" "strings" + "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" ) var ( From ee51d56772ac2b22e355c666368768a21c2499c4 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 15:00:27 +0800 Subject: [PATCH 28/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 197 +----------------- contrib/drivers/mssql/mssql_tools.go | 22 -- .../drivers/mssql/mssql_z_unit_init_test.go | 6 +- database/gdb/gdb.go | 2 +- database/gdb/gdb_core.go | 38 +++- database/gdb/gdb_driver_wrapper_db.go | 4 +- 6 files changed, 44 insertions(+), 225 deletions(-) delete mode 100644 contrib/drivers/mssql/mssql_tools.go diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index b243813a6d7..e22d05fe278 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -12,17 +12,11 @@ import ( "fmt" "strings" - "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" - "github.com/gogf/gf/v2/util/gconv" -) - -var ( - createdFiledNames = []string{"created_at", "create_at"} ) const ( @@ -36,7 +30,7 @@ const ( ) // DoInsert inserts or updates data for given table. rewrite db.core.DoInsert -func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) { +func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionSave: return d.doSave(ctx, link, table, list, option) @@ -46,101 +40,15 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gcode.CodeNotSupported, `Replace operation is not supported by mssql driver`, ) - //default: - // return d.Core.DoInsert(ctx, link, table, list, option) - } - var ( - keys []string // Field names. - values []string // Value holder string array, like: (?,?,?) - params []interface{} // Values that will be committed to underlying database driver. - onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement. - ) - // Group the list by fields. Different fields to different list. - // It here uses ListMap to keep sequence for data inserting. - var keyListMap = gmap.NewListMap() - for _, item := range list { - var ( - tmpKeys = make([]string, 0) - tmpKeysInSequenceStr string - ) - for k := range item { - tmpKeys = append(tmpKeys, k) - } - keys, err = d.fieldsToSequence(ctx, table, tmpKeys) - if err != nil { - return nil, err - } - tmpKeysInSequenceStr = gstr.Join(keys, ",") - - if !keyListMap.Contains(tmpKeysInSequenceStr) { - keyListMap.Set(tmpKeysInSequenceStr, make(gdb.List, 0)) - } - tmpKeysInSequenceList := keyListMap.Get(tmpKeysInSequenceStr).(gdb.List) - tmpKeysInSequenceList = append(tmpKeysInSequenceList, item) - keyListMap.Set(tmpKeysInSequenceStr, tmpKeysInSequenceList) - } - if keyListMap.Size() > 1 { - var ( - tmpResult sql.Result - sqlResult gdb.SqlResult - rowsAffected int64 - ) - keyListMap.Iterator(func(key, value interface{}) bool { - tmpResult, err = d.DoInsert(ctx, link, table, value.(gdb.List), option) - if err != nil { - return false - } - rowsAffected, err = tmpResult.RowsAffected() - if err != nil { - return false - } - sqlResult.Result = tmpResult - sqlResult.Affected += rowsAffected - return true - }) - return &sqlResult, nil - } - // Prepare the batch result pointer. - var ( - charL, charR = d.GetDB().GetChars() - batchResult = new(gdb.SqlResult) - keysStr = charL + strings.Join(keys, charR+","+charL) + charR - operation = gdb.GetInsertOperationByOption(option.InsertOption) - ) - if option.InsertOption == gdb.InsertOptionSave { - onDuplicateStr = d.formatOnDuplicate(keys, option) - } - var ( - listLength = len(list) - valueHolder = make([]string, 0) - ) - for i := 0; i < listLength; i++ { - values = values[:0] - // Note that the map type is unordered, - // so it should use slice+key to retrieve the value. - for _, k := range keys { - if s, ok := list[i][k].(gdb.Raw); ok { - values = append(values, gconv.String(s)) - } else { - values = append(values, "?") - params = append(params, list[i][k]) - } - } - valueHolder = append(valueHolder, "("+gstr.Join(values, ",")+")") - // Batch package checks: It meets the batch number, or it is the last element. - if len(valueHolder) == option.BatchCount || (i == listLength-1 && len(valueHolder) > 0) { + default: + outPutStr := d.GetInsertOutputSql(ctx, table) + var insertHandler gdb.InsertHandler + insertHandler = func(db gdb.DB, ctx context.Context, link gdb.Link, sqlStr string, args ...interface{}) (sql.Result, error) { var ( stdSqlResult gdb.Result retResult interface{} ) - - stdSqlResult, err = d.GetDB().DoQuery(ctx, link, fmt.Sprintf( - "%s INTO %s(%s) %s VALUES%s %s ", - operation, d.QuotePrefixTableName(table), keysStr, - d.GetInsertOutputSql(ctx, table), - gstr.Join(valueHolder, ","), - onDuplicateStr, - ), params...) + stdSqlResult, err = d.GetDB().DoQuery(ctx, link, sqlStr, args...) if err != nil { retResult = &InsertResult{lastInsertId: 0, rowsAffected: 0, err: err} return retResult.(sql.Result), err @@ -160,15 +68,10 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() retResult = &InsertResult{lastInsertId: lId, rowsAffected: aCount} - - batchResult.Result = retResult.(sql.Result) - batchResult.Affected += aCount - - params = params[:0] - valueHolder = valueHolder[:0] + return retResult.(sql.Result), nil } + return d.Core.DoInsert(ctx, link, table, list, option, insertHandler, outPutStr) } - return batchResult, nil } // InsertResult instance of sql.Result @@ -215,90 +118,6 @@ func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { //";select ID = convert(bigint, SCOPE_IDENTITY()), AffectCount = @@ROWCOUNT;" } -func (d *Driver) fieldsToSequence(ctx context.Context, table string, fields []string) ([]string, error) { - var ( - fieldSet = gset.NewStrSetFrom(fields) - fieldsResultInSequence = make([]string, 0) - tableFields, err = d.GetDB().TableFields(ctx, table) - ) - if err != nil { - return nil, err - } - // Sort the fields in order. - var fieldsOfTableInSequence = make([]string, len(tableFields)) - for _, field := range tableFields { - fieldsOfTableInSequence[field.Index] = field.Name - } - // Sort the input fields. - for _, fieldName := range fieldsOfTableInSequence { - if fieldSet.Contains(fieldName) { - fieldsResultInSequence = append(fieldsResultInSequence, fieldName) - } - } - return fieldsResultInSequence, nil -} - -func (d *Driver) formatOnDuplicate(columns []string, option gdb.DoInsertOption) string { - var onDuplicateStr string - if option.OnDuplicateStr != "" { - onDuplicateStr = option.OnDuplicateStr - } else if len(option.OnDuplicateMap) > 0 { - for k, v := range option.OnDuplicateMap { - if len(onDuplicateStr) > 0 { - onDuplicateStr += "," - } - switch v.(type) { - case gdb.Raw, *gdb.Raw: - onDuplicateStr += fmt.Sprintf( - "%s=%s", - d.QuoteWord(k), - v, - ) - default: - onDuplicateStr += fmt.Sprintf( - "%s=VALUES(%s)", - d.QuoteWord(k), - d.QuoteWord(gconv.String(v)), - ) - } - } - } else { - for _, column := range columns { - // If it's SAVE operation, do not automatically update the creating time. - if d.isSoftCreatedFieldName(column) { - continue - } - if len(onDuplicateStr) > 0 { - onDuplicateStr += "," - } - onDuplicateStr += fmt.Sprintf( - "%s=VALUES(%s)", - d.QuoteWord(column), - d.QuoteWord(column), - ) - } - } - return fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", onDuplicateStr) -} - -func (d *Driver) isSoftCreatedFieldName(fieldName string) bool { - if fieldName == "" { - return false - } - if config := d.GetDB().GetConfig(); config.CreatedAt != "" { - if equalFoldWithoutChars(fieldName, config.CreatedAt) { - return true - } - return gstr.InArray(append([]string{config.CreatedAt}, createdFiledNames...), fieldName) - } - for _, v := range createdFiledNames { - if equalFoldWithoutChars(fieldName, v) { - return true - } - } - return false -} - // doSave support upsert for SQL server func (d *Driver) doSave(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, diff --git a/contrib/drivers/mssql/mssql_tools.go b/contrib/drivers/mssql/mssql_tools.go deleted file mode 100644 index 410d599b2e8..00000000000 --- a/contrib/drivers/mssql/mssql_tools.go +++ /dev/null @@ -1,22 +0,0 @@ -package mssql - -import "strings" - -// RemoveSymbols removes all symbols from string and lefts only numbers and letters. -func removeSymbols(s string) string { - var b = make([]rune, 0, len(s)) - for _, c := range s { - if c > 127 { - b = append(b, c) - } else if (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') { - b = append(b, c) - } - } - return string(b) -} - -// equalFoldWithoutChars checks string `s1` and `s2` equal case-insensitively, -// with/without chars '-'/'_'/'.'/' '. -func equalFoldWithoutChars(s1, s2 string) bool { - return strings.EqualFold(removeSymbols(s1), removeSymbols(s2)) -} diff --git a/contrib/drivers/mssql/mssql_z_unit_init_test.go b/contrib/drivers/mssql/mssql_z_unit_init_test.go index a7171332eb7..b962504574e 100644 --- a/contrib/drivers/mssql/mssql_z_unit_init_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_init_test.go @@ -31,17 +31,17 @@ const ( TestSchema2 = "test2" TableNamePrefix1 = "gf_" TestDbUser = "sa" - TestDbPass = "LoremIpsum86" //"theone@123" + TestDbPass = "theone@123" // "LoremIpsum86" CreateTime = "2018-10-24 10:00:00" ) func init() { node := gdb.ConfigNode{ - Host: "127.0.0.1", //192.168.5.72 127.0.0.1 + Host: "192.168.5.72", // 192.168.5.72 127.0.0.1 Port: "1433", User: TestDbUser, Pass: TestDbPass, - Name: "test", //"QPLogDB", // + Name: "QPLogDB", // "test", Type: "mssql", Role: "master", Charset: "utf8", diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index da52e75267c..6fc0840cda9 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -133,7 +133,7 @@ type DB interface { // DoInsert performs the actual INSERT operation with given options. // This is an internal method that can be overridden by custom implementations. - DoInsert(ctx context.Context, link Link, table string, data List, option DoInsertOption) (result sql.Result, err error) + DoInsert(ctx context.Context, link Link, table string, data List, option DoInsertOption, ext ...interface{}) (result sql.Result, err error) // DoUpdate performs the actual UPDATE operation. // This is an internal method that can be overridden by custom implementations. diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index f75ff878f37..f6d6c6af5c5 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -421,6 +421,9 @@ func (c *Core) fieldsToSequence(ctx context.Context, table string, fields []stri return fieldsResultInSequence, nil } +// InsertHandler special need for mssql insert and get id +type InsertHandler func(db DB, ctx context.Context, link Link, sql string, args ...interface{}) (sql.Result, error) + // DoInsert inserts or updates data for given table. // This function is usually used for custom interface definition, you do not need call it manually. // The parameter `data` can be type of map/gmap/struct/*struct/[]map/[]struct, etc. @@ -433,13 +436,30 @@ func (c *Core) fieldsToSequence(ctx context.Context, table string, fields []stri // InsertOptionReplace: if there's unique/primary key in the data, it deletes it from table and inserts a new one; // InsertOptionSave: if there's unique/primary key in the data, it updates it or else inserts a new one; // InsertOptionIgnore: if there's unique/primary key in the data, it ignores the inserting; -func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption) (result sql.Result, err error) { +func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption, ext ...interface{}) (result sql.Result, err error) { var ( - keys []string // Field names. - values []string // Value holder string array, like: (?,?,?) - params []interface{} // Values that will be committed to underlying database driver. - onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement. + keys []string // Field names. + values []string // Value holder string array, like: (?,?,?) + params []interface{} // Values that will be committed to underlying database driver. + onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement. + insertDefaultHandler InsertHandler // drive to do insert data + insertOutPutStr string ) + insertOutPutStr = "" + insertDefaultHandler = func(db DB, ctx context.Context, link Link, sql string, args ...interface{}) (sql.Result, error) { + return db.DoExec(ctx, link, sql, args...) + } + //deal special insert. for example: mssql + if len(ext) > 0 { + if fn, ok := ext[0].(InsertHandler); ok { + insertDefaultHandler = fn + } + if len(ext) > 1 { + if outStr, ok := ext[1].(string); ok { + insertOutPutStr = outStr + } + } + } // ============================================================================================ // Group the list by fields. Different fields to different list. // It here uses ListMap to keep sequence for data inserting. @@ -524,12 +544,14 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, stdSqlResult sql.Result affectedRows int64 ) - stdSqlResult, err = c.db.DoExec(ctx, link, fmt.Sprintf( - "%s INTO %s(%s) VALUES%s %s", + sqlStr := fmt.Sprintf( + "%s INTO %s(%s) %s VALUES%s %s ", operation, c.QuotePrefixTableName(table), keysStr, + insertOutPutStr, gstr.Join(valueHolders, ","), onDuplicateStr, - ), params...) + ) + stdSqlResult, err = insertDefaultHandler(c.db, ctx, link, sqlStr, params...) if err != nil { return stdSqlResult, err } diff --git a/database/gdb/gdb_driver_wrapper_db.go b/database/gdb/gdb_driver_wrapper_db.go index 4a6670627d7..305af9c68a9 100644 --- a/database/gdb/gdb_driver_wrapper_db.go +++ b/database/gdb/gdb_driver_wrapper_db.go @@ -109,7 +109,7 @@ func (d *DriverWrapperDB) TableFields( // InsertOptionReplace: if there's unique/primary key in the data, it deletes it from table and inserts a new one; // InsertOptionSave: if there's unique/primary key in the data, it updates it or else inserts a new one; // InsertOptionIgnore: if there's unique/primary key in the data, it ignores the inserting; -func (d *DriverWrapperDB) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption) (result sql.Result, err error) { +func (d *DriverWrapperDB) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption, ext ...interface{}) (result sql.Result, err error) { // Convert data type before commit it to underlying db driver. for i, item := range list { list[i], err = d.GetCore().ConvertDataForRecord(ctx, item, table) @@ -117,5 +117,5 @@ func (d *DriverWrapperDB) DoInsert(ctx context.Context, link Link, table string, return nil, err } } - return d.DB.DoInsert(ctx, link, table, list, option) + return d.DB.DoInsert(ctx, link, table, list, option, ext) } From 7c161841f97437cda7a636f6d826a370ee71ef0b Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 15:01:11 +0800 Subject: [PATCH 29/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_z_unit_init_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/drivers/mssql/mssql_z_unit_init_test.go b/contrib/drivers/mssql/mssql_z_unit_init_test.go index b962504574e..e1284ab3e3d 100644 --- a/contrib/drivers/mssql/mssql_z_unit_init_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_init_test.go @@ -31,17 +31,17 @@ const ( TestSchema2 = "test2" TableNamePrefix1 = "gf_" TestDbUser = "sa" - TestDbPass = "theone@123" // "LoremIpsum86" + TestDbPass = "LoremIpsum86" // "theone@123" CreateTime = "2018-10-24 10:00:00" ) func init() { node := gdb.ConfigNode{ - Host: "192.168.5.72", // 192.168.5.72 127.0.0.1 + Host: "127.0.0.1", // 192.168.5.72 127.0.0.1 Port: "1433", User: TestDbUser, Pass: TestDbPass, - Name: "QPLogDB", // "test", + Name: "test", // "QPLogDB", Type: "mssql", Role: "master", Charset: "utf8", From bcd54f88ad68094dba3119f4ac89efe45d3b32f6 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 15:15:41 +0800 Subject: [PATCH 30/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/clickhouse/clickhouse_do_insert.go | 3 +-- contrib/drivers/dm/dm_do_insert.go | 2 +- contrib/drivers/oracle/oracle_do_insert.go | 2 +- contrib/drivers/pgsql/pgsql_do_insert.go | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/contrib/drivers/clickhouse/clickhouse_do_insert.go b/contrib/drivers/clickhouse/clickhouse_do_insert.go index efa076305fb..d6b63d2fca6 100644 --- a/contrib/drivers/clickhouse/clickhouse_do_insert.go +++ b/contrib/drivers/clickhouse/clickhouse_do_insert.go @@ -17,8 +17,7 @@ import ( // DoInsert inserts or updates data for given table. func (d *Driver) DoInsert( - ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, -) (result sql.Result, err error) { + ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}) (result sql.Result, err error) { var ( keys []string // Field names. valueHolder = make([]string, 0) diff --git a/contrib/drivers/dm/dm_do_insert.go b/contrib/drivers/dm/dm_do_insert.go index de2b216a40f..4606b433f05 100644 --- a/contrib/drivers/dm/dm_do_insert.go +++ b/contrib/drivers/dm/dm_do_insert.go @@ -21,7 +21,7 @@ import ( // DoInsert inserts or updates data for given table. func (d *Driver) DoInsert( - ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, + ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}, ) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionSave: diff --git a/contrib/drivers/oracle/oracle_do_insert.go b/contrib/drivers/oracle/oracle_do_insert.go index cf6a9b14bbb..2edae82e5f1 100644 --- a/contrib/drivers/oracle/oracle_do_insert.go +++ b/contrib/drivers/oracle/oracle_do_insert.go @@ -22,7 +22,7 @@ import ( // DoInsert inserts or updates data for given table. func (d *Driver) DoInsert( - ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, + ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}, ) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionSave: diff --git a/contrib/drivers/pgsql/pgsql_do_insert.go b/contrib/drivers/pgsql/pgsql_do_insert.go index ec24edde302..4b3fd4a5bb3 100644 --- a/contrib/drivers/pgsql/pgsql_do_insert.go +++ b/contrib/drivers/pgsql/pgsql_do_insert.go @@ -16,7 +16,7 @@ import ( ) // DoInsert inserts or updates data for given table. -func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) { +func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionReplace: return nil, gerror.NewCode( @@ -36,5 +36,5 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list } } } - return d.Core.DoInsert(ctx, link, table, list, option) + return d.Core.DoInsert(ctx, link, table, list, option, ext) } From 3ec18661fead5ac32aec40c28db296637c72cc8b Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 16:29:58 +0800 Subject: [PATCH 31/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 11 +++--- .../drivers/mysql/mysql_z_unit_init_test.go | 10 +++--- .../drivers/mysql/mysql_z_unit_issue_test.go | 36 +++++++++++++++++++ database/gdb/gdb_core.go | 2 +- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index e22d05fe278..c030e3cd108 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -48,7 +48,7 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list stdSqlResult gdb.Result retResult interface{} ) - stdSqlResult, err = d.GetDB().DoQuery(ctx, link, sqlStr, args...) + stdSqlResult, err = db.DoQuery(ctx, link, sqlStr, args...) if err != nil { retResult = &InsertResult{lastInsertId: 0, rowsAffected: 0, err: err} return retResult.(sql.Result), err @@ -96,26 +96,25 @@ func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { return "" } extraSqlAry := make([]string, 0) - extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s %s", mssqlOutPutKey, mssqlAffectFd)) + extraSqlAry = append(extraSqlAry, fmt.Sprintf(" %s %s", mssqlOutPutKey, mssqlAffectFd)) incrNo := 0 if len(fds) > 0 { for _, fd := range fds { // has primary key and is auto-incement if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { incrNoStr := "" - if incrNo == 0 { //fixed first field named id, convenient to get + if incrNo == 0 { // fixed first field named id, convenient to get incrNoStr = fmt.Sprintf(" as %s", fdId) } extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) incrNo++ } - //fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) + // fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) } } - //fmt.Println(extraSqlAry) return strings.Join(extraSqlAry, ",") - //";select ID = convert(bigint, SCOPE_IDENTITY()), AffectCount = @@ROWCOUNT;" + // sql example:INSERT INTO "ip_to_id"("ip") OUTPUT 1 as AffectCount,INSERTED.id as ID VALUES(?) } // doSave support upsert for SQL server diff --git a/contrib/drivers/mysql/mysql_z_unit_init_test.go b/contrib/drivers/mysql/mysql_z_unit_init_test.go index f0621741c7b..0e69a4c5f16 100644 --- a/contrib/drivers/mysql/mysql_z_unit_init_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_init_test.go @@ -27,7 +27,7 @@ const ( TestPartitionDB = "test3" TableNamePrefix1 = "gf_" TestDbUser = "root" - TestDbPass = "12345678" + TestDbPass = "12345678" //12345678 123456 CreateTime = "2018-10-24 10:00:00" ) @@ -43,19 +43,19 @@ var ( func init() { nodeDefault := gdb.ConfigNode{ ExecTimeout: time.Second * 2, - Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3306)/?loc=Local&parseTime=true", TestDbPass), + Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3306)/?loc=Local&parseTime=true", TestDbPass), // 192.168.0.10:3306 127.0.0.1:3306 } partitionDefault := gdb.ConfigNode{ - Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3307)/?loc=Local&parseTime=true", TestDbPass), + Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3307)/?loc=Local&parseTime=true", TestDbPass), // 127.0.0.1:3307 192.168.2.99:3306 Debug: true, } nodePrefix := gdb.ConfigNode{ - Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3306)/?loc=Local&parseTime=true", TestDbPass), + Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3306)/?loc=Local&parseTime=true", TestDbPass), // 192.168.0.10:3306 127.0.0.1:3306 } nodePrefix.Prefix = TableNamePrefix1 nodeInvalid := gdb.ConfigNode{ - Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3307)/?loc=Local&parseTime=true", TestDbPass), + Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3307)/?loc=Local&parseTime=true", TestDbPass), // 127.0.0.1:3307 192.168.2.99:3306 } gdb.AddConfigNode("test", nodeDefault) gdb.AddConfigNode("prefix", nodePrefix) diff --git a/contrib/drivers/mysql/mysql_z_unit_issue_test.go b/contrib/drivers/mysql/mysql_z_unit_issue_test.go index 04a24bc194a..c1322b6127a 100644 --- a/contrib/drivers/mysql/mysql_z_unit_issue_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_issue_test.go @@ -924,6 +924,42 @@ func Test_Issue3086(t *testing.T) { }) } +func Test_InsertedAndGetId(t *testing.T) { + table := createInitTable() + defer dropTable(table) + // data + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id interface{} `orm:"id,omitempty"` + Passport interface{} `orm:"passport,omitempty"` + Password interface{} `orm:"password,omitempty"` + Nickname interface{} `orm:"nickname,omitempty"` + CreateTime interface{} `orm:"create_time,omitempty"` + } + var ( + err error + sqlArray []string + insertId int64 + data = User{ + Id: 20, + Passport: "passport_20", + Password: "", + } + ) + sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error { + insertId, err = db.Ctx(ctx).Model(table).Data(data).InsertAndGetId() + return err + }) + t.AssertNil(err) + t.Assert(insertId, 20) + t.Assert( + gstr.Contains(sqlArray[len(sqlArray)-1], "(`id`,`passport`) VALUES(20,'passport_20')"), + true, + ) + }) +} + // https://github.com/gogf/gf/issues/3204 func Test_Issue3204(t *testing.T) { table := createInitTable() diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index f6d6c6af5c5..0205cd65b93 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -545,7 +545,7 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, affectedRows int64 ) sqlStr := fmt.Sprintf( - "%s INTO %s(%s) %s VALUES%s %s ", + "%s INTO %s(%s)%s VALUES%s %s ", operation, c.QuotePrefixTableName(table), keysStr, insertOutPutStr, gstr.Join(valueHolders, ","), From ee463d456d8f8947ecb94ce9f8083a031024b8f8 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Wed, 18 Dec 2024 16:59:15 +0800 Subject: [PATCH 32/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database/gdb/gdb_core.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index 0205cd65b93..b4f52517a23 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -449,7 +449,7 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, insertDefaultHandler = func(db DB, ctx context.Context, link Link, sql string, args ...interface{}) (sql.Result, error) { return db.DoExec(ctx, link, sql, args...) } - //deal special insert. for example: mssql + // deal special insert. for example: mssql if len(ext) > 0 { if fn, ok := ext[0].(InsertHandler); ok { insertDefaultHandler = fn From 5beb48c46b685da2493d1735d92626fc5a6eca79 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Thu, 19 Dec 2024 15:53:28 +0800 Subject: [PATCH 33/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20=E9=87=8D=E5=86=99Mssql=E7=9A=84DoExec?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BE=BE=E5=88=B0=E6=8F=92=E5=85=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=94=E5=9B=9E=E6=8F=92=E5=85=A5ID=E7=9A=84?= =?UTF-8?q?=E7=9B=AE=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clickhouse/clickhouse_do_insert.go | 3 +- contrib/drivers/dm/dm_do_insert.go | 2 +- contrib/drivers/mssql/mssql_do_exec.go | 196 ++++++++++++++++++ contrib/drivers/mssql/mssql_do_insert.go | 86 +------- .../drivers/mssql/mssql_z_unit_basic_test.go | 29 +++ contrib/drivers/oracle/oracle_do_insert.go | 2 +- contrib/drivers/pgsql/pgsql_do_insert.go | 5 +- database/gdb/gdb.go | 6 +- database/gdb/gdb_core.go | 35 +--- database/gdb/gdb_core_underlying.go | 8 +- database/gdb/gdb_driver_wrapper_db.go | 8 +- database/gdb/gdb_func.go | 4 +- 12 files changed, 255 insertions(+), 129 deletions(-) create mode 100644 contrib/drivers/mssql/mssql_do_exec.go diff --git a/contrib/drivers/clickhouse/clickhouse_do_insert.go b/contrib/drivers/clickhouse/clickhouse_do_insert.go index d6b63d2fca6..efa076305fb 100644 --- a/contrib/drivers/clickhouse/clickhouse_do_insert.go +++ b/contrib/drivers/clickhouse/clickhouse_do_insert.go @@ -17,7 +17,8 @@ import ( // DoInsert inserts or updates data for given table. func (d *Driver) DoInsert( - ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}) (result sql.Result, err error) { + ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, +) (result sql.Result, err error) { var ( keys []string // Field names. valueHolder = make([]string, 0) diff --git a/contrib/drivers/dm/dm_do_insert.go b/contrib/drivers/dm/dm_do_insert.go index 4606b433f05..de2b216a40f 100644 --- a/contrib/drivers/dm/dm_do_insert.go +++ b/contrib/drivers/dm/dm_do_insert.go @@ -21,7 +21,7 @@ import ( // DoInsert inserts or updates data for given table. func (d *Driver) DoInsert( - ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}, + ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionSave: diff --git a/contrib/drivers/mssql/mssql_do_exec.go b/contrib/drivers/mssql/mssql_do_exec.go new file mode 100644 index 00000000000..a1525a64bbe --- /dev/null +++ b/contrib/drivers/mssql/mssql_do_exec.go @@ -0,0 +1,196 @@ +package mssql + +import ( + "context" + "database/sql" + "fmt" + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + "regexp" + "strings" +) + +const ( + backIdInsertHeadDefault = "INSERT INTO" + backIdInsertHeadInsertIgnore = "INSERT IGNORE INTO" + + autoIncrementName = "auto_increment" + mssqlOutPutKey = "OUTPUT" + mssqlInsertedObjName = "INSERTED" + mssqlAffectFd = " 1 as AffectCount" + affectCountFieldName = "AffectCount" + mssqlPrimaryKeyName = "PRI" + fdId = "ID" + positionInsertValues = ") VALUES" // find the position of the string "VALUES" in the INSERT SQL statement to embed output code for retrieving the last inserted ID +) + +func (d *Driver) DoExec(ctx context.Context, link gdb.Link, sqlStr string, args ...interface{}) (result sql.Result, err error) { + // Transaction checks. + if link == nil { + if tx := gdb.TXFromCtx(ctx, d.GetGroup()); tx != nil { + // Firstly, check and retrieve transaction link from context. + link = &txLinkMssql{tx.GetSqlTX()} + } else if link, err = d.Core.MasterLink(); err != nil { + // Or else it creates one from master node. + return nil, err + } + } else if !link.IsTransaction() { + // If current link is not transaction link, it checks and retrieves transaction from context. + if tx := gdb.TXFromCtx(ctx, d.GetGroup()); tx != nil { + link = &txLinkMssql{tx.GetSqlTX()} + } + } + + // SQL filtering. + sqlStr, args = d.Core.FormatSqlBeforeExecuting(sqlStr, args) + sqlStr, args, err = d.DoFilter(ctx, link, sqlStr, args) + if err != nil { + return nil, err + } + // SQL format and retrieve. + if v := ctx.Value(gdb.CtxKeyCatchSQL); v != nil { + var ( + manager = v.(*gdb.CatchSQLManager) + formattedSql = gdb.FormatSqlWithArgs(sqlStr, args) + ) + manager.SQLArray.Append(formattedSql) + if !manager.DoCommit && ctx.Value(gdb.CtxKeyInternalProducedSQL) == nil { + return new(gdb.SqlResult), nil + } + } + + if !(strings.HasPrefix(sqlStr, backIdInsertHeadDefault) || strings.HasPrefix(sqlStr, backIdInsertHeadInsertIgnore)) { + return d.Core.DoExec(ctx, link, sqlStr, args) + } + //find the first pos + pos := strings.Index(sqlStr, positionInsertValues) + + table := d.GetTableNameFromSql(sqlStr) + outPutSql := d.GetInsertOutputSql(ctx, table) + //rebuild sql add output + sqlValueBefore := sqlStr[:pos+1] + sqlValueAfter := sqlStr[pos+1:] + sqlStr = fmt.Sprintf("%s%s%s", sqlValueBefore, outPutSql, sqlValueAfter) + + fmt.Println("sql str:", sqlStr) + // Link execution. + var out gdb.DoCommitOutput + out, err = d.DoCommit(ctx, gdb.DoCommitInput{ + Link: link, + Sql: sqlStr, + Args: args, + Stmt: nil, + Type: gdb.SqlTypeQueryContext, + IsTransaction: link.IsTransaction(), + }) + if err != nil { + return &InsertResult{lastInsertId: 0, rowsAffected: 0, err: err}, err + } + var ( + aCount int64 // affect count + lId int64 // last insert id + ) + stdSqlResult := out.Records + if len(stdSqlResult) == 0 { + err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) + return &InsertResult{lastInsertId: 0, rowsAffected: 0, err: err}, err + } + // get affect count + aCount = stdSqlResult[0].GMap().GetVar(affectCountFieldName).Int64() + // get last_insert_id + lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() + + return &InsertResult{lastInsertId: lId, rowsAffected: aCount}, err +} + +// GetTableNameFromSql get table name from sql statement +// It handles table string like: +// "user" +// "user u" +// "DbLog.dbo.user", +// "user as u". +func (d *Driver) GetTableNameFromSql(sqlStr string) (table string) { + // INSERT INTO "ip_to_id"("ip") OUTPUT 1 as AffectCount,INSERTED.id as ID VALUES(?) + leftChars, rightChars := d.GetChars() + trimStr := leftChars + rightChars + "[] " + pattern := "INTO(.+?)\\(" + regCompile := regexp.MustCompile(pattern) + tableInfo := regCompile.FindStringSubmatch(sqlStr) + //get the first one. after the first it may be content of the value, it's not table name. + table = tableInfo[1] + table = strings.Trim(table, " ") + if strings.Contains(table, ".") { + tmpAry := strings.Split(table, ".") + // the last one is tablename + table = tmpAry[len(tmpAry)-1] + } else if strings.Contains(table, "as") || strings.Contains(table, " ") { + tmpAry := strings.Split(table, "as") + if len(tmpAry) < 2 { + tmpAry = strings.Split(table, " ") + } + // get the first one + table = tmpAry[0] + } + table = strings.Trim(table, trimStr) + return table +} + +// txLink is used to implement interface Link for TX. +type txLinkMssql struct { + *sql.Tx +} + +// IsTransaction returns if current Link is a transaction. +func (l *txLinkMssql) IsTransaction() bool { + return true +} + +// IsOnMaster checks and returns whether current link is operated on master node. +// Note that, transaction operation is always operated on master node. +func (l *txLinkMssql) IsOnMaster() bool { + return true +} + +// InsertResult instance of sql.Result +type InsertResult struct { + lastInsertId int64 + rowsAffected int64 + err error +} + +func (r *InsertResult) LastInsertId() (int64, error) { + return r.lastInsertId, r.err +} + +func (r *InsertResult) RowsAffected() (int64, error) { + return r.rowsAffected, r.err +} + +// GetInsertOutputSql gen get last_insert_id code +func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { + fds, errFd := m.GetDB().TableFields(ctx, table) + if errFd != nil { + return "" + } + extraSqlAry := make([]string, 0) + extraSqlAry = append(extraSqlAry, fmt.Sprintf(" %s %s", mssqlOutPutKey, mssqlAffectFd)) + incrNo := 0 + if len(fds) > 0 { + for _, fd := range fds { + // has primary key and is auto-incement + if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { + incrNoStr := "" + if incrNo == 0 { // fixed first field named id, convenient to get + incrNoStr = fmt.Sprintf(" as %s", fdId) + } + + extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) + incrNo++ + } + // fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) + } + } + return strings.Join(extraSqlAry, ",") + // sql example:INSERT INTO "ip_to_id"("ip") OUTPUT 1 as AffectCount,INSERTED.id as ID VALUES(?) +} diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index c030e3cd108..d16c7ad55b8 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -19,18 +19,8 @@ import ( "github.com/gogf/gf/v2/text/gstr" ) -const ( - autoIncrementName = "auto_increment" - mssqlOutPutKey = "OUTPUT" - mssqlInsertedObjName = "INSERTED" - mssqlAffectFd = " 1 as AffectCount" - affectCountFieldName = "AffectCount" - mssqlPrimaryKeyName = "PRI" - fdId = "ID" -) - // DoInsert inserts or updates data for given table. rewrite db.core.DoInsert -func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}) (result sql.Result, err error) { +func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionSave: return d.doSave(ctx, link, table, list, option) @@ -41,80 +31,8 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list `Replace operation is not supported by mssql driver`, ) default: - outPutStr := d.GetInsertOutputSql(ctx, table) - var insertHandler gdb.InsertHandler - insertHandler = func(db gdb.DB, ctx context.Context, link gdb.Link, sqlStr string, args ...interface{}) (sql.Result, error) { - var ( - stdSqlResult gdb.Result - retResult interface{} - ) - stdSqlResult, err = db.DoQuery(ctx, link, sqlStr, args...) - if err != nil { - retResult = &InsertResult{lastInsertId: 0, rowsAffected: 0, err: err} - return retResult.(sql.Result), err - } - var ( - aCount int64 // affect count - lId int64 // last insert id - ) - if len(stdSqlResult) == 0 { - err = gerror.WrapCode(gcode.CodeDbOperationError, gerror.New("affectcount is zero"), `sql.Result.RowsAffected failed`) - retResult = &InsertResult{lastInsertId: 0, rowsAffected: 0, err: err} - return retResult.(sql.Result), err - } - // get affect count - aCount = stdSqlResult[0].GMap().GetVar(affectCountFieldName).Int64() - // get last_insert_id - lId = stdSqlResult[0].GMap().GetVar(fdId).Int64() - - retResult = &InsertResult{lastInsertId: lId, rowsAffected: aCount} - return retResult.(sql.Result), nil - } - return d.Core.DoInsert(ctx, link, table, list, option, insertHandler, outPutStr) - } -} - -// InsertResult instance of sql.Result -type InsertResult struct { - lastInsertId int64 - rowsAffected int64 - err error -} - -func (r *InsertResult) LastInsertId() (int64, error) { - return r.lastInsertId, r.err -} - -func (r *InsertResult) RowsAffected() (int64, error) { - return r.rowsAffected, r.err -} - -// GetInsertOutputSql gen get last_insert_id code -func (m *Driver) GetInsertOutputSql(ctx context.Context, table string) string { - fds, errFd := m.GetDB().TableFields(ctx, table) - if errFd != nil { - return "" - } - extraSqlAry := make([]string, 0) - extraSqlAry = append(extraSqlAry, fmt.Sprintf(" %s %s", mssqlOutPutKey, mssqlAffectFd)) - incrNo := 0 - if len(fds) > 0 { - for _, fd := range fds { - // has primary key and is auto-incement - if fd.Extra == autoIncrementName && fd.Key == mssqlPrimaryKeyName && !fd.Null { - incrNoStr := "" - if incrNo == 0 { // fixed first field named id, convenient to get - incrNoStr = fmt.Sprintf(" as %s", fdId) - } - - extraSqlAry = append(extraSqlAry, fmt.Sprintf("%s.%s%s", mssqlInsertedObjName, fd.Name, incrNoStr)) - incrNo++ - } - // fmt.Printf("null:%t name:%s key:%s k:%s \n", fd.Null, fd.Name, fd.Key, k) - } + return d.Core.DoInsert(ctx, link, table, list, option) } - return strings.Join(extraSqlAry, ",") - // sql example:INSERT INTO "ip_to_id"("ip") OUTPUT 1 as AffectCount,INSERTED.id as ID VALUES(?) } // doSave support upsert for SQL server diff --git a/contrib/drivers/mssql/mssql_z_unit_basic_test.go b/contrib/drivers/mssql/mssql_z_unit_basic_test.go index 14505d8eed8..a093b775bd8 100644 --- a/contrib/drivers/mssql/mssql_z_unit_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_basic_test.go @@ -10,6 +10,8 @@ import ( "context" "database/sql" "fmt" + "github.com/gogf/gf/contrib/drivers/mssql/v2" + "github.com/gogf/gf/v2/database/gdb" "testing" "time" @@ -164,6 +166,33 @@ func TestDoInsertGetId(t *testing.T) { }) } +func TestGetTableFromSql(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + okTable := "ip_to_id" + sqlStr := "INSERT INTO \"ip_to_id\"(\"ip\") VALUES(?)" + dbMssql, _ := db.GetCore().GetDB().(*gdb.DriverWrapperDB).DB.(*mssql.Driver) + //fmt.Println("db:", fmt.Sprintf("%T", dbMssql), " ok:", ok) + table := dbMssql.GetTableNameFromSql(sqlStr) + // fmt.Println("default table:", table) + t.Assert(table, okTable) + + sqlStr = "INSERT INTO \"MyLogDb\".\"dbo\".\"ip_to_id\"(\"ip\") VALUES(?)" + table = dbMssql.GetTableNameFromSql(sqlStr) + // fmt.Println("MyLogDb.dbo.ip_to_id table:", table) + t.Assert(table, okTable) + + sqlStr = "INSERT INTO \"ip_to_id\" as \"tt\" (\"ip\") VALUES(?)" + table = dbMssql.GetTableNameFromSql(sqlStr) + // fmt.Println("ip_to_id as tt table:", table) + t.Assert(table, okTable) + + sqlStr = "INSERT INTO \"ip_to_id\" \"tt\" (\"ip\") VALUES(?)" + table = dbMssql.GetTableNameFromSql(sqlStr) + // fmt.Println("ip_to_id tt table:", table) + t.Assert(table, okTable) + }) +} + func Test_DB_Ping(t *testing.T) { gtest.C(t, func(t *gtest.T) { err1 := db.PingMaster() diff --git a/contrib/drivers/oracle/oracle_do_insert.go b/contrib/drivers/oracle/oracle_do_insert.go index 2edae82e5f1..cf6a9b14bbb 100644 --- a/contrib/drivers/oracle/oracle_do_insert.go +++ b/contrib/drivers/oracle/oracle_do_insert.go @@ -22,7 +22,7 @@ import ( // DoInsert inserts or updates data for given table. func (d *Driver) DoInsert( - ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}, + ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionSave: diff --git a/contrib/drivers/pgsql/pgsql_do_insert.go b/contrib/drivers/pgsql/pgsql_do_insert.go index 4b3fd4a5bb3..fc8cf8a55f6 100644 --- a/contrib/drivers/pgsql/pgsql_do_insert.go +++ b/contrib/drivers/pgsql/pgsql_do_insert.go @@ -16,7 +16,8 @@ import ( ) // DoInsert inserts or updates data for given table. -func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, ext ...interface{}) (result sql.Result, err error) { +func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, +) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionReplace: return nil, gerror.NewCode( @@ -36,5 +37,5 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list } } } - return d.Core.DoInsert(ctx, link, table, list, option, ext) + return d.Core.DoInsert(ctx, link, table, list, option) } diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index cdcc4c80223..525e19752b2 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -133,7 +133,7 @@ type DB interface { // DoInsert performs the actual INSERT operation with given options. // This is an internal method that can be overridden by custom implementations. - DoInsert(ctx context.Context, link Link, table string, data List, option DoInsertOption, ext ...interface{}) (result sql.Result, err error) + DoInsert(ctx context.Context, link Link, table string, data List, option DoInsertOption) (result sql.Result, err error) // DoUpdate performs the actual UPDATE operation. // This is an internal method that can be overridden by custom implementations. @@ -705,8 +705,8 @@ const ( modelForDaoSuffix = `ForDao` dbRoleSlave = `slave` ctxKeyForDB gctx.StrKey = `CtxKeyForDB` - ctxKeyCatchSQL gctx.StrKey = `CtxKeyCatchSQL` - ctxKeyInternalProducedSQL gctx.StrKey = `CtxKeyInternalProducedSQL` + CtxKeyCatchSQL gctx.StrKey = `CtxKeyCatchSQL` // To facilitate the rewrite, it should be public + CtxKeyInternalProducedSQL gctx.StrKey = `CtxKeyInternalProducedSQL` // To facilitate the rewrite, it should be public linkPattern = `(\w+):([\w\-\$]*):(.*?)@(\w+?)\((.+?)\)/{0,1}([^\?]*)\?{0,1}(.*)` linkPatternDescription = `type:username:password@protocol(host:port)/dbname?param1=value1&...¶mN=valueN` diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index 63a778ed37a..e507d34390a 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -435,30 +435,13 @@ type InsertHandler func(db DB, ctx context.Context, link Link, sql string, args // InsertOptionReplace: if there's unique/primary key in the data, it deletes it from table and inserts a new one; // InsertOptionSave: if there's unique/primary key in the data, it updates it or else inserts a new one; // InsertOptionIgnore: if there's unique/primary key in the data, it ignores the inserting; -func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption, ext ...interface{}) (result sql.Result, err error) { +func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption) (result sql.Result, err error) { var ( - keys []string // Field names. - values []string // Value holder string array, like: (?,?,?) - params []interface{} // Values that will be committed to underlying database driver. - onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement. - insertDefaultHandler InsertHandler // drive to do insert data - insertOutPutStr string + keys []string // Field names. + values []string // Value holder string array, like: (?,?,?) + params []interface{} // Values that will be committed to underlying database driver. + onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement. ) - insertOutPutStr = "" - insertDefaultHandler = func(db DB, ctx context.Context, link Link, sql string, args ...interface{}) (sql.Result, error) { - return db.DoExec(ctx, link, sql, args...) - } - // deal special insert. for example: mssql - if len(ext) > 0 { - if fn, ok := ext[0].(InsertHandler); ok { - insertDefaultHandler = fn - } - if len(ext) > 1 { - if outStr, ok := ext[1].(string); ok { - insertOutPutStr = outStr - } - } - } // ============================================================================================ // Group the list by fields. Different fields to different list. // It here uses ListMap to keep sequence for data inserting. @@ -543,14 +526,12 @@ func (c *Core) DoInsert(ctx context.Context, link Link, table string, list List, stdSqlResult sql.Result affectedRows int64 ) - sqlStr := fmt.Sprintf( - "%s INTO %s(%s)%s VALUES%s %s ", + stdSqlResult, err = c.db.DoExec(ctx, link, fmt.Sprintf( + "%s INTO %s(%s) VALUES%s %s", operation, c.QuotePrefixTableName(table), keysStr, - insertOutPutStr, gstr.Join(valueHolders, ","), onDuplicateStr, - ) - stdSqlResult, err = insertDefaultHandler(c.db, ctx, link, sqlStr, params...) + ), params...) if err != nil { return stdSqlResult, err } diff --git a/database/gdb/gdb_core_underlying.go b/database/gdb/gdb_core_underlying.go index 045d11c65af..c54c9d840a1 100644 --- a/database/gdb/gdb_core_underlying.go +++ b/database/gdb/gdb_core_underlying.go @@ -58,13 +58,13 @@ func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...inter return nil, err } // SQL format and retrieve. - if v := ctx.Value(ctxKeyCatchSQL); v != nil { + if v := ctx.Value(CtxKeyCatchSQL); v != nil { var ( manager = v.(*CatchSQLManager) formattedSql = FormatSqlWithArgs(sql, args) ) manager.SQLArray.Append(formattedSql) - if !manager.DoCommit && ctx.Value(ctxKeyInternalProducedSQL) == nil { + if !manager.DoCommit && ctx.Value(CtxKeyInternalProducedSQL) == nil { return nil, nil } } @@ -116,13 +116,13 @@ func (c *Core) DoExec(ctx context.Context, link Link, sql string, args ...interf return nil, err } // SQL format and retrieve. - if v := ctx.Value(ctxKeyCatchSQL); v != nil { + if v := ctx.Value(CtxKeyCatchSQL); v != nil { var ( manager = v.(*CatchSQLManager) formattedSql = FormatSqlWithArgs(sql, args) ) manager.SQLArray.Append(formattedSql) - if !manager.DoCommit && ctx.Value(ctxKeyInternalProducedSQL) == nil { + if !manager.DoCommit && ctx.Value(CtxKeyInternalProducedSQL) == nil { return new(SqlResult), nil } } diff --git a/database/gdb/gdb_driver_wrapper_db.go b/database/gdb/gdb_driver_wrapper_db.go index 305af9c68a9..4ee0ba51e7a 100644 --- a/database/gdb/gdb_driver_wrapper_db.go +++ b/database/gdb/gdb_driver_wrapper_db.go @@ -39,7 +39,7 @@ func (d *DriverWrapperDB) Open(node *ConfigNode) (db *sql.DB, err error) { // Tables retrieves and returns the tables of current schema. // It's mainly used in cli tool chain for automatically generating the models. func (d *DriverWrapperDB) Tables(ctx context.Context, schema ...string) (tables []string, err error) { - ctx = context.WithValue(ctx, ctxKeyInternalProducedSQL, struct{}{}) + ctx = context.WithValue(ctx, CtxKeyInternalProducedSQL, struct{}{}) return d.DB.Tables(ctx, schema...) } @@ -79,7 +79,7 @@ func (d *DriverWrapperDB) TableFields( ) cacheFunc = func(ctx context.Context) (interface{}, error) { return d.DB.TableFields( - context.WithValue(ctx, ctxKeyInternalProducedSQL, struct{}{}), + context.WithValue(ctx, CtxKeyInternalProducedSQL, struct{}{}), table, schema..., ) } @@ -109,7 +109,7 @@ func (d *DriverWrapperDB) TableFields( // InsertOptionReplace: if there's unique/primary key in the data, it deletes it from table and inserts a new one; // InsertOptionSave: if there's unique/primary key in the data, it updates it or else inserts a new one; // InsertOptionIgnore: if there's unique/primary key in the data, it ignores the inserting; -func (d *DriverWrapperDB) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption, ext ...interface{}) (result sql.Result, err error) { +func (d *DriverWrapperDB) DoInsert(ctx context.Context, link Link, table string, list List, option DoInsertOption) (result sql.Result, err error) { // Convert data type before commit it to underlying db driver. for i, item := range list { list[i], err = d.GetCore().ConvertDataForRecord(ctx, item, table) @@ -117,5 +117,5 @@ func (d *DriverWrapperDB) DoInsert(ctx context.Context, link Link, table string, return nil, err } } - return d.DB.DoInsert(ctx, link, table, list, option, ext) + return d.DB.DoInsert(ctx, link, table, list, option) } diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index ba402e5c970..a095c3183ea 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -109,7 +109,7 @@ func ToSQL(ctx context.Context, f func(ctx context.Context) error) (sql string, SQLArray: garray.NewStrArray(), DoCommit: false, } - ctx = context.WithValue(ctx, ctxKeyCatchSQL, manager) + ctx = context.WithValue(ctx, CtxKeyCatchSQL, manager) err = f(ctx) sql, _ = manager.SQLArray.PopRight() return @@ -122,7 +122,7 @@ func CatchSQL(ctx context.Context, f func(ctx context.Context) error) (sqlArray SQLArray: garray.NewStrArray(), DoCommit: true, } - ctx = context.WithValue(ctx, ctxKeyCatchSQL, manager) + ctx = context.WithValue(ctx, CtxKeyCatchSQL, manager) err = f(ctx) return manager.SQLArray.Slice(), err } From bf4330721babf4c71750f3c0530d5124c5ba8eca Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Thu, 19 Dec 2024 15:54:25 +0800 Subject: [PATCH 34/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20=E9=87=8D=E5=86=99Mssql=E7=9A=84DoExec?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BE=BE=E5=88=B0=E6=8F=92=E5=85=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=94=E5=9B=9E=E6=8F=92=E5=85=A5ID=E7=9A=84?= =?UTF-8?q?=E7=9B=AE=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_exec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/drivers/mssql/mssql_do_exec.go b/contrib/drivers/mssql/mssql_do_exec.go index a1525a64bbe..73a02dc65fb 100644 --- a/contrib/drivers/mssql/mssql_do_exec.go +++ b/contrib/drivers/mssql/mssql_do_exec.go @@ -73,7 +73,7 @@ func (d *Driver) DoExec(ctx context.Context, link gdb.Link, sqlStr string, args sqlValueAfter := sqlStr[pos+1:] sqlStr = fmt.Sprintf("%s%s%s", sqlValueBefore, outPutSql, sqlValueAfter) - fmt.Println("sql str:", sqlStr) + // fmt.Println("sql str:", sqlStr) // Link execution. var out gdb.DoCommitOutput out, err = d.DoCommit(ctx, gdb.DoCommitInput{ From 405c531cb02f066f385262d30fdd8ec59d2831a0 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Thu, 19 Dec 2024 16:00:03 +0800 Subject: [PATCH 35/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20=E9=87=8D=E5=86=99Mssql=E7=9A=84DoExec?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BE=BE=E5=88=B0=E6=8F=92=E5=85=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=94=E5=9B=9E=E6=8F=92=E5=85=A5ID=E7=9A=84?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=20=E5=A2=9E=E5=8A=A0=E5=A4=9A=E6=9D=A1?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=8F=92=E5=85=A5=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_z_unit_basic_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contrib/drivers/mssql/mssql_z_unit_basic_test.go b/contrib/drivers/mssql/mssql_z_unit_basic_test.go index a093b775bd8..42ac67c3d2e 100644 --- a/contrib/drivers/mssql/mssql_z_unit_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_basic_test.go @@ -152,7 +152,7 @@ func TestDoInsert(t *testing.T) { } func TestDoInsertGetId(t *testing.T) { - //先创建表 + // 先创建表 createInsertAndGetIdTableForTest() gtest.C(t, func(t *gtest.T) { table := "ip_to_id" @@ -162,7 +162,13 @@ func TestDoInsertGetId(t *testing.T) { id, err := db.InsertAndGetId(gctx.New(), table, data) t.AssertNil(err) t.AssertGT(id, 0) - //fmt.Println("id:", id) + // fmt.Println("id:", id) + + // multiple insert test + dataAry := []map[string]interface{}{{"ip": "192.168.5.9"}, {"ip": "192.168.5.10"}} + id1, err1 := db.InsertAndGetId(gctx.New(), table, dataAry) + t.AssertNil(err1) + t.AssertGT(id1, 0) }) } From 7248bb5d03dc72f8a448ad442c6ca5692994375e Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Thu, 19 Dec 2024 16:22:19 +0800 Subject: [PATCH 36/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20=E9=87=8D=E5=86=99Mssql=E7=9A=84DoExec?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BE=BE=E5=88=B0=E6=8F=92=E5=85=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=94=E5=9B=9E=E6=8F=92=E5=85=A5ID=E7=9A=84?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=20=E5=A2=9E=E5=8A=A0=E5=A4=9A=E6=9D=A1?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=8F=92=E5=85=A5=E6=B5=8B=E8=AF=95=20?= =?UTF-8?q?=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 2 +- .../drivers/mysql/mysql_z_unit_init_test.go | 2 +- .../drivers/mysql/mysql_z_unit_issue_test.go | 36 ------------------- contrib/drivers/pgsql/pgsql_do_insert.go | 3 +- database/gdb/gdb_core.go | 3 -- 5 files changed, 3 insertions(+), 43 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index d16c7ad55b8..97f829e0724 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -19,7 +19,7 @@ import ( "github.com/gogf/gf/v2/text/gstr" ) -// DoInsert inserts or updates data for given table. rewrite db.core.DoInsert +// DoInsert inserts or updates data for given table. func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionSave: diff --git a/contrib/drivers/mysql/mysql_z_unit_init_test.go b/contrib/drivers/mysql/mysql_z_unit_init_test.go index 60c77399e29..3c0f2f76201 100644 --- a/contrib/drivers/mysql/mysql_z_unit_init_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_init_test.go @@ -27,7 +27,7 @@ const ( TestPartitionDB = "test3" TableNamePrefix1 = "gf_" TestDbUser = "root" - TestDbPass = "12345678" //12345678 123456 + TestDbPass = "12345678" CreateTime = "2018-10-24 10:00:00" ) diff --git a/contrib/drivers/mysql/mysql_z_unit_issue_test.go b/contrib/drivers/mysql/mysql_z_unit_issue_test.go index a8bc5344cf9..af4e43b29e1 100644 --- a/contrib/drivers/mysql/mysql_z_unit_issue_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_issue_test.go @@ -924,42 +924,6 @@ func Test_Issue3086(t *testing.T) { }) } -func Test_InsertedAndGetId(t *testing.T) { - table := createInitTable() - defer dropTable(table) - // data - gtest.C(t, func(t *gtest.T) { - type User struct { - g.Meta `orm:"do:true"` - Id interface{} `orm:"id,omitempty"` - Passport interface{} `orm:"passport,omitempty"` - Password interface{} `orm:"password,omitempty"` - Nickname interface{} `orm:"nickname,omitempty"` - CreateTime interface{} `orm:"create_time,omitempty"` - } - var ( - err error - sqlArray []string - insertId int64 - data = User{ - Id: 20, - Passport: "passport_20", - Password: "", - } - ) - sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error { - insertId, err = db.Ctx(ctx).Model(table).Data(data).InsertAndGetId() - return err - }) - t.AssertNil(err) - t.Assert(insertId, 20) - t.Assert( - gstr.Contains(sqlArray[len(sqlArray)-1], "(`id`,`passport`) VALUES(20,'passport_20')"), - true, - ) - }) -} - // https://github.com/gogf/gf/issues/3204 func Test_Issue3204(t *testing.T) { table := createInitTable() diff --git a/contrib/drivers/pgsql/pgsql_do_insert.go b/contrib/drivers/pgsql/pgsql_do_insert.go index fc8cf8a55f6..ec24edde302 100644 --- a/contrib/drivers/pgsql/pgsql_do_insert.go +++ b/contrib/drivers/pgsql/pgsql_do_insert.go @@ -16,8 +16,7 @@ import ( ) // DoInsert inserts or updates data for given table. -func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption, -) (result sql.Result, err error) { +func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) { switch option.InsertOption { case gdb.InsertOptionReplace: return nil, gerror.NewCode( diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index e507d34390a..50971611258 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -420,9 +420,6 @@ func (c *Core) fieldsToSequence(ctx context.Context, table string, fields []stri return fieldsResultInSequence, nil } -// InsertHandler special need for mssql insert and get id -type InsertHandler func(db DB, ctx context.Context, link Link, sql string, args ...interface{}) (sql.Result, error) - // DoInsert inserts or updates data for given table. // This function is usually used for custom interface definition, you do not need call it manually. // The parameter `data` can be type of map/gmap/struct/*struct/[]map/[]struct, etc. From 8cccf2d77094f2a76f99d0e643ef50e349af8967 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Fri, 20 Dec 2024 09:46:59 +0800 Subject: [PATCH 37/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20=E9=87=8D=E5=86=99Mssql=E7=9A=84DoExec?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BE=BE=E5=88=B0=E6=8F=92=E5=85=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=94=E5=9B=9E=E6=8F=92=E5=85=A5ID=E7=9A=84?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=20=E5=A2=9E=E5=8A=A0=E5=A4=9A=E6=9D=A1?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=8F=92=E5=85=A5=E6=B5=8B=E8=AF=95=20?= =?UTF-8?q?=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_exec.go | 27 +++++++------------ .../drivers/mssql/mssql_z_unit_basic_test.go | 5 ++-- database/gdb/gdb.go | 4 +-- database/gdb/gdb_core_underlying.go | 8 +++--- database/gdb/gdb_driver_wrapper_db.go | 4 +-- database/gdb/gdb_func.go | 4 +-- 6 files changed, 23 insertions(+), 29 deletions(-) diff --git a/contrib/drivers/mssql/mssql_do_exec.go b/contrib/drivers/mssql/mssql_do_exec.go index 73a02dc65fb..edce43318c7 100644 --- a/contrib/drivers/mssql/mssql_do_exec.go +++ b/contrib/drivers/mssql/mssql_do_exec.go @@ -4,11 +4,12 @@ import ( "context" "database/sql" "fmt" + "regexp" + "strings" + "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" - "regexp" - "strings" ) const ( @@ -48,29 +49,21 @@ func (d *Driver) DoExec(ctx context.Context, link gdb.Link, sqlStr string, args if err != nil { return nil, err } - // SQL format and retrieve. - if v := ctx.Value(gdb.CtxKeyCatchSQL); v != nil { - var ( - manager = v.(*gdb.CatchSQLManager) - formattedSql = gdb.FormatSqlWithArgs(sqlStr, args) - ) - manager.SQLArray.Append(formattedSql) - if !manager.DoCommit && ctx.Value(gdb.CtxKeyInternalProducedSQL) == nil { - return new(gdb.SqlResult), nil - } - } if !(strings.HasPrefix(sqlStr, backIdInsertHeadDefault) || strings.HasPrefix(sqlStr, backIdInsertHeadInsertIgnore)) { return d.Core.DoExec(ctx, link, sqlStr, args) } - //find the first pos + // find the first pos pos := strings.Index(sqlStr, positionInsertValues) table := d.GetTableNameFromSql(sqlStr) outPutSql := d.GetInsertOutputSql(ctx, table) - //rebuild sql add output - sqlValueBefore := sqlStr[:pos+1] - sqlValueAfter := sqlStr[pos+1:] + // rebuild sql add output + var ( + sqlValueBefore = sqlStr[:pos+1] + sqlValueAfter = sqlStr[pos+1:] + ) + sqlStr = fmt.Sprintf("%s%s%s", sqlValueBefore, outPutSql, sqlValueAfter) // fmt.Println("sql str:", sqlStr) diff --git a/contrib/drivers/mssql/mssql_z_unit_basic_test.go b/contrib/drivers/mssql/mssql_z_unit_basic_test.go index 42ac67c3d2e..63dc2f0c013 100644 --- a/contrib/drivers/mssql/mssql_z_unit_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_basic_test.go @@ -10,17 +10,18 @@ import ( "context" "database/sql" "fmt" - "github.com/gogf/gf/contrib/drivers/mssql/v2" - "github.com/gogf/gf/v2/database/gdb" "testing" "time" + "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/encoding/gxml" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/test/gtest" + + "github.com/gogf/gf/contrib/drivers/mssql/v2" ) func TestTables(t *testing.T) { diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index 525e19752b2..dd4143f4843 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -705,8 +705,8 @@ const ( modelForDaoSuffix = `ForDao` dbRoleSlave = `slave` ctxKeyForDB gctx.StrKey = `CtxKeyForDB` - CtxKeyCatchSQL gctx.StrKey = `CtxKeyCatchSQL` // To facilitate the rewrite, it should be public - CtxKeyInternalProducedSQL gctx.StrKey = `CtxKeyInternalProducedSQL` // To facilitate the rewrite, it should be public + ctxKeyCatchSQL gctx.StrKey = `ctxKeyCatchSQL` + ctxKeyInternalProducedSQL gctx.StrKey = `ctxKeyInternalProducedSQL` linkPattern = `(\w+):([\w\-\$]*):(.*?)@(\w+?)\((.+?)\)/{0,1}([^\?]*)\?{0,1}(.*)` linkPatternDescription = `type:username:password@protocol(host:port)/dbname?param1=value1&...¶mN=valueN` diff --git a/database/gdb/gdb_core_underlying.go b/database/gdb/gdb_core_underlying.go index c54c9d840a1..045d11c65af 100644 --- a/database/gdb/gdb_core_underlying.go +++ b/database/gdb/gdb_core_underlying.go @@ -58,13 +58,13 @@ func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...inter return nil, err } // SQL format and retrieve. - if v := ctx.Value(CtxKeyCatchSQL); v != nil { + if v := ctx.Value(ctxKeyCatchSQL); v != nil { var ( manager = v.(*CatchSQLManager) formattedSql = FormatSqlWithArgs(sql, args) ) manager.SQLArray.Append(formattedSql) - if !manager.DoCommit && ctx.Value(CtxKeyInternalProducedSQL) == nil { + if !manager.DoCommit && ctx.Value(ctxKeyInternalProducedSQL) == nil { return nil, nil } } @@ -116,13 +116,13 @@ func (c *Core) DoExec(ctx context.Context, link Link, sql string, args ...interf return nil, err } // SQL format and retrieve. - if v := ctx.Value(CtxKeyCatchSQL); v != nil { + if v := ctx.Value(ctxKeyCatchSQL); v != nil { var ( manager = v.(*CatchSQLManager) formattedSql = FormatSqlWithArgs(sql, args) ) manager.SQLArray.Append(formattedSql) - if !manager.DoCommit && ctx.Value(CtxKeyInternalProducedSQL) == nil { + if !manager.DoCommit && ctx.Value(ctxKeyInternalProducedSQL) == nil { return new(SqlResult), nil } } diff --git a/database/gdb/gdb_driver_wrapper_db.go b/database/gdb/gdb_driver_wrapper_db.go index 4ee0ba51e7a..4a6670627d7 100644 --- a/database/gdb/gdb_driver_wrapper_db.go +++ b/database/gdb/gdb_driver_wrapper_db.go @@ -39,7 +39,7 @@ func (d *DriverWrapperDB) Open(node *ConfigNode) (db *sql.DB, err error) { // Tables retrieves and returns the tables of current schema. // It's mainly used in cli tool chain for automatically generating the models. func (d *DriverWrapperDB) Tables(ctx context.Context, schema ...string) (tables []string, err error) { - ctx = context.WithValue(ctx, CtxKeyInternalProducedSQL, struct{}{}) + ctx = context.WithValue(ctx, ctxKeyInternalProducedSQL, struct{}{}) return d.DB.Tables(ctx, schema...) } @@ -79,7 +79,7 @@ func (d *DriverWrapperDB) TableFields( ) cacheFunc = func(ctx context.Context) (interface{}, error) { return d.DB.TableFields( - context.WithValue(ctx, CtxKeyInternalProducedSQL, struct{}{}), + context.WithValue(ctx, ctxKeyInternalProducedSQL, struct{}{}), table, schema..., ) } diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index a095c3183ea..ba402e5c970 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -109,7 +109,7 @@ func ToSQL(ctx context.Context, f func(ctx context.Context) error) (sql string, SQLArray: garray.NewStrArray(), DoCommit: false, } - ctx = context.WithValue(ctx, CtxKeyCatchSQL, manager) + ctx = context.WithValue(ctx, ctxKeyCatchSQL, manager) err = f(ctx) sql, _ = manager.SQLArray.PopRight() return @@ -122,7 +122,7 @@ func CatchSQL(ctx context.Context, f func(ctx context.Context) error) (sqlArray SQLArray: garray.NewStrArray(), DoCommit: true, } - ctx = context.WithValue(ctx, CtxKeyCatchSQL, manager) + ctx = context.WithValue(ctx, ctxKeyCatchSQL, manager) err = f(ctx) return manager.SQLArray.Slice(), err } From 282c169c5848e4020dffd84e7ee614d6fced6286 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Fri, 20 Dec 2024 09:53:47 +0800 Subject: [PATCH 38/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20=E9=87=8D=E5=86=99Mssql=E7=9A=84DoExec?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BE=BE=E5=88=B0=E6=8F=92=E5=85=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=94=E5=9B=9E=E6=8F=92=E5=85=A5ID=E7=9A=84?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=20=E5=A2=9E=E5=8A=A0=E5=A4=9A=E6=9D=A1?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=8F=92=E5=85=A5=E6=B5=8B=E8=AF=95=20?= =?UTF-8?q?=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_insert.go | 1 + contrib/drivers/mssql/mssql_z_unit_basic_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/drivers/mssql/mssql_do_insert.go b/contrib/drivers/mssql/mssql_do_insert.go index 97f829e0724..7b71dab42f1 100644 --- a/contrib/drivers/mssql/mssql_do_insert.go +++ b/contrib/drivers/mssql/mssql_do_insert.go @@ -30,6 +30,7 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gcode.CodeNotSupported, `Replace operation is not supported by mssql driver`, ) + default: return d.Core.DoInsert(ctx, link, table, list, option) } diff --git a/contrib/drivers/mssql/mssql_z_unit_basic_test.go b/contrib/drivers/mssql/mssql_z_unit_basic_test.go index 63dc2f0c013..0e92c709f9e 100644 --- a/contrib/drivers/mssql/mssql_z_unit_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_basic_test.go @@ -153,7 +153,7 @@ func TestDoInsert(t *testing.T) { } func TestDoInsertGetId(t *testing.T) { - // 先创建表 + // create test table createInsertAndGetIdTableForTest() gtest.C(t, func(t *gtest.T) { table := "ip_to_id" From 81645220bd760f5df5b102f1dd72d7a52f34991c Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Fri, 20 Dec 2024 09:55:13 +0800 Subject: [PATCH 39/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20=E9=87=8D=E5=86=99Mssql=E7=9A=84DoExec?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BE=BE=E5=88=B0=E6=8F=92=E5=85=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=94=E5=9B=9E=E6=8F=92=E5=85=A5ID=E7=9A=84?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=20=E5=A2=9E=E5=8A=A0=E5=A4=9A=E6=9D=A1?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=8F=92=E5=85=A5=E6=B5=8B=E8=AF=95=20?= =?UTF-8?q?=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database/gdb/gdb.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index dd4143f4843..de3cdf3d369 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -705,8 +705,8 @@ const ( modelForDaoSuffix = `ForDao` dbRoleSlave = `slave` ctxKeyForDB gctx.StrKey = `CtxKeyForDB` - ctxKeyCatchSQL gctx.StrKey = `ctxKeyCatchSQL` - ctxKeyInternalProducedSQL gctx.StrKey = `ctxKeyInternalProducedSQL` + ctxKeyCatchSQL gctx.StrKey = `CtxKeyCatchSQL` + ctxKeyInternalProducedSQL gctx.StrKey = `CtxKeyInternalProducedSQL` linkPattern = `(\w+):([\w\-\$]*):(.*?)@(\w+?)\((.+?)\)/{0,1}([^\?]*)\?{0,1}(.*)` linkPatternDescription = `type:username:password@protocol(host:port)/dbname?param1=value1&...¶mN=valueN` From 4536b678d64ac7d1576abe6b03af2baaa99ee2e7 Mon Sep 17 00:00:00 2001 From: lxy1151 <316543569@qq.com> Date: Fri, 20 Dec 2024 09:57:36 +0800 Subject: [PATCH 40/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmssql=E7=9A=84InsertAnd?= =?UTF-8?q?GetId=E6=96=B9=E6=B3=95=20=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20=E6=92=A4=E9=94=80=E4=BF=AE=E6=94=B9=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=98=8E=E6=98=8E=E9=81=BF=E5=BC=80=E5=8C=85=E5=90=8D=E5=BC=80?= =?UTF-8?q?=E5=A4=B4=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6DoInsert=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=8F=E5=B0=91=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20=E9=87=8D=E5=86=99Mssql=E7=9A=84DoExec?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BE=BE=E5=88=B0=E6=8F=92=E5=85=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BF=94=E5=9B=9E=E6=8F=92=E5=85=A5ID=E7=9A=84?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=20=E5=A2=9E=E5=8A=A0=E5=A4=9A=E6=9D=A1?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=8F=92=E5=85=A5=E6=B5=8B=E8=AF=95=20?= =?UTF-8?q?=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20=E5=8E=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/drivers/mssql/mssql_do_exec.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/drivers/mssql/mssql_do_exec.go b/contrib/drivers/mssql/mssql_do_exec.go index edce43318c7..c0eb915623a 100644 --- a/contrib/drivers/mssql/mssql_do_exec.go +++ b/contrib/drivers/mssql/mssql_do_exec.go @@ -26,6 +26,8 @@ const ( positionInsertValues = ") VALUES" // find the position of the string "VALUES" in the INSERT SQL statement to embed output code for retrieving the last inserted ID ) +// DoExec commits the sql string and its arguments to underlying driver +// through given link object and returns the execution result. func (d *Driver) DoExec(ctx context.Context, link gdb.Link, sqlStr string, args ...interface{}) (result sql.Result, err error) { // Transaction checks. if link == nil {