diff --git a/Makefile b/Makefile index 12b9ce55f29..9d0ee13e91a 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,20 @@ SHELL := /bin/bash +# execute "go mod tidy" on all folders that have go.mod file .PHONY: tidy tidy: $(eval files=$(shell find . -name go.mod)) @set -e; \ for file in ${files}; do \ goModPath=$$(dirname $$file); \ - cd $$goModPath; \ - go mod tidy; \ - cd -; \ + if ! echo $$goModPath | grep -q "testdata"; then \ + cd $$goModPath; \ + go mod tidy; \ + cd -; \ + fi \ done +# execute "golangci-lint" to check code style .PHONY: lint lint: golangci-lint run -c .golangci.yml @@ -22,5 +26,3 @@ version: newVersion=$(to); \ ./.set_version.sh ./ $$newVersion; \ echo "make version to=$(to) done" - - diff --git a/cmd/gf/go.mod b/cmd/gf/go.mod index 48efa73eee5..b85ac264e11 100644 --- a/cmd/gf/go.mod +++ b/cmd/gf/go.mod @@ -23,7 +23,7 @@ require ( github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.17.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -35,10 +35,10 @@ require ( github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/magiconair/properties v1.8.7 // indirect + github.com/magiconair/properties v1.8.9 // 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.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/microsoft/go-mssqldb v1.7.1 // indirect github.com/paulmach/orb v0.7.1 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect @@ -50,11 +50,11 @@ require ( go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/sdk v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/crypto v0.30.0 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.22.5 // indirect modernc.org/mathutil v1.5.0 // indirect diff --git a/cmd/gf/go.sum b/cmd/gf/go.sum index e66bcfaa11f..1451be4ef79 100644 --- a/cmd/gf/go.sum +++ b/cmd/gf/go.sum @@ -22,8 +22,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 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.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= @@ -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.8.2 h1:4g5n8QdJA7ZEuDfWFeVQKMhul6RtOT89ObYAgVnxN+U= +github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.8.2/go.mod h1:xW1mgNK0vTLfRSCnO0No8G4lCGNpXx1Jlhs6B1vzD+8= +github.com/gogf/gf/contrib/drivers/mssql/v2 v2.8.2 h1:aNscErx5mcC28Q1L0MsZFFXybzLY/IJhskyiPAbxB78= +github.com/gogf/gf/contrib/drivers/mssql/v2 v2.8.2/go.mod h1:yj6+Ds2BGzYcHthPvMnxhDRzq0o28HyO9E1Fsko0Lf8= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.2 h1:thK4DZT0irDrnhIxkap5JqBuBIJaXQ0IMvlIzuRGgVQ= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.2/go.mod h1:Vg7XaiwsQ27YmpDqzwCQ+yt10KntTvcP9iOoFL5DF40= +github.com/gogf/gf/contrib/drivers/oracle/v2 v2.8.2 h1:ZukTXB9drVDmSdrFjCYHVzHj0kAvGKISrrW3WKU1xTg= +github.com/gogf/gf/contrib/drivers/oracle/v2 v2.8.2/go.mod h1:wr+KA5h3+aJQk5XiA1qSNKxWBVrzlu8MVYKl1NqcQj4= +github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.2 h1:BsEBGoVfa4SPJ8GhNkH9PPtoSLydXK+VgcbpxyGF9Ps= +github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.2/go.mod h1:OSlAQeO7fZMbscxZomMCBcZWHSxpfeXIi6ELeKszSPU= +github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.8.2 h1:144IdPDn6xyHVQ5aP4qsstFvNOLqvWyz+GtH3JD1rWg= +github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.8.2/go.mod h1:xOgOp3SSdWHIEqviYC1kd3p6mJtfFkrcinBWdpgVUxc= +github.com/gogf/gf/v2 v2.8.2 h1:4k641rn+hV1COAKygqsqcTm8+lDTkcO8HQ4iBv/uTFs= +github.com/gogf/gf/v2 v2.8.2/go.mod h1:n++xPYGUUMadw6IygLEgGZqc6y6DRLrJKg5kqCrPLWY= 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= @@ -68,16 +82,16 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/microsoft/go-mssqldb v1.7.1 h1:KU/g8aWeM3Hx7IMOFpiwYiUkU+9zeISb4+tx3ScVfsM= github.com/microsoft/go-mssqldb v1.7.1/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= @@ -131,8 +145,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= @@ -141,13 +155,13 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -159,13 +173,13 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= diff --git a/contrib/drivers/mysql/mysql_z_unit_init_test.go b/contrib/drivers/mysql/mysql_z_unit_init_test.go index f0621741c7b..3c0f2f76201 100644 --- a/contrib/drivers/mysql/mysql_z_unit_init_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_init_test.go @@ -44,18 +44,22 @@ 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), + TranTimeout: time.Second * 3, } partitionDefault := gdb.ConfigNode{ - Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3307)/?loc=Local&parseTime=true", TestDbPass), - Debug: true, + Link: fmt.Sprintf("mysql:root:%s@tcp(127.0.0.1:3307)/?loc=Local&parseTime=true", TestDbPass), + Debug: true, + TranTimeout: time.Second * 3, } 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), + TranTimeout: time.Second * 3, } 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), + TranTimeout: time.Second * 3, } 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..af4e43b29e1 100644 --- a/contrib/drivers/mysql/mysql_z_unit_issue_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_issue_test.go @@ -1556,3 +1556,37 @@ func Test_Issue2119(t *testing.T) { } }) } + +// https://github.com/gogf/gf/issues/4034 +func Test_Issue4034(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + table := "issue4034" + array := gstr.SplitAndTrim(gtest.DataContent(`issue4034.sql`), ";") + for _, v := range array { + _, err := db.Exec(ctx, v) + t.AssertNil(err) + } + defer dropTable(table) + + err := issue4034SaveDeviceAndToken(ctx, table) + t.AssertNil(err) + }) +} + +func issue4034SaveDeviceAndToken(ctx context.Context, table string) error { + return db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { + if err := issue4034SaveAppDevice(ctx, table, tx); err != nil { + return err + } + return nil + }) +} + +func issue4034SaveAppDevice(ctx context.Context, table string, tx gdb.TX) error { + _, err := db.Model(table).Safe().Ctx(ctx).TX(tx).Data(g.Map{ + "passport": "111", + "password": "222", + "nickname": "333", + }).Save() + return err +} diff --git a/contrib/drivers/mysql/testdata/issue4034.sql b/contrib/drivers/mysql/testdata/issue4034.sql new file mode 100644 index 00000000000..abb99cedc22 --- /dev/null +++ b/contrib/drivers/mysql/testdata/issue4034.sql @@ -0,0 +1,8 @@ +CREATE TABLE issue4034 ( + id INT PRIMARY KEY AUTO_INCREMENT, + passport VARCHAR(255), + password VARCHAR(255), + nickname VARCHAR(255), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/contrib/drivers/pgsql/pgsql_do_exec.go b/contrib/drivers/pgsql/pgsql_do_exec.go index ca3f3a86e3b..a44721752b0 100644 --- a/contrib/drivers/pgsql/pgsql_do_exec.go +++ b/contrib/drivers/pgsql/pgsql_do_exec.go @@ -64,12 +64,6 @@ func (d *Driver) DoExec(ctx context.Context, link gdb.Link, sql string, args ... // Only the insert operation with primary key can execute the following code - if d.GetConfig().ExecTimeout > 0 { - var cancelFunc context.CancelFunc - ctx, cancelFunc = context.WithTimeout(ctx, d.GetConfig().ExecTimeout) - defer cancelFunc() - } - // Sql filtering. sql, args = d.FormatSqlBeforeExecuting(sql, args) sql, args, err = d.DoFilter(ctx, link, sql, args) diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index da52e75267c..de3cdf3d369 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -528,24 +528,53 @@ type dynamicConfig struct { // DoCommitInput is the input parameters for function DoCommit. type DoCommitInput struct { - Db *sql.DB - Tx *sql.Tx - Stmt *sql.Stmt - Link Link - Sql string - Args []interface{} - Type SqlType - TxOptions sql.TxOptions + // Db is the underlying database connection object. + Db *sql.DB + + // Tx is the underlying transaction object. + Tx *sql.Tx + + // Stmt is the prepared statement object. + Stmt *sql.Stmt + + // Link is the common database function wrapper interface. + Link Link + + // Sql is the SQL string to be executed. + Sql string + + // Args is the arguments for SQL placeholders. + Args []interface{} + + // Type indicates the type of SQL operation. + Type SqlType + + // TxOptions specifies the transaction options. + TxOptions sql.TxOptions + + // TxCancelFunc is the context cancel function for transaction. + TxCancelFunc context.CancelFunc + + // IsTransaction indicates whether current operation is in transaction. IsTransaction bool } // DoCommitOutput is the output parameters for function DoCommit. type DoCommitOutput struct { - Result sql.Result // Result is the result of exec statement. - Records []Record // Records is the result of query statement. - Stmt *Stmt // Stmt is the Statement object result for Prepare. - Tx TX // Tx is the transaction object result for Begin. - RawResult interface{} // RawResult is the underlying result, which might be sql.Result/*sql.Rows/*sql.Row. + // Result is the result of exec statement. + Result sql.Result + + // Records is the result of query statement. + Records []Record + + // Stmt is the Statement object result for Prepare. + Stmt *Stmt + + // Tx is the transaction object result for Begin. + Tx TX + + // RawResult is the underlying result, which might be sql.Result/*sql.Rows/*sql.Row. + RawResult interface{} } // Driver is the interface for integrating sql drivers into package gdb. @@ -581,43 +610,84 @@ type Sql struct { // DoInsertOption is the input struct for function DoInsert. type DoInsertOption struct { - OnDuplicateStr string // Custom string for `on duplicated` statement. - OnDuplicateMap map[string]interface{} // Custom key-value map from `OnDuplicateEx` function for `on duplicated` statement. - OnConflict []string // Custom conflict key of upsert clause, if the database needs it. - InsertOption InsertOption // Insert operation in constant value. - BatchCount int // Batch count for batch inserting. + // OnDuplicateStr is the custom string for `on duplicated` statement. + OnDuplicateStr string + + // OnDuplicateMap is the custom key-value map from `OnDuplicateEx` function for `on duplicated` statement. + OnDuplicateMap map[string]interface{} + + // OnConflict is the custom conflict key of upsert clause, if the database needs it. + OnConflict []string + + // InsertOption is the insert operation in constant value. + InsertOption InsertOption + + // BatchCount is the batch count for batch inserting. + BatchCount int } // TableField is the struct for table field. type TableField struct { - Index int // For ordering purpose as map is unordered. - Name string // Field name. - Type string // Field type. Eg: 'int(10) unsigned', 'varchar(64)'. - Null bool // Field can be null or not. - Key string // The index information(empty if it's not an index). Eg: PRI, MUL. - Default interface{} // Default value for the field. - Extra string // Extra information. Eg: auto_increment. - Comment string // Field comment. + // Index is for ordering purpose as map is unordered. + Index int + + // Name is the field name. + Name string + + // Type is the field type. Eg: 'int(10) unsigned', 'varchar(64)'. + Type string + + // Null is whether the field can be null or not. + Null bool + + // Key is the index information(empty if it's not an index). Eg: PRI, MUL. + Key string + + // Default is the default value for the field. + Default interface{} + + // Extra is the extra information. Eg: auto_increment. + Extra string + + // Comment is the field comment. + Comment string } -// Counter is the type for update count. +// Counter is the type for update count. type Counter struct { + // Field is the field name. Field string + + // Value is the value. Value float64 } type ( - Raw string // Raw is a raw sql that will not be treated as argument but as a direct sql part. - Value = *gvar.Var // Value is the field value type. - Record map[string]Value // Record is the row record of the table. - Result []Record // Result is the row record array. - Map = map[string]interface{} // Map is alias of map[string]interface{}, which is the most common usage map type. - List = []Map // List is type of map array. + // Raw is a raw sql that will not be treated as argument but as a direct sql part. + Raw string + + // Value is the field value type. + Value = *gvar.Var + + // Record is the row record of the table. + Record map[string]Value + + // Result is the row record array. + Result []Record + + // Map is alias of map[string]interface{}, which is the most common usage map type. + Map = map[string]interface{} + + // List is type of map array. + List = []Map ) type CatchSQLManager struct { + // SQLArray is the array of sql. SQLArray *garray.StrArray - DoCommit bool // DoCommit marks it will be committed to underlying driver or not. + + // DoCommit marks it will be committed to underlying driver or not. + DoCommit bool } const ( diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index f75ff878f37..50971611258 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -92,7 +92,6 @@ func (c *Core) GetCtxTimeout(ctx context.Context, timeoutType ctxTimeoutType) (c if c.db.GetConfig().PrepareTimeout > 0 { return context.WithTimeout(ctx, config.PrepareTimeout) } - case ctxTimeoutTypeTrans: if c.db.GetConfig().TranTimeout > 0 { return context.WithTimeout(ctx, config.TranTimeout) diff --git a/database/gdb/gdb_core_config.go b/database/gdb/gdb_core_config.go index 291ade99544..3a15024b42c 100644 --- a/database/gdb/gdb_core_config.go +++ b/database/gdb/gdb_core_config.go @@ -27,36 +27,126 @@ type ConfigGroup []ConfigNode // ConfigNode is configuration for one node. type ConfigNode struct { - Host string `json:"host"` // Host of server, ip or domain like: 127.0.0.1, localhost - Port string `json:"port"` // Port, it's commonly 3306. - User string `json:"user"` // Authentication username. - Pass string `json:"pass"` // Authentication password. - Name string `json:"name"` // Default used database name. - Type string `json:"type"` // Database type: mysql, mariadb, sqlite, mssql, pgsql, oracle, clickhouse, dm. - Link string `json:"link"` // (Optional) Custom link information for all configuration in one single string. - Extra string `json:"extra"` // (Optional) Extra configuration according the registered third-party database driver. - Role string `json:"role"` // (Optional, "master" in default) Node role, used for master-slave mode: master, slave. - Debug bool `json:"debug"` // (Optional) Debug mode enables debug information logging and output. - Prefix string `json:"prefix"` // (Optional) Table prefix. - DryRun bool `json:"dryRun"` // (Optional) Dry run, which does SELECT but no INSERT/UPDATE/DELETE statements. - Weight int `json:"weight"` // (Optional) Weight for load balance calculating, it's useless if there's just one node. - Charset string `json:"charset"` // (Optional, "utf8" in default) Custom charset when operating on database. - Protocol string `json:"protocol"` // (Optional, "tcp" in default) See net.Dial for more information which networks are available. - Timezone string `json:"timezone"` // (Optional) Sets the time zone for displaying and interpreting time stamps. - Namespace string `json:"namespace"` // (Optional) Namespace for some databases. Eg, in pgsql, the `Name` acts as the `catalog`, the `NameSpace` acts as the `schema`. - MaxIdleConnCount int `json:"maxIdle"` // (Optional) Max idle connection configuration for underlying connection pool. - MaxOpenConnCount int `json:"maxOpen"` // (Optional) Max open connection configuration for underlying connection pool. - MaxConnLifeTime time.Duration `json:"maxLifeTime"` // (Optional) Max amount of time a connection may be idle before being closed. - QueryTimeout time.Duration `json:"queryTimeout"` // (Optional) Max query time for per dql. - ExecTimeout time.Duration `json:"execTimeout"` // (Optional) Max exec time for dml. - TranTimeout time.Duration `json:"tranTimeout"` // (Optional) Max exec time for a transaction. - PrepareTimeout time.Duration `json:"prepareTimeout"` // (Optional) Max exec time for prepare operation. - CreatedAt string `json:"createdAt"` // (Optional) The field name of table for automatic-filled created datetime. - UpdatedAt string `json:"updatedAt"` // (Optional) The field name of table for automatic-filled updated datetime. - DeletedAt string `json:"deletedAt"` // (Optional) The field name of table for automatic-filled updated datetime. - TimeMaintainDisabled bool `json:"timeMaintainDisabled"` // (Optional) Disable the automatic time maintaining feature. + // Host specifies the server address, can be either IP address or domain name + // Example: "127.0.0.1", "localhost" + Host string `json:"host"` + + // Port specifies the server port number + // Default is typically "3306" for MySQL + Port string `json:"port"` + + // User specifies the authentication username for database connection + User string `json:"user"` + + // Pass specifies the authentication password for database connection + Pass string `json:"pass"` + + // Name specifies the default database name to be used + Name string `json:"name"` + + // Type specifies the database type + // Example: mysql, mariadb, sqlite, mssql, pgsql, oracle, clickhouse, dm. + Type string `json:"type"` + + // Link provides custom connection string that combines all configuration in one string + // Optional field + Link string `json:"link"` + + // Extra provides additional configuration options for third-party database drivers + // Optional field + Extra string `json:"extra"` + + // Role specifies the node role in master-slave setup + // Optional field, defaults to "master" + // Available values: "master", "slave" + Role Role `json:"role"` + + // Debug enables debug mode for logging and output + // Optional field + Debug bool `json:"debug"` + + // Prefix specifies the table name prefix + // Optional field + Prefix string `json:"prefix"` + + // DryRun enables simulation mode where SELECT statements are executed + // but INSERT/UPDATE/DELETE statements are not + // Optional field + DryRun bool `json:"dryRun"` + + // Weight specifies the node weight for load balancing calculations + // Optional field, only effective in multi-node setups + Weight int `json:"weight"` + + // Charset specifies the character set for database operations + // Optional field, defaults to "utf8" + Charset string `json:"charset"` + + // Protocol specifies the network protocol for database connection + // Optional field, defaults to "tcp" + // See net.Dial for available network protocols + Protocol string `json:"protocol"` + + // Timezone sets the time zone for timestamp interpretation and display + // Optional field + Timezone string `json:"timezone"` + + // Namespace specifies the schema namespace for certain databases + // Optional field, e.g., in PostgreSQL, Name is the catalog and Namespace is the schema + Namespace string `json:"namespace"` + + // MaxIdleConnCount specifies the maximum number of idle connections in the pool + // Optional field + MaxIdleConnCount int `json:"maxIdle"` + + // MaxOpenConnCount specifies the maximum number of open connections in the pool + // Optional field + MaxOpenConnCount int `json:"maxOpen"` + + // MaxConnLifeTime specifies the maximum lifetime of a connection + // Optional field + MaxConnLifeTime time.Duration `json:"maxLifeTime"` + + // QueryTimeout specifies the maximum execution time for DQL operations + // Optional field + QueryTimeout time.Duration `json:"queryTimeout"` + + // ExecTimeout specifies the maximum execution time for DML operations + // Optional field + ExecTimeout time.Duration `json:"execTimeout"` + + // TranTimeout specifies the maximum execution time for a transaction block + // Optional field + TranTimeout time.Duration `json:"tranTimeout"` + + // PrepareTimeout specifies the maximum execution time for prepare operations + // Optional field + PrepareTimeout time.Duration `json:"prepareTimeout"` + + // CreatedAt specifies the field name for automatic timestamp on record creation + // Optional field + CreatedAt string `json:"createdAt"` + + // UpdatedAt specifies the field name for automatic timestamp on record updates + // Optional field + UpdatedAt string `json:"updatedAt"` + + // DeletedAt specifies the field name for automatic timestamp on record deletion + // Optional field + DeletedAt string `json:"deletedAt"` + + // TimeMaintainDisabled controls whether automatic time maintenance is disabled + // Optional field + TimeMaintainDisabled bool `json:"timeMaintainDisabled"` } +type Role string + +const ( + RoleMaster Role = "master" + RoleSlave Role = "slave" +) + const ( DefaultGroupName = "default" // Default group name. ) diff --git a/database/gdb/gdb_core_txcore.go b/database/gdb/gdb_core_txcore.go index 187ea27cdd9..79154068f13 100644 --- a/database/gdb/gdb_core_txcore.go +++ b/database/gdb/gdb_core_txcore.go @@ -20,13 +20,30 @@ import ( // TXCore is the struct for transaction management. type TXCore struct { - db DB // db is the current gdb database manager. - tx *sql.Tx // tx is the raw and underlying transaction manager. - ctx context.Context // ctx is the context for this transaction only. - master *sql.DB // master is the raw and underlying database manager. - transactionId string // transactionId is a unique id generated by this object for this transaction. - transactionCount int // transactionCount marks the times that Begins. - isClosed bool // isClosed marks this transaction has already been committed or rolled back. + // db is the database management interface that implements the DB interface, + // providing access to database operations and configuration. + db DB + // tx is the underlying SQL transaction object from database/sql package, + // which manages the actual transaction operations. + tx *sql.Tx + // ctx is the context specific to this transaction, + // which can be used for timeout control and cancellation. + ctx context.Context + // master is the underlying master database connection pool, + // used for direct database operations when needed. + master *sql.DB + // transactionId is a unique identifier for this transaction instance, + // used for tracking and debugging purposes. + transactionId string + // transactionCount tracks the number of nested transaction begins, + // used for managing transaction nesting depth. + transactionCount int + // isClosed indicates whether this transaction has been finalized + // through either a commit or rollback operation. + isClosed bool + // cancelFunc is the context cancellation function associated with ctx, + // used to cancel the transaction context when needed. + cancelFunc context.CancelFunc } // transactionKeyForNestedPoint forms and returns the transaction key at current save point. @@ -73,6 +90,7 @@ func (tx *TXCore) Commit() error { Tx: tx.tx, Sql: "COMMIT", Type: SqlTypeTXCommit, + TxCancelFunc: tx.cancelFunc, IsTransaction: true, }) if err == nil { @@ -94,6 +112,7 @@ func (tx *TXCore) Rollback() error { Tx: tx.tx, Sql: "ROLLBACK", Type: SqlTypeTXRollback, + TxCancelFunc: tx.cancelFunc, IsTransaction: true, }) if err == nil { diff --git a/database/gdb/gdb_core_underlying.go b/database/gdb/gdb_core_underlying.go index d8c1171ca58..045d11c65af 100644 --- a/database/gdb/gdb_core_underlying.go +++ b/database/gdb/gdb_core_underlying.go @@ -51,12 +51,6 @@ func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...inter } } - if c.db.GetConfig().QueryTimeout > 0 { - var cancelFunc context.CancelFunc - ctx, cancelFunc = context.WithTimeout(ctx, c.db.GetConfig().QueryTimeout) - defer cancelFunc() - } - // Sql filtering. sql, args = c.FormatSqlBeforeExecuting(sql, args) sql, args, err = c.db.DoFilter(ctx, link, sql, args) @@ -115,12 +109,6 @@ func (c *Core) DoExec(ctx context.Context, link Link, sql string, args ...interf } } - if c.db.GetConfig().ExecTimeout > 0 { - var cancelFunc context.CancelFunc - ctx, cancelFunc = context.WithTimeout(ctx, c.db.GetConfig().ExecTimeout) - defer cancelFunc() - } - // SQL filtering. sql, args = c.FormatSqlBeforeExecuting(sql, args) sql, args, err = c.db.DoFilter(ctx, link, sql, args) @@ -183,11 +171,10 @@ func (c *Core) DoCommit(ctx context.Context, in DoCommitInput) (out DoCommitOutp ctx, span := tr.Start(ctx, string(in.Type), trace.WithSpanKind(trace.SpanKindInternal)) defer span.End() - // Execution cased by type. + // Execution by type. switch in.Type { case SqlTypeBegin: ctx, cancelFuncForTimeout = c.GetCtxTimeout(ctx, ctxTimeoutTypeTrans) - defer cancelFuncForTimeout() formattedSql = fmt.Sprintf( `%s (IosolationLevel: %s, ReadOnly: %t)`, formattedSql, in.TxOptions.Isolation.String(), in.TxOptions.ReadOnly, @@ -199,15 +186,22 @@ func (c *Core) DoCommit(ctx context.Context, in DoCommitInput) (out DoCommitOutp ctx: context.WithValue(ctx, transactionIdForLoggerCtx, transactionIdGenerator.Add(1)), master: in.Db, transactionId: guid.S(), + cancelFunc: cancelFuncForTimeout, } ctx = out.Tx.GetCtx() } out.RawResult = sqlTx case SqlTypeTXCommit: + if in.TxCancelFunc != nil { + defer in.TxCancelFunc() + } err = in.Tx.Commit() case SqlTypeTXRollback: + if in.TxCancelFunc != nil { + defer in.TxCancelFunc() + } err = in.Tx.Rollback() case SqlTypeExecContext: diff --git a/net/gudp/gudp_z_unit_test.go b/net/gudp/gudp_z_unit_test.go index 505d59e115a..55404a976da 100644 --- a/net/gudp/gudp_z_unit_test.go +++ b/net/gudp/gudp_z_unit_test.go @@ -99,14 +99,6 @@ func Test_Basic(t *testing.T) { t.AssertNil(err) } }) - // gudp.SendRecv - gtest.C(t, func(t *gtest.T) { - for i := 0; i < 100; i++ { - result, err := gudp.SendRecv(s.GetListenedAddress(), []byte(gconv.String(i)), -1) - t.AssertNil(err) - t.Assert(string(result), fmt.Sprintf(`> %d`, i)) - } - }) } // If the read buffer size is less than the sent package size,