diff --git a/cmd/gf/go.mod b/cmd/gf/go.mod index a46f187466f..1f091cf678e 100644 --- a/cmd/gf/go.mod +++ b/cmd/gf/go.mod @@ -9,6 +9,10 @@ require ( github.com/gogf/gf/contrib/drivers/oracle/v2 v2.9.6 github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.9.6 github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.9.6 + github.com/gogf/gf/contrib/drivers/tidb/v2 v2.9.6 + github.com/gogf/gf/contrib/drivers/oceanbase/v2 v2.9.6 + github.com/gogf/gf/contrib/drivers/gaussdb/v2 v2.9.6 + github.com/gogf/gf/contrib/drivers/mariadb/v2 v2.9.6 github.com/gogf/gf/v2 v2.9.6 github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f github.com/olekukonko/tablewriter v1.1.0 diff --git a/cmd/gf/go.work b/cmd/gf/go.work index edf43a26c5f..f5326281dfe 100644 --- a/cmd/gf/go.work +++ b/cmd/gf/go.work @@ -14,5 +14,9 @@ replace ( github.com/gogf/gf/contrib/drivers/oracle/v2 => ../../contrib/drivers/oracle github.com/gogf/gf/contrib/drivers/pgsql/v2 => ../../contrib/drivers/pgsql github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite + github.com/gogf/gf/contrib/drivers/mariadb/v2 => ../../contrib/drivers/mariadb + github.com/gogf/gf/contrib/drivers/tidb/v2 => ../../contrib/drivers/tidb + github.com/gogf/gf/contrib/drivers/oceanbase/v2 => ../../contrib/drivers/oceanbase + github.com/gogf/gf/contrib/drivers/gaussdb/v2 => ../../contrib/drivers/gaussdb github.com/gogf/gf/v2 => ../../ ) diff --git a/contrib/drivers/README.MD b/contrib/drivers/README.MD index 1adc943c0a7..29827f019e9 100644 --- a/contrib/drivers/README.MD +++ b/contrib/drivers/README.MD @@ -9,14 +9,19 @@ Let's take `mysql` for example. ```shell go get github.com/gogf/gf/contrib/drivers/mysql/v2@latest + # Easy for copying: go get github.com/gogf/gf/contrib/drivers/clickhouse/v2@latest go get github.com/gogf/gf/contrib/drivers/dm/v2@latest +go get github.com/gogf/gf/contrib/drivers/gaussdb/v2@latest +go get github.com/gogf/gf/contrib/drivers/mariadb/v2@latest go get github.com/gogf/gf/contrib/drivers/mssql/v2@latest +go get github.com/gogf/gf/contrib/drivers/oceanbase/v2@latest go get github.com/gogf/gf/contrib/drivers/oracle/v2@latest go get github.com/gogf/gf/contrib/drivers/pgsql/v2@latest go get github.com/gogf/gf/contrib/drivers/sqlite/v2@latest go get github.com/gogf/gf/contrib/drivers/sqlitecgo/v2@latest +go get github.com/gogf/gf/contrib/drivers/tidb/v2@latest ``` Choose and import the driver to your project: @@ -43,12 +48,36 @@ func main() { ## Supported Drivers -### MySQL/MariaDB/TiDB/OceanBase +### MySQL ```go import _ "github.com/gogf/gf/contrib/drivers/mysql/v2" ``` +### MariaDB + +```go +import _ "github.com/gogf/gf/contrib/drivers/mariadb/v2" +``` + +### TiDB + +```go +import _ "github.com/gogf/gf/contrib/drivers/tidb/v2" +``` + +### OceanBase + +```go +import _ "github.com/gogf/gf/contrib/drivers/oceanbase/v2" +``` + +### GaussDB + +```go +import _ "github.com/gogf/gf/contrib/drivers/gaussdb/v2" +``` + ### SQLite ```go diff --git a/contrib/drivers/gaussdb/gaussdb.go b/contrib/drivers/gaussdb/gaussdb.go new file mode 100644 index 00000000000..d5de50f75cd --- /dev/null +++ b/contrib/drivers/gaussdb/gaussdb.go @@ -0,0 +1,48 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// Package gaussdb implements gdb.Driver, which supports operations for database GaussDB. +package gaussdb + +import ( + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + + "github.com/gogf/gf/contrib/drivers/mysql/v2" +) + +// Driver is the driver for GaussDB database. +// +// GaussDB is an enterprise-level distributed database developed by Huawei. GaussDB for MySQL is a cloud-native +// database that is fully compatible with MySQL protocol. +// +// Although GaussDB is compatible with MySQL protocol, it is packaged as a separate driver component +// rather than reusing the mysql adapter directly. This design allows for future extensibility, +// such as implementing GaussDB-specific features or optimizations for cloud-native scenarios. +type Driver struct { + *mysql.Driver +} + +func init() { + var ( + err error + driverObj = New() + driverNames = g.SliceStr{"gaussdb"} + ) + for _, driverName := range driverNames { + if err = gdb.Register(driverName, driverObj); err != nil { + panic(err) + } + } +} + +// New creates and returns a driver that implements gdb.Driver, which supports operations for GaussDB. +func New() gdb.Driver { + mysqlDriver := mysql.New().(*mysql.Driver) + return &Driver{ + Driver: mysqlDriver, + } +} diff --git a/contrib/drivers/gaussdb/go.mod b/contrib/drivers/gaussdb/go.mod new file mode 100644 index 00000000000..6895f9e0351 --- /dev/null +++ b/contrib/drivers/gaussdb/go.mod @@ -0,0 +1,44 @@ +module github.com/gogf/gf/contrib/drivers/gaussdb/v2 + +go 1.23.0 + +require ( + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.6 + github.com/gogf/gf/v2 v2.9.6 +) + +require ( + github.com/BurntSushi/toml v1.5.0 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect + github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grokify/html-strip-tags-go v0.1.0 // indirect + github.com/magiconair/properties v1.8.10 // 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.16 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.0.9 // indirect + github.com/olekukonko/tablewriter v1.1.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.25.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace ( + github.com/gogf/gf/contrib/drivers/mysql/v2 => ../mysql + github.com/gogf/gf/v2 => ../../../ +) diff --git a/contrib/drivers/gaussdb/go.sum b/contrib/drivers/gaussdb/go.sum new file mode 100644 index 00000000000..f96db96f24f --- /dev/null +++ b/contrib/drivers/gaussdb/go.sum @@ -0,0 +1,81 @@ +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU= +github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A= +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.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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/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/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= +github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= +github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= +github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY= +github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +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.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/contrib/drivers/mariadb/go.mod b/contrib/drivers/mariadb/go.mod new file mode 100644 index 00000000000..1628e405e0a --- /dev/null +++ b/contrib/drivers/mariadb/go.mod @@ -0,0 +1,44 @@ +module github.com/gogf/gf/contrib/drivers/mariadb/v2 + +go 1.23.0 + +require ( + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.6 + github.com/gogf/gf/v2 v2.9.6 +) + +require ( + github.com/BurntSushi/toml v1.5.0 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect + github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grokify/html-strip-tags-go v0.1.0 // indirect + github.com/magiconair/properties v1.8.10 // 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.16 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.0.9 // indirect + github.com/olekukonko/tablewriter v1.1.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.25.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace ( + github.com/gogf/gf/contrib/drivers/mysql/v2 => ../mysql + github.com/gogf/gf/v2 => ../../../ +) diff --git a/contrib/drivers/mariadb/go.sum b/contrib/drivers/mariadb/go.sum new file mode 100644 index 00000000000..f96db96f24f --- /dev/null +++ b/contrib/drivers/mariadb/go.sum @@ -0,0 +1,81 @@ +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU= +github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A= +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.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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/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/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= +github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= +github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= +github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY= +github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +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.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/contrib/drivers/mariadb/mariadb.go b/contrib/drivers/mariadb/mariadb.go new file mode 100644 index 00000000000..666dfef0694 --- /dev/null +++ b/contrib/drivers/mariadb/mariadb.go @@ -0,0 +1,49 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// Package mariadb implements gdb.Driver, which supports operations for database MariaDB. +package mariadb + +import ( + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + + "github.com/gogf/gf/contrib/drivers/mysql/v2" +) + +// Driver is the driver for MariaDB database. +// +// MariaDB is a community-developed, commercially supported fork of the MySQL relational database. +// This driver uses the MySQL protocol to communicate with MariaDB database, as MariaDB maintains +// high compatibility with MySQL protocol. +// +// Although MariaDB is compatible with MySQL protocol, it is packaged as a separate driver component +// rather than reusing the mysql adapter directly. This design allows for future extensibility, +// such as implementing MariaDB-specific features or optimizations. +type Driver struct { + *mysql.Driver +} + +func init() { + var ( + err error + driverObj = New() + driverNames = g.SliceStr{"mariadb"} + ) + for _, driverName := range driverNames { + if err = gdb.Register(driverName, driverObj); err != nil { + panic(err) + } + } +} + +// New creates and returns a driver that implements gdb.Driver, which supports operations for MariaDB. +func New() gdb.Driver { + mysqlDriver := mysql.New().(*mysql.Driver) + return &Driver{ + Driver: mysqlDriver, + } +} diff --git a/contrib/drivers/mariadb/mariadb_table_fields.go b/contrib/drivers/mariadb/mariadb_table_fields.go new file mode 100644 index 00000000000..ebd0ba9835f --- /dev/null +++ b/contrib/drivers/mariadb/mariadb_table_fields.go @@ -0,0 +1,82 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mariadb + +import ( + "context" + "fmt" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/util/gutil" +) + +var ( + tableFieldsSqlByMariadb = ` +SELECT + c.COLUMN_NAME AS 'Field', + ( CASE WHEN ch.CHECK_CLAUSE LIKE 'json_valid%%' THEN 'json' ELSE c.COLUMN_TYPE END ) AS 'Type', + c.COLLATION_NAME AS 'Collation', + c.IS_NULLABLE AS 'Null', + c.COLUMN_KEY AS 'Key', + ( CASE WHEN c.COLUMN_DEFAULT = 'NULL' OR c.COLUMN_DEFAULT IS NULL THEN NULL ELSE c.COLUMN_DEFAULT END) AS 'Default', + c.EXTRA AS 'Extra', + c.PRIVILEGES AS 'Privileges', + c.COLUMN_COMMENT AS 'Comment' +FROM + information_schema.COLUMNS AS c + LEFT JOIN information_schema.CHECK_CONSTRAINTS AS ch ON c.TABLE_NAME = ch.TABLE_NAME + AND c.COLUMN_NAME = ch.CONSTRAINT_NAME +WHERE + c.TABLE_SCHEMA = '%s' + AND c.TABLE_NAME = '%s' + ORDER BY c.ORDINAL_POSITION` +) + +func init() { + var err error + tableFieldsSqlByMariadb, err = gdb.FormatMultiLineSqlToSingle(tableFieldsSqlByMariadb) + if err != nil { + panic(err) + } +} + +// TableFields retrieves and returns the fields' information of specified table of current +// schema. +func (d *Driver) TableFields( + ctx context.Context, table string, schema ...string, +) (fields map[string]*gdb.TableField, err error) { + var ( + result gdb.Result + link gdb.Link + usedSchema = gutil.GetOrDefaultStr(d.GetSchema(), schema...) + ) + if link, err = d.SlaveLink(usedSchema); err != nil { + return nil, err + } + + result, err = d.DoSelect( + ctx, link, + fmt.Sprintf(tableFieldsSqlByMariadb, usedSchema, table), + ) + if err != nil { + return nil, err + } + fields = make(map[string]*gdb.TableField) + for i, m := range result { + fields[m["Field"].String()] = &gdb.TableField{ + Index: i, + Name: m["Field"].String(), + Type: m["Type"].String(), + Null: m["Null"].Bool(), + Key: m["Key"].String(), + Default: m["Default"].Val(), + Extra: m["Extra"].String(), + Comment: m["Comment"].String(), + } + } + return fields, nil +} diff --git a/contrib/drivers/mariadb/mariadb_unit_init_test.go b/contrib/drivers/mariadb/mariadb_unit_init_test.go new file mode 100644 index 00000000000..54c7ae499bb --- /dev/null +++ b/contrib/drivers/mariadb/mariadb_unit_init_test.go @@ -0,0 +1,126 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mariadb_test + +import ( + "context" + "fmt" + "time" + + _ "github.com/gogf/gf/contrib/drivers/mariadb/v2" + + "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/test/gtest" +) + +const ( + TableSize = 10 + TableName = "user" + TestSchema1 = "test1" + TestSchema2 = "test2" + TestDbPass = "12345678" + CreateTime = "2018-10-24 10:00:00" +) + +var ( + db gdb.DB + ctx = context.TODO() +) + +func init() { + nodeDefault := gdb.ConfigNode{ + ExecTimeout: time.Second * 2, + Link: fmt.Sprintf("mariadb:root:%s@tcp(127.0.0.1:3307)/?loc=Local&parseTime=true", TestDbPass), + TranTimeout: time.Second * 3, + } + err := gdb.AddConfigNode(gdb.DefaultGroupName, nodeDefault) + if err != nil { + panic(err) + } + + // Default db. + if r, err := gdb.NewByGroup(); err != nil { + gtest.Error(err) + } else { + db = r + } + schemaTemplate := "CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET UTF8" + if _, err := db.Exec(ctx, fmt.Sprintf(schemaTemplate, TestSchema1)); err != nil { + gtest.Error(err) + } + if _, err := db.Exec(ctx, fmt.Sprintf(schemaTemplate, TestSchema2)); err != nil { + gtest.Error(err) + } + db = db.Schema(TestSchema1) +} + +func createTable(table ...string) string { + return createTableWithDb(db, table...) +} + +func createInitTable(table ...string) string { + return createInitTableWithDb(db, table...) +} + +func dropTable(table string) { + dropTableWithDb(db, table) +} + +func createTableWithDb(db gdb.DB, table ...string) (name string) { + if len(table) > 0 { + name = table[0] + } else { + name = fmt.Sprintf(`%s_%d`, TableName, gtime.TimestampNano()) + } + dropTableWithDb(db, name) + if _, err := db.Exec(ctx, fmt.Sprintf(` + CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + passport varchar(45) NULL, + password char(32) NULL, + nickname varchar(45) NULL, + create_time timestamp(6) NULL, + create_date date NULL, + PRIMARY KEY (id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, name, + )); err != nil { + gtest.Fatal(err) + } + return name +} + +func createInitTableWithDb(db gdb.DB, table ...string) (name string) { + name = createTableWithDb(db, table...) + array := garray.New(true) + for i := 1; i <= TableSize; i++ { + array.Append(g.Map{ + "id": i, + "passport": fmt.Sprintf(`user_%d`, i), + "password": fmt.Sprintf(`pass_%d`, i), + "nickname": fmt.Sprintf(`name_%d`, i), + "create_time": gtime.NewFromStr(CreateTime).String(), + }) + } + + result, err := db.Insert(ctx, name, array.Slice()) + gtest.AssertNil(err) + + n, e := result.RowsAffected() + gtest.Assert(e, nil) + gtest.Assert(n, TableSize) + return +} + +func dropTableWithDb(db gdb.DB, table string) { + if _, err := db.Exec(ctx, fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)); err != nil { + gtest.Error(err) + } +} diff --git a/contrib/drivers/mariadb/mariadb_unit_model_test.go b/contrib/drivers/mariadb/mariadb_unit_model_test.go new file mode 100644 index 00000000000..262661bfec9 --- /dev/null +++ b/contrib/drivers/mariadb/mariadb_unit_model_test.go @@ -0,0 +1,1421 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mariadb_test + +import ( + "database/sql" + "fmt" + "testing" + "time" + + "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/guid" +) + +func Test_Model_Insert(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + user := db.Model(table) + result, err := user.Data(g.Map{ + "id": 1, + "uid": 1, + "passport": "t1", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_1", + "create_time": gtime.Now().String(), + }).Insert() + t.AssertNil(err) + n, _ := result.LastInsertId() + t.Assert(n, 1) + + result, err = db.Model(table).Data(g.Map{ + "id": "2", + "uid": "2", + "passport": "t2", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_2", + "create_time": gtime.Now().String(), + }).Insert() + t.AssertNil(err) + n, _ = result.RowsAffected() + t.Assert(n, 1) + + type User struct { + Id int `gconv:"id"` + Uid int `gconv:"uid"` + Passport string `json:"passport"` + Password string `gconv:"password"` + Nickname string `gconv:"nickname"` + CreateTime *gtime.Time `json:"create_time"` + } + // Model inserting. + result, err = db.Model(table).Data(User{ + Id: 3, + Uid: 3, + Passport: "t3", + Password: "25d55ad283aa400af464c76d713c07ad", + Nickname: "name_3", + }).Insert() + t.AssertNil(err) + n, _ = result.RowsAffected() + t.Assert(n, 1) + value, err := db.Model(table).Fields("passport").Where("id=3").Value() + t.AssertNil(err) + t.Assert(value.String(), "t3") + + result, err = db.Model(table).Data(&User{ + Id: 4, + Uid: 4, + Passport: "t4", + Password: "25d55ad283aa400af464c76d713c07ad", + Nickname: "T4", + CreateTime: gtime.Now(), + }).Insert() + t.AssertNil(err) + n, _ = result.RowsAffected() + t.Assert(n, 1) + value, err = db.Model(table).Fields("passport").Where("id=4").Value() + t.AssertNil(err) + t.Assert(value.String(), "t4") + + result, err = db.Model(table).Where("id>?", 1).Delete() + t.AssertNil(err) + n, _ = result.RowsAffected() + t.Assert(n, 3) + }) +} + +func Test_Model_InsertIgnore(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + _, err := db.Model(table).Data(g.Map{ + "id": 1, + "uid": 1, + "passport": "t1", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_1", + "create_time": gtime.Now().String(), + }).Insert() + t.AssertNE(err, nil) + }) + gtest.C(t, func(t *gtest.T) { + _, err := db.Model(table).Data(g.Map{ + "id": 1, + "uid": 1, + "passport": "t1", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_1", + "create_time": gtime.Now().String(), + }).InsertIgnore() + t.AssertNil(err) + }) +} + +func Test_Model_Batch(t *testing.T) { + // batch insert + gtest.C(t, func(t *gtest.T) { + table := createTable() + defer dropTable(table) + result, err := db.Model(table).Data(g.List{ + { + "id": 2, + "uid": 2, + "passport": "t2", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_2", + "create_time": gtime.Now().String(), + }, + { + "id": 3, + "uid": 3, + "passport": "t3", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_3", + "create_time": gtime.Now().String(), + }, + }).Batch(1).Insert() + if err != nil { + gtest.Error(err) + } + n, _ := result.RowsAffected() + t.Assert(n, 2) + }) + + // batch insert, retrieving last insert auto-increment id. + gtest.C(t, func(t *gtest.T) { + table := createTable() + defer dropTable(table) + result, err := db.Model(table).Data(g.List{ + {"passport": "t1"}, + {"passport": "t2"}, + {"passport": "t3"}, + {"passport": "t4"}, + {"passport": "t5"}, + }).Batch(2).Insert() + if err != nil { + gtest.Error(err) + } + n, _ := result.RowsAffected() + t.Assert(n, 5) + }) + + // batch save + gtest.C(t, func(t *gtest.T) { + table := createInitTable() + defer dropTable(table) + result, err := db.Model(table).All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + for _, v := range result { + v["nickname"].Set(v["nickname"].String() + v["id"].String()) + } + r, e := db.Model(table).Data(result).Save() + t.Assert(e, nil) + n, e := r.RowsAffected() + t.Assert(e, nil) + t.Assert(n, TableSize*2) + }) + + // batch replace + gtest.C(t, func(t *gtest.T) { + table := createInitTable() + defer dropTable(table) + result, err := db.Model(table).All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + for _, v := range result { + v["nickname"].Set(v["nickname"].String() + v["id"].String()) + } + r, e := db.Model(table).Data(result).Replace() + t.Assert(e, nil) + n, e := r.RowsAffected() + t.Assert(e, nil) + t.Assert(n, TableSize*2) + }) +} + +func Test_Model_Replace(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Data(g.Map{ + "id": 1, + "passport": "t11", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "T11", + "create_time": "2018-10-24 10:00:00", + }).Replace() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + }) +} + +func Test_Model_Save(t *testing.T) { + table := createTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Data(g.Map{ + "id": 1, + "passport": "t111", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "T111", + "create_time": "2018-10-24 10:00:00", + }).Save() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + }) +} + +func Test_Model_Update(t *testing.T) { + table := createInitTable() + defer dropTable(table) + // UPDATE...LIMIT + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Data("nickname", "T100").Where(1).Order("id desc").Limit(2).Update() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 2) + + v1, err := db.Model(table).Fields("nickname").Where("id", 10).Value() + t.AssertNil(err) + t.Assert(v1.String(), "T100") + + v2, err := db.Model(table).Fields("nickname").Where("id", 8).Value() + t.AssertNil(err) + t.Assert(v2.String(), "name_8") + }) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Data("passport", "user_22").Where("passport=?", "user_2").Update() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + }) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Data("passport", "user_2").Where("passport='user_22'").Update() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + }) + + // Update + Data(string) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Data("passport='user_33'").Where("passport='user_3'").Update() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + }) + // Update + Fields(string) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Fields("passport").Data(g.Map{ + "passport": "user_44", + "none": "none", + }).Where("passport='user_4'").Update() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + }) +} + +func Test_Model_Clone(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + md := db.Model(table).Safe(true).Where("id IN(?)", g.Slice{1, 3}) + count, err := md.Count() + t.AssertNil(err) + + record, err := md.Safe(true).Order("id DESC").One() + t.AssertNil(err) + + result, err := md.Safe(true).Order("id ASC").All() + t.AssertNil(err) + + t.Assert(count, int64(2)) + t.Assert(record["id"].Int(), 3) + t.Assert(len(result), 2) + t.Assert(result[0]["id"].Int(), 1) + t.Assert(result[1]["id"].Int(), 3) + }) +} + +func Test_Model_Safe(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + md := db.Model(table).Safe(false).Where("id IN(?)", g.Slice{1, 3}) + count, err := md.Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + + md.Where("id = ?", 1) + count, err = md.Count() + t.AssertNil(err) + t.Assert(count, int64(1)) + }) + gtest.C(t, func(t *gtest.T) { + md := db.Model(table).Safe(true).Where("id IN(?)", g.Slice{1, 3}) + count, err := md.Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + + md.Where("id = ?", 1) + count, err = md.Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + }) + + gtest.C(t, func(t *gtest.T) { + md := db.Model(table).Safe().Where("id IN(?)", g.Slice{1, 3}) + count, err := md.Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + + md.Where("id = ?", 1) + count, err = md.Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + }) + gtest.C(t, func(t *gtest.T) { + md1 := db.Model(table).Safe() + md2 := md1.Where("id in (?)", g.Slice{1, 3}) + count, err := md2.Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + + all, err := md2.All() + t.AssertNil(err) + t.Assert(len(all), 2) + + all, err = md2.Page(1, 10).All() + t.AssertNil(err) + t.Assert(len(all), 2) + }) + + gtest.C(t, func(t *gtest.T) { + table := createInitTable() + defer dropTable(table) + + md1 := db.Model(table).Where("id>", 0).Safe() + md2 := md1.Where("id in (?)", g.Slice{1, 3}) + md3 := md1.Where("id in (?)", g.Slice{4, 5, 6}) + + // 1,3 + count, err := md2.Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + + all, err := md2.Order("id asc").All() + t.AssertNil(err) + t.Assert(len(all), 2) + t.Assert(all[0]["id"].Int(), 1) + t.Assert(all[1]["id"].Int(), 3) + + all, err = md2.Page(1, 10).All() + t.AssertNil(err) + t.Assert(len(all), 2) + + // 4,5,6 + count, err = md3.Count() + t.AssertNil(err) + t.Assert(count, int64(3)) + + all, err = md3.Order("id asc").All() + t.AssertNil(err) + t.Assert(len(all), 3) + t.Assert(all[0]["id"].Int(), 4) + t.Assert(all[1]["id"].Int(), 5) + t.Assert(all[2]["id"].Int(), 6) + + all, err = md3.Page(1, 10).All() + t.AssertNil(err) + t.Assert(len(all), 3) + }) +} + +func Test_Model_All(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + }) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Where("id<0").All() + t.Assert(result, nil) + t.AssertNil(err) + }) +} + +func Test_Model_Fields(t *testing.T) { + tableName1 := createInitTable() + defer dropTable(tableName1) + + tableName2 := "user_" + gtime.Now().TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` + CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NULL, + age int(10) unsigned, + PRIMARY KEY (id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableName2, + )); err != nil { + gtest.AssertNil(err) + } + defer dropTable(tableName2) + + r, err := db.Insert(ctx, tableName2, g.Map{ + "id": 1, + "name": "table2_1", + "age": 18, + }) + gtest.AssertNil(err) + n, _ := r.RowsAffected() + gtest.Assert(n, 1) + + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(tableName1).As("u").Fields("u.passport,u.id").Where("u.id<2").All() + t.AssertNil(err) + t.Assert(len(all), 1) + t.Assert(len(all[0]), 2) + }) + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(tableName1).As("u1"). + LeftJoin(tableName1, "u2", "u2.id=u1.id"). + Fields("u1.passport,u1.id,u2.id AS u2id"). + Where("u1.id<2"). + All() + t.AssertNil(err) + t.Assert(len(all), 1) + t.Assert(len(all[0]), 3) + }) + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(tableName1).As("u1"). + LeftJoin(tableName2, "u2", "u2.id=u1.id"). + Fields("u1.passport,u1.id,u2.name,u2.age"). + Where("u1.id<2"). + All() + t.AssertNil(err) + t.Assert(len(all), 1) + t.Assert(len(all[0]), 4) + t.Assert(all[0]["id"], 1) + t.Assert(all[0]["age"], 18) + t.Assert(all[0]["name"], "table2_1") + t.Assert(all[0]["passport"], "user_1") + }) +} + +func Test_Model_One(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + record, err := db.Model(table).Where("id", 1).One() + t.AssertNil(err) + t.Assert(record["nickname"].String(), "name_1") + }) + + gtest.C(t, func(t *gtest.T) { + record, err := db.Model(table).Where("id", 0).One() + t.AssertNil(err) + t.Assert(record, nil) + }) +} + +func Test_Model_Value(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + value, err := db.Model(table).Fields("nickname").Where("id", 1).Value() + t.AssertNil(err) + t.Assert(value.String(), "name_1") + }) + + gtest.C(t, func(t *gtest.T) { + value, err := db.Model(table).Fields("nickname").Where("id", 0).Value() + t.AssertNil(err) + t.Assert(value, nil) + }) +} + +func Test_Model_Array(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(table).Where("id", g.Slice{1, 2, 3}).All() + t.AssertNil(err) + t.Assert(all.Array("id"), g.Slice{1, 2, 3}) + t.Assert(all.Array("nickname"), g.Slice{"name_1", "name_2", "name_3"}) + }) + + gtest.C(t, func(t *gtest.T) { + array, err := db.Model(table).Fields("nickname").Where("id", g.Slice{1, 2, 3}).Array() + t.AssertNil(err) + t.Assert(array, g.Slice{"name_1", "name_2", "name_3"}) + }) + gtest.C(t, func(t *gtest.T) { + array, err := db.Model(table).Array("nickname", "id", g.Slice{1, 2, 3}) + t.AssertNil(err) + t.Assert(array, g.Slice{"name_1", "name_2", "name_3"}) + }) +} + +func Test_Model_Count(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + count, err := db.Model(table).Count() + t.AssertNil(err) + t.Assert(count, int64(TableSize)) + }) + // Count with cache, check internal ctx data feature. + gtest.C(t, func(t *gtest.T) { + for i := 0; i < 10; i++ { + count, err := db.Model(table).Cache(gdb.CacheOption{ + Duration: time.Second * 10, + Name: guid.S(), + Force: false, + }).Count() + t.AssertNil(err) + t.Assert(count, int64(TableSize)) + } + }) + gtest.C(t, func(t *gtest.T) { + count, err := db.Model(table).FieldsEx("id").Where("id>8").Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + }) + gtest.C(t, func(t *gtest.T) { + count, err := db.Model(table).Fields("distinct id,nickname").Where("id>8").Count() + t.AssertNil(err) + t.Assert(count, int64(2)) + }) + // COUNT...LIMIT... + gtest.C(t, func(t *gtest.T) { + count, err := db.Model(table).Page(1, 2).Count() + t.AssertNil(err) + t.Assert(count, int64(TableSize)) + }) +} + +func Test_Model_Exist(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + exist, err := db.Model(table).Exist() + t.AssertNil(err) + t.Assert(exist, TableSize > 0) + exist, err = db.Model(table).Where("id", -1).Exist() + t.AssertNil(err) + t.Assert(exist, false) + }) +} + +func Test_Model_Select(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime gtime.Time + } + gtest.C(t, func(t *gtest.T) { + var users []User + err := db.Model(table).Scan(&users) + t.AssertNil(err) + t.Assert(len(users), TableSize) + }) +} + +func Test_Model_Struct(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime gtime.Time + } + user := new(User) + err := db.Model(table).Where("id=1").Scan(user) + t.AssertNil(err) + t.Assert(user.NickName, "name_1") + t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") + }) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + user := new(User) + err := db.Model(table).Where("id=1").Scan(user) + t.AssertNil(err) + t.Assert(user.NickName, "name_1") + t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") + }) + // Auto creating struct object. + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + user := (*User)(nil) + err := db.Model(table).Where("id=1").Scan(&user) + t.AssertNil(err) + t.Assert(user.NickName, "name_1") + t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") + }) + // Just using Scan. + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + user := (*User)(nil) + err := db.Model(table).Where("id=1").Scan(&user) + if err != nil { + gtest.Error(err) + } + t.Assert(user.NickName, "name_1") + t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") + }) + // sql.ErrNoRows + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + user := new(User) + err := db.Model(table).Where("id=-1").Scan(user) + t.Assert(err, sql.ErrNoRows) + }) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + var user *User + err := db.Model(table).Where("id=-1").Scan(&user) + t.AssertNil(err) + }) +} + +func Test_Model_Structs(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime gtime.Time + } + var users []User + err := db.Model(table).Order("id asc").Scan(&users) + if err != nil { + gtest.Error(err) + } + t.Assert(len(users), TableSize) + t.Assert(users[0].Id, 1) + t.Assert(users[1].Id, 2) + t.Assert(users[2].Id, 3) + t.Assert(users[0].NickName, "name_1") + t.Assert(users[1].NickName, "name_2") + t.Assert(users[2].NickName, "name_3") + t.Assert(users[0].CreateTime.String(), "2018-10-24 10:00:00") + }) + // Auto create struct slice. + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + var users []*User + err := db.Model(table).Order("id asc").Scan(&users) + if err != nil { + gtest.Error(err) + } + t.Assert(len(users), TableSize) + t.Assert(users[0].Id, 1) + t.Assert(users[1].Id, 2) + t.Assert(users[2].Id, 3) + t.Assert(users[0].NickName, "name_1") + t.Assert(users[1].NickName, "name_2") + t.Assert(users[2].NickName, "name_3") + t.Assert(users[0].CreateTime.String(), "2018-10-24 10:00:00") + }) + // Just using Scan. + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + var users []*User + err := db.Model(table).Order("id asc").Scan(&users) + if err != nil { + gtest.Error(err) + } + t.Assert(len(users), TableSize) + t.Assert(users[0].Id, 1) + t.Assert(users[1].Id, 2) + t.Assert(users[2].Id, 3) + t.Assert(users[0].NickName, "name_1") + t.Assert(users[1].NickName, "name_2") + t.Assert(users[2].NickName, "name_3") + t.Assert(users[0].CreateTime.String(), "2018-10-24 10:00:00") + }) + // sql.ErrNoRows + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + var users []*User + err := db.Model(table).Where("id<0").Scan(&users) + t.AssertNil(err) + }) +} + +func Test_Model_Scan(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime gtime.Time + } + user := new(User) + err := db.Model(table).Where("id=1").Scan(user) + t.AssertNil(err) + t.Assert(user.NickName, "name_1") + t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") + }) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + user := new(User) + err := db.Model(table).Where("id=1").Scan(user) + t.AssertNil(err) + t.Assert(user.NickName, "name_1") + t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") + }) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime gtime.Time + } + var users []User + err := db.Model(table).Order("id asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), TableSize) + t.Assert(users[0].Id, 1) + t.Assert(users[1].Id, 2) + t.Assert(users[2].Id, 3) + t.Assert(users[0].NickName, "name_1") + t.Assert(users[1].NickName, "name_2") + t.Assert(users[2].NickName, "name_3") + t.Assert(users[0].CreateTime.String(), "2018-10-24 10:00:00") + }) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + var users []*User + err := db.Model(table).Order("id asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), TableSize) + t.Assert(users[0].Id, 1) + t.Assert(users[1].Id, 2) + t.Assert(users[2].Id, 3) + t.Assert(users[0].NickName, "name_1") + t.Assert(users[1].NickName, "name_2") + t.Assert(users[2].NickName, "name_3") + t.Assert(users[0].CreateTime.String(), "2018-10-24 10:00:00") + }) + // sql.ErrNoRows + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + NickName string + CreateTime *gtime.Time + } + var ( + user = new(User) + users = new([]*User) + ) + err1 := db.Model(table).Where("id < 0").Scan(user) + err2 := db.Model(table).Where("id < 0").Scan(users) + t.Assert(err1, sql.ErrNoRows) + t.Assert(err2, nil) + }) +} + +func Test_Model_OrderBy(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Order("id DESC").All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["nickname"].String(), fmt.Sprintf("name_%d", TableSize)) + }) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Order(gdb.Raw("NULL")).All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["nickname"].String(), "name_1") + }) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Order(gdb.Raw("field(id, 10,1,2,3,4,5,6,7,8,9)")).All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["nickname"].String(), "name_10") + t.Assert(result[1]["nickname"].String(), "name_1") + t.Assert(result[2]["nickname"].String(), "name_2") + }) +} + +func Test_Model_GroupBy(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Group("id").All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + t.Assert(result[0]["nickname"].String(), "name_1") + }) +} + +func Test_Model_Data(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + table := createInitTable() + defer dropTable(table) + result, err := db.Model(table).Data("nickname=?", "test").Where("id=?", 3).Update() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 1) + }) + gtest.C(t, func(t *gtest.T) { + table := createTable() + defer dropTable(table) + users := make([]g.MapStrAny, 0) + for i := 1; i <= 10; i++ { + users = append(users, g.MapStrAny{ + "id": i, + "passport": fmt.Sprintf(`passport_%d`, i), + "password": fmt.Sprintf(`password_%d`, i), + "nickname": fmt.Sprintf(`nickname_%d`, i), + }) + } + result, err := db.Model(table).Data(users).Batch(2).Insert() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 10) + }) + gtest.C(t, func(t *gtest.T) { + table := createTable() + defer dropTable(table) + users := garray.New() + for i := 1; i <= 10; i++ { + users.Append(g.MapStrAny{ + "id": i, + "passport": fmt.Sprintf(`passport_%d`, i), + "password": fmt.Sprintf(`password_%d`, i), + "nickname": fmt.Sprintf(`nickname_%d`, i), + }) + } + result, err := db.Model(table).Data(users).Batch(2).Insert() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 10) + }) +} + +func Test_Model_Delete(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + // DELETE...LIMIT + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Where(1).Limit(2).Delete() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, 2) + }) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Where(1).Delete() + t.AssertNil(err) + n, _ := result.RowsAffected() + t.Assert(n, TableSize-2) + }) +} + +func Test_Model_Offset(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Limit(2).Offset(5).Order("id").All() + t.AssertNil(err) + t.Assert(len(result), 2) + t.Assert(result[0]["id"], 6) + t.Assert(result[1]["id"], 7) + }) +} + +func Test_Model_Page(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).Page(3, 3).Order("id").All() + t.AssertNil(err) + t.Assert(len(result), 3) + t.Assert(result[0]["id"], 7) + t.Assert(result[1]["id"], 8) + }) + gtest.C(t, func(t *gtest.T) { + model := db.Model(table).Safe().Order("id") + all, err := model.Page(3, 3).All() + count, err := model.Count() + t.AssertNil(err) + t.Assert(len(all), 3) + t.Assert(all[0]["id"], "7") + t.Assert(count, int64(TableSize)) + }) +} + +func Test_Model_OmitEmpty(t *testing.T) { + table := fmt.Sprintf(`table_%s`, gtime.TimestampNanoStr()) + if _, err := db.Exec(ctx, fmt.Sprintf(` + CREATE TABLE IF NOT EXISTS %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + _, err := db.Model(table).OmitEmpty().Data(g.Map{ + "id": 1, + "name": "", + }).Save() + t.AssertNE(err, nil) + }) + gtest.C(t, func(t *gtest.T) { + _, err := db.Model(table).OmitEmptyData().Data(g.Map{ + "id": 1, + "name": "", + }).Save() + t.AssertNE(err, nil) + }) + gtest.C(t, func(t *gtest.T) { + _, err := db.Model(table).OmitEmptyWhere().Data(g.Map{ + "id": 1, + "name": "", + }).Save() + t.AssertNil(err) + }) +} + +func Test_Model_OmitNil(t *testing.T) { + table := fmt.Sprintf(`table_%s`, gtime.TimestampNanoStr()) + if _, err := db.Exec(ctx, fmt.Sprintf(` + CREATE TABLE IF NOT EXISTS %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + _, err := db.Model(table).OmitNil().Data(g.Map{ + "id": 1, + "name": nil, + }).Save() + t.AssertNE(err, nil) + }) + gtest.C(t, func(t *gtest.T) { + _, err := db.Model(table).OmitNil().Data(g.Map{ + "id": 1, + "name": "", + }).Save() + t.AssertNil(err) + }) + gtest.C(t, func(t *gtest.T) { + _, err := db.Model(table).OmitNilWhere().Data(g.Map{ + "id": 1, + "name": "", + }).Save() + t.AssertNil(err) + }) +} + +func Test_Model_FieldsEx(t *testing.T) { + table := createInitTable() + defer dropTable(table) + // Select. + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).FieldsEx("create_time, id").Where("id in (?)", g.Slice{1, 2}).Order("id asc").All() + t.AssertNil(err) + t.Assert(len(r), 2) + t.Assert(len(r[0]), 4) + t.Assert(r[0]["id"], "") + t.Assert(r[0]["passport"], "user_1") + t.Assert(r[0]["password"], "pass_1") + t.Assert(r[0]["nickname"], "name_1") + t.Assert(r[0]["create_time"], "") + t.Assert(r[1]["id"], "") + t.Assert(r[1]["passport"], "user_2") + t.Assert(r[1]["password"], "pass_2") + t.Assert(r[1]["nickname"], "name_2") + t.Assert(r[1]["create_time"], "") + }) + // Update. + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).FieldsEx("password").Data(g.Map{"nickname": "123", "password": "456"}).Where("id", 3).Update() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).Where("id", 3).One() + t.AssertNil(err) + t.Assert(one["nickname"], "123") + t.AssertNE(one["password"], "456") + }) +} + +func Test_Model_FieldsExStruct(t *testing.T) { + table := createTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int `orm:"id" json:"id"` + Passport string `orm:"password" json:"pass_port"` + Password string `orm:"password" json:"password"` + NickName string `orm:"nickname" json:"nick__name"` + } + user := &User{ + Id: 1, + Passport: "111", + Password: "222", + NickName: "333", + } + r, err := db.Model(table).FieldsEx("create_time, password").OmitEmpty().Data(user).Insert() + t.AssertNil(err) + n, err := r.RowsAffected() + t.AssertNil(err) + t.Assert(n, 1) + }) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int `orm:"id" json:"id"` + Passport string `orm:"password" json:"pass_port"` + Password string `orm:"password" json:"password"` + NickName string `orm:"nickname" json:"nick__name"` + } + users := make([]*User, 0) + for i := 100; i < 110; i++ { + users = append(users, &User{ + Id: i, + Passport: fmt.Sprintf(`passport_%d`, i), + Password: fmt.Sprintf(`password_%d`, i), + NickName: fmt.Sprintf(`nickname_%d`, i), + }) + } + r, err := db.Model(table).FieldsEx("create_time, password"). + OmitEmpty(). + Batch(2). + Data(users). + Insert() + t.AssertNil(err) + n, err := r.RowsAffected() + t.AssertNil(err) + t.Assert(n, 10) + }) +} + +func Test_Model_Join_SubQuery(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + subQuery := fmt.Sprintf("select * from `%s`", table) + r, err := db.Model(table, "t1").Fields("t2.id").LeftJoin(subQuery, "t2", "t2.id=t1.id").Array() + t.AssertNil(err) + t.Assert(len(r), TableSize) + t.Assert(r[0], "1") + t.Assert(r[TableSize-1], TableSize) + }) +} + +func Test_Model_Having(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(table).Where("id > 1").Having("id > 8").All() + t.AssertNil(err) + t.Assert(len(all), 2) + }) + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(table).Where("id > 1").Having("id > ?", 8).All() + t.AssertNil(err) + t.Assert(len(all), 2) + }) + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(table).Where("id > ?", 1).Having("id > ?", 8).All() + t.AssertNil(err) + t.Assert(len(all), 2) + }) + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(table).Where("id > ?", 1).Having("id", 8).All() + t.AssertNil(err) + t.Assert(len(all), 1) + }) +} + +func Test_Model_Distinct(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(table, "t").Fields("distinct t.id").Where("id > 1").Having("id > 8").All() + t.AssertNil(err) + t.Assert(len(all), 2) + }) + gtest.C(t, func(t *gtest.T) { + count, err := db.Model(table).Where("id > 1").Distinct().Count() + t.AssertNil(err) + t.Assert(count, int64(9)) + }) +} + +func Test_Model_Min_Max(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + value, err := db.Model(table, "t").Fields("min(t.id)").Where("id > 1").Value() + t.AssertNil(err) + t.Assert(value.Int(), 2) + }) + gtest.C(t, func(t *gtest.T) { + value, err := db.Model(table, "t").Fields("max(t.id)").Where("id > 1").Value() + t.AssertNil(err) + t.Assert(value.Int(), 10) + }) +} + +func Test_Model_Fields_AutoMapping(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + value, err := db.Model(table).Fields("ID").Where("id", 2).Value() + t.AssertNil(err) + t.Assert(value.Int(), 2) + }) + + gtest.C(t, func(t *gtest.T) { + value, err := db.Model(table).Fields("NICK_NAME").Where("id", 2).Value() + t.AssertNil(err) + t.Assert(value.String(), "name_2") + }) + // Map + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Fields(g.Map{ + "ID": 1, + "NICK_NAME": 1, + }).Where("id", 2).One() + t.AssertNil(err) + t.Assert(len(one), 2) + t.Assert(one["id"], 2) + t.Assert(one["nickname"], "name_2") + }) + // Struct + gtest.C(t, func(t *gtest.T) { + type T struct { + ID int + NICKNAME int + } + one, err := db.Model(table).Fields(&T{ + ID: 0, + NICKNAME: 0, + }).Where("id", 2).One() + t.AssertNil(err) + t.Assert(len(one), 2) + t.Assert(one["id"], 2) + t.Assert(one["nickname"], "name_2") + }) +} + +func Test_Model_FieldsEx_AutoMapping(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + // "id": i, + // "passport": fmt.Sprintf(`user_%d`, i), + // "password": fmt.Sprintf(`pass_%d`, i), + // "nickname": fmt.Sprintf(`name_%d`, i), + // "create_time": gtime.NewFromStr("2018-10-24 10:00:00").String(), + + gtest.C(t, func(t *gtest.T) { + value, err := db.Model(table).FieldsEx("create_date, Passport, Password, NickName, CreateTime").Where("id", 2).Value() + t.AssertNil(err) + t.Assert(value.Int(), 2) + }) + + gtest.C(t, func(t *gtest.T) { + value, err := db.Model(table).FieldsEx("create_date, ID, Passport, Password, CreateTime").Where("id", 2).Value() + t.AssertNil(err) + t.Assert(value.String(), "name_2") + }) + // Map + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).FieldsEx(g.Map{ + "Passport": 1, + "Password": 1, + "CreateTime": 1, + }).Where("id", 2).One() + t.AssertNil(err) + t.Assert(len(one), 3) + t.Assert(one["id"], 2) + t.Assert(one["nickname"], "name_2") + }) + // Struct + gtest.C(t, func(t *gtest.T) { + type T struct { + Passport int + Password int + CreateTime int + } + one, err := db.Model(table).FieldsEx(&T{ + Passport: 0, + Password: 0, + CreateTime: 0, + }).Where("id", 2).One() + t.AssertNil(err) + t.Assert(len(one), 3) + t.Assert(one["id"], 2) + t.Assert(one["nickname"], "name_2") + }) +} + +func Test_Model_Fields_Struct(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + type A struct { + Passport string + Password string + } + type B struct { + A + NickName string + } + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Fields(A{}).Where("id", 2).One() + t.AssertNil(err) + t.Assert(len(one), 2) + t.Assert(one["passport"], "user_2") + t.Assert(one["password"], "pass_2") + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Fields(&A{}).Where("id", 2).One() + t.AssertNil(err) + t.Assert(len(one), 2) + t.Assert(one["passport"], "user_2") + t.Assert(one["password"], "pass_2") + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Fields(B{}).Where("id", 2).One() + t.AssertNil(err) + t.Assert(len(one), 3) + t.Assert(one["passport"], "user_2") + t.Assert(one["password"], "pass_2") + t.Assert(one["nickname"], "name_2") + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Fields(&B{}).Where("id", 2).One() + t.AssertNil(err) + t.Assert(len(one), 3) + t.Assert(one["passport"], "user_2") + t.Assert(one["password"], "pass_2") + t.Assert(one["nickname"], "name_2") + }) +} + +func Test_Model_HasTable(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + t.AssertNil(db.GetCore().ClearCacheAll(ctx)) + result, err := db.GetCore().HasTable(table) + t.Assert(result, true) + t.AssertNil(err) + }) + + gtest.C(t, func(t *gtest.T) { + t.AssertNil(db.GetCore().ClearCacheAll(ctx)) + result, err := db.GetCore().HasTable("table12321") + t.Assert(result, false) + t.AssertNil(err) + }) +} + +func Test_Model_HasField(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).HasField("id") + t.Assert(result, true) + t.AssertNil(err) + }) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).HasField("id123") + t.Assert(result, false) + t.AssertNil(err) + }) +} diff --git a/contrib/drivers/mysql/mysql.go b/contrib/drivers/mysql/mysql.go index ce142f51315..8e13aa28dd1 100644 --- a/contrib/drivers/mysql/mysql.go +++ b/contrib/drivers/mysql/mysql.go @@ -27,7 +27,7 @@ func init() { var ( err error driverObj = New() - driverNames = g.SliceStr{"mysql", "mariadb", "tidb"} + driverNames = g.SliceStr{"mysql", "mariadb", "tidb"} // TODO remove mariadb and tidb in future versions. ) for _, driverName := range driverNames { if err = gdb.Register(driverName, driverObj); err != nil { diff --git a/contrib/drivers/mysql/mysql_table_fields.go b/contrib/drivers/mysql/mysql_table_fields.go index 72ffa7e29ec..59ea2adb372 100644 --- a/contrib/drivers/mysql/mysql_table_fields.go +++ b/contrib/drivers/mysql/mysql_table_fields.go @@ -15,6 +15,9 @@ import ( ) var ( + // tableFieldsSqlByMariadb is the query statement for retrieving table fields' information in MariaDB. + // Deprecated: Use package `contrib/drivers/mariadb` instead. + // TODO remove in next version. tableFieldsSqlByMariadb = ` SELECT c.COLUMN_NAME AS 'Field', @@ -68,6 +71,8 @@ func (d *Driver) TableFields(ctx context.Context, table string, schema ...string } dbType := d.GetConfig().Type switch dbType { + // Deprecated: Use package `contrib/drivers/mariadb` instead. + // TODO remove in next version. case "mariadb": tableFieldsSql = fmt.Sprintf(tableFieldsSqlByMariadb, usedSchema, table) default: diff --git a/contrib/drivers/mysql/mysql_z_unit_init_test.go b/contrib/drivers/mysql/mysql_z_unit_init_test.go index 3c0f2f76201..0269d898ee8 100644 --- a/contrib/drivers/mysql/mysql_z_unit_init_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_init_test.go @@ -178,7 +178,7 @@ func Test_PartitionTable(t *testing.T) { createShopDBTable() insertShopDBData() - //defer dropShopDBTable() + // defer dropShopDBTable() gtest.C(t, func(t *gtest.T) { data, err := db3.Ctx(ctx).Model("dbx_order").Partition("p3", "p4").All() t.AssertNil(err) diff --git a/contrib/drivers/oceanbase/go.mod b/contrib/drivers/oceanbase/go.mod new file mode 100644 index 00000000000..ed4c2d1c7a0 --- /dev/null +++ b/contrib/drivers/oceanbase/go.mod @@ -0,0 +1,44 @@ +module github.com/gogf/gf/contrib/drivers/oceanbase/v2 + +go 1.23.0 + +require ( + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.6 + github.com/gogf/gf/v2 v2.9.6 +) + +require ( + github.com/BurntSushi/toml v1.5.0 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect + github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grokify/html-strip-tags-go v0.1.0 // indirect + github.com/magiconair/properties v1.8.10 // 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.16 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.0.9 // indirect + github.com/olekukonko/tablewriter v1.1.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.25.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace ( + github.com/gogf/gf/contrib/drivers/mysql/v2 => ../mysql + github.com/gogf/gf/v2 => ../../../ +) diff --git a/contrib/drivers/oceanbase/go.sum b/contrib/drivers/oceanbase/go.sum new file mode 100644 index 00000000000..f96db96f24f --- /dev/null +++ b/contrib/drivers/oceanbase/go.sum @@ -0,0 +1,81 @@ +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU= +github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A= +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.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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/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/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= +github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= +github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= +github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY= +github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +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.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/contrib/drivers/oceanbase/oceanbase.go b/contrib/drivers/oceanbase/oceanbase.go new file mode 100644 index 00000000000..30f90a763b9 --- /dev/null +++ b/contrib/drivers/oceanbase/oceanbase.go @@ -0,0 +1,49 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// Package oceanbase implements gdb.Driver, which supports operations for database OceanBase. +package oceanbase + +import ( + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + + "github.com/gogf/gf/contrib/drivers/mysql/v2" +) + +// Driver is the driver for OceanBase database. +// +// OceanBase is a distributed relational database developed by Ant Group. It supports both MySQL and Oracle +// protocol modes. This driver uses the MySQL protocol to communicate with OceanBase database in MySQL +// compatibility mode. +// +// Although OceanBase is compatible with MySQL protocol, it is packaged as a separate driver component +// rather than reusing the mysql adapter directly. This design allows for future extensibility, +// such as implementing OceanBase-specific features like distributed transactions or Oracle mode support. +type Driver struct { + *mysql.Driver +} + +func init() { + var ( + err error + driverObj = New() + driverNames = g.SliceStr{"oceanbase"} + ) + for _, driverName := range driverNames { + if err = gdb.Register(driverName, driverObj); err != nil { + panic(err) + } + } +} + +// New creates and returns a driver that implements gdb.Driver, which supports operations for OceanBase. +func New() gdb.Driver { + mysqlDriver := mysql.New().(*mysql.Driver) + return &Driver{ + Driver: mysqlDriver, + } +} diff --git a/contrib/drivers/tidb/go.mod b/contrib/drivers/tidb/go.mod new file mode 100644 index 00000000000..a55a25bb508 --- /dev/null +++ b/contrib/drivers/tidb/go.mod @@ -0,0 +1,44 @@ +module github.com/gogf/gf/contrib/drivers/tidb/v2 + +go 1.23.0 + +require ( + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.6 + github.com/gogf/gf/v2 v2.9.6 +) + +require ( + github.com/BurntSushi/toml v1.5.0 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect + github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grokify/html-strip-tags-go v0.1.0 // indirect + github.com/magiconair/properties v1.8.10 // 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.16 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.0.9 // indirect + github.com/olekukonko/tablewriter v1.1.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.25.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace ( + github.com/gogf/gf/contrib/drivers/mysql/v2 => ../mysql + github.com/gogf/gf/v2 => ../../../ +) diff --git a/contrib/drivers/tidb/go.sum b/contrib/drivers/tidb/go.sum new file mode 100644 index 00000000000..f96db96f24f --- /dev/null +++ b/contrib/drivers/tidb/go.sum @@ -0,0 +1,81 @@ +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU= +github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A= +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.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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/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/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= +github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= +github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= +github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY= +github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +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.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/contrib/drivers/tidb/tidb.go b/contrib/drivers/tidb/tidb.go new file mode 100644 index 00000000000..99318d8e656 --- /dev/null +++ b/contrib/drivers/tidb/tidb.go @@ -0,0 +1,49 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// Package tidb implements gdb.Driver, which supports operations for database TiDB. +package tidb + +import ( + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + + "github.com/gogf/gf/contrib/drivers/mysql/v2" +) + +// Driver is the driver for TiDB database. +// +// TiDB is an open-source NewSQL database that supports Hybrid Transactional and Analytical Processing (HTAP). +// This driver uses the MySQL protocol to communicate with TiDB database, as TiDB is designed to be highly +// compatible with the MySQL protocol. +// +// Although TiDB is compatible with MySQL protocol, it is packaged as a separate driver component +// rather than reusing the mysql adapter directly. This design allows for future extensibility, +// such as implementing TiDB-specific features like distributed transactions or optimizations. +type Driver struct { + *mysql.Driver +} + +func init() { + var ( + err error + driverObj = New() + driverNames = g.SliceStr{"tidb"} + ) + for _, driverName := range driverNames { + if err = gdb.Register(driverName, driverObj); err != nil { + panic(err) + } + } +} + +// New creates and returns a driver that implements gdb.Driver, which supports operations for TiDB. +func New() gdb.Driver { + mysqlDriver := mysql.New().(*mysql.Driver) + return &Driver{ + Driver: mysqlDriver, + } +}