-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Closed
Labels
type:with reproduction stepswith reproduction stepswith reproduction steps
Description
GORM Playground Link
Description
When you wrap db.Transaction
, go will only put that closure in memory once:
func Transaction(ctx context.Context, db *gorm.DB, apply func(ctx context.Context, db *gorm.DB) error) error {
return db.
WithContext(ctx).
Transaction(func(db *gorm.DB) error {
return apply(ctx, db)
})
}
This means that the inner function passed to Transaction
always has the same memory address.
This causes issues in https://github.com/go-gorm/gorm/blob/master/finisher_api.go#L626, where we use the memory address to decide the savepoint name.
With the current implementation, the following statements execute:
2024/08/28 11:32:41 /Users/leosjoberg/Code/open-source/gorm-playground/main_test.go:17 record not found
[0.155ms] [rows:0] SELECT * FROM `users` WHERE name = "jinzhu" AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1
2024/08/28 11:32:41 /Users/leosjoberg/Code/Go/pkg/mod/gorm.io/driver/sqlite@v1.5.6/sqlite.go:237
[0.021ms] [rows:0] SAVEPOINT sp0x10050efe0
2024/08/28 11:32:41 /Users/leosjoberg/Code/open-source/gorm-playground/main_test.go:31
[1.206ms] [rows:1] INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`) VALUES ("2024-08-28 11:32:41.299","2024-08-28 11:32:41.299",NULL,"jinzhu",0,NULL,NULL,NULL,false) RETURNING `id`
User created: 1
2024/08/28 11:32:41 /Users/leosjoberg/Code/Go/pkg/mod/gorm.io/driver/sqlite@v1.5.6/sqlite.go:237
[0.011ms] [rows:0] SAVEPOINT sp0x10050efe0
2024/08/28 11:32:41 /Users/leosjoberg/Code/open-source/gorm-playground/main_test.go:45 record not found
[0.143ms] [rows:0] SELECT * FROM `accounts` WHERE `accounts`.`id` = 1 AND `accounts`.`deleted_at` IS NULL ORDER BY `accounts`.`id` LIMIT 1
2024/08/28 11:32:41 /Users/leosjoberg/Code/Go/pkg/mod/gorm.io/driver/sqlite@v1.5.6/sqlite.go:242
[0.009ms] [rows:0] ROLLBACK TO SAVEPOINT sp0x10050efe0
2024/08/28 11:32:41 /Users/leosjoberg/Code/Go/pkg/mod/gorm.io/driver/sqlite@v1.5.6/sqlite.go:242
[0.006ms] [rows:0] ROLLBACK TO SAVEPOINT sp0x10050efe0
2024/08/28 11:32:41 /Users/leosjoberg/Code/open-source/gorm-playground/main_test.go:63
[0.194ms] [rows:1] SELECT * FROM `users` WHERE name = "jinzhu" AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1
Note that we are rolling back to the same savepoint, making it impossible to rollback the INSERT
statement.
A correct implementation will instead generate unique savepoints:
2024/08/28 11:24:38 /Users/leosjoberg/Code/open-source/gorm-playground/main_test.go:17 record not found
[1.964ms] [rows:0] SELECT * FROM "users" WHERE name = 'jinzhu' AND "users"."deleted_at" IS NULL ORDER BY "users"."id" LIMIT 1
2024/08/28 11:24:38 /Users/leosjoberg/Code/Go/pkg/mod/gorm.io/driver/postgres@v1.5.9/postgres.go:269
[0.486ms] [rows:0] SAVEPOINT sp11014777973198018981
2024/08/28 11:24:38 /Users/leosjoberg/Code/open-source/gorm-playground/main_test.go:31
[21.092ms] [rows:1] INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active") VALUES ('2024-08-28 11:24:38.233','2024-08-28 11:24:38.233',NULL,'jinzhu',0,NULL,NULL,NULL,false) RETURNING "id"
User created: 1
2024/08/28 11:24:38 /Users/leosjoberg/Code/Go/pkg/mod/gorm.io/driver/postgres@v1.5.9/postgres.go:269
[1.623ms] [rows:0] SAVEPOINT sp17326545142615515993
2024/08/28 11:24:38 /Users/leosjoberg/Code/open-source/gorm-playground/main_test.go:45 record not found
[1.504ms] [rows:0] SELECT * FROM "accounts" WHERE "accounts"."id" = 1 AND "accounts"."deleted_at" IS NULL ORDER BY "accounts"."id" LIMIT 1
2024/08/28 11:24:38 /Users/leosjoberg/Code/Go/pkg/mod/gorm.io/driver/postgres@v1.5.9/postgres.go:274
[0.607ms] [rows:0] ROLLBACK TO SAVEPOINT sp17326545142615515993
2024/08/28 11:24:38 /Users/leosjoberg/Code/Go/pkg/mod/gorm.io/driver/postgres@v1.5.9/postgres.go:274
[0.568ms] [rows:0] ROLLBACK TO SAVEPOINT sp11014777973198018981
lucasbn, isaacseymour, ivila and aaronsheah
Metadata
Metadata
Assignees
Labels
type:with reproduction stepswith reproduction stepswith reproduction steps