├── .gitignore ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── stale.yml │ └── tests.yml ├── main.go ├── main_test.go ├── go.mod ├── docker-compose.yml ├── test.sh ├── License ├── models.go ├── README.md └── db.go /.gitignore: -------------------------------------------------------------------------------- 1 | gorm 2 | go.sum 3 | .* 4 | *.db 5 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Explain your user case and expected results 2 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("vim-go") 7 | } 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [jinzhu] 4 | patreon: jinzhu 5 | open_collective: gorm 6 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // GORM_REPO: https://github.com/go-gorm/gorm.git 8 | // GORM_BRANCH: master 9 | // TEST_DRIVERS: sqlite, mysql, postgres, sqlserver 10 | 11 | func TestGORM(t *testing.T) { 12 | user := User{Name: "jinzhu"} 13 | 14 | DB.Create(&user) 15 | 16 | var result User 17 | if err := DB.First(&result, user.ID).Error; err != nil { 18 | t.Errorf("Failed, got error: %v", err) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | - package-ecosystem: "gomod" 13 | directory: "/" 14 | schedule: 15 | interval: "daily" 16 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module gorm.io/playground 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/denisenkom/go-mssqldb v0.10.0 // indirect 7 | github.com/jackc/pgproto3/v2 v2.0.7 // indirect 8 | github.com/jackc/pgx/v4 v4.11.0 // indirect 9 | github.com/mattn/go-sqlite3 v1.14.7 // indirect 10 | golang.org/x/crypto v0.0.0-20210505212654-3497b51f5e64 // indirect 11 | golang.org/x/text v0.3.6 // indirect 12 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect 13 | gorm.io/driver/mysql v1.0.6 14 | gorm.io/driver/postgres v1.1.0 15 | gorm.io/driver/sqlite v1.1.4 16 | gorm.io/driver/sqlserver v1.0.7 17 | gorm.io/gorm v1.21.9 18 | ) 19 | 20 | replace gorm.io/gorm => ./gorm 21 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues" 2 | on: 3 | schedule: 4 | - cron: "0 0 * * *" 5 | 6 | jobs: 7 | stale: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/stale@v3 11 | with: 12 | repo-token: ${{ secrets.GITHUB_TOKEN }} 13 | stale-issue-message: "This issue has been automatically marked as stale because it has not been commented on for at least 7 days" 14 | stale-pr-message: "This pull request has been automatically marked as stale because it has not been commented on for at least 7 days, if you encounter a bug in GORM, please report it at [https://github.com/go-gorm/gorm/issues](https://github.com/go-gorm/gorm/issues) with the pull request's link" 15 | days-before-stale: 7 16 | days-before-close: 5 17 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | mysql: 5 | image: 'mysql:latest' 6 | ports: 7 | - 9910:3306 8 | environment: 9 | - MYSQL_DATABASE=gorm 10 | - MYSQL_USER=gorm 11 | - MYSQL_PASSWORD=gorm 12 | - MYSQL_RANDOM_ROOT_PASSWORD="yes" 13 | postgres: 14 | image: 'postgres:latest' 15 | ports: 16 | - 9920:5432 17 | environment: 18 | - TZ=Asia/Shanghai 19 | - POSTGRES_DB=gorm 20 | - POSTGRES_USER=gorm 21 | - POSTGRES_PASSWORD=gorm 22 | mssql: 23 | image: 'mcmoe/mssqldocker:latest' 24 | ports: 25 | - 9930:1433 26 | environment: 27 | - ACCEPT_EULA=Y 28 | - SA_PASSWORD=LoremIpsum86 29 | - MSSQL_DB=gorm 30 | - MSSQL_USER=gorm 31 | - MSSQL_PASSWORD=LoremIpsum86 32 | 33 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | dialects=("sqlite" "mysql" "postgres" "sqlserver") 4 | 5 | if [ "$GORM_ENABLE_CACHE" = "" ] 6 | then 7 | rm -rf gorm 8 | fi 9 | 10 | [ -d gorm ] || (echo "git clone --depth 1 -b $(cat main_test.go | grep GORM_BRANCH | awk '{print $3}') $(cat main_test.go | grep GORM_REPO | awk '{print $3}')"; git clone --depth 1 -b $(cat main_test.go | grep GORM_BRANCH | awk '{print $3}') $(cat main_test.go | grep GORM_REPO | awk '{print $3}')) 11 | 12 | go get -u ./... 13 | 14 | for dialect in "${dialects[@]}" ; do 15 | if [ "$GORM_DIALECT" = "" ] || [ "$GORM_DIALECT" = "${dialect}" ] 16 | then 17 | if [[ $(grep TEST_DRIVER main_test.go) =~ "${dialect}" ]] 18 | then 19 | echo "testing ${dialect}..." 20 | GORM_DIALECT=${dialect} go test -race -count=1 -v ./... 21 | else 22 | echo "skip ${dialect}..." 23 | fi 24 | fi 25 | done 26 | -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-NOW Jinzhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /models.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "time" 6 | 7 | "gorm.io/gorm" 8 | ) 9 | 10 | // User has one `Account` (has one), many `Pets` (has many) and `Toys` (has many - polymorphic) 11 | // He works in a Company (belongs to), he has a Manager (belongs to - single-table), and also managed a Team (has many - single-table) 12 | // He speaks many languages (many to many) and has many friends (many to many - single-table) 13 | // His pet also has one Toy (has one - polymorphic) 14 | type User struct { 15 | gorm.Model 16 | Name string 17 | Age uint 18 | Birthday *time.Time 19 | Account Account 20 | Pets []*Pet 21 | Toys []Toy `gorm:"polymorphic:Owner"` 22 | CompanyID *int 23 | Company Company 24 | ManagerID *uint 25 | Manager *User 26 | Team []User `gorm:"foreignkey:ManagerID"` 27 | Languages []Language `gorm:"many2many:UserSpeak"` 28 | Friends []*User `gorm:"many2many:user_friends"` 29 | Active bool 30 | } 31 | 32 | type Account struct { 33 | gorm.Model 34 | UserID sql.NullInt64 35 | Number string 36 | } 37 | 38 | type Pet struct { 39 | gorm.Model 40 | UserID *uint 41 | Name string 42 | Toy Toy `gorm:"polymorphic:Owner;"` 43 | } 44 | 45 | type Toy struct { 46 | gorm.Model 47 | Name string 48 | OwnerID string 49 | OwnerType string 50 | } 51 | 52 | type Company struct { 53 | ID int 54 | Name string 55 | } 56 | 57 | type Language struct { 58 | Code string `gorm:"primarykey"` 59 | Name string 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GORM Playground 2 | 3 | GORM Playground can be used to play GORM and reports issues, if you encounter a bug in GORM, please report it at [https://github.com/go-gorm/gorm/issues](https://github.com/go-gorm/gorm/issues) with the Playground Pull Request's link 4 | 5 | [![test status](https://github.com/go-gorm/playground/workflows/tests/badge.svg?branch=master "test status")](https://github.com/go-gorm/playground/actions) 6 | 7 | ### Quick Start 8 | 9 | ##### 1. [Fork this repo](https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/fork-a-repo) 10 | 11 | ##### 2. [Clone the forked repo to your local](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository) 12 | 13 | ##### 3. Setup test database 14 | 15 | ```bash 16 | # install docker-compose https://docs.docker.com/compose/install/ 17 | 18 | # setup test databases 19 | docker-compose up 20 | ``` 21 | 22 | ##### 4. Run tests with lastest GORM and all drivers 23 | 24 | ```bash 25 | ./test.sh 26 | 27 | # Run tests with cached GORM and latest drivers 28 | GORM_ENABLE_CACHE=true ./test.sh 29 | 30 | # Run tests with specfied database 31 | GORM_DIALECT=mysql go test 32 | ``` 33 | 34 | ##### 5. Modify tests and make it fail 35 | 36 | ##### 6. [Create Playground Pull Request](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) and [Create a GORM issue](https://github.com/go-gorm/gorm/issues/new?template=bug_report.md) with the link 37 | 38 | ### Advanced Usage 39 | 40 | We are using the following configuration run your code (GORM's latest master branch, latest database drivers: sqlite, mysql, postgres, sqlserver), you could change the configuration in file [main_test.go](https://github.com/go-gorm/playground/edit/master/main_test.go) 41 | 42 | ```go 43 | // GORM_REPO: https://github.com/go-gorm/gorm.git 44 | // GORM_BRANCH: master 45 | // TEST_DRIVERS: sqlite, mysql, postgres, sqlserver 46 | ``` 47 | 48 | We have prepared some structs with relationships in [https://github.com/go-gorm/playground/blob/master/models.go](https://github.com/go-gorm/playground/blob/master/models.go) that you can use for your tests 49 | 50 | ## Happy Hacking! 51 | -------------------------------------------------------------------------------- /db.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "math/rand" 6 | "os" 7 | "path/filepath" 8 | "time" 9 | 10 | "gorm.io/driver/mysql" 11 | "gorm.io/driver/postgres" 12 | "gorm.io/driver/sqlite" 13 | "gorm.io/driver/sqlserver" 14 | "gorm.io/gorm" 15 | "gorm.io/gorm/logger" 16 | ) 17 | 18 | var DB *gorm.DB 19 | 20 | func init() { 21 | var err error 22 | if DB, err = OpenTestConnection(); err != nil { 23 | log.Printf("failed to connect database, got error %v\n", err) 24 | os.Exit(1) 25 | } else { 26 | sqlDB, err := DB.DB() 27 | if err == nil { 28 | err = sqlDB.Ping() 29 | } 30 | 31 | if err != nil { 32 | log.Printf("failed to connect database, got error %v\n", err) 33 | } 34 | 35 | RunMigrations() 36 | if DB.Dialector.Name() == "sqlite" { 37 | DB.Exec("PRAGMA foreign_keys = ON") 38 | } 39 | 40 | DB.Logger = DB.Logger.LogMode(logger.Info) 41 | } 42 | } 43 | 44 | func OpenTestConnection() (db *gorm.DB, err error) { 45 | dbDSN := os.Getenv("GORM_DSN") 46 | switch os.Getenv("GORM_DIALECT") { 47 | case "mysql": 48 | log.Println("testing mysql...") 49 | if dbDSN == "" { 50 | dbDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local" 51 | } 52 | db, err = gorm.Open(mysql.Open(dbDSN), &gorm.Config{}) 53 | case "postgres": 54 | log.Println("testing postgres...") 55 | if dbDSN == "" { 56 | dbDSN = "user=gorm password=gorm host=localhost dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai" 57 | } 58 | db, err = gorm.Open(postgres.Open(dbDSN), &gorm.Config{}) 59 | case "sqlserver": 60 | // CREATE LOGIN gorm WITH PASSWORD = 'LoremIpsum86'; 61 | // CREATE DATABASE gorm; 62 | // USE gorm; 63 | // CREATE USER gorm FROM LOGIN gorm; 64 | // sp_changedbowner 'gorm'; 65 | log.Println("testing sqlserver...") 66 | if dbDSN == "" { 67 | dbDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" 68 | } 69 | db, err = gorm.Open(sqlserver.Open(dbDSN), &gorm.Config{}) 70 | default: 71 | log.Println("testing sqlite3...") 72 | db, err = gorm.Open(sqlite.Open(filepath.Join(os.TempDir(), "gorm.db")), &gorm.Config{}) 73 | } 74 | 75 | if debug := os.Getenv("DEBUG"); debug == "true" { 76 | db.Logger = db.Logger.LogMode(logger.Info) 77 | } else if debug == "false" { 78 | db.Logger = db.Logger.LogMode(logger.Silent) 79 | } 80 | 81 | return 82 | } 83 | 84 | func RunMigrations() { 85 | var err error 86 | allModels := []interface{}{&User{}, &Account{}, &Pet{}, &Company{}, &Toy{}, &Language{}} 87 | rand.Seed(time.Now().UnixNano()) 88 | rand.Shuffle(len(allModels), func(i, j int) { allModels[i], allModels[j] = allModels[j], allModels[i] }) 89 | 90 | DB.Migrator().DropTable("user_friends", "user_speaks") 91 | 92 | if err = DB.Migrator().DropTable(allModels...); err != nil { 93 | log.Printf("Failed to drop table, got error %v\n", err) 94 | os.Exit(1) 95 | } 96 | 97 | if err = DB.AutoMigrate(allModels...); err != nil { 98 | log.Printf("Failed to auto migrate, but got error %v\n", err) 99 | os.Exit(1) 100 | } 101 | 102 | for _, m := range allModels { 103 | if !DB.Migrator().HasTable(m) { 104 | log.Printf("Failed to create table for %#v\n", m) 105 | os.Exit(1) 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches-ignore: 8 | - 'gh-pages' 9 | 10 | jobs: 11 | # Label of the container job 12 | sqlite: 13 | strategy: 14 | matrix: 15 | go: ['1.14'] 16 | platform: [ubuntu-latest] 17 | runs-on: ${{ matrix.platform }} 18 | 19 | steps: 20 | - name: Set up Go 1.x 21 | uses: actions/setup-go@v2 22 | with: 23 | go-version: ${{ matrix.go }} 24 | 25 | - name: Check out code into the Go module directory 26 | uses: actions/checkout@v2 27 | 28 | - name: go mod pakcage cache 29 | uses: actions/cache@v2 30 | with: 31 | path: ~/go/pkg/mod 32 | key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('go.mod') }} 33 | 34 | - name: Tests 35 | run: GORM_DIALECT=sqlite ./test.sh 36 | 37 | mysql: 38 | needs: sqlite 39 | strategy: 40 | matrix: 41 | dbversion: ['mysql:latest'] # 'mysql:5.7', 'mysql:5.6' 42 | go: ['1.14'] 43 | platform: [ubuntu-latest] 44 | runs-on: ${{ matrix.platform }} 45 | 46 | services: 47 | mysql: 48 | image: ${{ matrix.dbversion }} 49 | env: 50 | MYSQL_DATABASE: gorm 51 | MYSQL_USER: gorm 52 | MYSQL_PASSWORD: gorm 53 | MYSQL_RANDOM_ROOT_PASSWORD: "yes" 54 | ports: 55 | - 9910:3306 56 | options: >- 57 | --health-cmd "mysqladmin ping -ugorm -pgorm" 58 | --health-interval 10s 59 | --health-start-period 10s 60 | --health-timeout 5s 61 | --health-retries 10 62 | 63 | steps: 64 | - name: Set up Go 1.x 65 | uses: actions/setup-go@v2 66 | with: 67 | go-version: ${{ matrix.go }} 68 | 69 | - name: Check out code into the Go module directory 70 | uses: actions/checkout@v2 71 | 72 | - name: go mod pakcage cache 73 | uses: actions/cache@v2 74 | with: 75 | path: ~/go/pkg/mod 76 | key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('go.mod') }} 77 | 78 | - name: Tests 79 | run: GORM_ENABLE_CACHE=true GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True" ./test.sh 80 | 81 | postgres: 82 | needs: sqlite 83 | strategy: 84 | matrix: 85 | dbversion: ['postgres:latest'] # 'postgres:11', 'postgres:10' 86 | go: ['1.14'] 87 | platform: [ubuntu-latest] # can not run in macOS and widnowsOS 88 | runs-on: ${{ matrix.platform }} 89 | 90 | services: 91 | postgres: 92 | image: ${{ matrix.dbversion }} 93 | env: 94 | POSTGRES_PASSWORD: gorm 95 | POSTGRES_USER: gorm 96 | POSTGRES_DB: gorm 97 | TZ: Asia/Shanghai 98 | ports: 99 | - 9920:5432 100 | # Set health checks to wait until postgres has started 101 | options: >- 102 | --health-cmd pg_isready 103 | --health-interval 10s 104 | --health-timeout 5s 105 | --health-retries 5 106 | 107 | steps: 108 | - name: Set up Go 1.x 109 | uses: actions/setup-go@v2 110 | with: 111 | go-version: ${{ matrix.go }} 112 | 113 | - name: Check out code into the Go module directory 114 | uses: actions/checkout@v2 115 | 116 | - name: go mod pakcage cache 117 | uses: actions/cache@v2 118 | with: 119 | path: ~/go/pkg/mod 120 | key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('go.mod') }} 121 | 122 | - name: Tests 123 | run: GORM_ENABLE_CACHE=true GORM_DIALECT=postgres GORM_DSN="user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai" ./test.sh 124 | 125 | sqlserver: 126 | needs: sqlite 127 | strategy: 128 | matrix: 129 | go: ['1.14'] 130 | platform: [ubuntu-latest] # can not run test in macOS and windows 131 | runs-on: ${{ matrix.platform }} 132 | 133 | services: 134 | mssql: 135 | image: mcmoe/mssqldocker:latest 136 | env: 137 | ACCEPT_EULA: Y 138 | SA_PASSWORD: LoremIpsum86 139 | MSSQL_DB: gorm 140 | MSSQL_USER: gorm 141 | MSSQL_PASSWORD: LoremIpsum86 142 | ports: 143 | - 9930:1433 144 | options: >- 145 | --health-cmd="/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P LoremIpsum86 -l 30 -Q \"SELECT 1\" || exit 1" 146 | --health-start-period 10s 147 | --health-interval 10s 148 | --health-timeout 5s 149 | --health-retries 10 150 | 151 | steps: 152 | - name: Set up Go 1.x 153 | uses: actions/setup-go@v2 154 | with: 155 | go-version: ${{ matrix.go }} 156 | 157 | - name: Check out code into the Go module directory 158 | uses: actions/checkout@v2 159 | 160 | - name: go mod pakcage cache 161 | uses: actions/cache@v2 162 | with: 163 | path: ~/go/pkg/mod 164 | key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('go.mod') }} 165 | 166 | - name: Tests 167 | run: GORM_ENABLE_CACHE=true GORM_DIALECT=sqlserver GORM_DSN="sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" ./test.sh 168 | --------------------------------------------------------------------------------