From c63374f5d154709f99de902cb4d90a1aa8279103 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Mon, 21 Jul 2025 17:55:07 +0800 Subject: [PATCH] Don't request LastInsertID from database if not necessary, close #7469 --- callbacks/create.go | 26 ++++++++++++++++---------- tests/create_test.go | 33 +++++++++++++++++++++++++-------- tests/go.mod | 16 +++++++--------- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/callbacks/create.go b/callbacks/create.go index d8701f51..cb8429b3 100644 --- a/callbacks/create.go +++ b/callbacks/create.go @@ -53,9 +53,13 @@ func Create(config *Config) func(db *gorm.DB) { if _, ok := db.Statement.Clauses["RETURNING"]; !ok { fromColumns := make([]clause.Column, 0, len(db.Statement.Schema.FieldsWithDefaultDBValue)) for _, field := range db.Statement.Schema.FieldsWithDefaultDBValue { - fromColumns = append(fromColumns, clause.Column{Name: field.DBName}) + if field.Readable { + fromColumns = append(fromColumns, clause.Column{Name: field.DBName}) + } + } + if len(fromColumns) > 0 { + db.Statement.AddClause(clause.Returning{Columns: fromColumns}) } - db.Statement.AddClause(clause.Returning{Columns: fromColumns}) } } } @@ -122,6 +126,16 @@ func Create(config *Config) func(db *gorm.DB) { pkFieldName = "@id" ) + if db.Statement.Schema != nil { + if db.Statement.Schema.PrioritizedPrimaryField == nil || + !db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue || + !db.Statement.Schema.PrioritizedPrimaryField.Readable { + return + } + pkField = db.Statement.Schema.PrioritizedPrimaryField + pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName + } + insertID, err := result.LastInsertId() insertOk := err == nil && insertID > 0 @@ -132,14 +146,6 @@ func Create(config *Config) func(db *gorm.DB) { return } - if db.Statement.Schema != nil { - if db.Statement.Schema.PrioritizedPrimaryField == nil || !db.Statement.Schema.PrioritizedPrimaryField.HasDefaultValue { - return - } - pkField = db.Statement.Schema.PrioritizedPrimaryField - pkFieldName = db.Statement.Schema.PrioritizedPrimaryField.DBName - } - // append @id column with value for auto-increment primary key // the @id value is correct, when: 1. without setting auto-increment primary key, 2. database AutoIncrementIncrement = 1 switch values := db.Statement.Dest.(type) { diff --git a/tests/create_test.go b/tests/create_test.go index abb82472..5200427e 100644 --- a/tests/create_test.go +++ b/tests/create_test.go @@ -14,31 +14,48 @@ import ( ) func TestCreate(t *testing.T) { - user := *GetUser("create", Config{}) + u1 := *GetUser("create", Config{}) - if results := DB.Create(&user); results.Error != nil { + if results := DB.Create(&u1); results.Error != nil { t.Fatalf("errors happened when create: %v", results.Error) } else if results.RowsAffected != 1 { t.Fatalf("rows affected expects: %v, got %v", 1, results.RowsAffected) } - if user.ID == 0 { - t.Errorf("user's primary key should has value after create, got : %v", user.ID) + if u1.ID == 0 { + t.Errorf("user's primary key should has value after create, got : %v", u1.ID) } - if user.CreatedAt.IsZero() { + if u1.CreatedAt.IsZero() { t.Errorf("user's created at should be not zero") } - if user.UpdatedAt.IsZero() { + if u1.UpdatedAt.IsZero() { t.Errorf("user's updated at should be not zero") } var newUser User - if err := DB.Where("id = ?", user.ID).First(&newUser).Error; err != nil { + if err := DB.Where("id = ?", u1.ID).First(&newUser).Error; err != nil { t.Fatalf("errors happened when query: %v", err) } else { - CheckUser(t, newUser, user) + CheckUser(t, newUser, u1) + } + + type user struct { + ID int `gorm:"primaryKey;->:false"` + Name string + Age int + } + + var u2 user + if results := DB.Create(&u2); results.Error != nil { + t.Fatalf("errors happened when create: %v", results.Error) + } else if results.RowsAffected != 1 { + t.Fatalf("rows affected expects: %v, got %v", 1, results.RowsAffected) + } + + if u2.ID != 0 { + t.Errorf("don't have the permission to read primary key from db, but got %v", u2.ID) } } diff --git a/tests/go.mod b/tests/go.mod index aa8b8e53..30b0c16e 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -11,7 +11,7 @@ require ( gorm.io/driver/mysql v1.6.0 gorm.io/driver/postgres v1.6.0 gorm.io/driver/sqlite v1.6.0 - gorm.io/driver/sqlserver v1.6.0 + gorm.io/driver/sqlserver v1.6.1 gorm.io/gorm v1.30.0 ) @@ -19,7 +19,7 @@ require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/HuaweiCloudDeveloper/gaussdb-go v1.0.0-rc1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-sql-driver/mysql v1.9.2 // indirect + github.com/go-sql-driver/mysql v1.9.3 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -27,16 +27,14 @@ require ( github.com/jackc/pgx/v5 v5.7.5 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/kr/text v0.2.0 // indirect github.com/mattn/go-sqlite3 v1.14.28 // indirect - github.com/microsoft/go-mssqldb v1.8.2 // indirect + github.com/microsoft/go-mssqldb v1.9.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect - golang.org/x/crypto v0.38.0 // indirect - golang.org/x/sync v0.14.0 // indirect - golang.org/x/text v0.25.0 // indirect + golang.org/x/crypto v0.40.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/text v0.27.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace gorm.io/gorm => ../ \ No newline at end of file +replace gorm.io/gorm => ../