From 7f75b12bb2c3c44b0b894d5cbf3128e000834add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leo=20Sj=C3=B6berg?= Date: Sat, 14 Sep 2024 13:58:29 +0100 Subject: [PATCH 1/8] Generate unique savepoint names for nested transactions (#7174) * Generate unique savepoint names * Add a test for deeply nested wrapped transactions --- finisher_api.go | 6 ++-- tests/go.mod | 4 +-- tests/transaction_test.go | 68 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/finisher_api.go b/finisher_api.go index f97571ed..6802945c 100644 --- a/finisher_api.go +++ b/finisher_api.go @@ -4,6 +4,7 @@ import ( "database/sql" "errors" "fmt" + "hash/maphash" "reflect" "strings" @@ -623,14 +624,15 @@ func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err er if committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil { // nested transaction if !db.DisableNestedTransaction { - err = db.SavePoint(fmt.Sprintf("sp%p", fc)).Error + spID := new(maphash.Hash).Sum64() + err = db.SavePoint(fmt.Sprintf("sp%d", spID)).Error if err != nil { return } defer func() { // Make sure to rollback when panic, Block error or Commit error if panicked || err != nil { - db.RollbackTo(fmt.Sprintf("sp%p", fc)) + db.RollbackTo(fmt.Sprintf("sp%d", spID)) } }() } diff --git a/tests/go.mod b/tests/go.mod index 350d1794..8eeab51d 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -29,8 +29,8 @@ require ( github.com/microsoft/go-mssqldb v1.7.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/text v0.17.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tests/transaction_test.go b/tests/transaction_test.go index d2cbc9a9..9f0f067c 100644 --- a/tests/transaction_test.go +++ b/tests/transaction_test.go @@ -297,6 +297,74 @@ func TestNestedTransactionWithBlock(t *testing.T) { } } +func TestDeeplyNestedTransactionWithBlockAndWrappedCallback(t *testing.T) { + transaction := func(ctx context.Context, db *gorm.DB, callback func(ctx context.Context, db *gorm.DB) error) error { + return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + return callback(ctx, tx) + }) + } + var ( + user = *GetUser("transaction-nested", Config{}) + user1 = *GetUser("transaction-nested-1", Config{}) + user2 = *GetUser("transaction-nested-2", Config{}) + ) + + if err := transaction(context.Background(), DB, func(ctx context.Context, tx *gorm.DB) error { + tx.Create(&user) + + if err := tx.First(&User{}, "name = ?", user.Name).Error; err != nil { + t.Fatalf("Should find saved record") + } + + if err := transaction(ctx, tx, func(ctx context.Context, tx1 *gorm.DB) error { + tx1.Create(&user1) + + if err := tx1.First(&User{}, "name = ?", user1.Name).Error; err != nil { + t.Fatalf("Should find saved record") + } + + if err := transaction(ctx, tx1, func(ctx context.Context, tx2 *gorm.DB) error { + tx2.Create(&user2) + + if err := tx2.First(&User{}, "name = ?", user2.Name).Error; err != nil { + t.Fatalf("Should find saved record") + } + + return errors.New("inner rollback") + }); err == nil { + t.Fatalf("nested transaction has no error") + } + + return errors.New("rollback") + }); err == nil { + t.Fatalf("nested transaction should returns error") + } + + if err := tx.First(&User{}, "name = ?", user1.Name).Error; err == nil { + t.Fatalf("Should not find rollbacked record") + } + + if err := tx.First(&User{}, "name = ?", user2.Name).Error; err != nil { + t.Fatalf("Should find saved record") + } + return nil + }); err != nil { + t.Fatalf("no error should return, but got %v", err) + } + + if err := DB.First(&User{}, "name = ?", user.Name).Error; err != nil { + t.Fatalf("Should find saved record") + } + + if err := DB.First(&User{}, "name = ?", user1.Name).Error; err == nil { + t.Fatalf("Should not find rollbacked parent record") + } + + if err := DB.First(&User{}, "name = ?", user2.Name).Error; err != nil { + t.Fatalf("Should not find rollbacked nested record") + } +} + func TestDisabledNestedTransaction(t *testing.T) { var ( user = *GetUser("transaction-nested", Config{}) From c2515ce260e8fcd90916aa0882f35e2907cb9a9e Mon Sep 17 00:00:00 2001 From: Kazuki Isogai <39211268+isso-719@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:42:52 +0900 Subject: [PATCH 2/8] feat: remove version top-level element and rename. (#7086) --- tests/{docker-compose.yml => compose.yml} | 2 -- 1 file changed, 2 deletions(-) rename tests/{docker-compose.yml => compose.yml} (98%) diff --git a/tests/docker-compose.yml b/tests/compose.yml similarity index 98% rename from tests/docker-compose.yml rename to tests/compose.yml index 5a3a10f2..666b1fb0 100644 --- a/tests/docker-compose.yml +++ b/tests/compose.yml @@ -1,5 +1,3 @@ -version: '3' - services: mysql: image: 'mysql/mysql-server:latest' From 68434b76eb567e00858a9f0eef72e79026e37b83 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Wed, 18 Sep 2024 20:03:30 +0800 Subject: [PATCH 3/8] fix test script with latest docker release --- tests/go.mod | 10 +++++----- tests/tests_all.sh | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/go.mod b/tests/go.mod index 8eeab51d..ba8a84a8 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -11,7 +11,7 @@ require ( gorm.io/driver/postgres v1.5.9 gorm.io/driver/sqlite v1.5.6 gorm.io/driver/sqlserver v1.5.3 - gorm.io/gorm v1.25.10 + gorm.io/gorm v1.25.12 ) require ( @@ -22,15 +22,15 @@ require ( github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.6.0 // indirect + github.com/jackc/pgx/v5 v5.7.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-sqlite3 v1.14.22 // indirect + github.com/mattn/go-sqlite3 v1.14.23 // indirect github.com/microsoft/go-mssqldb v1.7.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - golang.org/x/crypto v0.26.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/text v0.18.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tests/tests_all.sh b/tests/tests_all.sh index ee9e7675..0622f934 100755 --- a/tests/tests_all.sh +++ b/tests/tests_all.sh @@ -21,13 +21,13 @@ if [[ -z $GITHUB_ACTION ]]; then then cd tests if [[ $(uname -a) == *" arm64" ]]; then - MSSQL_IMAGE=mcr.microsoft.com/azure-sql-edge docker-compose start || true + MSSQL_IMAGE=mcr.microsoft.com/azure-sql-edge docker compose up -d || true go install github.com/microsoft/go-sqlcmd/cmd/sqlcmd@latest || true SQLCMDPASSWORD=LoremIpsum86 sqlcmd -U sa -S localhost:9930 -Q "IF DB_ID('gorm') IS NULL CREATE DATABASE gorm" > /dev/null || true SQLCMDPASSWORD=LoremIpsum86 sqlcmd -U sa -S localhost:9930 -Q "IF SUSER_ID (N'gorm') IS NULL CREATE LOGIN gorm WITH PASSWORD = 'LoremIpsum86';" > /dev/null || true SQLCMDPASSWORD=LoremIpsum86 sqlcmd -U sa -S localhost:9930 -Q "IF USER_ID (N'gorm') IS NULL CREATE USER gorm FROM LOGIN gorm; ALTER SERVER ROLE sysadmin ADD MEMBER [gorm];" > /dev/null || true else - docker-compose start + docker compose up -d fi cd .. fi From c6ac54812a4f253529858f7f41cc91ccf1fbaae6 Mon Sep 17 00:00:00 2001 From: Omkar P <45419097+omkar-foss@users.noreply.github.com> Date: Mon, 30 Sep 2024 08:51:19 +0530 Subject: [PATCH 4/8] Use official SQL Server docker image for tests (#7205) * Use official SQL Server docker image for tests * Try with tag 2019-latest instead of latest * Use platform ubuntu-20.04 for SQL Server * Switch to 2019-CU18-ubuntu-20.04 * Check with 2022-latest image tag and ubuntu-latest platform * Update health-cmd * Try sqlcmd without -N -C * Re-include -N -C, try with ubuntu-20.04 * Try ubuntu-20.04 without -N -C (last trial) * Finalize working config * Remove unused env variables --- .github/workflows/tests.yml | 12 +++++------- tests/compose.yml | 7 ++----- tests/tests_all.sh | 2 +- tests/tests_test.go | 2 +- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0601f006..24eab55a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -176,17 +176,15 @@ jobs: services: mssql: - image: mcmoe/mssqldocker:latest + image: mcr.microsoft.com/mssql/server:2022-latest env: + TZ: Asia/Shanghai ACCEPT_EULA: Y - SA_PASSWORD: LoremIpsum86 - MSSQL_DB: gorm - MSSQL_USER: gorm - MSSQL_PASSWORD: LoremIpsum86 + MSSQL_SA_PASSWORD: LoremIpsum86 ports: - 9930:1433 options: >- - --health-cmd="/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P LoremIpsum86 -l 30 -Q \"SELECT 1\" || exit 1" + --health-cmd="/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P ${MSSQL_SA_PASSWORD} -N -C -l 30 -Q \"SELECT 1\" || exit 1" --health-start-period 10s --health-interval 10s --health-timeout 5s @@ -208,7 +206,7 @@ jobs: key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('tests/go.mod') }} - name: Tests - run: GITHUB_ACTION=true GORM_DIALECT=sqlserver GORM_DSN="sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" ./tests/tests_all.sh + run: GITHUB_ACTION=true GORM_DIALECT=sqlserver GORM_DSN="sqlserver://sa:LoremIpsum86@localhost:9930?database=master" ./tests/tests_all.sh tidb: strategy: diff --git a/tests/compose.yml b/tests/compose.yml index 666b1fb0..66f2daee 100644 --- a/tests/compose.yml +++ b/tests/compose.yml @@ -18,16 +18,13 @@ services: - POSTGRES_USER=gorm - POSTGRES_PASSWORD=gorm mssql: - image: '${MSSQL_IMAGE:-mcmoe/mssqldocker}:latest' + image: '${MSSQL_IMAGE}:2022-latest' ports: - "127.0.0.1:9930:1433" environment: - TZ=Asia/Shanghai - ACCEPT_EULA=Y - - SA_PASSWORD=LoremIpsum86 - - MSSQL_DB=gorm - - MSSQL_USER=gorm - - MSSQL_PASSWORD=LoremIpsum86 + - MSSQL_SA_PASSWORD=LoremIpsum86 tidb: image: 'pingcap/tidb:v6.5.0' ports: diff --git a/tests/tests_all.sh b/tests/tests_all.sh index 0622f934..67c6938e 100755 --- a/tests/tests_all.sh +++ b/tests/tests_all.sh @@ -27,7 +27,7 @@ if [[ -z $GITHUB_ACTION ]]; then SQLCMDPASSWORD=LoremIpsum86 sqlcmd -U sa -S localhost:9930 -Q "IF SUSER_ID (N'gorm') IS NULL CREATE LOGIN gorm WITH PASSWORD = 'LoremIpsum86';" > /dev/null || true SQLCMDPASSWORD=LoremIpsum86 sqlcmd -U sa -S localhost:9930 -Q "IF USER_ID (N'gorm') IS NULL CREATE USER gorm FROM LOGIN gorm; ALTER SERVER ROLE sysadmin ADD MEMBER [gorm];" > /dev/null || true else - docker compose up -d + MSSQL_IMAGE=mcr.microsoft.com/mssql/server docker compose up -d fi cd .. fi diff --git a/tests/tests_test.go b/tests/tests_test.go index a127734e..e84162cd 100644 --- a/tests/tests_test.go +++ b/tests/tests_test.go @@ -20,7 +20,7 @@ var DB *gorm.DB var ( mysqlDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local" postgresDSN = "user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai" - sqlserverDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" + sqlserverDSN = "sqlserver://sa:LoremIpsum86@localhost:9930?database=master" tidbDSN = "root:@tcp(localhost:9940)/test?charset=utf8&parseTime=True&loc=Local" ) From 62bd0b9331b8b191e5c1177c665d608603d9b802 Mon Sep 17 00:00:00 2001 From: Yidi Sprei Date: Mon, 30 Sep 2024 02:18:13 -0400 Subject: [PATCH 5/8] Add GitHub Actions workflow to automate release creation on tagged pushes (#7209) * feat(workflows): add GitHub Action to create release on new tag This workflow automates the release creation process whenever a new tag is pushed to the repository. It checks if a release for the tag already exists and creates one if it doesn't, enhancing the release management and streamlining the deployment process. * test * fix(workflow): improve release existence check in release-on-tag.yml Refactor the script to improve checking for existing releases by tag. Return an object instead of using core.setOutput to streamline the workflow logic. Also, set result-encoding to string for better compatibility. * fix(workflow): correct output handling in release-on-tag.yml Corrected the output handling in the 'release-on-tag.yml' workflow file by changing 'result-encoding' to 'outputs'. This ensures that the step correctly checks if a release exists before attempting to create a new one, thereby avoiding potential errors during the release process. Added a blank line for better readability. * fix(workflow): correct output setting in release-on-tag workflow Refactored how the release_exists output is set to be compatible with GitHub Actions syntax. This ensures the workflow reliably detects if a release already exists, improving the robustness of the release process. * fix(release): correct output handling in release-on-tag workflow Improved the way outputs are managed in the 'check_release' step by returning values instead of direct assignments. This change ensures better handling of release existence checks and improves code readability. Added 'result-encoding' to specify string encoding for results. * fix(workflow): correct release existence check and add debug output Refactored the release existence check to return a simple boolean string ('true'/'false') rather than an object. Added a step to print the release existence status for debugging purposes. This ensures correct conditional evaluation and aids in troubleshooting workflow issues. * fix(workflow): simplify release process by removing redundant checks The release-on-tag workflow has been streamlined by eliminating the redundant steps checking for existing releases. This change reduces complexity and speeds up the release process by directly creating a release on every tag push without prior existence verification. --- .github/workflows/release-on-tag.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/release-on-tag.yml diff --git a/.github/workflows/release-on-tag.yml b/.github/workflows/release-on-tag.yml new file mode 100644 index 00000000..3868a8f5 --- /dev/null +++ b/.github/workflows/release-on-tag.yml @@ -0,0 +1,23 @@ +name: Create Release on Tag + +on: + push: + tags: + - '*' + +jobs: + create_release: + runs-on: ubuntu-latest + + steps: + - name: Create Release + uses: actions/create-release@v1 + with: + tag_name: ${{ github.ref_name }} + release_name: ${{ github.ref_name }} + body: | + Release ${{ github.ref_name }} of GORM. + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 05110579bed9e8d55192b042db4f4b9c4d62dd06 Mon Sep 17 00:00:00 2001 From: henryjcee Date: Tue, 8 Oct 2024 12:23:57 +0100 Subject: [PATCH 6/8] Remove pgx replace --- tests/go.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/go.mod b/tests/go.mod index ba8a84a8..44535b03 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -36,6 +36,4 @@ require ( replace gorm.io/gorm => ../ -replace github.com/jackc/pgx/v5 => github.com/jackc/pgx/v5 v5.4.3 - replace github.com/microsoft/go-mssqldb => github.com/microsoft/go-mssqldb v1.7.0 From 72e580c566d783cc0c42bacb183c4abb5ab85a87 Mon Sep 17 00:00:00 2001 From: henryjcee Date: Tue, 8 Oct 2024 17:55:24 +0100 Subject: [PATCH 7/8] Partially revert the change made in https://github.com/go-gorm/gorm/pull/6311 that appears to have broken this for us and at least one other person. --- schema/field.go | 3 ++- tests/go.mod | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/schema/field.go b/schema/field.go index a16c98ab..bdc0b761 100644 --- a/schema/field.go +++ b/schema/field.go @@ -12,6 +12,7 @@ import ( "time" "github.com/jinzhu/now" + "gorm.io/gorm/clause" "gorm.io/gorm/utils" ) @@ -922,7 +923,7 @@ func (field *Field) setupValuerAndSetter() { if !reflectV.IsValid() { field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem()) } else if reflectV.Kind() == reflect.Ptr && reflectV.IsNil() { - return + field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem()) } else if reflectV.Type().AssignableTo(field.FieldType) { field.ReflectValueOf(ctx, value).Set(reflectV) } else if reflectV.Kind() == reflect.Ptr { diff --git a/tests/go.mod b/tests/go.mod index 44535b03..db1d067c 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -1,6 +1,8 @@ module gorm.io/gorm/tests -go 1.18 +go 1.21 + +toolchain go1.23.2 require ( github.com/google/uuid v1.6.0 From 65bfecae14f451d2294a17eba7dcbbdec946aa16 Mon Sep 17 00:00:00 2001 From: henryjcee Date: Wed, 9 Oct 2024 14:06:29 +0100 Subject: [PATCH 8/8] Revert go.mod migration to 1.2x+ --- tests/go.mod | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/go.mod b/tests/go.mod index db1d067c..44535b03 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -1,8 +1,6 @@ module gorm.io/gorm/tests -go 1.21 - -toolchain go1.23.2 +go 1.18 require ( github.com/google/uuid v1.6.0